From 316d4a60166cebf692449846d38d6e43d3ca6bc4 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 01:10:53 +0900 Subject: [PATCH 1/9] feat(linter): implement `no-negated-condition` rule --- crates/oxc_linter/src/rules.rs | 2 +- .../src/rules/eslint/no_negated_condition.rs | 127 ++++++++++++++++++ .../eslint_no_negated_condition.snap | 39 ++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 crates/oxc_linter/src/rules/eslint/no_negated_condition.rs create mode 100644 crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 053fec48b501e..92b582e6710b3 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -93,6 +93,7 @@ mod eslint { pub mod no_loss_of_precision; pub mod no_magic_numbers; pub mod no_multi_str; + pub mod no_negated_condition; pub mod no_nested_ternary; pub mod no_new; pub mod no_new_func; @@ -536,7 +537,6 @@ oxc_macros::declare_all_lint_rules! { eslint::max_classes_per_file, eslint::max_lines, eslint::max_params, - eslint::no_nested_ternary, eslint::no_labels, eslint::no_restricted_imports, eslint::no_object_constructor, diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs new file mode 100644 index 0000000000000..d6d8edd7e01cb --- /dev/null +++ b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs @@ -0,0 +1,127 @@ +use crate::{context::LintContext, rule::Rule, AstNode}; +use oxc_ast::ast::{ConditionalExpression, Expression, IfStatement, Statement}; +use oxc_ast::AstKind; +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_span::{GetSpan, Span}; +use oxc_syntax::operator::{BinaryOperator, UnaryOperator}; + +fn no_negated_condition_diagnostic(span: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("Unexpected negated condition.").with_label(span) +} + +#[derive(Debug, Default, Clone)] +pub struct NoNegatedCondition; + +declare_oxc_lint!( + /// ### What it does + /// + /// This rule disallows the use of negated conditions in `if` statements to improve readability. + /// + /// ### Why is this bad? + /// + /// Negated conditions can make code harder to read and understand, especially in complex logic. + /// It is often clearer to use positive conditions or to refactor the code structure. + /// + /// ### Examples + /// + /// Examples of **incorrect** code for this rule: + /// ```js + /// if (!isReady) { + /// doSomething(); + /// } else { + /// doSomethingElse(); + /// } + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// if (isReady) { + /// doSomethingElse(); + /// } else { + /// doSomething(); + /// } + /// ``` + NoNegatedCondition, + style, +); + +impl Rule for NoNegatedCondition { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + match node.kind() { + AstKind::IfStatement(if_stmt) => { + if !has_else_without_condition(if_stmt) { + return; + } + + if is_negated_if(if_stmt) { + ctx.diagnostic(no_negated_condition_diagnostic(node.span())); + } + } + AstKind::ConditionalExpression(conditional_expr) => { + if is_negated_if_conditional(conditional_expr) { + ctx.diagnostic(no_negated_condition_diagnostic(node.span())); + } + } + _ => {} + } + } +} + +fn has_else_without_condition(node: &IfStatement) -> bool { + matches!(node.alternate, Some(Statement::BlockStatement(_))) +} + +fn is_negated_unary_expression(test: &Expression) -> bool { + matches!(test, Expression::UnaryExpression(unary) if unary.operator == UnaryOperator::LogicalNot) +} + +fn is_negated_binary_expression(test: &Expression) -> bool { + matches!( + test, + Expression::BinaryExpression(binary) + if binary.operator == BinaryOperator::Inequality + || binary.operator == BinaryOperator::StrictInequality + ) +} + +fn is_negated_if(node: &IfStatement) -> bool { + is_negated_unary_expression(&node.test) || is_negated_binary_expression(&node.test) +} + +fn is_negated_if_conditional(node: &ConditionalExpression) -> bool { + is_negated_unary_expression(&node.test) || is_negated_binary_expression(&node.test) +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + "if (a) {}", + "if (a) {} else {}", + "if (!a) {}", + "if (!a) {} else if (b) {}", + "if (!a) {} else if (b) {} else {}", + "if (a == b) {}", + "if (a == b) {} else {}", + "if (a != b) {}", + "if (a != b) {} else if (b) {}", + "if (a != b) {} else if (b) {} else {}", + "if (a !== b) {}", + "if (a === b) {} else {}", + "a ? b : c", + ]; + + let fail = vec![ + "if (!a) {;} else {;}", + "if (a != b) {;} else {;}", + "if (a !== b) {;} else {;}", + "!a ? b : c", + "a != b ? c : d", + "a !== b ? c : d", + ]; + + Tester::new(NoNegatedCondition::NAME, NoNegatedCondition::CATEGORY, pass, fail) + .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap new file mode 100644 index 0000000000000..1e518008449d0 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap @@ -0,0 +1,39 @@ +--- +source: crates/oxc_linter/src/tester.rs +snapshot_kind: text +--- + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ if (!a) {;} else {;} + · ──────────────────── + ╰──── + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ if (a != b) {;} else {;} + · ──────────────────────── + ╰──── + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ if (a !== b) {;} else {;} + · ───────────────────────── + ╰──── + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !a ? b : c + · ────────── + ╰──── + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a != b ? c : d + · ────────────── + ╰──── + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a !== b ? c : d + · ─────────────── + ╰──── From 75aba6c2765b7547a5bd7201e7f4581e7ee6b340 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 02:00:49 +0900 Subject: [PATCH 2/9] update according to comment --- crates/oxc_linter/src/rules/eslint/no_negated_condition.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs index d6d8edd7e01cb..bc3938834427a 100644 --- a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs +++ b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs @@ -44,6 +44,7 @@ declare_oxc_lint!( /// ``` NoNegatedCondition, style, + pending, ); impl Rule for NoNegatedCondition { @@ -55,12 +56,12 @@ impl Rule for NoNegatedCondition { } if is_negated_if(if_stmt) { - ctx.diagnostic(no_negated_condition_diagnostic(node.span())); + ctx.diagnostic(no_negated_condition_diagnostic(if_stmt.span())); } } AstKind::ConditionalExpression(conditional_expr) => { if is_negated_if_conditional(conditional_expr) { - ctx.diagnostic(no_negated_condition_diagnostic(node.span())); + ctx.diagnostic(no_negated_condition_diagnostic(conditional_expr.span())); } } _ => {} From 5a8ae3d005b4a571ba638db47505534083775789 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 02:26:12 +0900 Subject: [PATCH 3/9] span() -> span --- crates/oxc_linter/src/rules/eslint/no_negated_condition.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs index bc3938834427a..71c2cbc8b50e8 100644 --- a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs +++ b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs @@ -3,7 +3,7 @@ use oxc_ast::ast::{ConditionalExpression, Expression, IfStatement, Statement}; use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; +use oxc_span::Span; use oxc_syntax::operator::{BinaryOperator, UnaryOperator}; fn no_negated_condition_diagnostic(span: Span) -> OxcDiagnostic { @@ -56,12 +56,12 @@ impl Rule for NoNegatedCondition { } if is_negated_if(if_stmt) { - ctx.diagnostic(no_negated_condition_diagnostic(if_stmt.span())); + ctx.diagnostic(no_negated_condition_diagnostic(if_stmt.span)); } } AstKind::ConditionalExpression(conditional_expr) => { if is_negated_if_conditional(conditional_expr) { - ctx.diagnostic(no_negated_condition_diagnostic(conditional_expr.span())); + ctx.diagnostic(no_negated_condition_diagnostic(conditional_expr.span)); } } _ => {} From d3df51d879481e9a3b195a6e877405370cad8a51 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 04:22:01 +0900 Subject: [PATCH 4/9] merge eslint-plugin-unicorn --- .../src/rules/eslint/no_negated_condition.rs | 47 +------------------ .../src/rules/unicorn/no_negated_condition.rs | 21 +++++++++ .../eslint_no_negated_condition.snap | 24 ++++++---- .../unicorn_no_negated_condition.snap | 42 +++++++++++++++++ 4 files changed, 80 insertions(+), 54 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs index 71c2cbc8b50e8..0e59342810bab 100644 --- a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs +++ b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs @@ -1,10 +1,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; -use oxc_ast::ast::{ConditionalExpression, Expression, IfStatement, Statement}; -use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; -use oxc_syntax::operator::{BinaryOperator, UnaryOperator}; fn no_negated_condition_diagnostic(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Unexpected negated condition.").with_label(span) @@ -49,51 +46,11 @@ declare_oxc_lint!( impl Rule for NoNegatedCondition { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - match node.kind() { - AstKind::IfStatement(if_stmt) => { - if !has_else_without_condition(if_stmt) { - return; - } - - if is_negated_if(if_stmt) { - ctx.diagnostic(no_negated_condition_diagnostic(if_stmt.span)); - } - } - AstKind::ConditionalExpression(conditional_expr) => { - if is_negated_if_conditional(conditional_expr) { - ctx.diagnostic(no_negated_condition_diagnostic(conditional_expr.span)); - } - } - _ => {} - } + // This rule is exactly the same as the eslint-plugin-unicorn's no-negated-condition rule. + crate::rules::unicorn::no_negated_condition::NoNegatedCondition::default().run(node, ctx); } } -fn has_else_without_condition(node: &IfStatement) -> bool { - matches!(node.alternate, Some(Statement::BlockStatement(_))) -} - -fn is_negated_unary_expression(test: &Expression) -> bool { - matches!(test, Expression::UnaryExpression(unary) if unary.operator == UnaryOperator::LogicalNot) -} - -fn is_negated_binary_expression(test: &Expression) -> bool { - matches!( - test, - Expression::BinaryExpression(binary) - if binary.operator == BinaryOperator::Inequality - || binary.operator == BinaryOperator::StrictInequality - ) -} - -fn is_negated_if(node: &IfStatement) -> bool { - is_negated_unary_expression(&node.test) || is_negated_binary_expression(&node.test) -} - -fn is_negated_if_conditional(node: &ConditionalExpression) -> bool { - is_negated_unary_expression(&node.test) || is_negated_binary_expression(&node.test) -} - #[test] fn test() { use crate::tester::Tester; diff --git a/crates/oxc_linter/src/rules/unicorn/no_negated_condition.rs b/crates/oxc_linter/src/rules/unicorn/no_negated_condition.rs index 2786b86798af2..ffdf1251ddeff 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_negated_condition.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_negated_condition.rs @@ -119,6 +119,20 @@ fn test() { r"if (a !== b) {}", r"if (a === b) {} else {}", r"a ? b : c", + // Test cases from ESLint + "if (a) {}", + "if (a) {} else {}", + "if (!a) {}", + "if (!a) {} else if (b) {}", + "if (!a) {} else if (b) {} else {}", + "if (a == b) {}", + "if (a == b) {} else {}", + "if (a != b) {}", + "if (a != b) {} else if (b) {}", + "if (a != b) {} else if (b) {} else {}", + "if (a !== b) {}", + "if (a === b) {} else {}", + "a ? b : c", ]; let fail = vec![ @@ -140,6 +154,13 @@ fn test() { r"if(!a) {b()} else {c()}", r"if(!!a) b(); else c();", r"(!!a) ? b() : c();", + // Test cases from ESLint + "if (!a) {;} else {;}", + "if (a != b) {;} else {;}", + "if (a !== b) {;} else {;}", + "!a ? b : c", + "a != b ? c : d", + "a !== b ? c : d", ]; Tester::new(NoNegatedCondition::NAME, NoNegatedCondition::CATEGORY, pass, fail) diff --git a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap index 1e518008449d0..9267f7ac2ddae 100644 --- a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap +++ b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap @@ -3,37 +3,43 @@ source: crates/oxc_linter/src/tester.rs snapshot_kind: text --- ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] + ╭─[no_negated_condition.tsx:1:5] 1 │ if (!a) {;} else {;} - · ──────────────────── + · ── ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] + ╭─[no_negated_condition.tsx:1:5] 1 │ if (a != b) {;} else {;} - · ──────────────────────── + · ────── ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] + ╭─[no_negated_condition.tsx:1:5] 1 │ if (a !== b) {;} else {;} - · ───────────────────────── + · ─────── ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. ⚠ eslint(no-negated-condition): Unexpected negated condition. ╭─[no_negated_condition.tsx:1:1] 1 │ !a ? b : c - · ────────── + · ── ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. ⚠ eslint(no-negated-condition): Unexpected negated condition. ╭─[no_negated_condition.tsx:1:1] 1 │ a != b ? c : d - · ────────────── + · ────── ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. ⚠ eslint(no-negated-condition): Unexpected negated condition. ╭─[no_negated_condition.tsx:1:1] 1 │ a !== b ? c : d - · ─────────────── + · ─────── ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. diff --git a/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap b/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap index 97873e2abaf6c..3912da9b2ab85 100644 --- a/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap +++ b/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap @@ -127,3 +127,45 @@ snapshot_kind: text · ─── ╰──── help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (!a) {;} else {;} + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (a != b) {;} else {;} + · ────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (a !== b) {;} else {;} + · ─────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !a ? b : c + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a != b ? c : d + · ────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a !== b ? c : d + · ─────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. From cf76f8a820f66348f598996589529f560bd4e54a Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 04:27:50 +0900 Subject: [PATCH 5/9] fix lint --- .../oxc_linter/src/rules/eslint/no_negated_condition.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs index 0e59342810bab..5fdbc39e6b97e 100644 --- a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs +++ b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs @@ -1,11 +1,5 @@ use crate::{context::LintContext, rule::Rule, AstNode}; -use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; - -fn no_negated_condition_diagnostic(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Unexpected negated condition.").with_label(span) -} #[derive(Debug, Default, Clone)] pub struct NoNegatedCondition; @@ -47,7 +41,7 @@ declare_oxc_lint!( impl Rule for NoNegatedCondition { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { // This rule is exactly the same as the eslint-plugin-unicorn's no-negated-condition rule. - crate::rules::unicorn::no_negated_condition::NoNegatedCondition::default().run(node, ctx); + crate::rules::unicorn::no_negated_condition::NoNegatedCondition.run(node, ctx); } } From 24388b5b54110e06e79ca871c1f96251c4a45786 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 10:07:11 +0900 Subject: [PATCH 6/9] update transform_rule_and_plugin_name --- crates/oxc_linter/src/config/rules.rs | 4 + crates/oxc_linter/src/rules.rs | 1 - .../src/rules/eslint/no_negated_condition.rs | 79 ------------------- 3 files changed, 4 insertions(+), 80 deletions(-) delete mode 100644 crates/oxc_linter/src/rules/eslint/no_negated_condition.rs diff --git a/crates/oxc_linter/src/config/rules.rs b/crates/oxc_linter/src/config/rules.rs index e661f876f9fe9..251026b5f088c 100644 --- a/crates/oxc_linter/src/config/rules.rs +++ b/crates/oxc_linter/src/config/rules.rs @@ -160,6 +160,10 @@ fn transform_rule_and_plugin_name<'a>( return (rule_name, "eslint"); } + if plugin_name == "unicorn" && rule_name == "no-negated-condition" { + return ("no-negated-condition", "eslint"); + } + (rule_name, plugin_name) } diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 92b582e6710b3..d5f23e69b27fc 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -93,7 +93,6 @@ mod eslint { pub mod no_loss_of_precision; pub mod no_magic_numbers; pub mod no_multi_str; - pub mod no_negated_condition; pub mod no_nested_ternary; pub mod no_new; pub mod no_new_func; diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs deleted file mode 100644 index 5fdbc39e6b97e..0000000000000 --- a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::{context::LintContext, rule::Rule, AstNode}; -use oxc_macros::declare_oxc_lint; - -#[derive(Debug, Default, Clone)] -pub struct NoNegatedCondition; - -declare_oxc_lint!( - /// ### What it does - /// - /// This rule disallows the use of negated conditions in `if` statements to improve readability. - /// - /// ### Why is this bad? - /// - /// Negated conditions can make code harder to read and understand, especially in complex logic. - /// It is often clearer to use positive conditions or to refactor the code structure. - /// - /// ### Examples - /// - /// Examples of **incorrect** code for this rule: - /// ```js - /// if (!isReady) { - /// doSomething(); - /// } else { - /// doSomethingElse(); - /// } - /// ``` - /// - /// Examples of **correct** code for this rule: - /// ```js - /// if (isReady) { - /// doSomethingElse(); - /// } else { - /// doSomething(); - /// } - /// ``` - NoNegatedCondition, - style, - pending, -); - -impl Rule for NoNegatedCondition { - fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - // This rule is exactly the same as the eslint-plugin-unicorn's no-negated-condition rule. - crate::rules::unicorn::no_negated_condition::NoNegatedCondition.run(node, ctx); - } -} - -#[test] -fn test() { - use crate::tester::Tester; - - let pass = vec![ - "if (a) {}", - "if (a) {} else {}", - "if (!a) {}", - "if (!a) {} else if (b) {}", - "if (!a) {} else if (b) {} else {}", - "if (a == b) {}", - "if (a == b) {} else {}", - "if (a != b) {}", - "if (a != b) {} else if (b) {}", - "if (a != b) {} else if (b) {} else {}", - "if (a !== b) {}", - "if (a === b) {} else {}", - "a ? b : c", - ]; - - let fail = vec![ - "if (!a) {;} else {;}", - "if (a != b) {;} else {;}", - "if (a !== b) {;} else {;}", - "!a ? b : c", - "a != b ? c : d", - "a !== b ? c : d", - ]; - - Tester::new(NoNegatedCondition::NAME, NoNegatedCondition::CATEGORY, pass, fail) - .test_and_snapshot(); -} From 0cdc22e58c84c6d5c3808b481406954ba26ffa39 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 28 Dec 2024 10:29:33 +0900 Subject: [PATCH 7/9] fix --- crates/oxc_linter/src/rules.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index d5f23e69b27fc..053fec48b501e 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -536,6 +536,7 @@ oxc_macros::declare_all_lint_rules! { eslint::max_classes_per_file, eslint::max_lines, eslint::max_params, + eslint::no_nested_ternary, eslint::no_labels, eslint::no_restricted_imports, eslint::no_object_constructor, From 6cd942005af0bd4d9ffecb017e0e73127aa03aff Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 29 Dec 2024 11:16:33 +0900 Subject: [PATCH 8/9] move from unicorn -> eslint --- crates/oxc_linter/src/rules.rs | 4 +- .../no_negated_condition.rs | 0 .../eslint_no_negated_condition.snap | 126 +++++++++++++ .../unicorn_no_negated_condition.snap | 171 ------------------ 4 files changed, 128 insertions(+), 173 deletions(-) rename crates/oxc_linter/src/rules/{unicorn => eslint}/no_negated_condition.rs (100%) delete mode 100644 crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 053fec48b501e..bacd8e377b754 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -93,6 +93,7 @@ mod eslint { pub mod no_loss_of_precision; pub mod no_magic_numbers; pub mod no_multi_str; + pub mod no_negated_condition; pub mod no_nested_ternary; pub mod no_new; pub mod no_new_func; @@ -320,7 +321,6 @@ mod unicorn { pub mod no_length_as_slice_end; pub mod no_lonely_if; pub mod no_magic_array_flat_depth; - pub mod no_negated_condition; pub mod no_negation_in_equality_check; pub mod no_nested_ternary; pub mod no_new_array; @@ -587,6 +587,7 @@ oxc_macros::declare_all_lint_rules! { eslint::no_label_var, eslint::no_loss_of_precision, eslint::no_magic_numbers, + eslint::no_negated_condition, eslint::no_multi_str, eslint::no_new_func, eslint::no_new_native_nonconstructor, @@ -918,7 +919,6 @@ oxc_macros::declare_all_lint_rules! { unicorn::no_length_as_slice_end, unicorn::no_lonely_if, unicorn::no_magic_array_flat_depth, - unicorn::no_negated_condition, unicorn::no_negation_in_equality_check, unicorn::no_nested_ternary, unicorn::no_new_array, diff --git a/crates/oxc_linter/src/rules/unicorn/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs similarity index 100% rename from crates/oxc_linter/src/rules/unicorn/no_negated_condition.rs rename to crates/oxc_linter/src/rules/eslint/no_negated_condition.rs diff --git a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap index 9267f7ac2ddae..606a9eac3f812 100644 --- a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap +++ b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap @@ -43,3 +43,129 @@ snapshot_kind: text · ─────── ╰──── help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:4] + 1 │ (( !a )) ? b : c + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !(( a )) ? b : c + · ──────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:4] + 1 │ if(!(( a ))) b(); else c(); + · ──────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:7] + 1 │ if((( !a ))) b(); else c(); + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:21] + 1 │ function a() {return!a ? b : c} + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:21] + 1 │ function a() {return!(( a )) ? b : c} + · ──────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !a ? b : c ? d : e + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !a ? b : (( c ? d : e )) + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:4] + 1 │ if(!a) b(); else c() + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:4] + 1 │ if(!a) {b()} else {c()} + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:4] + 1 │ if(!!a) b(); else c(); + · ─── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:2] + 1 │ (!!a) ? b() : c(); + · ─── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (!a) {;} else {;} + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (a != b) {;} else {;} + · ────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (a !== b) {;} else {;} + · ─────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !a ? b : c + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a != b ? c : d + · ────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a !== b ? c : d + · ─────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. diff --git a/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap b/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap deleted file mode 100644 index 3912da9b2ab85..0000000000000 --- a/crates/oxc_linter/src/snapshots/unicorn_no_negated_condition.snap +++ /dev/null @@ -1,171 +0,0 @@ ---- -source: crates/oxc_linter/src/tester.rs -snapshot_kind: text ---- - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (!a) {;} else {;} - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (a != b) {;} else {;} - · ────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (a !== b) {;} else {;} - · ─────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ !a ? b : c - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ a != b ? c : d - · ────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ a !== b ? c : d - · ─────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:4] - 1 │ (( !a )) ? b : c - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ !(( a )) ? b : c - · ──────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:4] - 1 │ if(!(( a ))) b(); else c(); - · ──────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:7] - 1 │ if((( !a ))) b(); else c(); - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:21] - 1 │ function a() {return!a ? b : c} - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:21] - 1 │ function a() {return!(( a )) ? b : c} - · ──────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ !a ? b : c ? d : e - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ !a ? b : (( c ? d : e )) - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:4] - 1 │ if(!a) b(); else c() - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:4] - 1 │ if(!a) {b()} else {c()} - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:4] - 1 │ if(!!a) b(); else c(); - · ─── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:2] - 1 │ (!!a) ? b() : c(); - · ─── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (!a) {;} else {;} - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (a != b) {;} else {;} - · ────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (a !== b) {;} else {;} - · ─────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ !a ? b : c - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ a != b ? c : d - · ────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint-plugin-unicorn(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ a !== b ? c : d - · ─────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. From 68b1863c46d1d2641c3043e394ea4d1e81067f36 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 29 Dec 2024 11:18:14 +0900 Subject: [PATCH 9/9] change test order --- .../src/rules/eslint/no_negated_condition.rs | 42 +++++----- .../eslint_no_negated_condition.snap | 84 +++++++++---------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs index ffdf1251ddeff..60ffa1770a169 100644 --- a/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs +++ b/crates/oxc_linter/src/rules/eslint/no_negated_condition.rs @@ -106,20 +106,6 @@ fn test() { use crate::tester::Tester; let pass = vec![ - r"if (a) {}", - r"if (a) {} else {}", - r"if (!a) {}", - r"if (!a) {} else if (b) {}", - r"if (!a) {} else if (b) {} else {}", - r"if (a == b) {}", - r"if (a == b) {} else {}", - r"if (a != b) {}", - r"if (a != b) {} else if (b) {}", - r"if (a != b) {} else if (b) {} else {}", - r"if (a !== b) {}", - r"if (a === b) {} else {}", - r"a ? b : c", - // Test cases from ESLint "if (a) {}", "if (a) {} else {}", "if (!a) {}", @@ -133,9 +119,30 @@ fn test() { "if (a !== b) {}", "if (a === b) {} else {}", "a ? b : c", + // Test cases from eslint-plugin-unicorn + r"if (a) {}", + r"if (a) {} else {}", + r"if (!a) {}", + r"if (!a) {} else if (b) {}", + r"if (!a) {} else if (b) {} else {}", + r"if (a == b) {}", + r"if (a == b) {} else {}", + r"if (a != b) {}", + r"if (a != b) {} else if (b) {}", + r"if (a != b) {} else if (b) {} else {}", + r"if (a !== b) {}", + r"if (a === b) {} else {}", + r"a ? b : c", ]; let fail = vec![ + "if (!a) {;} else {;}", + "if (a != b) {;} else {;}", + "if (a !== b) {;} else {;}", + "!a ? b : c", + "a != b ? c : d", + "a !== b ? c : d", + // Test cases from eslint-plugin-unicorn r"if (!a) {;} else {;}", r"if (a != b) {;} else {;}", r"if (a !== b) {;} else {;}", @@ -154,13 +161,6 @@ fn test() { r"if(!a) {b()} else {c()}", r"if(!!a) b(); else c();", r"(!!a) ? b() : c();", - // Test cases from ESLint - "if (!a) {;} else {;}", - "if (a != b) {;} else {;}", - "if (a !== b) {;} else {;}", - "!a ? b : c", - "a != b ? c : d", - "a !== b ? c : d", ]; Tester::new(NoNegatedCondition::NAME, NoNegatedCondition::CATEGORY, pass, fail) diff --git a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap index 606a9eac3f812..88967b97f4f88 100644 --- a/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap +++ b/crates/oxc_linter/src/snapshots/eslint_no_negated_condition.snap @@ -44,6 +44,48 @@ snapshot_kind: text ╰──── help: Remove the negation operator and switch the consequent and alternate branches. + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (!a) {;} else {;} + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (a != b) {;} else {;} + · ────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:5] + 1 │ if (a !== b) {;} else {;} + · ─────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ !a ? b : c + · ── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a != b ? c : d + · ────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + + ⚠ eslint(no-negated-condition): Unexpected negated condition. + ╭─[no_negated_condition.tsx:1:1] + 1 │ a !== b ? c : d + · ─────── + ╰──── + help: Remove the negation operator and switch the consequent and alternate branches. + ⚠ eslint(no-negated-condition): Unexpected negated condition. ╭─[no_negated_condition.tsx:1:4] 1 │ (( !a )) ? b : c @@ -127,45 +169,3 @@ snapshot_kind: text · ─── ╰──── help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (!a) {;} else {;} - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (a != b) {;} else {;} - · ────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:5] - 1 │ if (a !== b) {;} else {;} - · ─────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ !a ? b : c - · ── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ a != b ? c : d - · ────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches. - - ⚠ eslint(no-negated-condition): Unexpected negated condition. - ╭─[no_negated_condition.tsx:1:1] - 1 │ a !== b ? c : d - · ─────── - ╰──── - help: Remove the negation operator and switch the consequent and alternate branches.