mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
perf(linter/eslint/no-unassigned-vars): batch by declaration (#28358)
Share declaration context checks across candidate bindings while preserving per-binding read/write decisions. Reduce fixture callbacks from 37,499 to 31,363. --- <sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
1108352314
commit
dbd8a0b7f1
4 files changed
+53
-25
No files matched your search
+1
-1
@@ -1095,7 +1095,7 @@ impl RuleRunner for crate::rules::eslint::no_throw_literal::NoThrowLiteral {
|
||||
|
||||
impl RuleRunner for crate::rules::eslint::no_unassigned_vars::NoUnassignedVars {
|
||||
const NODE_TYPES: Option<&AstTypesBitset> =
|
||||
Some(&AstTypesBitset::from_types(&[AstType::VariableDeclarator]));
|
||||
Some(&AstTypesBitset::from_types(&[AstType::VariableDeclaration]));
|
||||
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,27 +65,30 @@ declare_oxc_lint!(
|
||||
|
||||
impl Rule for NoUnassignedVars {
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
let AstKind::VariableDeclarator(declarator) = node.kind() else {
|
||||
let AstKind::VariableDeclaration(declaration) = node.kind() else {
|
||||
return;
|
||||
};
|
||||
if declarator.init.is_some() {
|
||||
if declaration.kind.is_const() || declaration.declare {
|
||||
return;
|
||||
}
|
||||
let parent_node = ctx.nodes().parent_node(node.id());
|
||||
let AstKind::VariableDeclaration(parent) = parent_node.kind() else {
|
||||
return;
|
||||
};
|
||||
if parent.kind.is_const() || parent.declare {
|
||||
let mut identifiers = declaration
|
||||
.declarations
|
||||
.iter()
|
||||
.filter_map(|declarator| match (&declarator.id, &declarator.init) {
|
||||
(BindingPattern::BindingIdentifier(ident), None) => Some(ident),
|
||||
_ => None,
|
||||
})
|
||||
.peekable();
|
||||
if identifiers.peek().is_none() {
|
||||
return;
|
||||
}
|
||||
let grand_parent = ctx.nodes().parent_node(parent_node.id());
|
||||
if matches!(
|
||||
grand_parent.kind(),
|
||||
ctx.nodes().parent_kind(node.id()),
|
||||
AstKind::ForStatement(_) | AstKind::ForInStatement(_) | AstKind::ForOfStatement(_)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if ctx.nodes().ancestors(node.id()).skip(1).any(|ancestor| {
|
||||
if ctx.nodes().ancestors(node.id()).any(|ancestor| {
|
||||
matches!(
|
||||
ancestor.kind(),
|
||||
AstKind::TSExternalModuleDeclaration(_)
|
||||
@@ -95,22 +98,21 @@ impl Rule for NoUnassignedVars {
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
let BindingPattern::BindingIdentifier(ident) = &declarator.id else {
|
||||
return;
|
||||
};
|
||||
let symbol_id = ident.symbol_id();
|
||||
let mut has_read = false;
|
||||
for reference in ctx.symbol_references(symbol_id) {
|
||||
if reference.is_write() {
|
||||
return;
|
||||
for ident in identifiers {
|
||||
let mut has_read = false;
|
||||
for reference in ctx.symbol_references(ident.symbol_id()) {
|
||||
if reference.is_write() {
|
||||
has_read = false;
|
||||
break;
|
||||
}
|
||||
if reference.is_read() {
|
||||
has_read = true;
|
||||
}
|
||||
}
|
||||
if reference.is_read() {
|
||||
has_read = true;
|
||||
if has_read {
|
||||
ctx.diagnostic(no_unassigned_vars_diagnostic(ident.span, ident.name.as_str()));
|
||||
}
|
||||
}
|
||||
if has_read {
|
||||
ctx.diagnostic(no_unassigned_vars_diagnostic(ident.span, ident.name.as_str()));
|
||||
}
|
||||
}
|
||||
|
||||
fn should_run(&self, ctx: &crate::context::ContextHost) -> bool {
|
||||
@@ -150,6 +152,8 @@ fn test() {
|
||||
}
|
||||
",
|
||||
"for (let p of pathToRemove) { p.remove() }",
|
||||
"for (let a, b; check(a, b);) { break; }",
|
||||
"declare let a, b; log(a, b);",
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
@@ -162,6 +166,9 @@ fn test() {
|
||||
"let config; function init() { return config?.enabled; }",
|
||||
"let x: number; log(x);",
|
||||
"let x: number | undefined; log(x);",
|
||||
"let assigned, unassigned; assigned = 1; log(assigned, unassigned);",
|
||||
"let a, b; log(a, b); a = 1;",
|
||||
"let initialized = 1, unassigned; log(initialized, unassigned);",
|
||||
"const foo = (two: string): void => { let one: string | undefined; if (one === two) {} }",
|
||||
"
|
||||
declare module 'module' {
|
||||
|
||||
@@ -72,6 +72,27 @@ source: crates/oxc_linter/src/tester.rs
|
||||
╰────
|
||||
help: Variable declared without assignment. Either assign a value or remove the declaration.
|
||||
|
||||
⚠ eslint(no-unassigned-vars): 'unassigned' is always 'undefined' because it's never assigned.
|
||||
╭─[no_unassigned_vars.tsx:1:15]
|
||||
1 │ let assigned, unassigned; assigned = 1; log(assigned, unassigned);
|
||||
· ──────────
|
||||
╰────
|
||||
help: Variable declared without assignment. Either assign a value or remove the declaration.
|
||||
|
||||
⚠ eslint(no-unassigned-vars): 'b' is always 'undefined' because it's never assigned.
|
||||
╭─[no_unassigned_vars.tsx:1:8]
|
||||
1 │ let a, b; log(a, b); a = 1;
|
||||
· ─
|
||||
╰────
|
||||
help: Variable declared without assignment. Either assign a value or remove the declaration.
|
||||
|
||||
⚠ eslint(no-unassigned-vars): 'unassigned' is always 'undefined' because it's never assigned.
|
||||
╭─[no_unassigned_vars.tsx:1:22]
|
||||
1 │ let initialized = 1, unassigned; log(initialized, unassigned);
|
||||
· ──────────
|
||||
╰────
|
||||
help: Variable declared without assignment. Either assign a value or remove the declaration.
|
||||
|
||||
⚠ eslint(no-unassigned-vars): 'one' is always 'undefined' because it's never assigned.
|
||||
╭─[no_unassigned_vars.tsx:1:42]
|
||||
1 │ const foo = (two: string): void => { let one: string | undefined; if (one === two) {} }
|
||||
|
||||
@@ -121,7 +121,7 @@ eslint/no-template-curly-in-string | 62460
|
||||
eslint/no-ternary | 4722
|
||||
eslint/no-this-before-super | 4
|
||||
eslint/no-throw-literal | 224
|
||||
eslint/no-unassigned-vars | 37499
|
||||
eslint/no-unassigned-vars | 31363
|
||||
eslint/no-undef | 7
|
||||
eslint/no-undefined | 282877
|
||||
eslint/no-underscore-dangle | 200305
|
||||
|
||||
Reference in new issue
Block a user