You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
4.4 KiB
142 lines
4.4 KiB
/** |
|
* @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; |
|
} |
|
};
|
|
|