From b3934300a5e223392cc51f1eefd2f36b2be90ff6 Mon Sep 17 00:00:00 2001 From: camc314 <18101008+camc314@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:09:26 +0000 Subject: [PATCH] fix(linter/curly): fix multi-or-nest and consistent conflict (#18660) Skip else-if statements when running the curly rule, as they are already handled as part of the parent if-else chain. This prevents duplicate diagnostics and fixes the conflict where multi-or-nest would suggest removing braces while consistent would require them. fixes #18566 --- crates/oxc_linter/src/rules/eslint/curly.rs | 24 ++++++- .../src/snapshots/eslint_curly.snap | 66 ------------------- 2 files changed, 23 insertions(+), 67 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/curly.rs b/crates/oxc_linter/src/rules/eslint/curly.rs index 05e3fd78b2be8..6668b287db26c 100644 --- a/crates/oxc_linter/src/rules/eslint/curly.rs +++ b/crates/oxc_linter/src/rules/eslint/curly.rs @@ -278,7 +278,9 @@ impl Rule for Curly { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { match node.kind() { - AstKind::IfStatement(stmt) => self.run_for_if_statement(stmt, ctx), + AstKind::IfStatement(stmt) if !is_else_if(node, stmt, ctx) => { + self.run_for_if_statement(stmt, ctx); + } AstKind::ForStatement(stmt) => self.run_for_loop("for", &stmt.body, ctx), AstKind::ForInStatement(stmt) => self.run_for_loop("for-in", &stmt.body, ctx), AstKind::ForOfStatement(stmt) => self.run_for_loop("for-of", &stmt.body, ctx), @@ -360,6 +362,15 @@ fn get_if_else_keyword(is_else: bool) -> &'static str { if is_else { "else" } else { "if" } } +fn is_else_if(node: &AstNode, stmt: &IfStatement, ctx: &LintContext) -> bool { + if let AstKind::IfStatement(parent_if) = ctx.nodes().parent_kind(node.id()) + && parent_if.alternate.as_ref().is_some_and(|alt| alt.span() == stmt.span) + { + return true; + } + false +} + fn has_braces(body: &Statement) -> bool { matches!(body, Statement::BlockStatement(_)) } @@ -885,6 +896,17 @@ fn test() { "if (a) { if (b) foo(); } else { bar(); }", Some(serde_json::json!(["multi-or-nest", "consistent"])), ), + ( + "if (dividerPosition) { + if (condition1 && condition2) { + closePos = state.pos; + const y = closePos; + } + } else if (condition3 && condition4) { + dividerPosition = state.pos; + }", + Some(serde_json::json!(["multi-or-nest", "consistent"])), + ), ("if (a) { if (b) { foo(); bar(); } } else baz();", Some(serde_json::json!(["multi"]))), ( "if (a) foo(); else if (b) { if (c) bar(); } else baz();", diff --git a/crates/oxc_linter/src/snapshots/eslint_curly.snap b/crates/oxc_linter/src/snapshots/eslint_curly.snap index d6d03423c1a1a..6d165a687eba3 100644 --- a/crates/oxc_linter/src/snapshots/eslint_curly.snap +++ b/crates/oxc_linter/src/snapshots/eslint_curly.snap @@ -30,13 +30,6 @@ source: crates/oxc_linter/src/tester.rs ╰──── help: Replace `baz()` with `{baz()}`. - ⚠ eslint(curly): Expected { after 'if' condition. - ╭─[curly.tsx:1:34] - 1 │ if (foo) { bar() } else if (faa) baz() - · ───── - ╰──── - help: Replace `baz()` with `{baz()}`. - ⚠ eslint(curly): Expected { after 'while' condition. ╭─[curly.tsx:1:13] 1 │ while (foo) bar() @@ -161,13 +154,6 @@ source: crates/oxc_linter/src/tester.rs ╰──── help: Replace `{ quuux(); }` with ` quuux(); `. - ⚠ eslint(curly): Unexpected { after 'if' condition. - ╭─[curly.tsx:1:41] - 1 │ if (foo) if (bar) baz(); else if (quux) { quuux(); } - · ──────────── - ╰──── - help: Replace `{ quuux(); }` with ` quuux(); `. - ⚠ eslint(curly): Unexpected { after 'while' condition. ╭─[curly.tsx:1:13] 1 │ while (foo) { bar() } @@ -211,28 +197,6 @@ source: crates/oxc_linter/src/tester.rs 8 │ │ console.log(2) 9 │ │ else 10 │ │ console.log(3) - 11 │ ╰─▶ } - ╰──── - help: Replace `{ - if (2) - console.log(2) - else - console.log(3) - }` with ` - if (2) - console.log(2) - else - console.log(3) - `. - - ⚠ eslint(curly): Unexpected { after 'else'. - ╭─[curly.tsx:6:11] - 5 │ console.log(1) - 6 │ ╭─▶ } else { - 7 │ │ if (2) - 8 │ │ console.log(2) - 9 │ │ else - 10 │ │ console.log(3) 11 │ ╰─▶ } ╰──── help: Replace `{ @@ -560,13 +524,6 @@ source: crates/oxc_linter/src/tester.rs ╰──── help: Replace `faa();` with `{faa();}`. - ⚠ eslint(curly): Expected { after 'if' condition. - ╭─[curly.tsx:1:33] - 1 │ if (true) foo(); else if (true) faa(); else { bar(); baz(); } - · ────── - ╰──── - help: Replace `faa();` with `{faa();}`. - ⚠ eslint(curly): Expected { after 'if' condition. ╭─[curly.tsx:1:21] 1 │ if (true) if (true) foo(); else { bar(); baz(); } @@ -749,22 +706,6 @@ source: crates/oxc_linter/src/tester.rs 2 │ ╭─▶ else if (bar) { 3 │ │ doSomethingElse() 4 │ │ ; - 5 │ ╰─▶ } - ╰──── - help: Replace `{ - doSomethingElse() - ; - }` with ` - doSomethingElse() - ; - `. - - ⚠ eslint(curly): Unexpected { after 'if' condition. - ╭─[curly.tsx:2:18] - 1 │ if (foo) doSomething(); - 2 │ ╭─▶ else if (bar) { - 3 │ │ doSomethingElse() - 4 │ │ ; 5 │ ╰─▶ } ╰──── help: Replace `{ @@ -1016,13 +957,6 @@ source: crates/oxc_linter/src/tester.rs ╰──── help: Replace `{bar();}` with `bar();`. - ⚠ eslint(curly): Unexpected { after 'if' condition. - ╭─[curly.tsx:1:51] - 1 │ if(a) { if (b) foo(); } if (c) bar(); else if(foo){bar();} - · ──────── - ╰──── - help: Replace `{bar();}` with `bar();`. - ⚠ eslint(curly): Expected { after 'if' condition. ╭─[curly.tsx:1:11] 1 │ ╭─▶ if (true) [1, 2, 3]