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

Commit

Permalink
New: no-useless-rename (fixes eslint#6058) (eslint#6249)
Browse files Browse the repository at this point in the history
  • Loading branch information
kaicataldo authored and nzakas committed May 26, 2016
1 parent b4cff9d commit fea8fe6
Show file tree
Hide file tree
Showing 5 changed files with 577 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/eslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"no-useless-concat": "off",
"no-useless-constructor": "off",
"no-useless-escape": "off",
"no-useless-rename": "off",
"no-void": "off",
"no-var": "off",
"no-warning-comments": "off",
Expand Down
1 change: 1 addition & 0 deletions docs/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ These rules relate to ES6, also known as ES2015:
* [no-this-before-super](no-this-before-super.md): disallow `this`/`super` before calling `super()` in constructors (recommended)
* [no-useless-computed-key](no-useless-computed-key.md): disallow unnecessary computed property keys in object literals
* [no-useless-constructor](no-useless-constructor.md): disallow unnecessary constructors
* [no-useless-rename](no-useless-rename.md): disallow renaming import, export, and destructured assignments to the same name
* [no-var](no-var.md): require `let` or `const` instead of `var`
* [object-shorthand](object-shorthand.md): require or disallow method and property shorthand syntax for object literals
* [prefer-arrow-callback](prefer-arrow-callback.md): require arrow functions as callbacks
Expand Down
122 changes: 122 additions & 0 deletions docs/rules/no-useless-rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Disallow renaming import, export, and destructured assignments to the same name (no-useless-rename)

(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.

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:

```js
import { foo as bar } from "baz";
export { foo as bar };
let { foo: bar } = baz;
```

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:

```js
import { foo as foo } from "bar";
export { foo as foo };
let { foo: foo } = bar;
```

is the same as:

```js
import { foo } from "bar";
export { foo };
let { foo } = bar;
```

## Rule Details

This rule disallows the renaming of import, export, and destructured assignments to the same name.

## Options

This rule allows for more fine-grained control with the following options:

* `ignoreImport`: When set to `true`, this rule does not check imports
* `ignoreExport`: When set to `true`, this rule does not check exports
* `ignoreDestructuring`: When set to `true`, this rule does not check destructuring assignments

By default, all options are set to `false`:

```json
"no-useless-rename": ["error", {
"ignoreDestructuring": false,
"ignoreImport": false,
"ignoreExport": false
}]
```

Examples of **incorrect** code for this rule by default:

```js
/*eslint no-useless-rename: "error"*/

import { foo as foo } from "bar";
export { foo as foo };
export { foo as foo } from "bar";
let { foo: foo } = bar;
let { 'foo': foo } = bar;
function foo({ bar: bar }) {}
({ foo: foo }) => {}
```

Examples of **correct** code for this rule by default:

```js
/*eslint no-useless-rename: "error"*/

import * as foo from "foo";
import { foo } from "bar";
import { foo as bar } from "baz";

export { foo };
export { foo as bar };
export { foo as bar } from "foo";

let { foo } = bar;
let { foo: bar } = baz;
let { [foo]: foo } = bar;

function foo({ bar }) {}
function foo({ bar: baz }) {}

({ foo }) => {}
({ foo: bar }) => {}
```

Examples of **correct** code for this rule with `{ ignoreImport: true }`:

```js
/*eslint no-useless-rename: ["error", { ignoreImport: true }]*/

import { foo as foo } from "bar";
```

Examples of **correct** code for this rule with `{ ignoreExport: true }`:

```js
/*eslint no-useless-rename: ["error", { ignoreExport: true }]*/

export { foo as foo };
export { foo as foo } from "bar";
```

Examples of **correct** code for this rule with `{ ignoreDestructuring: true }`:

```js
/*eslint no-useless-rename: ["error", { ignoreDestructuring: true }]*/

let { foo: foo } = bar;
function foo({ bar: bar }) {}
({ foo: foo }) => {}
```

## When Not To Use It

You can safely disable this rule if you do not care about redundantly renaming import, export, and destructuring assignments.

## Compatibility

* **JSCS**: [disallowIdenticalDestructuringNames](http://jscs.info/rule/disallowIdenticalDestructuringNames)
142 changes: 142 additions & 0 deletions lib/rules/no-useless-rename.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
* @fileoverview Disallow renaming import, export, and destructured assignments to the same name.
* @author Kai Cataldo
*/

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: "disallow renaming import, export, and destructured assignments to the same name",
category: "ECMAScript 6",
recommended: false
},
fixable: "code",
schema: [
{
type: "object",
properties: {
ignoreDestructuring: { type: "boolean" },
ignoreImport: { type: "boolean" },
ignoreExport: { type: "boolean" }
},
additionalProperties: false
}
]
},

create: function(context) {
var 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) {
var name = initial.type === "Identifier" ? initial.name : initial.value;

return context.report({
node: node,
message: "{{type}} {{name}} unnecessarily renamed.",
data: {
name: name,
type: type
},
fix: function(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) {
var properties,
i;

if (ignoreDestructuring) {
return;
}

properties = node.properties;

for (i = 0; i < properties.length; i++) {
if (properties[i].shorthand) {
return;
}

if (properties[i].computed) {
return;
}

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) {
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) {
reportError(node, node.local, node.exported, "Export");
}

}

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------

return {
ObjectPattern: checkDestructured,
ImportSpecifier: checkImport,
ExportSpecifier: checkExport
};
}
};
Loading

0 comments on commit fea8fe6

Please sign in to comment.