From 8ff6f2cb860419e9e293f04868955f470a730c9e Mon Sep 17 00:00:00 2001 From: DonIsaac <22823424+DonIsaac@users.noreply.github.com> Date: Sun, 25 Aug 2024 21:26:45 +0000 Subject: [PATCH] fix(linter/no-unused-vars): panic on UsingDeclarations (#5206) Closes #5202 --- .../eslint/no_unused_vars/fixers/fix_vars.rs | 34 +++++++++++++------ .../rules/eslint/no_unused_vars/tests/oxc.rs | 10 ++++++ .../no_unused_vars@oxc-vars-using.snap | 10 ++++++ 3 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 crates/oxc_linter/src/snapshots/no_unused_vars@oxc-vars-using.snap diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs b/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs index dac197a6c2c8a..e4e03d44b731e 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs @@ -34,10 +34,26 @@ impl NoUnusedVars { return fixer.noop(); } - let Some(AstKind::VariableDeclaration(declaration)) = - symbol.nodes().parent_node(decl_id).map(AstNode::kind) - else { - panic!("VariableDeclarator nodes should always be direct children of VariableDeclaration nodes"); + let Some(parent) = symbol.nodes().parent_node(decl_id).map(AstNode::kind) else { + #[cfg(debug_assertions)] + panic!("VariableDeclarator nodes should always have a parent node"); + #[cfg(not(debug_assertions))] + return fixer.noop(); + }; + let (span, declarations) = match parent { + AstKind::VariableDeclaration(decl) => (decl.span, &decl.declarations), + AstKind::UsingDeclaration(decl) => { + if decl.is_await { + return fixer.noop(); + } + (decl.span, &decl.declarations) + } + _ => { + #[cfg(debug_assertions)] + panic!("VariableDeclarator nodes should always be direct children of VariableDeclaration or UsingDeclaration nodes"); + #[cfg(not(debug_assertions))] + return fixer.noop(); + } }; // `true` even if references aren't considered a usage. @@ -48,18 +64,16 @@ impl NoUnusedVars { // for `let x = 1;` or `const { x } = obj; the whole declaration can // be removed, but for `const { x, y } = obj;` or `let x = 1, y = 2` // we need to keep the other declarations - let has_neighbors = declaration.declarations.len() > 1; - debug_assert!(!declaration.declarations.is_empty()); + let has_neighbors = declarations.len() > 1; + debug_assert!(!declarations.is_empty()); let binding_info = symbol.get_binding_info(&decl.id.kind); match binding_info { BindingInfo::SingleDestructure | BindingInfo::NotDestructure => { if has_neighbors { - return symbol - .delete_from_list(fixer, &declaration.declarations, decl) - .dangerously(); + return symbol.delete_from_list(fixer, declarations, decl).dangerously(); } - return fixer.delete(declaration).dangerously(); + return fixer.delete_range(span).dangerously(); } BindingInfo::MultiDestructure(mut span, is_object, is_last) => { let source_after = &fixer.source_text()[(span.end as usize)..]; diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_vars/tests/oxc.rs b/crates/oxc_linter/src/rules/eslint/no_unused_vars/tests/oxc.rs index 6e672a4317275..ebe11f0f0c495 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_vars/tests/oxc.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_vars/tests/oxc.rs @@ -370,6 +370,16 @@ fn test_vars_catch() { .test_and_snapshot(); } +#[test] +fn test_vars_using() { + let pass = vec![("using a = 1; console.log(a)", None)]; + + let fail = vec![("using a = 1;", None)]; + + Tester::new(NoUnusedVars::NAME, pass, fail) + .with_snapshot_suffix("oxc-vars-using") + .test_and_snapshot(); +} #[test] fn test_functions() { let pass = vec![ diff --git a/crates/oxc_linter/src/snapshots/no_unused_vars@oxc-vars-using.snap b/crates/oxc_linter/src/snapshots/no_unused_vars@oxc-vars-using.snap new file mode 100644 index 0000000000000..9db7ba5c13c99 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_unused_vars@oxc-vars-using.snap @@ -0,0 +1,10 @@ +--- +source: crates/oxc_linter/src/tester.rs +--- + ⚠ eslint(no-unused-vars): Variable 'a' is declared but never used. + ╭─[no_unused_vars.tsx:1:7] + 1 │ using a = 1; + · ┬ + · ╰── 'a' is declared here + ╰──── + help: Consider removing this declaration.