diff --git a/CHANGELOG.md b/CHANGELOG.md index d57a7523ee73..f4ee52ef4531 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,16 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b Contributed by @Conaclos +- `noUnusedImports` now reports empty named imports and suggests its removal ([#3574](https://github.com/biomejs/biome/issues/3574)). + + The rule now suggests the removal of empty named imports such as: + + ```diff + - import {} from "mod"; + ``` + + Contributed by @Conaclos + #### Bug fixes - [useArrayLiterals](https://biomejs.dev/linter/rules/use-array-literals/) now reports all expressions using the `Array` constructors. diff --git a/crates/biome_js_analyze/src/lint/correctness/no_unused_imports.rs b/crates/biome_js_analyze/src/lint/correctness/no_unused_imports.rs index fece37913250..411e80333ae7 100644 --- a/crates/biome_js_analyze/src/lint/correctness/no_unused_imports.rs +++ b/crates/biome_js_analyze/src/lint/correctness/no_unused_imports.rs @@ -11,10 +11,12 @@ use biome_console::markup; use biome_js_factory::make; use biome_js_semantic::ReferencesExtensions; use biome_js_syntax::{ - binding_ext::AnyJsBindingDeclaration, AnyJsCombinedSpecifier, AnyJsImportClause, - JsIdentifierBinding, JsImport, JsLanguage, JsNamedImportSpecifierList, JsSyntaxNode, T, + AnyJsBinding, AnyJsCombinedSpecifier, AnyJsImportClause, AnyJsNamedImportSpecifier, + JsNamedImportSpecifiers, T, +}; +use biome_rowan::{ + AstNode, AstSeparatedElement, AstSeparatedList, BatchMutationExt, NodeOrToken, TextRange, }; -use biome_rowan::{AstNode, AstSeparatedList, BatchMutation, BatchMutationExt}; declare_lint_rule! { /// Disallow unused imports. @@ -86,160 +88,310 @@ declare_lint_rule! { } impl Rule for NoUnusedImports { - type Query = Semantic; - type State = (); + type Query = Semantic; + type State = Unused; type Signals = Option; type Options = (); fn run(ctx: &RuleContext) -> Self::Signals { - let binding = ctx.query(); - let declaration = binding.declaration()?; - if !is_import(&declaration) { - return None; - } - if ctx.jsx_runtime() == JsxRuntime::ReactClassic - && is_global_react_import(binding, ReactLibrary::React) - { - return None; + match ctx.query() { + AnyJsImportClause::JsImportBareClause(_) => { + // ignore bare imports (aka side-effect imports) such as `import "mod"`. + None + } + AnyJsImportClause::JsImportCombinedClause(clause) => { + let default_local_name = clause.default_specifier().ok()?.local_name().ok()?; + let is_default_import_unused = is_unused(ctx, &default_local_name); + let (is_combined_unused, named_import_range) = match clause.specifier().ok()? { + AnyJsCombinedSpecifier::JsNamedImportSpecifiers(specifiers) => { + match unused_named_specifiers(ctx, &specifiers) { + Some(Unused::AllImports(range) | Unused::EmptyStatement(range)) => { + (true, range) + } + Some(Unused::NamedImports(unused_named_specifers)) => { + return Some(if is_default_import_unused { + Unused::DefaultNamedImport( + default_local_name.range(), + unused_named_specifers, + ) + } else { + Unused::NamedImports(unused_named_specifers) + }); + } + _ => (false, specifiers.range()), + } + } + AnyJsCombinedSpecifier::JsNamespaceImportSpecifier(specifier) => { + let local_name = specifier.local_name().ok()?; + (is_unused(ctx, &local_name), local_name.range()) + } + }; + match (is_default_import_unused, is_combined_unused) { + (true, true) => Some(Unused::AllImports(TextRange::new( + default_local_name.range().start(), + named_import_range.end(), + ))), + (true, false) => Some(Unused::DefaultImport(default_local_name.range())), + (false, true) => Some(Unused::CombinedImport(named_import_range)), + (false, false) => None, + } + } + AnyJsImportClause::JsImportDefaultClause(clause) => { + let local_name = clause.default_specifier().ok()?.local_name().ok()?; + is_unused(ctx, &local_name).then_some(Unused::AllImports(local_name.range())) + } + AnyJsImportClause::JsImportNamedClause(clause) => { + unused_named_specifiers(ctx, &clause.named_specifiers().ok()?) + } + AnyJsImportClause::JsImportNamespaceClause(clause) => { + let local_name = clause.namespace_specifier().ok()?.local_name().ok()?; + is_unused(ctx, &local_name).then_some(Unused::AllImports(local_name.range())) + } } - let model = ctx.model(); - binding.all_references(model).next().is_none().then_some(()) } - fn diagnostic(ctx: &RuleContext, _: &Self::State) -> Option { - let binding = ctx.query(); - Some( - RuleDiagnostic::new( + fn diagnostic(ctx: &RuleContext, state: &Self::State) -> Option { + let diagnostic = match state { + Unused::EmptyStatement(range) => RuleDiagnostic::new( rule_category!(), - binding.range(), + range, markup! { - "This ""import"" is unused." + "This ""import"" is empty." }, - ) - .note(markup! { - "Unused imports might be the result of an incomplete refactoring." - }), - ) + ), + Unused::AllImports(range) + | Unused::DefaultImport(range) + | Unused::CombinedImport(range) => { + let msg = match ctx.query() { + AnyJsImportClause::JsImportDefaultClause(_) + | AnyJsImportClause::JsImportNamedClause(_) + | AnyJsImportClause::JsImportNamespaceClause(_) => { + markup! { + "This ""import"" is unused." + } + } + _ => { + markup! { + "These ""imports"" are unused." + } + } + }; + RuleDiagnostic::new(rule_category!(), range, msg) + } + Unused::DefaultNamedImport(default_import_range, unused_named_imports) => { + let range = TextRange::new( + default_import_range.start(), + unused_named_imports.last()?.range().end(), + ); + RuleDiagnostic::new( + rule_category!(), + range, + markup! { + "Several of these ""imports"" are unused." + }, + ) + } + Unused::NamedImports(unused_named_imports) => { + let range = TextRange::new( + unused_named_imports.first()?.range().start(), + unused_named_imports.last()?.range().end(), + ); + RuleDiagnostic::new( + rule_category!(), + range, + markup! { + "Several of these ""imports"" are unused." + }, + ) + } + }; + Some(diagnostic.note(markup! { + "Unused imports might be the result of an incomplete refactoring." + })) } - fn action(ctx: &RuleContext, _: &Self::State) -> Option { - let declaration = ctx.query().declaration()?; + fn action(ctx: &RuleContext, state: &Self::State) -> Option { + let node = ctx.query(); let mut mutation = ctx.root().begin(); - match declaration { - AnyJsBindingDeclaration::JsShorthandNamedImportSpecifier(_) - | AnyJsBindingDeclaration::JsNamedImportSpecifier(_) - | AnyJsBindingDeclaration::JsBogusNamedImportSpecifier(_) => { - let specifier_list = declaration.parent::()?; - if specifier_list.len() == 1 { - remove_import_specifier(&mut mutation, &specifier_list.syntax().parent()?)?; - } else { - let following_separator = specifier_list - .iter() - .zip(specifier_list.separators().map(|separator| separator.ok())) - .find(|(specifier, _)| { - specifier - .as_ref() - .is_ok_and(|x| x.syntax() == declaration.syntax()) - }) - .and_then(|(_, separator)| separator); - if let Some(separator) = following_separator { - mutation.remove_token(separator); + match state { + Unused::EmptyStatement(_) | Unused::AllImports(_) => { + let parent = node.syntax().parent()?; + mutation.remove_element(parent.into()); + } + Unused::DefaultImport(_) => { + let prev_clause = node.as_js_import_combined_clause()?.clone(); + let new_clause: AnyJsImportClause = match prev_clause.specifier().ok()? { + AnyJsCombinedSpecifier::JsNamedImportSpecifiers(named_specifiers) => { + let new_clause = make::js_import_named_clause( + named_specifiers, + prev_clause.from_token().ok()?, + prev_clause.source().ok()?, + ); + if let Some(attributes) = prev_clause.assertion() { + new_clause.with_assertion(attributes) + } else { + new_clause + } + .build() + .into() } - mutation.remove_node(declaration); - } + AnyJsCombinedSpecifier::JsNamespaceImportSpecifier(specifier) => { + let new_clause = make::js_import_namespace_clause( + specifier, + prev_clause.from_token().ok()?, + prev_clause.source().ok()?, + ); + if let Some(attributes) = prev_clause.assertion() { + new_clause.with_assertion(attributes) + } else { + new_clause + } + .build() + .into() + } + }; + mutation.replace_node(prev_clause.into(), new_clause); } - AnyJsBindingDeclaration::JsDefaultImportSpecifier(_) - | AnyJsBindingDeclaration::JsNamespaceImportSpecifier(_) => { - remove_import_specifier(&mut mutation, declaration.syntax())?; + Unused::CombinedImport(_) => { + let prev_clause = node.as_js_import_combined_clause()?.clone(); + let new_clause = make::js_import_default_clause( + prev_clause.default_specifier().ok()?, + prev_clause.from_token().ok()?, + prev_clause.source().ok()?, + ); + let new_clause = if let Some(attributes) = prev_clause.assertion() { + new_clause.with_assertion(attributes) + } else { + new_clause + } + .build(); + mutation.replace_node::(prev_clause.into(), new_clause.into()); } - AnyJsBindingDeclaration::TsImportEqualsDeclaration(_) => { - mutation.remove_node(declaration); + Unused::DefaultNamedImport(_, unused_named_specifiers) => { + let prev_clause = node.as_js_import_combined_clause()?.clone(); + let Ok(AnyJsCombinedSpecifier::JsNamedImportSpecifiers(named_specifiers)) = + prev_clause.specifier() + else { + return None; + }; + let (specifiers, separators): (Vec<_>, Vec<_>) = named_specifiers + .specifiers() + .elements() + .filter_map( + |AstSeparatedElement { + node, + trailing_separator, + }| Some((node.ok()?, trailing_separator.ok()?)), + ) + .filter(|(node, _)| !unused_named_specifiers.contains(node)) + .unzip(); + let used_specifiers = make::js_named_import_specifier_list( + specifiers, + separators.into_iter().flatten().collect::>(), + ); + let used_named_specifiers = make::js_named_import_specifiers( + named_specifiers.l_curly_token().ok()?, + used_specifiers, + named_specifiers.r_curly_token().ok()?, + ); + let new_clause = make::js_import_named_clause( + used_named_specifiers, + prev_clause.from_token().ok()?, + prev_clause.source().ok()?, + ); + let new_clause = if let Some(attributes) = prev_clause.assertion() { + new_clause.with_assertion(attributes) + } else { + new_clause + } + .build(); + mutation.replace_node::(prev_clause.into(), new_clause.into()); } - _ => { - return None; + Unused::NamedImports(unused_named_specifiers) => { + for unused_specifier in unused_named_specifiers { + if let Some(NodeOrToken::Token(next_token)) = + unused_specifier.syntax().next_sibling_or_token() + { + if next_token.kind() == T![,] { + mutation.remove_token(next_token); + } + } + mutation.remove_node(unused_specifier.clone()); + } } } Some(JsRuleAction::new( ActionCategory::QuickFix, ctx.metadata().applicability(), - markup! { "Remove the unused import." }.to_owned(), + markup! { "Remove the unused imports." }.to_owned(), mutation, )) } } -fn remove_import_specifier( - mutation: &mut BatchMutation, - specifier: &JsSyntaxNode, -) -> Option<()> { - let clause = specifier.parent().and_then(AnyJsImportClause::cast)?; - match &clause { - AnyJsImportClause::JsImportCombinedClause(default_extra_clause) => { - let default_specifier = default_extra_clause.default_specifier().ok()?; - let from_token = default_extra_clause.from_token().ok()?; - let source = default_extra_clause.source().ok()?; - let assertion = default_extra_clause.assertion(); - if default_specifier.syntax() == specifier { - let new_clause = match default_extra_clause.specifier().ok()? { - AnyJsCombinedSpecifier::JsNamedImportSpecifiers(named_specifier) => { - let named_clause = - make::js_import_named_clause(named_specifier, from_token, source); - let named_clause = if let Some(assertion) = assertion { - named_clause.with_assertion(assertion) - } else { - named_clause - }; - AnyJsImportClause::JsImportNamedClause(named_clause.build()) - } - AnyJsCombinedSpecifier::JsNamespaceImportSpecifier(namespace_specifier) => { - let namespace_clause = make::js_import_namespace_clause( - namespace_specifier, - from_token, - source, - ); - let namespace_clause = if let Some(assertion) = assertion { - namespace_clause.with_assertion(assertion) - } else { - namespace_clause - }; - AnyJsImportClause::JsImportNamespaceClause(namespace_clause.build()) - } - }; - mutation.replace_node(clause, new_clause); - } else { - let from_token = make::token_decorated_with_space(T![from]) - .with_trailing_trivia_pieces(from_token.trailing_trivia().pieces()); - let default_clause = - make::js_import_default_clause(default_specifier, from_token, source); - let default_clause = if let Some(assertion) = assertion { - default_clause.with_assertion(assertion) - } else { - default_clause - }; - mutation.replace_node(clause, default_clause.build().into()); +#[derive(Debug)] +pub enum Unused { + /// Empty import such as `import {} from "mod"` + EmptyStatement(TextRange), + //// All imports of the statements are unused + AllImports(TextRange), + /// The default import of the combined clause is unused. e.g.: + /// - `import UnusedDefault, * as Ns from "mod"` + /// - `import UnusedDefault, { A } from "mod"` + DefaultImport(TextRange), + /// The imports of the second specifier of the combined clause are unused. e.g.: + /// - `import Default, * as UnusedNs from "mod"` + /// - `import Default, { UnusedA }from "mod"` + CombinedImport(TextRange), + /// The default and some named imports in a combined clause are unused. e.g.: + /// - `import UnusedDefault, { UnusedA, B, UnusedC } from "mod"` + DefaultNamedImport(TextRange, Box<[AnyJsNamedImportSpecifier]>), + /// Some named specifoers are unused. e.g.: + /// - import { UnusedA, B, UnusedC } from "mod"` + /// - `import Default, { UnusedA, B, UnusedC }from "mod"` + NamedImports(Box<[AnyJsNamedImportSpecifier]>), +} + +fn unused_named_specifiers( + ctx: &RuleContext, + named_specifiers: &JsNamedImportSpecifiers, +) -> Option { + let specifiers = named_specifiers.specifiers(); + let len = specifiers.len(); + if len == 0 { + // `import {} from` + Some(Unused::EmptyStatement(specifiers.range())) + } else { + let mut unused_imports = Vec::new(); + for specifier in specifiers.into_iter().flatten() { + let Some(local_name) = specifier.local_name() else { + continue; + }; + if is_unused(ctx, &local_name) { + unused_imports.push(specifier); } } - AnyJsImportClause::JsImportBareClause(_) - | AnyJsImportClause::JsImportDefaultClause(_) - | AnyJsImportClause::JsImportNamedClause(_) - | AnyJsImportClause::JsImportNamespaceClause(_) => { - // Remove the entire statement - let import = clause.parent::()?; - // This will also remove the trivia of the node - // which is intended - mutation.remove_node(import); + if unused_imports.is_empty() { + // All imports are used + None + } else if unused_imports.len() == len { + // All imports are unused + Some(Unused::AllImports(named_specifiers.range())) + } else { + Some(Unused::NamedImports(unused_imports.into_boxed_slice())) } } - Some(()) } -const fn is_import(declaration: &AnyJsBindingDeclaration) -> bool { - matches!( - declaration, - AnyJsBindingDeclaration::JsDefaultImportSpecifier(_) - | AnyJsBindingDeclaration::JsNamedImportSpecifier(_) - | AnyJsBindingDeclaration::JsNamespaceImportSpecifier(_) - | AnyJsBindingDeclaration::JsShorthandNamedImportSpecifier(_) - | AnyJsBindingDeclaration::TsImportEqualsDeclaration(_) - ) +fn is_unused(ctx: &RuleContext, local_name: &AnyJsBinding) -> bool { + let AnyJsBinding::JsIdentifierBinding(binding) = &local_name else { + return false; + }; + if ctx.jsx_runtime() == JsxRuntime::ReactClassic + && is_global_react_import(binding, ReactLibrary::React) + { + return false; + } + let model = ctx.model(); + binding.all_references(model).next().is_none() } diff --git a/crates/biome_js_analyze/src/lint/style/use_import_type.rs b/crates/biome_js_analyze/src/lint/style/use_import_type.rs index cea7adaadc36..b669e12543cb 100644 --- a/crates/biome_js_analyze/src/lint/style/use_import_type.rs +++ b/crates/biome_js_analyze/src/lint/style/use_import_type.rs @@ -133,9 +133,6 @@ impl Rule for UseImportType { } let import = ctx.query(); let import_clause = import.import_clause().ok()?; - if import_clause.assertion().is_some() { - return None; - } // Import attributes and type-only imports are not compatible. if import_clause.assertion().is_some() { return None; diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-import-namespace.ts.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-import-namespace.ts.snap index 6ffbfd097b60..5d8a6a272ccc 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-import-namespace.ts.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-import-namespace.ts.snap @@ -1,6 +1,7 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: invalid-import-namespace.ts +snapshot_kind: text --- # Input ```ts @@ -24,7 +25,7 @@ invalid-import-namespace.ts:1:13 lint/correctness/noUnusedImports FIXABLE ━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 │ import·*·as·Ns1·from·"" │ ----------------------- @@ -44,7 +45,7 @@ invalid-import-namespace.ts:4:18 lint/correctness/noUnusedImports FIXABLE ━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ import * as Ns1 from "" 2 2 │ export type T1 = Ns1; diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-unused-react.jsx.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-unused-react.jsx.snap index f8ad82df81fa..837d41b94745 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-unused-react.jsx.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-unused-react.jsx.snap @@ -1,6 +1,7 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: invalid-unused-react.jsx +snapshot_kind: text --- # Input ```jsx @@ -28,7 +29,7 @@ invalid-unused-react.jsx:1:8 lint/correctness/noUnusedImports FIXABLE ━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 │ import·X·from·"react" │ --------------------- @@ -48,7 +49,7 @@ invalid-unused-react.jsx:2:13 lint/correctness/noUnusedImports FIXABLE ━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ import X from "react" 2 │ - import·*·as·X·from·"react" @@ -59,20 +60,20 @@ invalid-unused-react.jsx:2:13 lint/correctness/noUnusedImports FIXABLE ━━ ``` ``` -invalid-unused-react.jsx:3:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid-unused-react.jsx:3:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 1 │ import X from "react" 2 │ import * as X from "react" > 3 │ import { default as X } from "react" - │ ^ + │ ^^^^^^^^^^^^^^^^ 4 │ 5 │ import React from "x" i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ import X from "react" 2 2 │ import * as X from "react" @@ -97,7 +98,7 @@ invalid-unused-react.jsx:5:8 lint/correctness/noUnusedImports FIXABLE ━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 2 2 │ import * as X from "react" 3 3 │ import { default as X } from "react" @@ -122,7 +123,7 @@ invalid-unused-react.jsx:6:13 lint/correctness/noUnusedImports FIXABLE ━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 4 4 │ 5 5 │ import React from "x" @@ -134,20 +135,20 @@ invalid-unused-react.jsx:6:13 lint/correctness/noUnusedImports FIXABLE ━━ ``` ``` -invalid-unused-react.jsx:7:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid-unused-react.jsx:7:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 5 │ import React from "x" 6 │ import * as React from "x" > 7 │ import { default as React } from "x" - │ ^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^ 8 │ import React, { useEffect } from "x" 9 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 5 5 │ import React from "x" 6 6 │ import * as React from "x" @@ -161,39 +162,22 @@ invalid-unused-react.jsx:7:21 lint/correctness/noUnusedImports FIXABLE ━━ ``` invalid-unused-react.jsx:8:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 6 │ import * as React from "x" 7 │ import { default as React } from "x" > 8 │ import React, { useEffect } from "x" - │ ^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^ 9 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. - - 8 │ import·React,·{·useEffect·}·from·"x" - │ ------- - -``` - -``` -invalid-unused-react.jsx:8:17 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 6 │ import * as React from "x" - 7 │ import { default as React } from "x" - > 8 │ import React, { useEffect } from "x" - │ ^^^^^^^^^ - 9 │ + i Safe fix: Remove the unused imports. - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. + 6 6 │ import * as React from "x" + 7 7 │ import { default as React } from "x" + 8 │ - import·React,·{·useEffect·}·from·"x" + 9 8 │ - 8 │ import·React,·{·useEffect·}·from·"x" - │ --------------- ``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js index 13986e70352e..994d4d54efbe 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js @@ -27,4 +27,6 @@ import { L as M, } from "mod"; // Import comment import {a} from 'a' import {d} from 'd' import {b} from 'b' -export const bb = a + b \ No newline at end of file +export const bb = a + b + +import {} from "mod" diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js.snap index 48df23aa7621..951f4ca33ff1 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js.snap @@ -1,6 +1,7 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: invalid.js +snapshot_kind: text --- # Input ```jsx @@ -34,6 +35,9 @@ import {a} from 'a' import {d} from 'd' import {b} from 'b' export const bb = a + b + +import {} from "mod" + ``` # Diagnostics @@ -50,7 +54,7 @@ invalid.js:2:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 │ - //·Header·comment 2 │ - import·A·from·"mod"; @@ -74,7 +78,7 @@ invalid.js:5:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ // Header comment 2 2 │ import A from "mod"; @@ -88,19 +92,19 @@ invalid.js:5:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ ``` ``` -invalid.js:8:10 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:8:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 7 │ // Header comment > 8 │ import { C } from "mod"; // Import comment - │ ^ + │ ^^^^^ 9 │ 10 │ // Header comment i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 4 4 │ // Header comment 5 5 │ import * as B from "mod"; // Import comment @@ -116,192 +120,130 @@ invalid.js:8:10 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ ``` invalid.js:11:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 10 │ // Header comment > 11 │ import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment - │ ^ + │ ^^^^^^^^^^^^^^^^^^^ 12 │ 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 11 │ import·/*a*/·D·/*b*/,·/*c*/{·E·}/*d*/·from·"mod";·//·Import·comment - │ -------------- - -``` - -``` -invalid.js:11:30 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. + 7 7 │ // Header comment + 8 8 │ import { C } from "mod"; // Import comment + 9 │ - + 10 │ - //·Header·comment + 11 │ - import·/*a*/·D·/*b*/,·/*c*/{·E·}/*d*/·from·"mod";·//·Import·comment + 12 9 │ + 13 10 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - 10 │ // Header comment - > 11 │ import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment - │ ^ - 12 │ - 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. - - 11 │ import·/*a*/·D·/*b*/,·/*c*/{·E·}/*d*/·from·"mod";·//·Import·comment - │ ----------------- ``` ``` invalid.js:13:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 11 │ import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment 12 │ > 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - │ ^ + │ ^^^^^^^^^^^^^^^^^^^^^ 14 │ 15 │ import { i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 13 │ import·/*a*/·F·/*b*/,·/*c*/·*·as·G·/*d*/·from·"mod"; - │ --------------- - -``` - -``` -invalid.js:13:34 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 11 │ import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment - 12 │ - > 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - │ ^ - 14 │ - 15 │ import { - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. + 10 10 │ // Header comment + 11 11 │ import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment + 12 │ - + 13 │ - import·/*a*/·F·/*b*/,·/*c*/·*·as·G·/*d*/·from·"mod"; + 14 12 │ + 15 13 │ import { - 13 │ import·/*a*/·F·/*b*/,·/*c*/·*·as·G·/*d*/·from·"mod"; - │ -------------------- ``` ``` -invalid.js:17:5 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:15:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. - 15 │ import { - 16 │ // Comment + 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; + 14 │ + > 15 │ import { + │ ^ + > 16 │ // Comment > 17 │ H, - │ ^ - 18 │ I, - 19 │ } from "mod"; - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. - - 14 14 │ - 15 15 │ import { - 16 │ - ····//·Comment - 17 │ - ····H, - 18 16 │ I, - 19 17 │ } from "mod"; - - -``` - -``` -invalid.js:18:5 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 16 │ // Comment - 17 │ H, > 18 │ I, - │ ^ - 19 │ } from "mod"; + > 19 │ } from "mod"; + │ ^ 20 │ + 21 │ import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod"; i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 16 16 │ // Comment - 17 17 │ H, + 12 12 │ + 13 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; + 14 │ - + 15 │ - import·{ + 16 │ - ····//·Comment + 17 │ - ····H, 18 │ - ····I, - 19 18 │ } from "mod"; - 20 19 │ + 19 │ - }·from·"mod"; + 20 14 │ + 21 15 │ import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod"; ``` ``` -invalid.js:21:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:21:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 19 │ } from "mod"; 20 │ > 21 │ import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod"; - │ ^ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ 22 │ 23 │ // Header comment i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. - - 21 │ import·{/*a*/J/*b*/,·/*c*/K/*d*/}·from·"mod"; - │ ------------- - -``` - -``` -invalid.js:21:27 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 19 │ } from "mod"; - 20 │ - > 21 │ import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod"; - │ ^ - 22 │ - 23 │ // Header comment - - i Unused imports might be the result of an incomplete refactoring. + i Safe fix: Remove the unused imports. - i Safe fix: Remove the unused import. + 18 18 │ I, + 19 19 │ } from "mod"; + 20 │ - + 21 │ - import·{/*a*/J/*b*/,·/*c*/K/*d*/}·from·"mod"; + 22 20 │ + 23 21 │ // Header comment - 21 │ import·{/*a*/J/*b*/,·/*c*/K/*d*/}·from·"mod"; - │ ------ ``` ``` -invalid.js:24:15 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:24:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 23 │ // Header comment > 24 │ import { L as M, } from "mod"; // Import comment - │ ^ + │ ^^^^^^^^^^^ 25 │ 26 │ // See https://github.com/biomejs/biome/issues/653 i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 20 20 │ 21 21 │ import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod"; @@ -315,20 +257,20 @@ invalid.js:24:15 lint/correctness/noUnusedImports FIXABLE ━━━━━━ ``` ``` -invalid.js:28:9 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:28:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 26 │ // See https://github.com/biomejs/biome/issues/653 27 │ import {a} from 'a' > 28 │ import {d} from 'd' - │ ^ + │ ^^^ 29 │ import {b} from 'b' 30 │ export const bb = a + b i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 26 26 │ // See https://github.com/biomejs/biome/issues/653 27 27 │ import {a} from 'a' @@ -338,3 +280,27 @@ invalid.js:28:9 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ ``` + +``` +invalid.js:32:9 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This import is empty. + + 30 │ export const bb = a + b + 31 │ + > 32 │ import {} from "mod" + │ + 33 │ + + i Unused imports might be the result of an incomplete refactoring. + + i Safe fix: Remove the unused imports. + + 29 29 │ import {b} from 'b' + 30 30 │ export const bb = a + b + 31 │ - + 32 │ - import·{}·from·"mod" + 33 31 │ + + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.jsx.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.jsx.snap index cf8e90aca32f..e24dfaaa133c 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.jsx.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.jsx.snap @@ -1,6 +1,7 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: invalid.jsx +snapshot_kind: text --- # Input ```jsx @@ -38,7 +39,7 @@ invalid.jsx:1:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 │ import·X·from·"react" │ --------------------- @@ -58,7 +59,7 @@ invalid.jsx:2:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ import X from "react" 2 │ - import·*·as·X·from·"react" @@ -69,20 +70,20 @@ invalid.jsx:2:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━ ``` ``` -invalid.jsx:3:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.jsx:3:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 1 │ import X from "react" 2 │ import * as X from "react" > 3 │ import { default as X } from "react" - │ ^ + │ ^^^^^^^^^^^^^^^^ 4 │ 5 │ import React from "x" i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ import X from "react" 2 2 │ import * as X from "react" @@ -107,7 +108,7 @@ invalid.jsx:5:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 2 2 │ import * as X from "react" 3 3 │ import { default as X } from "react" @@ -132,7 +133,7 @@ invalid.jsx:6:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 4 4 │ 5 5 │ import React from "x" @@ -144,20 +145,20 @@ invalid.jsx:6:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━ ``` ``` -invalid.jsx:7:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.jsx:7:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 5 │ import React from "x" 6 │ import * as React from "x" > 7 │ import { default as React } from "x" - │ ^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^ 8 │ import React, { useEffect } from "x" 9 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 5 5 │ import React from "x" 6 6 │ import * as React from "x" @@ -171,124 +172,76 @@ invalid.jsx:7:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━ ``` invalid.jsx:8:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 6 │ import * as React from "x" 7 │ import { default as React } from "x" > 8 │ import React, { useEffect } from "x" - │ ^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^ 9 │ 10 │ // unsupported patterns i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. - - 8 │ import·React,·{·useEffect·}·from·"x" - │ ------- - -``` - -``` -invalid.jsx:8:17 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 6 │ import * as React from "x" - 7 │ import { default as React } from "x" - > 8 │ import React, { useEffect } from "x" - │ ^^^^^^^^^ - 9 │ - 10 │ // unsupported patterns - - i Unused imports might be the result of an incomplete refactoring. + i Safe fix: Remove the unused imports. - i Safe fix: Remove the unused import. + 6 6 │ import * as React from "x" + 7 7 │ import { default as React } from "x" + 8 │ - import·React,·{·useEffect·}·from·"x" + 9 8 │ + 10 9 │ // unsupported patterns - 8 │ import·React,·{·useEffect·}·from·"x" - │ --------------- ``` ``` invalid.jsx:11:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 10 │ // unsupported patterns > 11 │ import X, { default as React } from "react" - │ ^ + │ ^^^^^^^^^^^^^^^^^^^^^^^ 12 │ import X, * as React from "react" 13 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 11 │ import·X,·{·default·as·React·}·from·"react" - │ --- - -``` - -``` -invalid.jsx:11:24 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. + 7 7 │ import { default as React } from "x" + 8 8 │ import React, { useEffect } from "x" + 9 │ - + 10 │ - //·unsupported·patterns + 11 │ - import·X,·{·default·as·React·}·from·"react" + 12 9 │ import X, * as React from "react" + 13 10 │ - 10 │ // unsupported patterns - > 11 │ import X, { default as React } from "react" - │ ^^^^^ - 12 │ import X, * as React from "react" - 13 │ - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. - - 11 │ import·X,·{·default·as·React·}·from·"react" - │ ---------------------- ``` ``` invalid.jsx:12:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 10 │ // unsupported patterns 11 │ import X, { default as React } from "react" > 12 │ import X, * as React from "react" - │ ^ + │ ^^^^^^^^^^^^^ 13 │ 14 │ // React import (no exception) i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 12 │ import·X,·*·as·React·from·"react" - │ --- - -``` - -``` -invalid.jsx:12:16 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 10 │ // unsupported patterns - 11 │ import X, { default as React } from "react" - > 12 │ import X, * as React from "react" - │ ^^^^^ - 13 │ - 14 │ // React import (no exception) - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. + 10 10 │ // unsupported patterns + 11 11 │ import X, { default as React } from "react" + 12 │ - import·X,·*·as·React·from·"react" + 13 12 │ + 14 13 │ // React import (no exception) - 12 │ import·X,·*·as·React·from·"react" - │ ------------ ``` @@ -305,7 +258,7 @@ invalid.jsx:15:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 11 11 │ import X, { default as React } from "react" 12 12 │ import X, * as React from "react" @@ -332,7 +285,7 @@ invalid.jsx:16:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 14 14 │ // React import (no exception) 15 15 │ import React from "react" @@ -344,20 +297,20 @@ invalid.jsx:16:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━ ``` ``` -invalid.jsx:17:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.jsx:17:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 15 │ import React from "react" 16 │ import * as React from "react" > 17 │ import { default as React } from "react" - │ ^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^ 18 │ import React, { useEffect } from "react" 19 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 15 15 │ import React from "react" 16 16 │ import * as React from "react" @@ -371,39 +324,22 @@ invalid.jsx:17:21 lint/correctness/noUnusedImports FIXABLE ━━━━━━ ``` invalid.jsx:18:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 16 │ import * as React from "react" 17 │ import { default as React } from "react" > 18 │ import React, { useEffect } from "react" - │ ^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^ 19 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 18 │ import·React,·{·useEffect·}·from·"react" - │ ------- - -``` - -``` -invalid.jsx:18:17 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 16 │ import * as React from "react" - 17 │ import { default as React } from "react" - > 18 │ import React, { useEffect } from "react" - │ ^^^^^^^^^ - 19 │ - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. + 16 16 │ import * as React from "react" + 17 17 │ import { default as React } from "react" + 18 │ - import·React,·{·useEffect·}·from·"react" + 19 18 │ - 18 │ import·React,·{·useEffect·}·from·"react" - │ --------------- ``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.ts.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.ts.snap index 97137057d6d2..beb722619f3b 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.ts.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.ts.snap @@ -1,6 +1,7 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: invalid.ts +snapshot_kind: text --- # Input ```ts @@ -45,7 +46,7 @@ invalid.ts:2:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 │ - //·Header·comment 2 │ - import·type·A·from·"mod"; @@ -69,7 +70,7 @@ invalid.ts:5:18 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 1 1 │ // Header comment 2 2 │ import type A from "mod"; @@ -83,19 +84,19 @@ invalid.ts:5:18 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ ``` ``` -invalid.ts:8:15 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:8:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 7 │ // Header comment > 8 │ import type { C } from "mod"; // Import comment - │ ^ + │ ^^^^^ 9 │ 10 │ // Header comment i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 4 4 │ // Header comment 5 5 │ import type * as B from "mod"; // Import comment @@ -111,191 +112,129 @@ invalid.ts:8:15 lint/correctness/noUnusedImports FIXABLE ━━━━━━━ ``` invalid.ts:11:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 10 │ // Header comment > 11 │ import /*a*/ D /*b*/, /*c*/{ type E }/*d*/ from "mod"; // Import comment - │ ^ + │ ^^^^^^^^^^^^^^^^^^^^^^^^ 12 │ 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 11 │ import·/*a*/·D·/*b*/,·/*c*/{·type·E·}/*d*/·from·"mod";·//·Import·comment - │ -------------- - -``` - -``` -invalid.ts:11:35 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. + 7 7 │ // Header comment + 8 8 │ import type { C } from "mod"; // Import comment + 9 │ - + 10 │ - //·Header·comment + 11 │ - import·/*a*/·D·/*b*/,·/*c*/{·type·E·}/*d*/·from·"mod";·//·Import·comment + 12 9 │ + 13 10 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - 10 │ // Header comment - > 11 │ import /*a*/ D /*b*/, /*c*/{ type E }/*d*/ from "mod"; // Import comment - │ ^ - 12 │ - 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. - - 11 │ import·/*a*/·D·/*b*/,·/*c*/{·type·E·}/*d*/·from·"mod";·//·Import·comment - │ ---------------------- ``` ``` invalid.ts:13:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This import is unused. + ! These imports are unused. 11 │ import /*a*/ D /*b*/, /*c*/{ type E }/*d*/ from "mod"; // Import comment 12 │ > 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - │ ^ + │ ^^^^^^^^^^^^^^^^^^^^^ 14 │ 15 │ import { i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. - - 13 │ import·/*a*/·F·/*b*/,·/*c*/·*·as·G·/*d*/·from·"mod"; - │ --------------- - -``` - -``` -invalid.ts:13:34 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. + i Safe fix: Remove the unused imports. - 11 │ import /*a*/ D /*b*/, /*c*/{ type E }/*d*/ from "mod"; // Import comment - 12 │ - > 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; - │ ^ - 14 │ - 15 │ import { - - i Unused imports might be the result of an incomplete refactoring. + 10 10 │ // Header comment + 11 11 │ import /*a*/ D /*b*/, /*c*/{ type E }/*d*/ from "mod"; // Import comment + 12 │ - + 13 │ - import·/*a*/·F·/*b*/,·/*c*/·*·as·G·/*d*/·from·"mod"; + 14 12 │ + 15 13 │ import { - i Safe fix: Remove the unused import. - - 13 │ import·/*a*/·F·/*b*/,·/*c*/·*·as·G·/*d*/·from·"mod"; - │ -------------------- ``` ``` -invalid.ts:17:10 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:15:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. - 15 │ import { - 16 │ // Comment + 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; + 14 │ + > 15 │ import { + │ ^ + > 16 │ // Comment > 17 │ type H, - │ ^ - 18 │ type I, - 19 │ } from "mod"; - - i Unused imports might be the result of an incomplete refactoring. - - i Safe fix: Remove the unused import. - - 14 14 │ - 15 15 │ import { - 16 │ - ····//·Comment - 17 │ - ····type·H, - 18 16 │ type I, - 19 17 │ } from "mod"; - - -``` - -``` -invalid.ts:18:10 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 16 │ // Comment - 17 │ type H, > 18 │ type I, - │ ^ - 19 │ } from "mod"; + > 19 │ } from "mod"; + │ ^ 20 │ + 21 │ import {/*a*/type J/*b*/, /*c*/type K/*d*/} from "mod"; i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. - 16 16 │ // Comment - 17 17 │ type H, + 12 12 │ + 13 13 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod"; + 14 │ - + 15 │ - import·{ + 16 │ - ····//·Comment + 17 │ - ····type·H, 18 │ - ····type·I, - 19 18 │ } from "mod"; - 20 19 │ + 19 │ - }·from·"mod"; + 20 14 │ + 21 15 │ import {/*a*/type J/*b*/, /*c*/type K/*d*/} from "mod"; ``` ``` -invalid.ts:21:19 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:21:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 19 │ } from "mod"; 20 │ > 21 │ import {/*a*/type J/*b*/, /*c*/type K/*d*/} from "mod"; - │ ^ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 22 │ 23 │ // Header comment i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. - - 21 │ import·{/*a*/type·J/*b*/,·/*c*/type·K/*d*/}·from·"mod"; - │ ------------------ - -``` - -``` -invalid.ts:21:37 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This import is unused. - - 19 │ } from "mod"; - 20 │ - > 21 │ import {/*a*/type J/*b*/, /*c*/type K/*d*/} from "mod"; - │ ^ - 22 │ - 23 │ // Header comment - - i Unused imports might be the result of an incomplete refactoring. + i Safe fix: Remove the unused imports. - i Safe fix: Remove the unused import. + 18 18 │ type I, + 19 19 │ } from "mod"; + 20 │ - + 21 │ - import·{/*a*/type·J/*b*/,·/*c*/type·K/*d*/}·from·"mod"; + 22 20 │ + 23 21 │ // Header comment - 21 │ import·{/*a*/type·J/*b*/,·/*c*/type·K/*d*/}·from·"mod"; - │ ----------- ``` ``` -invalid.ts:24:20 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:24:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This import is unused. 23 │ // Header comment > 24 │ import type { L as M, } from "mod"; // Import comment - │ ^ + │ ^^^^^^^^^^^ 25 │ i Unused imports might be the result of an incomplete refactoring. - i Safe fix: Remove the unused import. + i Safe fix: Remove the unused imports. 20 20 │ 21 21 │ import {/*a*/type J/*b*/, /*c*/type K/*d*/} from "mod";