Skip to content

Commit

Permalink
no-duplicates: allow duplicate if one is namespace and other not
Browse files Browse the repository at this point in the history
It is a syntax error to put both namespace and non namespace import on the same line, so allow it.

Fixes #1538
  • Loading branch information
sveyret authored and ljharb committed Jan 15, 2020
1 parent 7e71b50 commit f84d457
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
- [`import/external-module-folders` setting] now correctly works with directories containing modules symlinked from `node_modules` ([#1605], thanks [@skozin])
- [`extensions`]: for invalid code where `name` does not exist, do not crash ([#1613], thanks [@ljharb])
- [`extentions`]: Fix scope regex ([#1611], thanks [@yordis])
- [`no-duplicates`]: allow duplicate imports if one is a namespace and the other not ([#1612], thanks [@sveyret])

### Changed
- [`import/external-module-folders` setting] behavior is more strict now: it will only match complete path segments ([#1605], thanks [@skozin])
Expand Down Expand Up @@ -644,6 +645,7 @@ for info on changes for earlier releases.
[`memo-parser`]: ./memo-parser/README.md

[#1613]: https://github.com/benmosher/eslint-plugin-import/issues/1613
[#1612]: https://github.com/benmosher/eslint-plugin-import/pull/1612
[#1611]: https://github.com/benmosher/eslint-plugin-import/pull/1611
[#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
[#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
Expand Down Expand Up @@ -1081,3 +1083,4 @@ for info on changes for earlier releases.
[@ivo-stefchev]: https://github.com/ivo-stefchev
[@skozin]: https://github.com/skozin
[@yordis]: https://github.com/yordis
[@sveyret]: https://github.com/sveyret
5 changes: 4 additions & 1 deletion src/rules/no-duplicates.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,14 @@ module.exports = {
}) : defaultResolver

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

if (importMap.has(resolvedPath)) {
importMap.get(resolvedPath).push(n)
Expand All @@ -273,6 +275,7 @@ module.exports = {

'Program:exit': function () {
checkImports(imported, context)
checkImports(nsImported, context)
checkImports(typesImported, context)
},
}
Expand Down
27 changes: 21 additions & 6 deletions tests/src/rules/no-duplicates.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,20 @@ ruleTester.run('no-duplicates', rule, {
code: "import x from './bar?optionX'; import y from './bar?optionY';",
options: [{'considerQueryString': true}],
settings: { 'import/resolver': 'webpack' },
}),
}),
test({
code: "import x from './foo'; import y from './bar';",
options: [{'considerQueryString': true}],
settings: { 'import/resolver': 'webpack' },
}),
}),

// #1538: It is impossible to import namespace and other in one line, so allow this.
test({
code: "import * as ns from './foo'; import {y} from './foo'",
}),
test({
code: "import {y} from './foo'; import * as ns from './foo'",
}),
],
invalid: [
test({
Expand Down Expand Up @@ -179,17 +187,24 @@ ruleTester.run('no-duplicates', rule, {
}),

test({
code: "import * as ns from './foo'; import {y} from './foo'",
// Autofix bail because first import is a namespace import.
output: "import * as ns from './foo'; import {y} from './foo'",
code: "import * as ns1 from './foo'; import * as ns2 from './foo'",
// Autofix bail because cannot merge namespace imports.
output: "import * as ns1 from './foo'; import * as ns2 from './foo'",
errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
}),

test({
code: "import * as ns from './foo'; import {x} from './foo'; import {y} from './foo'",
// Autofix could merge some imports, but not the namespace import.
output: "import * as ns from './foo'; import {x,y} from './foo'; ",
errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
}),

test({
code: "import {x} from './foo'; import * as ns from './foo'; import {y} from './foo'; import './foo'",
// Autofix could merge some imports, but not the namespace import.
output: "import {x,y} from './foo'; import * as ns from './foo'; ",
errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'],
}),

test({
Expand Down

0 comments on commit f84d457

Please sign in to comment.