Skip to content

Commit

Permalink
Merge pull request #2727 from xjamundx/computed-prop-spacing
Browse files Browse the repository at this point in the history
New: computed-property-spacing (part of #2226)
  • Loading branch information
ilyavolodin committed Jun 11, 2015
2 parents 531fffa + 8bc6ce9 commit 029f26d
Show file tree
Hide file tree
Showing 5 changed files with 557 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/eslint.json
Expand Up @@ -119,6 +119,7 @@
"comma-spacing": 2,
"comma-style": 0,
"complexity": [0, 11],
"computed-property-spacing": [0, "never"],
"consistent-return": 2,
"consistent-this": [0, "that"],
"curly": [2, "all"],
Expand Down
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -136,6 +136,7 @@ These rules are purely matters of style and are quite subjective.
* [camelcase](camelcase.md) - require camel case names
* [comma-spacing](comma-spacing.md) - enforce spacing before and after comma
* [comma-style](comma-style.md) - enforce one true comma style (off by default)
* [computed-property-spacing](computed-property-spacing.md) - require or disallow padding inside computed properties (off by default)
* [consistent-this](consistent-this.md) - enforces consistent naming when capturing the current execution context (off by default)
* [eol-last](eol-last.md) - enforce newline at the end of file, with no multiple empty lines
* [func-names](func-names.md) - require function expressions to have a name (off by default)
Expand Down
91 changes: 91 additions & 0 deletions docs/rules/computed-property-spacing.md
@@ -0,0 +1,91 @@
# Disallow or enforce spaces inside of computed properties. (computed-property-spacing)

While formatting preferences are very personal, a number of style guides require
or disallow spaces between computed properties in the following situations:

```js
// computed properties
var obj = { prop: "value" };
var a = "prop";
var x = obj[a];

// object literal computed properties (EcmaScript 6)
var a = "prop";
var obj = { [a]: "value" };
```

## Rule Details

This rule aims to maintain consistency around the spacing inside of computed properties.

It either requires or disallows spaces between the brackets and the values inside of them.
Brackets that are separated from the adjacent value by a new line are exempt from this rule.

### Options

There are two main options for the rule:

* `"always"` enforces a space inside of computed properties
* `"never"` disallows spaces inside of computed properties (default)

Depending on your coding conventions, you can choose either option by specifying it in your configuration:

```json
"computed-property-spacing": [2, "never"]
```

#### never

When `"never"` is set, the following patterns are considered correct:

```js
obj[foo]
obj['foo']
var x = {[b]: a}
obj[foo[bar]]
```

The following patterns will warn:

```js
obj[foo ]
obj[ 'foo']
var x = {[ b ]: a}
obj[foo[ bar ]]
```

#### always

When `"always"` is used, the following patterns are considered correct:

```js
obj[ foo ]
obj[ 'foo' ]
var x = {[ b ]: a}
obj[ foo[ bar ] ]

```

The following patterns will warn:

```js
obj[foo]
var x = {[b]: a}
obj[ foo]
obj[ foo ]
obj['foo' ]
obj[foo[ bar ]]
var x = {[ b]: a}
```

## When Not To Use It

You can turn this rule off if you are not concerned with the consistency of computed properties.

## Related Rules

* [comma-spacing](comma-spacing.md)
* [space-in-parens](space-in-parens.md)
* [curly-braces-spacing](curly-braces-spacing.md)
* [space-in-brackets](space-in-brackets.md) (deprecated)

144 changes: 144 additions & 0 deletions lib/rules/computed-property-spacing.js
@@ -0,0 +1,144 @@
/**
* @fileoverview Disallows or enforces spaces inside computed properties.
* @author Jamund Ferguson
* @copyright 2015 Jamund Ferguson. All rights reserved.
*/
"use strict";

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

module.exports = function(context) {
var propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"

//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------

/**
* Determines whether two adjacent tokens are have whitespace between them.
* @param {Object} left - The left token object.
* @param {Object} right - The right token object.
* @returns {boolean} Whether or not there is space between the tokens.
*/
function isSpaced(left, right) {
return left.range[1] < right.range[0];
}

/**
* Determines whether two adjacent tokens are on the same line.
* @param {Object} left - The left token object.
* @param {Object} right - The right token object.
* @returns {boolean} Whether or not the tokens are on the same line.
*/
function isSameLine(left, right) {
return left.loc.start.line === right.loc.start.line;
}

/**
* Reports that there shouldn't be a space after the first token
* @param {ASTNode} node - The node to report in the event of an error.
* @param {Token} token - The token to use for the report.
* @returns {void}
*/
function reportNoBeginningSpace(node, token) {
context.report(node, token.loc.start,
"There should be no space after '" + token.value + "'");
}

/**
* Reports that there shouldn't be a space before the last token
* @param {ASTNode} node - The node to report in the event of an error.
* @param {Token} token - The token to use for the report.
* @returns {void}
*/
function reportNoEndingSpace(node, token) {
context.report(node, token.loc.start,
"There should be no space before '" + token.value + "'");
}

/**
* Reports that there should be a space after the first token
* @param {ASTNode} node - The node to report in the event of an error.
* @param {Token} token - The token to use for the report.
* @returns {void}
*/
function reportRequiredBeginningSpace(node, token) {
context.report(node, token.loc.start,
"A space is required after '" + token.value + "'");
}

/**
* Reports that there should be a space before the last token
* @param {ASTNode} node - The node to report in the event of an error.
* @param {Token} token - The token to use for the report.
* @returns {void}
*/
function reportRequiredEndingSpace(node, token) {
context.report(node, token.loc.start,
"A space is required before '" + token.value + "'");
}

/**
* Returns a function that checks the spacing of a node on the property name
* that was passed in.
* @param {String} propertyName The property on the node to check for spacing
* @returns {Function} A function that will check spacing on a node
*/
function checkSpacing(propertyName) {
return function(node) {
if (!node.computed) {
return;
}

var property = node[propertyName];

var before = context.getTokenBefore(property),
first = context.getFirstToken(property),
last = context.getLastToken(property),
after = context.getTokenAfter(property);

if (isSameLine(before, first)) {
if (propertyNameMustBeSpaced) {
if (!isSpaced(before, first) && isSameLine(before, first)) {
reportRequiredBeginningSpace(node, before);
}
} else {
if (isSpaced(before, first)) {
reportNoBeginningSpace(node, before);
}
}
}

if (isSameLine(last, after)) {
if (propertyNameMustBeSpaced) {
if (!isSpaced(last, after) && isSameLine(last, after)) {
reportRequiredEndingSpace(node, after);
}
} else {
if (isSpaced(last, after)) {
reportNoEndingSpace(node, after);
}
}
}
};
}


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

return {
Property: checkSpacing("key"),
MemberExpression: checkSpacing("property")
};

};

module.exports.schema = [
{
"enum": ["always", "never"]
}
];

0 comments on commit 029f26d

Please sign in to comment.