From a45502cbcc93fca9496bfa1911f3e8e2e40a5aef Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Sat, 29 Jan 2022 13:15:22 +0100 Subject: [PATCH] [Fix] no-duplicates: Ignore duplicate modules in different TypeScript 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 --- CHANGELOG.md | 1 + src/rules/no-duplicates.js | 28 ++++++++++++++++++---------- tests/src/rules/no-duplicates.js | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39401934c9..d0fce78dbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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]) diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js index 43c2c5b201..efd9583fbc 100644 --- a/src/rules/no-duplicates.js +++ b/src/rules/no-duplicates.js @@ -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 { @@ -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); + } }, }; }, diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js index b481e6c823..cde41b3a07 100644 --- a/tests/src/rules/no-duplicates.js +++ b/tests/src/rules/no-duplicates.js @@ -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({