Skip to content

Commit cfc6aa4

Browse files
committed
perf(linter): run no-const-assign on AST node instead of symbols
1 parent e5d03c5 commit cfc6aa4

File tree

2 files changed

+53
-13
lines changed

2 files changed

+53
-13
lines changed

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,12 @@ 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::ArrayPattern,
234+
AstType::AssignmentPattern,
235+
AstType::VariableDeclaration,
236+
]));
237+
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
234238
}
235239

236240
impl RuleRunner

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

Lines changed: 47 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,53 @@ 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::VariableDeclaration(var_decl) if var_decl.kind.is_const() => {
57+
for decl in &var_decl.declarations {
58+
for ident in decl.id.get_binding_identifiers() {
59+
check_symbol(ident.symbol_id(), ctx);
60+
}
6361
}
6462
}
63+
AstKind::ArrayPattern(pat) => {
64+
let Some(idents) = &pat.rest else {
65+
return;
66+
};
67+
for ident in idents.argument.get_binding_identifiers() {
68+
let symbol_id = ident.symbol_id();
69+
let symbol_table = ctx.scoping();
70+
if symbol_table.symbol_flags(symbol_id).is_const_variable() {
71+
check_symbol(symbol_id, ctx);
72+
}
73+
}
74+
}
75+
AstKind::AssignmentPattern(pat) => {
76+
for ident in pat.left.get_binding_identifiers() {
77+
let symbol_id = ident.symbol_id();
78+
let symbol_table = ctx.scoping();
79+
if symbol_table.symbol_flags(symbol_id).is_const_variable() {
80+
check_symbol(symbol_id, ctx);
81+
}
82+
}
83+
}
84+
_ => {}
85+
}
86+
}
87+
}
88+
89+
fn check_symbol(symbol_id: SymbolId, ctx: &LintContext<'_>) {
90+
let symbol_table = ctx.scoping();
91+
// This symbol _should_ always be considered a const variable (since we got it from a const declaration),
92+
// but we check in debug mode just to be sure.
93+
debug_assert!(symbol_table.symbol_flags(symbol_id).is_const_variable());
94+
for reference in symbol_table.get_resolved_references(symbol_id) {
95+
if reference.is_write() {
96+
ctx.diagnostic(no_const_assign_diagnostic(
97+
symbol_table.symbol_name(symbol_id),
98+
symbol_table.symbol_span(symbol_id),
99+
ctx.semantic().reference_span(reference),
100+
));
65101
}
66102
}
67103
}

0 commit comments

Comments
 (0)