From 0faa410781261724032914f91f20c46ccf1ea11e Mon Sep 17 00:00:00 2001 From: Dunqing Date: Wed, 20 Mar 2024 18:29:28 +0800 Subject: [PATCH] feat(linter/import) check module import in no_duplicates --- .../src/rules/import/no_duplicates.rs | 44 ++++++++++--------- .../src/snapshots/no_duplicates.snap | 26 +++++++++++ 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/crates/oxc_linter/src/rules/import/no_duplicates.rs b/crates/oxc_linter/src/rules/import/no_duplicates.rs index de47aeddb7b0..241a06f32402 100644 --- a/crates/oxc_linter/src/rules/import/no_duplicates.rs +++ b/crates/oxc_linter/src/rules/import/no_duplicates.rs @@ -4,7 +4,7 @@ use oxc_macros::declare_oxc_lint; use crate::{context::LintContext, rule::Rule}; -/// +/// #[derive(Debug, Default, Clone)] pub struct NoDuplicates; @@ -21,19 +21,24 @@ impl Rule for NoDuplicates { let module_record = ctx.semantic().module_record(); let groups = module_record - .loaded_modules + .requested_modules .iter() - .map(|r| (r.value().resolved_absolute_path.clone(), r.key().clone())) + .map(|(source, spans)| { + let resolved_absolute_path = module_record.loaded_modules.get(source).map_or_else( + || source.to_string(), + |module| module.resolved_absolute_path.to_string_lossy().to_string(), + ); + (resolved_absolute_path, spans) + }) .group_by(|r| r.0.clone()); for (_path, group) in &groups { let labels = group .into_iter() - .map(|(_path, specifier)| specifier) - .filter_map(|specifier| module_record.requested_modules.get(&specifier)) - .flatten() + .flat_map(|(_path, spans)| spans) .map(|span| LabeledSpan::underline(*span)) .collect::>(); + if labels.len() > 1 { ctx.diagnostic(miette!( severity = Severity::Warning, @@ -175,20 +180,19 @@ export const value = {}", } export default TestComponent;", - // TODO: figure out module imports - // r#"import {A1,} from 'foo'; - // import {B1,} from 'foo'; - // import {C1,} from 'foo'; - - // import { - // A2, - // } from 'bar'; - // import { - // B2, - // } from 'bar'; - // import { - // C2, - // } from 'bar';"#, + r"import {A1,} from 'foo'; + import {B1,} from 'foo'; + import {C1,} from 'foo'; + + import { + A2, + } from 'bar'; + import { + B2, + } from 'bar'; + import { + C2, + } from 'bar';", // TypeScript // TODO: distinguish type imports in module record // r#"import type x from './foo'; import type y from './foo'"#, diff --git a/crates/oxc_linter/src/snapshots/no_duplicates.snap b/crates/oxc_linter/src/snapshots/no_duplicates.snap index 770ae4f91e02..9ed54b173e00 100644 --- a/crates/oxc_linter/src/snapshots/no_duplicates.snap +++ b/crates/oxc_linter/src/snapshots/no_duplicates.snap @@ -356,3 +356,29 @@ expression: no_duplicates · ─ 13 │ } ╰──── + + ⚠ eslint-plugin-import(no-duplicates): Forbid repeated import of the same module in multiple places + ╭─[index.ts:1:19] + 1 │ import {A1,} from 'foo'; + · ───── + 2 │ import {B1,} from 'foo'; + · ───── + 3 │ import {C1,} from 'foo'; + · ───── + 4 │ + ╰──── + + ⚠ eslint-plugin-import(no-duplicates): Forbid repeated import of the same module in multiple places + ╭─[index.ts:7:16] + 6 │ A2, + 7 │ } from 'bar'; + · ───── + 8 │ import { + 9 │ B2, + 10 │ } from 'bar'; + · ───── + 11 │ import { + 12 │ C2, + 13 │ } from 'bar'; + · ───── + ╰────