| /** |
| * @fileoverview Restrict usage of duplicate imports. |
| * @author Simen Bekkhus |
| */ |
| "use strict"; |
| |
| //------------------------------------------------------------------------------ |
| // Rule Definition |
| //------------------------------------------------------------------------------ |
| |
| /** |
| * Returns the name of the module imported or re-exported. |
| * |
| * @param {ASTNode} node - A node to get. |
| * @returns {string} the name of the module, or empty string if no name. |
| */ |
| function getValue(node) { |
| if (node && node.source && node.source.value) { |
| return node.source.value.trim(); |
| } |
| |
| return ""; |
| } |
| |
| /** |
| * Checks if the name of the import or export exists in the given array, and reports if so. |
| * |
| * @param {RuleContext} context - The ESLint rule context object. |
| * @param {ASTNode} node - A node to get. |
| * @param {string} value - The name of the imported or exported module. |
| * @param {string[]} array - The array containing other imports or exports in the file. |
| * @param {string} messageId - A messageId to be reported after the name of the module |
| * |
| * @returns {void} No return value |
| */ |
| function checkAndReport(context, node, value, array, messageId) { |
| if (array.indexOf(value) !== -1) { |
| context.report({ |
| node, |
| messageId, |
| data: { |
| module: value |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @callback nodeCallback |
| * @param {ASTNode} node - A node to handle. |
| */ |
| |
| /** |
| * Returns a function handling the imports of a given file |
| * |
| * @param {RuleContext} context - The ESLint rule context object. |
| * @param {boolean} includeExports - Whether or not to check for exports in addition to imports. |
| * @param {string[]} importsInFile - The array containing other imports in the file. |
| * @param {string[]} exportsInFile - The array containing other exports in the file. |
| * |
| * @returns {nodeCallback} A function passed to ESLint to handle the statement. |
| */ |
| function handleImports(context, includeExports, importsInFile, exportsInFile) { |
| return function(node) { |
| const value = getValue(node); |
| |
| if (value) { |
| checkAndReport(context, node, value, importsInFile, "import"); |
| |
| if (includeExports) { |
| checkAndReport(context, node, value, exportsInFile, "importAs"); |
| } |
| |
| importsInFile.push(value); |
| } |
| }; |
| } |
| |
| /** |
| * Returns a function handling the exports of a given file |
| * |
| * @param {RuleContext} context - The ESLint rule context object. |
| * @param {string[]} importsInFile - The array containing other imports in the file. |
| * @param {string[]} exportsInFile - The array containing other exports in the file. |
| * |
| * @returns {nodeCallback} A function passed to ESLint to handle the statement. |
| */ |
| function handleExports(context, importsInFile, exportsInFile) { |
| return function(node) { |
| const value = getValue(node); |
| |
| if (value) { |
| checkAndReport(context, node, value, exportsInFile, "export"); |
| checkAndReport(context, node, value, importsInFile, "exportAs"); |
| |
| exportsInFile.push(value); |
| } |
| }; |
| } |
| |
| module.exports = { |
| meta: { |
| type: "problem", |
| |
| docs: { |
| description: "disallow duplicate module imports", |
| category: "ECMAScript 6", |
| recommended: false, |
| url: "https://eslint.org/docs/rules/no-duplicate-imports" |
| }, |
| |
| schema: [{ |
| type: "object", |
| properties: { |
| includeExports: { |
| type: "boolean", |
| default: 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." |
| } |
| }, |
| |
| create(context) { |
| const includeExports = (context.options[0] || {}).includeExports, |
| importsInFile = [], |
| exportsInFile = []; |
| |
| const handlers = { |
| ImportDeclaration: handleImports(context, includeExports, importsInFile, exportsInFile) |
| }; |
| |
| if (includeExports) { |
| handlers.ExportNamedDeclaration = handleExports(context, importsInFile, exportsInFile); |
| handlers.ExportAllDeclaration = handleExports(context, importsInFile, exportsInFile); |
| } |
| |
| return handlers; |
| } |
| }; |