Skip to content

Commit

Permalink
feat(linter/import) check module import in no_duplicates (#2771)
Browse files Browse the repository at this point in the history
We should use `requested_modules` instead of `loaded_modules` because
`loaded_modules` only contains successfully resolved modules.
  • Loading branch information
Dunqing committed Mar 28, 2024
1 parent d63807e commit 920d1be
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
44 changes: 24 additions & 20 deletions crates/oxc_linter/src/rules/import/no_duplicates.rs
Expand Up @@ -4,7 +4,7 @@ use oxc_macros::declare_oxc_lint;

use crate::{context::LintContext, rule::Rule};

/// <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-unresolved.md>
/// <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-duplicates.md>
#[derive(Debug, Default, Clone)]
pub struct NoDuplicates;

Expand All @@ -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::<Vec<_>>();

if labels.len() > 1 {
ctx.diagnostic(miette!(
severity = Severity::Warning,
Expand Down Expand Up @@ -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'"#,
Expand Down
26 changes: 26 additions & 0 deletions crates/oxc_linter/src/snapshots/no_duplicates.snap
Expand Up @@ -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]
1import {A1,} from 'foo';
· ─────
2import {B1,} from 'foo';
· ─────
3import {C1,} from 'foo';
· ─────
4
╰────

eslint-plugin-import(no-duplicates): Forbid repeated import of the same module in multiple places
╭─[index.ts:7:16]
6A2,
7 │ } from 'bar';
· ─────
8import {
9 │ B2,
10 │ } from 'bar';
· ─────
11import {
12 │ C2,
13 │ } from 'bar';
· ─────
╰────

0 comments on commit 920d1be

Please sign in to comment.