mirror of
https://github.com/danbulant/oxc
synced 2026-05-21 21:29:01 +00:00
feat(linter): start import fixer for eslint/no-unused-vars (#4849)
This commit is contained in:
parent
ef057e7545
commit
cdbfcfb39a
4 changed files with 90 additions and 2 deletions
|
|
@ -0,0 +1,34 @@
|
||||||
|
use oxc_ast::ast::ImportDeclaration;
|
||||||
|
use oxc_span::GetSpan;
|
||||||
|
|
||||||
|
use super::{count_whitespace_or_commas, NoUnusedVars, Symbol};
|
||||||
|
use crate::fixer::{RuleFix, RuleFixer};
|
||||||
|
|
||||||
|
impl NoUnusedVars {
|
||||||
|
#[allow(clippy::unused_self)]
|
||||||
|
pub(in super::super) fn remove_unused_import_declaration<'a>(
|
||||||
|
&self,
|
||||||
|
fixer: RuleFixer<'_, 'a>,
|
||||||
|
symbol: &Symbol<'_, 'a>,
|
||||||
|
import: &ImportDeclaration<'a>,
|
||||||
|
) -> RuleFix<'a> {
|
||||||
|
let specifiers = import
|
||||||
|
.specifiers
|
||||||
|
.as_ref()
|
||||||
|
.expect("Found an unused variable in an ImportDeclaration with no specifiers. This should be impossible.");
|
||||||
|
|
||||||
|
debug_assert!(
|
||||||
|
!specifiers.is_empty(),
|
||||||
|
"Found an unused variable in an ImportDeclaration with no specifiers. This should be impossible."
|
||||||
|
);
|
||||||
|
|
||||||
|
if specifiers.len() == 1 {
|
||||||
|
return fixer.delete(import).dangerously();
|
||||||
|
}
|
||||||
|
let span = symbol.span();
|
||||||
|
let text_after = fixer.source_text()[(span.end as usize)..].chars();
|
||||||
|
let span = span.expand_right(count_whitespace_or_commas(text_after));
|
||||||
|
|
||||||
|
fixer.delete_range(span).dangerously()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod fix_imports;
|
||||||
mod fix_symbol;
|
mod fix_symbol;
|
||||||
mod fix_vars;
|
mod fix_vars;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use std::ops::Deref;
|
||||||
|
|
||||||
use oxc_ast::AstKind;
|
use oxc_ast::AstKind;
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
use oxc_semantic::{ScopeFlags, SymbolFlags, SymbolId};
|
use oxc_semantic::{AstNode, ScopeFlags, SymbolFlags, SymbolId};
|
||||||
use oxc_span::GetSpan;
|
use oxc_span::GetSpan;
|
||||||
|
|
||||||
use crate::{context::LintContext, rule::Rule};
|
use crate::{context::LintContext, rule::Rule};
|
||||||
|
|
@ -209,7 +209,20 @@ impl NoUnusedVars {
|
||||||
| AstKind::ImportExpression(_)
|
| AstKind::ImportExpression(_)
|
||||||
| AstKind::ImportDefaultSpecifier(_)
|
| AstKind::ImportDefaultSpecifier(_)
|
||||||
| AstKind::ImportNamespaceSpecifier(_) => {
|
| AstKind::ImportNamespaceSpecifier(_) => {
|
||||||
ctx.diagnostic(diagnostic::imported(symbol));
|
let diagnostic = diagnostic::imported(symbol);
|
||||||
|
let declaration =
|
||||||
|
symbol.iter_self_and_parents().map(AstNode::kind).find_map(|kind| match kind {
|
||||||
|
AstKind::ImportDeclaration(import) => Some(import),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(declaration) = declaration {
|
||||||
|
ctx.diagnostic_with_suggestion(diagnostic, |fixer| {
|
||||||
|
self.remove_unused_import_declaration(fixer, symbol, declaration)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ctx.diagnostic(diagnostic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AstKind::VariableDeclarator(decl) => {
|
AstKind::VariableDeclarator(decl) => {
|
||||||
if self.is_allowed_variable_declaration(symbol, decl) {
|
if self.is_allowed_variable_declaration(symbol, decl) {
|
||||||
|
|
|
||||||
|
|
@ -496,7 +496,47 @@ fn test_imports() {
|
||||||
("import { a as b } from 'a'; console.log(a)", None),
|
("import { a as b } from 'a'; console.log(a)", None),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let fix = vec![
|
||||||
|
// None used
|
||||||
|
("import foo from './foo';", "", None, FixKind::DangerousSuggestion),
|
||||||
|
("import * as foo from './foo';", "", None, FixKind::DangerousSuggestion),
|
||||||
|
("import { Foo } from './foo';", "", None, FixKind::DangerousSuggestion),
|
||||||
|
("import { Foo as Bar } from './foo';", "", None, FixKind::DangerousSuggestion),
|
||||||
|
// Some used
|
||||||
|
(
|
||||||
|
"import foo, { bar } from './foo'; bar();",
|
||||||
|
"import { bar } from './foo'; bar();",
|
||||||
|
None,
|
||||||
|
FixKind::DangerousSuggestion,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"import foo, { bar } from './foo'; foo();",
|
||||||
|
"import foo, { } from './foo'; foo();",
|
||||||
|
None,
|
||||||
|
FixKind::DangerousSuggestion,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"import { foo, bar, baz } from './foo'; foo(bar);",
|
||||||
|
"import { foo, bar, } from './foo'; foo(bar);",
|
||||||
|
None,
|
||||||
|
FixKind::DangerousSuggestion,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"import { foo, bar, baz } from './foo'; foo(baz);",
|
||||||
|
"import { foo, baz } from './foo'; foo(baz);",
|
||||||
|
None,
|
||||||
|
FixKind::DangerousSuggestion,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"import { foo, bar, baz } from './foo'; bar(baz);",
|
||||||
|
"import { bar, baz } from './foo'; bar(baz);",
|
||||||
|
None,
|
||||||
|
FixKind::DangerousSuggestion,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
Tester::new(NoUnusedVars::NAME, pass, fail)
|
Tester::new(NoUnusedVars::NAME, pass, fail)
|
||||||
|
.expect_fix(fix)
|
||||||
.with_snapshot_suffix("oxc-imports")
|
.with_snapshot_suffix("oxc-imports")
|
||||||
.test_and_snapshot();
|
.test_and_snapshot();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue