Skip to content

Commit a56cb68

Browse files
committed
perf(linter): update no-const-assign to run on nodes instead of symbols
1 parent b93e2d5 commit a56cb68

File tree

3 files changed

+111
-13
lines changed

3 files changed

+111
-13
lines changed

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,11 @@ impl RuleRunner for crate::rules::eslint::no_console::NoConsole {
229229
}
230230

231231
impl RuleRunner for crate::rules::eslint::no_const_assign::NoConstAssign {
232-
const NODE_TYPES: Option<&AstTypesBitset> = None;
233-
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::RunOnSymbol;
232+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
233+
AstType::BindingRestElement,
234+
AstType::VariableDeclarator,
235+
]));
236+
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
234237
}
235238

236239
impl RuleRunner

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

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use oxc_ast::AstKind;
12
use oxc_diagnostics::OxcDiagnostic;
23
use oxc_macros::declare_oxc_lint;
3-
use oxc_semantic::SymbolId;
4+
use oxc_semantic::{AstNode, SymbolId};
45
use oxc_span::Span;
56

67
use crate::{context::LintContext, rule::Rule};
@@ -50,18 +51,34 @@ declare_oxc_lint!(
5051
);
5152

5253
impl Rule for NoConstAssign {
53-
fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) {
54-
let symbol_table = ctx.scoping();
55-
if symbol_table.symbol_flags(symbol_id).is_const_variable() {
56-
for reference in symbol_table.get_resolved_references(symbol_id) {
57-
if reference.is_write() {
58-
ctx.diagnostic(no_const_assign_diagnostic(
59-
symbol_table.symbol_name(symbol_id),
60-
symbol_table.symbol_span(symbol_id),
61-
ctx.semantic().reference_span(reference),
62-
));
54+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
55+
match node.kind() {
56+
AstKind::VariableDeclarator(decl) if decl.kind.is_const() || decl.kind.is_using() => {
57+
for ident in decl.id.get_binding_identifiers() {
58+
check_symbol_id(ident.symbol_id(), ctx);
6359
}
6460
}
61+
AstKind::BindingRestElement(rest) => {
62+
for ident in rest.argument.get_binding_identifiers() {
63+
check_symbol_id(ident.symbol_id(), ctx);
64+
}
65+
}
66+
_ => {}
67+
}
68+
}
69+
}
70+
71+
fn check_symbol_id(symbol_id: SymbolId, ctx: &LintContext<'_>) {
72+
let symbol_table = ctx.scoping();
73+
if symbol_table.symbol_flags(symbol_id).is_const_variable() {
74+
for reference in symbol_table.get_resolved_references(symbol_id) {
75+
if reference.is_write() {
76+
ctx.diagnostic(no_const_assign_diagnostic(
77+
symbol_table.symbol_name(symbol_id),
78+
symbol_table.symbol_span(symbol_id),
79+
ctx.semantic().reference_span(reference),
80+
));
81+
}
6582
}
6683
}
6784
}
@@ -86,6 +103,11 @@ fn test() {
86103
("const a = 1; { let a = 2; { a += 1; } }", None),
87104
("const foo = 1;let bar;bar[foo ?? foo] = 42;", None),
88105
("const FOO = 1; ({ files = FOO } = arg1); ", None),
106+
// using + await using
107+
("using x = foo();", None),
108+
("await using x = foo();", None),
109+
("using x = foo(); bar(x);", None),
110+
("await using x = foo(); bar(x);", None),
89111
];
90112

91113
let fail = vec![
@@ -107,6 +129,15 @@ fn test() {
107129
("const [a, b, ...[c, ...d]] = [1, 2, 3, 4, 5]; d = 123", None),
108130
("const d = 123; [a, b, ...[c, ...d]] = [1, 2, 3, 4, 5]", None),
109131
("const b = 0; ({a, ...b} = {a: 1, c: 2, d: 3})", None),
132+
// using + await using
133+
("using x = foo(); x = 1;", None),
134+
("await using x = foo(); x = 1;", None),
135+
("using x = foo(); x ??= bar();", None),
136+
("await using x = foo(); x ||= bar();", None),
137+
("using x = foo(); [x, y] = bar();", None),
138+
("await using x = foo(); [x = baz, y] = bar();", None),
139+
("using x = foo(); ({a: x} = bar());", None),
140+
("await using x = foo(); ({a: x = baz} = bar());", None),
110141
];
111142

112143
Tester::new(NoConstAssign::NAME, NoConstAssign::PLUGIN, pass, fail).test_and_snapshot();

crates/oxc_linter/src/snapshots/eslint_no_const_assign.snap

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,67 @@ source: crates/oxc_linter/src/tester.rs
136136
· │ ╰── b is re-assigned here
137137
· ╰── b is declared here as const
138138
╰────
139+
140+
eslint(no-const-assign): Unexpected re-assignment of const variable x
141+
╭─[no_const_assign.tsx:1:7]
142+
1using x = foo(); x = 1;
143+
· ┬ ┬
144+
· │ ╰── x is re-assigned here
145+
· ╰── x is declared here as const
146+
╰────
147+
148+
eslint(no-const-assign): Unexpected re-assignment of const variable x
149+
╭─[no_const_assign.tsx:1:13]
150+
1await using x = foo(); x = 1;
151+
· ┬ ┬
152+
· │ ╰── x is re-assigned here
153+
· ╰── x is declared here as const
154+
╰────
155+
156+
eslint(no-const-assign): Unexpected re-assignment of const variable x
157+
╭─[no_const_assign.tsx:1:7]
158+
1using x = foo(); x ??= bar();
159+
· ┬ ┬
160+
· │ ╰── x is re-assigned here
161+
· ╰── x is declared here as const
162+
╰────
163+
164+
eslint(no-const-assign): Unexpected re-assignment of const variable x
165+
╭─[no_const_assign.tsx:1:13]
166+
1await using x = foo(); x ||= bar();
167+
· ┬ ┬
168+
· │ ╰── x is re-assigned here
169+
· ╰── x is declared here as const
170+
╰────
171+
172+
eslint(no-const-assign): Unexpected re-assignment of const variable x
173+
╭─[no_const_assign.tsx:1:7]
174+
1using x = foo(); [x, y] = bar();
175+
· ┬ ┬
176+
· │ ╰── x is re-assigned here
177+
· ╰── x is declared here as const
178+
╰────
179+
180+
eslint(no-const-assign): Unexpected re-assignment of const variable x
181+
╭─[no_const_assign.tsx:1:13]
182+
1await using x = foo(); [x = baz, y] = bar();
183+
· ┬ ┬
184+
· │ ╰── x is re-assigned here
185+
· ╰── x is declared here as const
186+
╰────
187+
188+
eslint(no-const-assign): Unexpected re-assignment of const variable x
189+
╭─[no_const_assign.tsx:1:7]
190+
1using x = foo(); ({a: x} = bar());
191+
· ┬ ┬
192+
· │ ╰── x is re-assigned here
193+
· ╰── x is declared here as const
194+
╰────
195+
196+
eslint(no-const-assign): Unexpected re-assignment of const variable x
197+
╭─[no_const_assign.tsx:1:13]
198+
1await using x = foo(); ({a: x = baz} = bar());
199+
· ┬ ┬
200+
· │ ╰── x is re-assigned here
201+
· ╰── x is declared here as const
202+
╰────

0 commit comments

Comments
 (0)