Skip to content

Commit 8776301

Browse files
committed
fix(linter/no-inner-declarations): flag var statement as body of for loop (#11632)
Follow-on after #11617. That change broke the rule (failed to report errors) in these cases: ```js for (const x in {}) var y = 5; for (const x of []) var y = 5; for (const x = 1; a < 10; a++) var y = 5; ``` We need to check that parent is a `for` statement *and* that the declaration is its `init` / `left`.
1 parent 7266200 commit 8776301

File tree

2 files changed

+48
-19
lines changed

2 files changed

+48
-19
lines changed

crates/oxc_linter/src/rules/eslint/no_inner_declarations.rs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use oxc_ast::AstKind;
22
use oxc_diagnostics::OxcDiagnostic;
33
use oxc_macros::declare_oxc_lint;
4-
use oxc_span::Span;
4+
use oxc_span::{GetSpan, Span};
55

66
use crate::{AstNode, context::LintContext, rule::Rule};
77

@@ -70,7 +70,8 @@ impl Rule for NoInnerDeclarations {
7070
}
7171

7272
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
73-
let span = match node.kind() {
73+
let kind = node.kind();
74+
let span = match kind {
7475
AstKind::VariableDeclaration(decl)
7576
if decl.kind.is_var() && self.config == NoInnerDeclarationsConfig::Both =>
7677
{
@@ -84,26 +85,30 @@ impl Rule for NoInnerDeclarations {
8485

8586
let mut parent = ctx.nodes().parent_node(node.id());
8687
if let Some(parent_node) = parent {
87-
let parent_kind = parent_node.kind();
88-
if let AstKind::FunctionBody(_) = parent_kind {
89-
if let Some(grandparent) = ctx.nodes().parent_node(parent_node.id()) {
90-
if grandparent.kind().is_function_like() {
91-
return;
88+
match parent_node.kind() {
89+
AstKind::FunctionBody(_) => {
90+
if let Some(grandparent) = ctx.nodes().parent_node(parent_node.id()) {
91+
if grandparent.kind().is_function_like() {
92+
return;
93+
}
9294
}
9395
}
94-
}
95-
96-
if matches!(
97-
parent_kind,
9896
AstKind::Program(_)
99-
| AstKind::StaticBlock(_)
100-
| AstKind::ExportNamedDeclaration(_)
101-
| AstKind::ExportDefaultDeclaration(_)
102-
| AstKind::ForStatement(_)
103-
| AstKind::ForInStatement(_)
104-
| AstKind::ForOfStatement(_)
105-
) {
106-
return;
97+
| AstKind::StaticBlock(_)
98+
| AstKind::ExportNamedDeclaration(_)
99+
| AstKind::ExportDefaultDeclaration(_) => return,
100+
AstKind::ForStatement(for_stmt) => {
101+
if for_stmt.init.as_ref().is_some_and(|init| init.span() == kind.span()) {
102+
return;
103+
}
104+
}
105+
AstKind::ForInStatement(for_stmt) if for_stmt.left.span() == kind.span() => {
106+
return;
107+
}
108+
AstKind::ForOfStatement(for_stmt) if for_stmt.left.span() == kind.span() => {
109+
return;
110+
}
111+
_ => {}
107112
}
108113
}
109114

@@ -213,6 +218,9 @@ fn test() {
213218
("for (const x in {}) { var y = 5; }", Some(serde_json::json!(["both"]))),
214219
("for (const x of []) { var y = 5; }", Some(serde_json::json!(["both"]))),
215220
("for (const x = 1; a < 10; a++) { var y = 5; }", Some(serde_json::json!(["both"]))),
221+
("for (const x in {}) var y = 5;", Some(serde_json::json!(["both"]))),
222+
("for (const x of []) var y = 5;", Some(serde_json::json!(["both"]))),
223+
("for (const x = 1; a < 10; a++) var y = 5;", Some(serde_json::json!(["both"]))),
216224
];
217225

218226
Tester::new(NoInnerDeclarations::NAME, NoInnerDeclarations::PLUGIN, pass, fail)

crates/oxc_linter/src/snapshots/eslint_no_inner_declarations.snap

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,24 @@ source: crates/oxc_linter/src/tester.rs
175175
· ───
176176
╰────
177177
help: Move variable declaration to program root
178+
179+
eslint(no-inner-declarations): Variable or `function` declarations are not allowed in nested blocks
180+
╭─[no_inner_declarations.tsx:1:21]
181+
1for (const x in {}) var y = 5;
182+
· ───
183+
╰────
184+
help: Move variable declaration to program root
185+
186+
eslint(no-inner-declarations): Variable or `function` declarations are not allowed in nested blocks
187+
╭─[no_inner_declarations.tsx:1:21]
188+
1for (const x of []) var y = 5;
189+
· ───
190+
╰────
191+
help: Move variable declaration to program root
192+
193+
eslint(no-inner-declarations): Variable or `function` declarations are not allowed in nested blocks
194+
╭─[no_inner_declarations.tsx:1:32]
195+
1for (const x = 1; a < 10; a++) var y = 5;
196+
· ───
197+
╰────
198+
help: Move variable declaration to program root

0 commit comments

Comments
 (0)