perf(linter): avoid collecting prefer-const binding identifiers (#28484)

Use the alloc-free `all_binding_identifiers` instead of the allocating
`get_binding_identifiers`.

On local fixtures:

Allocations: 4,911 → 3,288 (−33.1%)
Allocated bytes: 189,869 → 137,901 (−27.4%)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cam McHenryandCopilot authored and GitHub committed 2026-10-30 12:26:35 -04:00
1 parent 7c93eef0bc
commit 1043dfade2
1 file changed
+8 -8
@@ -7,6 +7,7 @@ use oxc_ast::{
}, },
}; };
use oxc_diagnostics::OxcDiagnostic; use oxc_diagnostics::OxcDiagnostic;
use oxc_ecmascript::BoundNames;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId; use oxc_semantic::SymbolId;
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
@@ -136,8 +137,8 @@ impl Rule for PreferConst {
if is_for_statement_init && decl.declarations.len() > 1 { if is_for_statement_init && decl.declarations.len() > 1 {
let any_reassigned = decl.declarations.iter().any(|declarator| { let any_reassigned = decl.declarations.iter().any(|declarator| {
let has_init = declarator.init.is_some(); let has_init = declarator.init.is_some();
declarator.id.get_binding_identifiers().iter().any(|ident| { !declarator.id.all_binding_identifiers(&mut |ident| {
!self.should_be_const(ident.symbol_id(), has_init, is_for_in_of_init, ctx) self.should_be_const(ident.symbol_id(), has_init, is_for_in_of_init, ctx)
}) })
}); });
@@ -148,11 +149,10 @@ impl Rule for PreferConst {
let mut all_declarators_const = true; let mut all_declarators_const = true;
for (declarator_index, declarator) in decl.declarations.iter().enumerate() { for (declarator_index, declarator) in decl.declarations.iter().enumerate() {
let binding_identifiers = declarator.id.get_binding_identifiers();
let has_init = declarator.init.is_some(); let has_init = declarator.init.is_some();
let is_destructuring = declarator.id.is_destructuring_pattern(); let is_destructuring = declarator.id.is_destructuring_pattern();
let all_const = binding_identifiers.iter().all(|ident| { let all_const = declarator.id.all_binding_identifiers(&mut |ident| {
let symbol_id = ident.symbol_id(); let symbol_id = ident.symbol_id();
self.should_be_const(symbol_id, has_init, is_for_in_of_init, ctx) self.should_be_const(symbol_id, has_init, is_for_in_of_init, ctx)
}); });
@@ -162,7 +162,7 @@ impl Rule for PreferConst {
if matches!(self.0.destructuring, Destructuring::All) && is_destructuring { if matches!(self.0.destructuring, Destructuring::All) && is_destructuring {
if all_const { if all_const {
// Flag all variables in the destructuring pattern // Flag all variables in the destructuring pattern
for ident in binding_identifiers { declarator.id.bound_names(&mut |ident| {
ctx.diagnostic_with_fix( ctx.diagnostic_with_fix(
prefer_const_diagnostic(ident.name.as_str(), ident.span), prefer_const_diagnostic(ident.name.as_str(), ident.span),
|fixer| { |fixer| {
@@ -176,12 +176,12 @@ impl Rule for PreferConst {
) )
}, },
); );
} });
} }
// If not all_const, don't flag any of them in "all" mode // If not all_const, don't flag any of them in "all" mode
} else { } else {
// "any" mode (default): check each binding identifier independently // "any" mode (default): check each binding identifier independently
for ident in binding_identifiers { declarator.id.bound_names(&mut |ident| {
if self.should_be_const(ident.symbol_id(), has_init, is_for_in_of_init, ctx) { if self.should_be_const(ident.symbol_id(), has_init, is_for_in_of_init, ctx) {
ctx.diagnostic_with_fix( ctx.diagnostic_with_fix(
prefer_const_diagnostic(ident.name.as_str(), ident.span), prefer_const_diagnostic(ident.name.as_str(), ident.span),
@@ -197,7 +197,7 @@ impl Rule for PreferConst {
}, },
); );
} }
} });
} }
} }
} }