Skip to content

Commit

Permalink
[Fix] no-duplicates: type import fixer generates valid TypeScript
Browse files Browse the repository at this point in the history
Fixes #2114, #2130
  • Loading branch information
GoodForOneFare committed Jul 10, 2021
1 parent 1012eb9 commit 7396b1b
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

### Fixed
- [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks])
- [`no-duplicates`]: type import fixer now generates valid TypeScript ([#2149])
- [`extensions`]: avoid crashing on partially typed import/export statements ([#2118], thanks [@ljharb])
- [`no-extraneous-dependencies`]: add ESM intermediate package.json support] ([#2121], thanks [@paztis])

Expand Down Expand Up @@ -808,6 +809,7 @@ for info on changes for earlier releases.

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

[#2149]: https://github.com/benmosher/eslint-plugin-import/pull/2149
[#2138]: https://github.com/benmosher/eslint-plugin-import/pull/2138
[#2121]: https://github.com/benmosher/eslint-plugin-import/pull/2121
[#2099]: https://github.com/benmosher/eslint-plugin-import/pull/2099
Expand Down
19 changes: 15 additions & 4 deletions src/rules/no-duplicates.js
Expand Up @@ -276,13 +276,23 @@ module.exports = {

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

function getImportMap(n) {
if (n.importKind === 'type') {
return n.specifiers[0].type === 'ImportDefaultSpecifier' ?
defaultTypesImported : namedTypesImported;
}

return hasNamespace(n) ? nsImported : imported;
}

return {
'ImportDeclaration': function (n) {
// resolved path will cover aliased duplicates
const resolvedPath = resolver(n.source.value);
const importMap = n.importKind === 'type' ? typesImported :
(hasNamespace(n) ? nsImported : imported);
const importMap = getImportMap(n);

if (importMap.has(resolvedPath)) {
importMap.get(resolvedPath).push(n);
Expand All @@ -294,7 +304,8 @@ module.exports = {
'Program:exit': function () {
checkImports(imported, context);
checkImports(nsImported, context);
checkImports(typesImported, context);
checkImports(defaultTypesImported, context);
checkImports(namedTypesImported, context);
},
};
},
Expand Down
83 changes: 82 additions & 1 deletion tests/src/rules/no-duplicates.js
Expand Up @@ -437,8 +437,89 @@ context('TypeScript', function() {
},
parserConfig,
),
test(
{
code: "import type x from './foo'; import type y from './bar'",
parser,
},
parserConfig,
),
test(
{
code: "import type {x} from './foo'; import type {y} from './bar'",
parser,
},
parserConfig,
),
test(
{
code: "import type x from './foo'; import type {y} from './foo'",
parser,
},
parserConfig,
),
],
invalid: [
test(
{
code: "import type x from './foo'; import type y from './foo'",
parser,
errors: [
{
line: 1,
column: 20,
message: "'./foo' imported multiple times.",
},
{
line: 1,
column: 48,
message: "'./foo' imported multiple times.",
},
],
},
parserConfig,
),
test(
{
code: "import type x from './foo'; import type x from './foo'",
output: "import type x from './foo'; ",
parser,
errors: [
{
line: 1,
column: 20,
message: "'./foo' imported multiple times.",
},
{
line: 1,
column: 48,
message: "'./foo' imported multiple times.",
},
],
},
parserConfig,
),
test(
{
code: "import type {x} from './foo'; import type {y} from './foo'",
parser,
output: `import type {x,y} from './foo'; `,
errors: [
{
line: 1,
column: 22,
message: "'./foo' imported multiple times.",
},
{
line: 1,
column: 52,
message: "'./foo' imported multiple times.",
},
],
},
parserConfig,
),
],
invalid: [],
});
});
});

0 comments on commit 7396b1b

Please sign in to comment.