| /** | |
| * @fileoverview Disallow renaming import, export, and destructured assignments to the same name. | |
| * @author Kai Cataldo | |
| */ | |
| "use strict"; | |
| //------------------------------------------------------------------------------ | |
| // Rule Definition | |
| //------------------------------------------------------------------------------ | |
| module.exports = { | |
| meta: { | |
| type: "suggestion", | |
| docs: { | |
| description: "disallow renaming import, export, and destructured assignments to the same name", | |
| category: "ECMAScript 6", | |
| recommended: false, | |
| url: "https://eslint.org/docs/rules/no-useless-rename" | |
| }, | |
| fixable: "code", | |
| schema: [ | |
| { | |
| type: "object", | |
| properties: { | |
| ignoreDestructuring: { type: "boolean", default: false }, | |
| ignoreImport: { type: "boolean", default: false }, | |
| ignoreExport: { type: "boolean", default: false } | |
| }, | |
| additionalProperties: false | |
| } | |
| ] | |
| }, | |
| create(context) { | |
| const options = context.options[0] || {}, | |
| ignoreDestructuring = options.ignoreDestructuring === true, | |
| ignoreImport = options.ignoreImport === true, | |
| ignoreExport = options.ignoreExport === true; | |
| //-------------------------------------------------------------------------- | |
| // Helpers | |
| //-------------------------------------------------------------------------- | |
| /** | |
| * Reports error for unnecessarily renamed assignments | |
| * @param {ASTNode} node - node to report | |
| * @param {ASTNode} initial - node with initial name value | |
| * @param {ASTNode} result - node with new name value | |
| * @param {string} type - the type of the offending node | |
| * @returns {void} | |
| */ | |
| function reportError(node, initial, result, type) { | |
| const name = initial.type === "Identifier" ? initial.name : initial.value; | |
| return context.report({ | |
| node, | |
| message: "{{type}} {{name}} unnecessarily renamed.", | |
| data: { | |
| name, | |
| type | |
| }, | |
| fix(fixer) { | |
| return fixer.replaceTextRange([ | |
| initial.range[0], | |
| result.range[1] | |
| ], name); | |
| } | |
| }); | |
| } | |
| /** | |
| * Checks whether a destructured assignment is unnecessarily renamed | |
| * @param {ASTNode} node - node to check | |
| * @returns {void} | |
| */ | |
| function checkDestructured(node) { | |
| if (ignoreDestructuring) { | |
| return; | |
| } | |
| const properties = node.properties; | |
| for (let i = 0; i < properties.length; i++) { | |
| if (properties[i].shorthand) { | |
| continue; | |
| } | |
| /** | |
| * If an ObjectPattern property is computed, we have no idea | |
| * if a rename is useless or not. If an ObjectPattern property | |
| * lacks a key, it is likely an ExperimentalRestProperty and | |
| * so there is no "renaming" occurring here. | |
| */ | |
| if (properties[i].computed || !properties[i].key) { | |
| continue; | |
| } | |
| if (properties[i].key.type === "Identifier" && properties[i].key.name === properties[i].value.name || | |
| properties[i].key.type === "Literal" && properties[i].key.value === properties[i].value.name) { | |
| reportError(properties[i], properties[i].key, properties[i].value, "Destructuring assignment"); | |
| } | |
| } | |
| } | |
| /** | |
| * Checks whether an import is unnecessarily renamed | |
| * @param {ASTNode} node - node to check | |
| * @returns {void} | |
| */ | |
| function checkImport(node) { | |
| if (ignoreImport) { | |
| return; | |
| } | |
| if (node.imported.name === node.local.name && | |
| node.imported.range[0] !== node.local.range[0]) { | |
| reportError(node, node.imported, node.local, "Import"); | |
| } | |
| } | |
| /** | |
| * Checks whether an export is unnecessarily renamed | |
| * @param {ASTNode} node - node to check | |
| * @returns {void} | |
| */ | |
| function checkExport(node) { | |
| if (ignoreExport) { | |
| return; | |
| } | |
| if (node.local.name === node.exported.name && | |
| node.local.range[0] !== node.exported.range[0]) { | |
| reportError(node, node.local, node.exported, "Export"); | |
| } | |
| } | |
| //-------------------------------------------------------------------------- | |
| // Public | |
| //-------------------------------------------------------------------------- | |
| return { | |
| ObjectPattern: checkDestructured, | |
| ImportSpecifier: checkImport, | |
| ExportSpecifier: checkExport | |
| }; | |
| } | |
| }; |