From d30fc24347fa5cc79056c439b60c8e1a4de83c0b Mon Sep 17 00:00:00 2001 From: soufianeboutahlil Date: Sun, 21 Mar 2021 21:47:42 +0100 Subject: [PATCH] Fix: ignore unmergable imports when checking no-duplicate-imports (fixes #13180) & Fix: Ignore re-export all in no-duplicate-imports (fixes #12760) --- lib/rules/no-duplicate-imports.js | 58 ++++++------- tests/lib/rules/no-duplicate-imports.js | 107 ++++++++++++------------ 2 files changed, 83 insertions(+), 82 deletions(-) diff --git a/lib/rules/no-duplicate-imports.js b/lib/rules/no-duplicate-imports.js index 1a92060698fc..0520a6e24bea 100644 --- a/lib/rules/no-duplicate-imports.js +++ b/lib/rules/no-duplicate-imports.js @@ -8,12 +8,12 @@ // Rule Definition //------------------------------------------------------------------------------ -const EXPORT_ALL_DECLARATION = 'ExportAllDeclaration' -const IMPORT_NAME_SPACE_SPECIFIER = 'ImportNamespaceSpecifier'; -const IMPORT_SPECIFIER = 'ImportSpecifier'; +const EXPORT_ALL_DECLARATION = "ExportAllDeclaration"; +const IMPORT_NAME_SPACE_SPECIFIER = "ImportNamespaceSpecifier"; +const IMPORT_SPECIFIER = "ImportSpecifier"; const CONTRADICTORY_IMPORT_TYPES = [ IMPORT_NAME_SPACE_SPECIFIER, - IMPORT_SPECIFIER, + IMPORT_SPECIFIER ]; /** @@ -28,17 +28,17 @@ function getImportType(node) { node.specifiers[0] && node.specifiers[0].type ) { - const index = node.specifiers.findIndex((specifier) => + const index = node.specifiers.findIndex(specifier => CONTRADICTORY_IMPORT_TYPES.includes( specifier.type - ) - ); + )); + if (index > -1) { return node.specifiers[index].type; - } else { - return node.specifiers[0].type; } - } else if (node && node.type) { + return node.specifiers[0].type; + } + if (node && node.type) { return node.type; } return ""; @@ -67,13 +67,11 @@ function getValue(node) { function shouldReportContradictoryImportType(importTypes, importType) { if (importTypes.indexOf(importType) > -1) { return true; - } else { - return ( - importTypes.findIndex((importTypeItem) => { - return CONTRADICTORY_IMPORT_TYPES.includes(importTypeItem); - }) === -1 - ); } + return ( + importTypes.findIndex(importTypeItem => CONTRADICTORY_IMPORT_TYPES.includes(importTypeItem)) === -1 + ); + } /** @@ -100,6 +98,7 @@ function checkAndReport( ExportAllDeclarationsInFile ) { let isDuplicate = false; + if (type === EXPORT_ALL_DECLARATION) { if (ExportAllDeclarationsInFile.indexOf(value) !== -1) { isDuplicate = true; @@ -118,8 +117,8 @@ function checkAndReport( node, messageId, data: { - module: value, - }, + module: value + } }); } } @@ -148,7 +147,7 @@ function handleImports( modulesWithImportTypes, ExportAllDeclarationsInFile ) { - return function (node) { + return function(node) { const value = getValue(node); const type = getImportType(node); @@ -205,9 +204,10 @@ function handleExports( modulesWithImportTypes, ExportAllDeclarationsInFile ) { - return function (node) { + return function(node) { const value = getValue(node); const type = getImportType(node); + if (value) { checkAndReport( context, @@ -246,7 +246,7 @@ module.exports = { description: "disallow duplicate module imports", category: "ECMAScript 6", recommended: false, - url: "https://eslint.org/docs/rules/no-duplicate-imports", + url: "https://eslint.org/docs/rules/no-duplicate-imports" }, schema: [ @@ -255,18 +255,18 @@ module.exports = { properties: { includeExports: { type: "boolean", - default: false, - }, + default: false + } }, - additionalProperties: false, - }, + additionalProperties: false + } ], messages: { import: "'{{module}}' import is duplicated.", importAs: "'{{module}}' import is duplicated as export.", export: "'{{module}}' export is duplicated.", - exportAs: "'{{module}}' export is duplicated as import.", - }, + exportAs: "'{{module}}' export is duplicated as import." + } }, create(context) { @@ -283,7 +283,7 @@ module.exports = { exportsInFile, modulesWithImportTypes, ExportAllDeclarationsInFile - ), + ) }; if (includeExports) { @@ -303,5 +303,5 @@ module.exports = { ); } return handlers; - }, + } }; diff --git a/tests/lib/rules/no-duplicate-imports.js b/tests/lib/rules/no-duplicate-imports.js index 3039f47c0814..80a99a3037cf 100644 --- a/tests/lib/rules/no-duplicate-imports.js +++ b/tests/lib/rules/no-duplicate-imports.js @@ -17,7 +17,7 @@ const rule = require("../../../lib/rules/no-duplicate-imports"), //------------------------------------------------------------------------------ const ruleTester = new RuleTester({ - parserOptions: { ecmaVersion: 6, sourceType: "module" }, + parserOptions: { ecmaVersion: 6, sourceType: "module" } }); ruleTester.run("no-duplicate-imports", rule, { @@ -32,46 +32,47 @@ ruleTester.run("no-duplicate-imports", rule, { 'import foo, * as bar from "mod";\nimport { baz } from "mod";', { code: 'import os from "os";\nexport { hello } from "hello";', - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: 'import os from "os";\nexport * from "hello";', - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: 'import os from "os";\nexport { hello as hi } from "hello";', - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: 'import os from "os";\nexport default function(){};', - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: 'import { merge } from "lodash-es";\nexport { merge as lodashMerge }', - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, + // ignore `export * from` declarations, they cannot be merged with any other import/export declarations { code: "import os from 'os'; export * from 'os';", - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: "export * from 'os'; import { a } from 'os';", - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: "import * as ns from 'os'; export * from 'os';", - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: "export * from 'os'; export { a } from 'os';", - options: [{ includeExports: true }], + options: [{ includeExports: true }] }, { code: "export { a as b } from 'os'; export * from 'os';", - options: [{ includeExports: true }], - }, + options: [{ includeExports: true }] + } ], invalid: [ { @@ -80,9 +81,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "fs" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -91,9 +92,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "lodash-es" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -102,9 +103,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "os" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -113,9 +114,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "os" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -124,14 +125,14 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "os" }, - type: "ImportDeclaration", + type: "ImportDeclaration" }, { messageId: "import", data: { module: "os" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -140,9 +141,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "lodash-es" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -151,9 +152,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "module" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: @@ -162,9 +163,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "import", data: { module: "lodash-es" }, - type: "ImportDeclaration", - }, - ], + type: "ImportDeclaration" + } + ] }, { code: 'export { os } from "os";\nexport { something } from "os";', @@ -173,9 +174,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "export", data: { module: "os" }, - type: "ExportNamedDeclaration", - }, - ], + type: "ExportNamedDeclaration" + } + ] }, { code: @@ -185,19 +186,19 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "exportAs", data: { module: "os" }, - type: "ExportNamedDeclaration", + type: "ExportNamedDeclaration" }, { messageId: "export", data: { module: "os" }, - type: "ExportNamedDeclaration", + type: "ExportNamedDeclaration" }, { messageId: "exportAs", data: { module: "os" }, - type: "ExportNamedDeclaration", - }, - ], + type: "ExportNamedDeclaration" + } + ] }, { code: 'import os from "os";\nexport { something } from "os";', @@ -206,9 +207,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "exportAs", data: { module: "os" }, - type: "ExportNamedDeclaration", - }, - ], + type: "ExportNamedDeclaration" + } + ] }, { code: "export * from 'os'; export * from 'os';", @@ -217,9 +218,9 @@ ruleTester.run("no-duplicate-imports", rule, { { messageId: "export", data: { module: "os" }, - type: "ExportAllDeclaration", - }, - ], - }, - ], + type: "ExportAllDeclaration" + } + ] + } + ] });