Navigation Menu

Skip to content

Commit

Permalink
Breaking: merges keyword spacing rules (fixes #3869)
Browse files Browse the repository at this point in the history
Also refs #1338, fixes #3878, fixes #4006, fixes #4585.

This commit creates a new rule: `keyword-spacing` (merged from
`space-after-keywords`, `space-before-keywords`, and
`space-return-throw-case`).

- `keyword-spacing` rule ignores usage of spacing at some places to not
conflict other spacing rules.
- `keyword-spacing` rule has `"overrides"` option to configure more
preference.
  • Loading branch information
mysticatea committed Jan 5, 2016
1 parent 009a949 commit c07ca39
Show file tree
Hide file tree
Showing 11 changed files with 3,577 additions and 5 deletions.
1 change: 1 addition & 0 deletions conf/eslint.json
Expand Up @@ -153,6 +153,7 @@
"init-declarations": 0,
"jsx-quotes": [0, "prefer-double"],
"key-spacing": [0, { "beforeColon": false, "afterColon": true }],
"keyword-spacing": 0,
"lines-around-comment": 0,
"max-depth": [0, 4],
"max-len": [0, 80, 4],
Expand Down
3 changes: 3 additions & 0 deletions conf/replacements.json
Expand Up @@ -10,8 +10,11 @@
"no-space-before-semi": ["semi-spacing"],
"no-wrap-func": ["no-extra-parens"],
"space-after-function-name": ["space-before-function-paren"],
"space-after-keywords": ["keyword-spacing"],
"space-before-function-parentheses": ["space-before-function-paren"],
"space-before-keywords": ["keyword-spacing"],
"space-in-brackets": ["object-curly-spacing", "array-bracket-spacing", "computed-property-spacing"],
"space-return-throw-case": ["keyword-spacing"],
"space-unary-word-ops": ["space-unary-ops"],
"spaced-line-comment": ["spaced-comment"]
}
Expand Down
7 changes: 4 additions & 3 deletions docs/rules/README.md
Expand Up @@ -160,6 +160,7 @@ These rules are purely matters of style and are quite subjective.
* [indent](indent.md) - specify tab or space width for your code (fixable)
* [jsx-quotes](jsx-quotes.md) - specify whether double or single quotes should be used in JSX attributes
* [key-spacing](key-spacing.md) - enforce spacing between keys and values in object literal properties
* [keyword-spacing](keyword-spacing.md) - enforce spacing before and after keywords (fixable)
* [linebreak-style](linebreak-style.md) - disallow mixed 'LF' and 'CRLF' as linebreaks
* [lines-around-comment](lines-around-comment.md) - enforce empty lines around comments
* [max-depth](max-depth.md) - specify the maximum depth that blocks can be nested
Expand Down Expand Up @@ -199,13 +200,10 @@ These rules are purely matters of style and are quite subjective.
* [semi-spacing](semi-spacing.md) - enforce spacing before and after semicolons (fixable)
* [semi](semi.md) - require or disallow use of semicolons instead of ASI (fixable)
* [sort-vars](sort-vars.md) - sort variables within the same declaration block
* [space-after-keywords](space-after-keywords.md) - require a space after certain keywords (fixable)
* [space-before-blocks](space-before-blocks.md) - require or disallow a space before blocks (fixable)
* [space-before-function-paren](space-before-function-paren.md) - require or disallow a space before function opening parenthesis (fixable)
* [space-before-keywords](space-before-keywords.md) - require a space before certain keywords (fixable)
* [space-in-parens](space-in-parens.md) - require or disallow spaces inside parentheses
* [space-infix-ops](space-infix-ops.md) - require spaces around operators (fixable)
* [space-return-throw-case](space-return-throw-case.md) - require a space after `return`, `throw`, and `case` (fixable)
* [space-unary-ops](space-unary-ops.md) - require or disallow spaces before/after unary operators (fixable)
* [spaced-comment](spaced-comment.md) - require or disallow a space immediately following the `//` or `/*` in a comment
* [wrap-regex](wrap-regex.md) - require regex literals to be wrapped in parentheses
Expand Down Expand Up @@ -251,7 +249,10 @@ These rules existed in a previous version of ESLint but have since been replaced
* [no-space-before-semi](no-space-before-semi.md) - disallow space before semicolon (replaced by [semi-spacing](semi-spacing.md))
* [no-wrap-func](no-wrap-func.md) - disallow wrapping of non-IIFE statements in parens (replaced by [no-extra-parens](no-extra-parens.md))
* [space-after-function-name](space-after-function-name.md) - require a space after function names (replaced by [space-before-function-paren](space-before-function-paren.md))
* [space-after-keywords](space-after-keywords.md) - require a space after certain keywords (fixable) (replaced by [keyword-spacing](keyword-spacing.md))
* [space-before-function-parentheses](space-before-function-parentheses.md) - require or disallow space before function parentheses (replaced by [space-before-function-paren](space-before-function-paren.md))
* [space-before-keywords](space-before-keywords.md) - require a space before certain keywords (fixable) (replaced by [keyword-spacing](keyword-spacing.md))
* [space-in-brackets](space-in-brackets.md) - require or disallow spaces inside brackets (replaced by [object-curly-spacing](object-curly-spacing.md) and [array-bracket-spacing](array-bracket-spacing.md))
* [space-return-throw-case](space-return-throw-case.md) - require a space after `return`, `throw`, and `case` (fixable) (replaced by [keyword-spacing](keyword-spacing.md))
* [space-unary-word-ops](space-unary-word-ops.md) - require or disallow spaces before/after unary operators (replaced by [space-unary-ops](space-unary-ops.md))
* [spaced-line-comment](spaced-line-comment.md) - require or disallow a space immediately following the `//` in a line comment (replaced by [spaced-comment](spaced-comment.md))
321 changes: 321 additions & 0 deletions docs/rules/keyword-spacing.md
@@ -0,0 +1,321 @@
# Enforce spacing before and after keywords (keyword-spacing)

Keywords are syntax elements of JavaScript, such as `function` and `if`.
These identifiers have special meaning to the language and so often appear in a different color in code editors.
As an important part of the language, style guides often refer to the spacing that should be used around keywords.
For example, you might have a style guide that says keywords should be always surrounded by spaces, which would mean `if-else` statements must look like this:

```js
if (foo) {
// ...
} else {
// ...
}
```

Of course, you could also have a style guide that disallows spaces around keywords.

**Fixable:** This rule is automatically fixable using the `--fix` flag on the command line.

## Rule Details

This rule will enforce consistency of spacing around keywords and keyword-like tokens: `as` (in module declarations), `break`, `case`, `catch`, `class`, `const`, `continue`, `debugger`, `default`, `delete`, `do`, `else`, `export`, `extends`, `finally`, `for`, `from` (in module declarations), `function`, `get` (of getters), `if`, `import`, `in`, `instanceof`, `let`, `new`, `of` (in for-of statements), `return`, `set` (of setters), `static`, `super`, `switch`, `this`, `throw`, `try`, `typeof`, `var`, `void`, `while`, `with`, and `yield`.

The following patterns are considered problems:

```js
/*eslint keyword-spacing: 2*/
/*eslint-env es6*/

if(foo){ /*error Expected space(s) after "if".*/
//...
}else if (bar) { /*error Expected space(s) before "else".*/
//...
} else{ /*error Expected space(s) after "else".*/
//...
}

try{ /*error Expected space(s) after "try".*/
//...
}catch(e) { /*error Expected space(s) before "catch".*/
/*error Expected space(s) after "catch".*/
//...
}

switch (a) {
case+1: /*error Expected space(s) after "case".*/
break;
}

function foo() {
return[0, 1, 2]; /*error Expected space(s) after "return".*/
}

for (let[a, b]of[foo, bar, baz]) { /*error Expected space(s) after "let".*/
/*error Expected space(s) before "of".*/
/*error Expected space(s) after "of".*/
//...
}

let obj = {
get[FOO]() { /*error Expected space(s) after "get".*/
//...
},
set[FOO](value) { /*error Expected space(s) after "set".*/
//...
}
};

import{foo}from"foo"; /*error Expected space(s) after "import".*/
/*error Expected space(s) before "from".*/
/*error Expected space(s) after "from".*/
import*as bar from "foo"; /*error Expected space(s) after "import".*/
/*error Expected space(s) before "as".*/
```

The following patterns are considered not problems:

```js
/*eslint keyword-spacing: 2*/
/*eslint-env es6*/

if (foo) {
//...
} else if (bar) {
//...
} else {
//...
}

try {
//...
} catch (e) {
//...
}

switch (a) {
case +1:
break;
}

function foo() {
return [0, 1, 2];
}

for (let [a, b] of [foo, bar, baz]) {
//...
}

let obj = {
get [FOO]() {
//...
},
set [FOO](value) {
//...
}
};

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

This rule is designed carefully to not conflict with other spacing rules.
Basically this rule ignores usage of spacing at places that other rules are catching.
So the following patterns are considered not problems.

```js
/*eslint keyword-spacing: 2*/
/*eslint-env es6*/

// not conflict with `array-bracket-spacing`
let a = [this];
let b = [function() {}];

// not conflict with `arrow-spacing`
let a = () =>this.foo;

// not conflict with `block-spacing`
{function foo() {}}

// not conflict with `comma-spacing`
let a = [100,this.foo, this.bar];

// not conflict with `computed-property-spacing`
obj[this.foo] = 0;

// not conflict with `generator-star-spacing`
function* foo() {}

// not conflict with `key-spacing`
let obj = {
foo:function() {}
};

// not conflict with `no-spaced-func`
class A {
constructor() {
super();
}
}

// not conflict with `object-curly-spacing`
let obj = {foo: this};

// not conflict with `semi-spacing`
let a = this;function foo() {}

// not conflict with `space-before-function-paren`
// not conflict with `space-in-parens`
(function() {})();

// not conflict with `space-infix-ops`
if ("foo"in{foo: 0}) {}
if (10+this.foo <=this.bar) {}

// not conflict with `space-unary-ops`
function* foo(a) {
return yield+a;
}

// not conflict with `yield-star-spacing`
function* foo(a) {
return yield* a;
}

// not conflict with `jsx-curly-spacing`
let a = <A foo={this.foo} bar={function(){}} />
```


### Options

This rule has 3 options.

```json
{
"keyword-spacing": [2, {"before": true, "after": true, "overrides": null}]
}
```

- `"before"` (`boolean`, default is `true`) -
This option specifies usage of spacing before the keywords.
If `true` then the keywords must be preceded by at least one space.
Otherwise, no spaces will be allowed before the keywords (if possible).
- `"after"` (`boolean`, default is `true`) -
This option specifies usage of spacing after the keywords.
If `true` then the keywords must be followed by at least one space.
Otherwise, no spaces will be allowed after the keywords (if possible).
- `"overrides"` (`object`, default is `null`) -
This option specifies overwriting usage of spacing for each keyword.
For Example:

```json
{
"keyword-spacing": [2, {"overrides": {
"if": {"after": false},
"for": {"after": false},
"while": {"after": false}
}}]
}
```

In this case, no spaces will be allowed only after `if`, `for`, and `while`.

The following patterns are considered problems when configured `{"before": false, "after": false}`:

```js
/*eslint keyword-spacing: [2, {before: false, after: false}]*/
/*eslint-env es6*/

if (foo){ /*error Unexpected space(s) after "if".*/
//...
} else if(bar) { /*error Unexpected space(s) before "else".*/
//...
}else { /*error Unexpected space(s) after "else".*/
//...
}

try { /*error Unexpected space(s) after "try".*/
//...
} catch (e) { /*error Unexpected space(s) before "catch".*/
/*error Unexpected space(s) after "catch".*/
//...
}

switch(a) {
case +1: /*error Unexpected space(s) after "case".*/
break;
}

function foo() {
return [0, 1, 2]; /*error Unexpected space(s) after "return".*/
}

for (let [a, b] of [foo, bar, baz]) { /*error Unexpected space(s) after "let".*/
/*error Unexpected space(s) before "of".*/
/*error Unexpected space(s) after "of".*/
//...
}

let obj = {
get [FOO]() { /*error Unexpected space(s) after "get".*/
//...
},
set [FOO](value) { /*error Unexpected space(s) after "set".*/
//...
}
};

import {foo} from "foo"; /*error Unexpected space(s) after "import".*/
/*error Unexpected space(s) before "from".*/
/*error Unexpected space(s) after "from".*/
import * as bar from"foo"; /*error Unexpected space(s) after "import".*/
/*error Unexpected space(s) before "as".*/
```

The following patterns are considered not problems when configured `{"before": false, "after": false}`:

```js
/*eslint keyword-spacing: [2, {before: false, after: false}]*/
/*eslint-env es6*/

if(foo) {
//...
}else if(bar) {
//...
}else{
//...
}

try{
//...
}catch(e) {
//...
}

switch(a) {
case+1:
break;
}

function foo() {
return[0, 1, 2];
}

for(let[a, b]of[foo, bar, baz]) {
//...
}

let obj = {
get[FOO]() {
//...
},
set[FOO](value) {
//...
}
};
```

## When Not To Use It

If you don't want to enforce consistency on keyword spacing, then it's safe to disable this rule.
2 changes: 2 additions & 0 deletions docs/rules/space-after-keywords.md
@@ -1,5 +1,7 @@
# Require or disallow spaces following keywords (space-after-keywords)

**Replacement notice**: This rule was removed in ESLint v2.0 and replaced by [keyword-spacing](keyword-spacing.md) rule.

Some style guides will require or disallow spaces following the certain keywords.

```js
Expand Down
2 changes: 2 additions & 0 deletions docs/rules/space-before-keywords.md
@@ -1,5 +1,7 @@
# Require or disallow spaces before keywords (space-before-keywords)

**Replacement notice**: This rule was removed in ESLint v2.0 and replaced by [keyword-spacing](keyword-spacing.md) rule.

Keywords are syntax elements of JavaScript, such as `function` and `if`. These identifiers have special meaning to the language and so often appear in a different color in code editors. As an important part of the language, style guides often refer to the spacing that should be used around keywords. For example, you might have a style guide that says keywords should be always be preceded by spaces, which would mean `if-else` statements must look like this:

```js
Expand Down
2 changes: 2 additions & 0 deletions docs/rules/space-return-throw-case.md
@@ -1,5 +1,7 @@
# Require spaces following `return`, `throw`, and `case` (space-return-throw-case)

**Replacement notice**: This rule was removed in ESLint v2.0 and replaced by [keyword-spacing](keyword-spacing.md) rule.

Require spaces following `return`, `throw`, and `case`.

**Fixable:** This rule is automatically fixable using the `--fix` flag on the command line.
Expand Down

0 comments on commit c07ca39

Please sign in to comment.