Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit fea8fe6

Browse files
kaicataldonzakas
authored andcommitted
New: no-useless-rename (fixes eslint#6058) (eslint#6249)
1 parent b4cff9d commit fea8fe6

File tree

5 files changed

+577
-0
lines changed

5 files changed

+577
-0
lines changed

conf/eslint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"no-useless-concat": "off",
121121
"no-useless-constructor": "off",
122122
"no-useless-escape": "off",
123+
"no-useless-rename": "off",
123124
"no-void": "off",
124125
"no-var": "off",
125126
"no-warning-comments": "off",

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ These rules relate to ES6, also known as ES2015:
242242
* [no-this-before-super](no-this-before-super.md): disallow `this`/`super` before calling `super()` in constructors (recommended)
243243
* [no-useless-computed-key](no-useless-computed-key.md): disallow unnecessary computed property keys in object literals
244244
* [no-useless-constructor](no-useless-constructor.md): disallow unnecessary constructors
245+
* [no-useless-rename](no-useless-rename.md): disallow renaming import, export, and destructured assignments to the same name
245246
* [no-var](no-var.md): require `let` or `const` instead of `var`
246247
* [object-shorthand](object-shorthand.md): require or disallow method and property shorthand syntax for object literals
247248
* [prefer-arrow-callback](prefer-arrow-callback.md): require arrow functions as callbacks

docs/rules/no-useless-rename.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Disallow renaming import, export, and destructured assignments to the same name (no-useless-rename)
2+
3+
(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.
4+
5+
ES2015 allows for the renaming of references in import and export statements as well as destructuring assignments. This gives programmers a concise syntax for performing these operations while renaming these references:
6+
7+
```js
8+
import { foo as bar } from "baz";
9+
export { foo as bar };
10+
let { foo: bar } = baz;
11+
```
12+
13+
With this syntax, it is possible to rename a reference to the same name. This is a completely redundant operation, as this is the same as not renaming at all. For example, this:
14+
15+
```js
16+
import { foo as foo } from "bar";
17+
export { foo as foo };
18+
let { foo: foo } = bar;
19+
```
20+
21+
is the same as:
22+
23+
```js
24+
import { foo } from "bar";
25+
export { foo };
26+
let { foo } = bar;
27+
```
28+
29+
## Rule Details
30+
31+
This rule disallows the renaming of import, export, and destructured assignments to the same name.
32+
33+
## Options
34+
35+
This rule allows for more fine-grained control with the following options:
36+
37+
* `ignoreImport`: When set to `true`, this rule does not check imports
38+
* `ignoreExport`: When set to `true`, this rule does not check exports
39+
* `ignoreDestructuring`: When set to `true`, this rule does not check destructuring assignments
40+
41+
By default, all options are set to `false`:
42+
43+
```json
44+
"no-useless-rename": ["error", {
45+
"ignoreDestructuring": false,
46+
"ignoreImport": false,
47+
"ignoreExport": false
48+
}]
49+
```
50+
51+
Examples of **incorrect** code for this rule by default:
52+
53+
```js
54+
/*eslint no-useless-rename: "error"*/
55+
56+
import { foo as foo } from "bar";
57+
export { foo as foo };
58+
export { foo as foo } from "bar";
59+
let { foo: foo } = bar;
60+
let { 'foo': foo } = bar;
61+
function foo({ bar: bar }) {}
62+
({ foo: foo }) => {}
63+
```
64+
65+
Examples of **correct** code for this rule by default:
66+
67+
```js
68+
/*eslint no-useless-rename: "error"*/
69+
70+
import * as foo from "foo";
71+
import { foo } from "bar";
72+
import { foo as bar } from "baz";
73+
74+
export { foo };
75+
export { foo as bar };
76+
export { foo as bar } from "foo";
77+
78+
let { foo } = bar;
79+
let { foo: bar } = baz;
80+
let { [foo]: foo } = bar;
81+
82+
function foo({ bar }) {}
83+
function foo({ bar: baz }) {}
84+
85+
({ foo }) => {}
86+
({ foo: bar }) => {}
87+
```
88+
89+
Examples of **correct** code for this rule with `{ ignoreImport: true }`:
90+
91+
```js
92+
/*eslint no-useless-rename: ["error", { ignoreImport: true }]*/
93+
94+
import { foo as foo } from "bar";
95+
```
96+
97+
Examples of **correct** code for this rule with `{ ignoreExport: true }`:
98+
99+
```js
100+
/*eslint no-useless-rename: ["error", { ignoreExport: true }]*/
101+
102+
export { foo as foo };
103+
export { foo as foo } from "bar";
104+
```
105+
106+
Examples of **correct** code for this rule with `{ ignoreDestructuring: true }`:
107+
108+
```js
109+
/*eslint no-useless-rename: ["error", { ignoreDestructuring: true }]*/
110+
111+
let { foo: foo } = bar;
112+
function foo({ bar: bar }) {}
113+
({ foo: foo }) => {}
114+
```
115+
116+
## When Not To Use It
117+
118+
You can safely disable this rule if you do not care about redundantly renaming import, export, and destructuring assignments.
119+
120+
## Compatibility
121+
122+
* **JSCS**: [disallowIdenticalDestructuringNames](http://jscs.info/rule/disallowIdenticalDestructuringNames)

lib/rules/no-useless-rename.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* @fileoverview Disallow renaming import, export, and destructured assignments to the same name.
3+
* @author Kai Cataldo
4+
*/
5+
6+
"use strict";
7+
8+
//------------------------------------------------------------------------------
9+
// Rule Definition
10+
//------------------------------------------------------------------------------
11+
12+
module.exports = {
13+
meta: {
14+
docs: {
15+
description: "disallow renaming import, export, and destructured assignments to the same name",
16+
category: "ECMAScript 6",
17+
recommended: false
18+
},
19+
fixable: "code",
20+
schema: [
21+
{
22+
type: "object",
23+
properties: {
24+
ignoreDestructuring: { type: "boolean" },
25+
ignoreImport: { type: "boolean" },
26+
ignoreExport: { type: "boolean" }
27+
},
28+
additionalProperties: false
29+
}
30+
]
31+
},
32+
33+
create: function(context) {
34+
var options = context.options[0] || {},
35+
ignoreDestructuring = options.ignoreDestructuring === true,
36+
ignoreImport = options.ignoreImport === true,
37+
ignoreExport = options.ignoreExport === true;
38+
39+
//--------------------------------------------------------------------------
40+
// Helpers
41+
//--------------------------------------------------------------------------
42+
43+
/**
44+
* Reports error for unnecessarily renamed assignments
45+
* @param {ASTNode} node - node to report
46+
* @param {ASTNode} initial - node with initial name value
47+
* @param {ASTNode} result - node with new name value
48+
* @param {string} type - the type of the offending node
49+
* @returns {void}
50+
*/
51+
function reportError(node, initial, result, type) {
52+
var name = initial.type === "Identifier" ? initial.name : initial.value;
53+
54+
return context.report({
55+
node: node,
56+
message: "{{type}} {{name}} unnecessarily renamed.",
57+
data: {
58+
name: name,
59+
type: type
60+
},
61+
fix: function(fixer) {
62+
return fixer.replaceTextRange([
63+
initial.range[0],
64+
result.range[1]
65+
], name);
66+
}
67+
});
68+
}
69+
70+
/**
71+
* Checks whether a destructured assignment is unnecessarily renamed
72+
* @param {ASTNode} node - node to check
73+
* @returns {void}
74+
*/
75+
function checkDestructured(node) {
76+
var properties,
77+
i;
78+
79+
if (ignoreDestructuring) {
80+
return;
81+
}
82+
83+
properties = node.properties;
84+
85+
for (i = 0; i < properties.length; i++) {
86+
if (properties[i].shorthand) {
87+
return;
88+
}
89+
90+
if (properties[i].computed) {
91+
return;
92+
}
93+
94+
if (properties[i].key.type === "Identifier" && properties[i].key.name === properties[i].value.name ||
95+
properties[i].key.type === "Literal" && properties[i].key.value === properties[i].value.name) {
96+
reportError(properties[i], properties[i].key, properties[i].value, "Destructuring assignment");
97+
}
98+
}
99+
}
100+
101+
/**
102+
* Checks whether an import is unnecessarily renamed
103+
* @param {ASTNode} node - node to check
104+
* @returns {void}
105+
*/
106+
function checkImport(node) {
107+
if (ignoreImport) {
108+
return;
109+
}
110+
111+
if (node.imported.name === node.local.name) {
112+
reportError(node, node.imported, node.local, "Import");
113+
}
114+
}
115+
116+
/**
117+
* Checks whether an export is unnecessarily renamed
118+
* @param {ASTNode} node - node to check
119+
* @returns {void}
120+
*/
121+
function checkExport(node) {
122+
if (ignoreExport) {
123+
return;
124+
}
125+
126+
if (node.local.name === node.exported.name) {
127+
reportError(node, node.local, node.exported, "Export");
128+
}
129+
130+
}
131+
132+
//--------------------------------------------------------------------------
133+
// Public
134+
//--------------------------------------------------------------------------
135+
136+
return {
137+
ObjectPattern: checkDestructured,
138+
ImportSpecifier: checkImport,
139+
ExportSpecifier: checkExport
140+
};
141+
}
142+
};

0 commit comments

Comments
 (0)