mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(linter): improve no_redeclare rule implementation (#2084)
This commit is contained in:
parent
a9e2158362
commit
721a869b6e
4 changed files with 51 additions and 17 deletions
|
|
@ -58,7 +58,7 @@ declare_oxc_lint!(
|
|||
/// var a = 10;
|
||||
/// ```
|
||||
NoRedeclare,
|
||||
nursery // There are false positives within TypeScript files (e.g. redeclare on interface)
|
||||
pedantic
|
||||
);
|
||||
|
||||
impl Rule for NoRedeclare {
|
||||
|
|
@ -81,13 +81,17 @@ impl Rule for NoRedeclare {
|
|||
match ctx.nodes().kind(decl) {
|
||||
AstKind::VariableDeclarator(var) => {
|
||||
if let BindingPatternKind::BindingIdentifier(ident) = &var.id.kind {
|
||||
self.report_diagnostic(ctx, variable, ident);
|
||||
if *symbol_table.get_name(variable.symbol_id) == ident.name {
|
||||
self.report_diagnostic(ctx, variable, ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
AstKind::FormalParameters(params) => {
|
||||
for item in ¶ms.items {
|
||||
if let BindingPatternKind::BindingIdentifier(ident) = &item.pattern.kind {
|
||||
self.report_diagnostic(ctx, variable, ident);
|
||||
if *symbol_table.get_name(variable.symbol_id) == ident.name {
|
||||
self.report_diagnostic(ctx, variable, ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -106,7 +110,7 @@ impl NoRedeclare {
|
|||
) {
|
||||
if self.built_in_globals && BUILTINS.get(&ident.name).is_some() {
|
||||
ctx.diagnostic(NoRedeclareAsBuiltiInDiagnostic(ident.name.clone(), ident.span));
|
||||
} else if variable.name == ident.name && variable.span != ident.span {
|
||||
} else if variable.span != ident.span {
|
||||
ctx.diagnostic(NoRedeclareDiagnostic(ident.name.clone(), ident.span, variable.span));
|
||||
}
|
||||
}
|
||||
|
|
@ -153,12 +157,10 @@ fn test() {
|
|||
("var a = 3; var a = 10; var a = 15;", None),
|
||||
("var a; var a;", None),
|
||||
("export var a; var a;", None),
|
||||
// `var` redeclaration in class static blocks. Redeclaration of functions is not allowed in class static blocks.
|
||||
("class C { static { var a; var a; } }", None),
|
||||
// Todo: Fix me
|
||||
// ("class C { static { var a; { var a; } } }", None),
|
||||
// ("class C { static { { var a; } var a; } }", None),
|
||||
// ("class C { static { { var a; } { var a; } } }", None),
|
||||
("class C { static { var a; { var a; } } }", None),
|
||||
("class C { static { { var a; } var a; } }", None),
|
||||
("class C { static { { var a; } { var a; } } }", None),
|
||||
// ("var Object = 0;", Some(serde_json::json!([{ "builtinGlobals": true }]))),
|
||||
(
|
||||
"var a; var {a = 0, b: Object = 0} = {};",
|
||||
|
|
@ -171,7 +173,7 @@ fn test() {
|
|||
),
|
||||
("function f() { var a; var a; }", None),
|
||||
("function f(a) { var a; }", None),
|
||||
// ("function f() { var a; if (test) { var a; } }", None),
|
||||
("function f() { var a; if (test) { var a; } }", None),
|
||||
("for (var a, a;;);", None),
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,30 @@ expression: no_redeclare
|
|||
· ╰── 'a' is already defined.
|
||||
╰────
|
||||
|
||||
⚠ eslint(no-redeclare): 'a' is already defined.
|
||||
╭─[no_redeclare.tsx:1:1]
|
||||
1 │ class C { static { var a; { var a; } } }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclare here.
|
||||
· ╰── 'a' is already defined.
|
||||
╰────
|
||||
|
||||
⚠ eslint(no-redeclare): 'a' is already defined.
|
||||
╭─[no_redeclare.tsx:1:1]
|
||||
1 │ class C { static { { var a; } var a; } }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclare here.
|
||||
· ╰── 'a' is already defined.
|
||||
╰────
|
||||
|
||||
⚠ eslint(no-redeclare): 'a' is already defined.
|
||||
╭─[no_redeclare.tsx:1:1]
|
||||
1 │ class C { static { { var a; } { var a; } } }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclare here.
|
||||
· ╰── 'a' is already defined.
|
||||
╰────
|
||||
|
||||
⚠ eslint(no-redeclare): 'a' is already defined.
|
||||
╭─[no_redeclare.tsx:1:1]
|
||||
1 │ var a; var {a = 0, b: Object = 0} = {};
|
||||
|
|
@ -132,6 +156,14 @@ expression: no_redeclare
|
|||
· ╰── 'a' is already defined.
|
||||
╰────
|
||||
|
||||
⚠ eslint(no-redeclare): 'a' is already defined.
|
||||
╭─[no_redeclare.tsx:1:1]
|
||||
1 │ function f() { var a; if (test) { var a; } }
|
||||
· ┬ ┬
|
||||
· │ ╰── It can not be redeclare here.
|
||||
· ╰── 'a' is already defined.
|
||||
╰────
|
||||
|
||||
⚠ eslint(no-redeclare): 'a' is already defined.
|
||||
╭─[no_redeclare.tsx:1:1]
|
||||
1 │ for (var a, a;;);
|
||||
|
|
|
|||
|
|
@ -60,11 +60,10 @@ impl<'a> Binder for VariableDeclarator<'a> {
|
|||
builder.check_redeclaration(*scope_id, span, name, excludes, true)
|
||||
{
|
||||
ident.symbol_id.set(Some(symbol_id));
|
||||
builder.add_redeclared_variables(VariableInfo {
|
||||
name: ident.name.clone(),
|
||||
span: ident.span,
|
||||
symbol_id,
|
||||
});
|
||||
if self.kind.is_var() {
|
||||
builder
|
||||
.add_redeclared_variables(VariableInfo { span: ident.span, symbol_id });
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ struct UnusedLabels<'a> {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VariableInfo {
|
||||
pub name: Atom,
|
||||
pub span: Span,
|
||||
pub symbol_id: SymbolId,
|
||||
}
|
||||
|
|
@ -253,7 +252,9 @@ impl<'a> SemanticBuilder<'a> {
|
|||
) -> SymbolId {
|
||||
if let Some(symbol_id) = self.check_redeclaration(scope_id, span, name, excludes, true) {
|
||||
self.symbols.union_flag(symbol_id, includes);
|
||||
self.add_redeclared_variables(VariableInfo { name: name.clone(), span, symbol_id });
|
||||
if includes.is_function_scoped_declaration() {
|
||||
self.add_redeclared_variables(VariableInfo { span, symbol_id });
|
||||
}
|
||||
return symbol_id;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue