Skip to content

Commit

Permalink
[Fix] no-duplicates: Ignore duplicate modules in different TypeScri…
Browse files Browse the repository at this point in the history
…pt module declarations

Without this the `import/no-duplicates` rule reports imports of the same
module inside different module declarations in the same file. It even
autofixed them, which break the code.

Closes #2273
  • Loading branch information
remcohaszing authored and ljharb committed Jan 29, 2022
1 parent 3603428 commit 0595a2f
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
### Fixed
- [`default`]: `typescript-eslint-parser`: avoid a crash on exporting as namespace (thanks [@ljharb])
- [`export`]/TypeScript: false positive for typescript namespace merging ([#1964], thanks [@magarcia])
- [`no-duplicates`]: ignore duplicate modules in different TypeScript module declarations ([#2378], thanks [@remcohaszing])

### Changed
- [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki])
Expand Down Expand Up @@ -968,6 +969,7 @@ for info on changes for earlier releases.

[`memo-parser`]: ./memo-parser/README.md

[#2378]: https://github.com/import-js/eslint-plugin-import/pull/2378
[#2371]: https://github.com/import-js/eslint-plugin-import/pull/2371
[#2367]: https://github.com/import-js/eslint-plugin-import/pull/2367
[#2332]: https://github.com/import-js/eslint-plugin-import/pull/2332
Expand Down
28 changes: 18 additions & 10 deletions src/rules/no-duplicates.js
Expand Up @@ -274,17 +274,23 @@ module.exports = {
return defaultResolver(parts[1]) + '?' + parts[2];
}) : defaultResolver;

const imported = new Map();
const nsImported = new Map();
const defaultTypesImported = new Map();
const namedTypesImported = new Map();
const moduleMaps = new Map();

function getImportMap(n) {
if (!moduleMaps.has(n.parent)) {
moduleMaps.set(n.parent, {
imported: new Map(),
nsImported: new Map(),
defaultTypesImported: new Map(),
namedTypesImported: new Map(),
});
}
const map = moduleMaps.get(n.parent);
if (n.importKind === 'type') {
return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported;
return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
}

return hasNamespace(n) ? nsImported : imported;
return hasNamespace(n) ? map.nsImported : map.imported;
}

return {
Expand All @@ -301,10 +307,12 @@ module.exports = {
},

'Program:exit': function () {
checkImports(imported, context);
checkImports(nsImported, context);
checkImports(defaultTypesImported, context);
checkImports(namedTypesImported, context);
for (const map of moduleMaps.values()) {
checkImports(map.imported, context);
checkImports(map.nsImported, context);
checkImports(map.defaultTypesImported, context);
checkImports(map.namedTypesImported, context);
}
},
};
},
Expand Down
14 changes: 14 additions & 0 deletions tests/src/rules/no-duplicates.js
Expand Up @@ -454,6 +454,20 @@ context('TypeScript', function () {
`,
...parserConfig,
}),
test({
code: `
import type { Identifier } from 'module';
declare module 'module2' {
import type { Identifier } from 'module';
}
declare module 'module3' {
import type { Identifier } from 'module';
}
`,
...parserConfig,
}),
],
invalid: [
test({
Expand Down

0 comments on commit 0595a2f

Please sign in to comment.