Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
61dfe68
commit 1313804
Showing
5 changed files
with
853 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
# Enforce spacing between rest and spread operators and their expressions (rest-spread-spacing) | ||
|
||
(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule. | ||
|
||
ES2015 introduced the rest and spread operators, which expand an iterable structure into its individual parts. Some examples of their usage are as follows: | ||
|
||
```js | ||
let numArr = [1, 2, 3]; | ||
function add(a, b, c) { | ||
return a + b + c; | ||
} | ||
add(...numArr); // -> 6 | ||
|
||
let arr1 = [1, 2, 3]; | ||
let arr2 = [4, 5, 6]; | ||
arr1.push(...arr2); // -> [1, 2, 3, 4, 5, 6] | ||
|
||
let [a, b, ...arr] = [1, 2, 3, 4, 5]; | ||
a; // -> 1 | ||
b // -> 2 | ||
arr; // -> [3, 4, 5] | ||
|
||
function numArgs(...args) { | ||
return args.length; | ||
} | ||
numArgs(a, b, c); // -> 3 | ||
``` | ||
|
||
In addition to the above, there is currently a proposal to add object rest and spread properties to the spec. They can be used as follows: | ||
|
||
```js | ||
|
||
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; | ||
x; // -> 1 | ||
y; // -> 2 | ||
z; // -> { a: 3, b: 4 } | ||
|
||
let n = { x, y, ...z }; | ||
n; // -> { x: 1, y: 2, a: 3, b: 4 } | ||
``` | ||
|
||
As with other operators, whitespace is allowed between the rest or spread operator and the expression it is operating on, which can lead to inconsistent spacing within a codebase. | ||
|
||
## Rule Details | ||
|
||
This rule aims to enforce consistent spacing between rest and spread operators and their expressions. The rule also supports the currently experimental object rest and spread properties when enabled: | ||
|
||
```json | ||
{ | ||
"parserOptions": { | ||
"ecmaVersion": 6, | ||
"ecmaFeatures": { | ||
"experimentalObjectRestSpread": true | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Please read the user guide's section on [configuring parser options](http://eslint.org/docs/user-guide/configuring#specifying-parser-options) to learn more. | ||
|
||
## Options | ||
|
||
This rule takes one option: a string with the value of `"never"` or `"always"`. The default value is `"never"`. | ||
|
||
### "never" | ||
|
||
When using the default `"never"` option, whitespace is not allowed between spread operators and their expressions. | ||
|
||
```json | ||
spread-spacing: ["error"] | ||
``` | ||
|
||
or | ||
|
||
```json | ||
spread-spacing: ["error", "never"] | ||
``` | ||
|
||
Examples of **incorrect** code for this rule with `"never"`: | ||
|
||
```js | ||
/*eslint spread-spacing: ["error", "never"]*/ | ||
|
||
fn(... args) | ||
[... arr, 4, 5, 6] | ||
let [a, b, ... arr] = [1, 2, 3, 4, 5]; | ||
function fn(... args) { console.log(args); } | ||
let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 }; | ||
let n = { x, y, ... z }; | ||
``` | ||
|
||
Examples of **correct** code for this rule with `"never"`: | ||
|
||
```js | ||
/*eslint spread-spacing: ["error", "never"]*/ | ||
|
||
fn(...args) | ||
[...arr, 4, 5, 6] | ||
let [a, b, ...arr] = [1, 2, 3, 4, 5]; | ||
function fn(...args) { console.log(args); } | ||
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; | ||
let n = { x, y, ...z }; | ||
``` | ||
|
||
### "always" | ||
|
||
When using the `"always"` option, whitespace is required between spread operators and their expressions. | ||
|
||
```json | ||
spread-spacing: ["error", "always"] | ||
``` | ||
|
||
Examples of **incorrect** code for this rule with `"always"`: | ||
|
||
```js | ||
/*eslint spread-spacing:["error", "always"]*/ | ||
|
||
fn(...args) | ||
[...arr, 4, 5, 6] | ||
let [a, b, ...arr] = [1, 2, 3, 4, 5]; | ||
function fn(...args) { console.log(args); } | ||
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; | ||
let n = { x, y, ...z }; | ||
``` | ||
|
||
Examples of **correct** code for this rule with `"always"`: | ||
|
||
```js | ||
/*eslint spread-spacing: ["error", "always"]*/ | ||
|
||
fn(... args) | ||
[... arr, 4, 5, 6] | ||
let [a, b, ... arr] = [1, 2, 3, 4, 5]; | ||
function fn(... args) { console.log(args); } | ||
let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 }; | ||
let n = { x, y, ... z }; | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
You can safely disable this rule if you do not care about enforcing consistent spacing between spread operators and their expressions. | ||
|
||
## Further Reading | ||
|
||
* [Object Rest/Spread Properties for ECMAScript](https://github.com/sebmarkbage/ecmascript-rest-spread) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** | ||
* @fileoverview Enforce spacing between rest and spread operators and their expressions. | ||
* @author Kai Cataldo | ||
*/ | ||
|
||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: "enforce spacing between rest and spread operators and their expressions", | ||
category: "ECMAScript 6", | ||
recommended: false | ||
}, | ||
fixable: "whitespace", | ||
schema: [ | ||
{ | ||
enum: ["always", "never"] | ||
} | ||
] | ||
}, | ||
|
||
create: function(context) { | ||
var sourceCode = context.getSourceCode(), | ||
alwaysSpace = context.options[0] === "always"; | ||
|
||
//-------------------------------------------------------------------------- | ||
// Helpers | ||
//-------------------------------------------------------------------------- | ||
|
||
/** | ||
* Checks whitespace between rest/spread operators and their expressions | ||
* @param {ASTNode} node - The node to check | ||
* @returns {void} | ||
*/ | ||
function checkWhiteSpace(node) { | ||
var operator = sourceCode.getFirstToken(node), | ||
nextToken = sourceCode.getTokenAfter(operator), | ||
hasWhitespace = sourceCode.isSpaceBetweenTokens(operator, nextToken), | ||
type; | ||
|
||
switch (node.type) { | ||
case "SpreadElement": | ||
type = "spread"; | ||
break; | ||
case "RestElement": | ||
type = "rest"; | ||
break; | ||
case "ExperimentalSpreadProperty": | ||
type = "spread property"; | ||
break; | ||
case "ExperimentalRestProperty": | ||
type = "rest property"; | ||
break; | ||
default: | ||
return; | ||
} | ||
|
||
if (alwaysSpace && !hasWhitespace) { | ||
context.report({ | ||
node: node, | ||
loc: { | ||
line: operator.loc.end.line, | ||
column: operator.loc.end.column | ||
}, | ||
message: "Expected whitespace after {{type}} operator", | ||
data: { | ||
type: type | ||
}, | ||
fix: function(fixer) { | ||
return fixer.replaceTextRange([operator.range[1], nextToken.range[0]], " "); | ||
} | ||
}); | ||
} else if (!alwaysSpace && hasWhitespace) { | ||
context.report({ | ||
node: node, | ||
loc: { | ||
line: operator.loc.end.line, | ||
column: operator.loc.end.column | ||
}, | ||
message: "Unexpected whitespace after {{type}} operator", | ||
data: { | ||
type: type | ||
}, | ||
fix: function(fixer) { | ||
return fixer.removeRange([operator.range[1], nextToken.range[0]]); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
//-------------------------------------------------------------------------- | ||
// Public | ||
//-------------------------------------------------------------------------- | ||
|
||
return { | ||
SpreadElement: checkWhiteSpace, | ||
RestElement: checkWhiteSpace, | ||
ExperimentalSpreadProperty: checkWhiteSpace, | ||
ExperimentalRestProperty: checkWhiteSpace | ||
}; | ||
} | ||
}; |
Oops, something went wrong.