Skip to content

Commit

Permalink
Update: Adds an avoidQuotes option for object-shorthand (fixes #3366) (
Browse files Browse the repository at this point in the history
  • Loading branch information
lemonmade authored and nzakas committed May 4, 2016
1 parent a9a4652 commit 3c44c2c
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 2 deletions.
31 changes: 31 additions & 0 deletions docs/rules/object-shorthand.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,37 @@ You can set the option in configuration like this:
}
```

While set to `"always"`, `"methods"`, or `"properties"`, shorthand syntax using string literal keys can be ignored using the optional parameter `"avoidQuotes"`. This will make it so longform syntax is preferred whenever the object key is a string literal. Note: The first parameter must be specified when using this optional parameter.

```json
{
"object-shorthand": ["error", "always", { "avoidQuotes": true }]
}
```

Examples of **incorrect** code for this rule with the `"avoidQuotes"` option:

```js
/*eslint object-shorthand: ["error", "always", { "avoidQuotes": true }]*/
/*eslint-env es6*/

var foo = {
"bar-baz"() {}
};
```

Examples of **correct** code for this rule with the `"avoidQuotes"` option:

```js
/*eslint object-shorthand: ["error", "always", { "avoidQuotes": true }]*/
/*eslint-env es6*/

var foo = {
"bar-baz": function() {},
"qux": qux
};
```

While set to `"always"` or `"methods"`, constructor functions can be ignored with the optional parameter `"ignoreConstructors"` enabled. Note: The first parameter must be specified when using this optional parameter.

```json
Expand Down
39 changes: 38 additions & 1 deletion lib/rules/object-shorthand.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ module.exports = {
minItems: 0,
maxItems: 1
},
{
type: "array",
items: [
{
enum: ["always", "methods", "properties"]
},
{
type: "object",
properties: {
avoidQuotes: {
type: "boolean"
}
},
additionalProperties: false
}
],
minItems: 0,
maxItems: 2
},
{
type: "array",
items: [
Expand All @@ -46,6 +65,9 @@ module.exports = {
properties: {
ignoreConstructors: {
type: "boolean"
},
avoidQuotes: {
type: "boolean"
}
},
additionalProperties: false
Expand All @@ -66,6 +88,7 @@ module.exports = {

var PARAMS = context.options[1] || {};
var IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors;
var AVOID_QUOTES = PARAMS.avoidQuotes;

//--------------------------------------------------------------------------
// Helpers
Expand All @@ -83,6 +106,15 @@ module.exports = {
return firstChar === firstChar.toUpperCase();
}

/**
* Checks whether a node is a string literal.
* @param {ASTNode} node - Any AST node.
* @returns {boolean} `true` if it is a string literal.
*/
function isStringLiteral(node) {
return node.type === "Literal" && typeof node.value === "string";
}

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
Expand All @@ -103,8 +135,13 @@ module.exports = {
context.report(node, "Expected longform " + type + " syntax.");
}

// {'xyz'() {}} should be written as {'xyz': function() {}}
if (AVOID_QUOTES && isStringLiteral(node.key) && isConciseProperty) {
context.report(node, "Expected longform method syntax for string literal keys.");
}

// at this point if we're concise or if we're "never" we can leave
if (APPLY_NEVER || isConciseProperty) {
if (APPLY_NEVER || AVOID_QUOTES || isConciseProperty) {
return;
}

Expand Down
11 changes: 10 additions & 1 deletion tests/lib/rules/object-shorthand.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ ruleTester.run("object-shorthand", rule, {
{ code: "var x = {ConstructorFunction: function(){}, a: b}", parserOptions: { ecmaVersion: 6 }, options: ["never"] },
{ code: "var x = {notConstructorFunction: function(){}, b: c}", parserOptions: { ecmaVersion: 6 }, options: ["never"] },

// avoidQuotes
{ code: "var x = {'a': function(){}}", parserOptions: { ecmaVersion: 6 }, options: ["always", {avoidQuotes: true}] },
{ code: "var x = {['a']: function(){}}", parserOptions: { ecmaVersion: 6 }, options: ["methods", {avoidQuotes: true}] },
{ code: "var x = {'y': y}", parserOptions: { ecmaVersion: 6 }, options: ["properties", {avoidQuotes: true}] },

// ignore object shorthand
{ code: "let {a, b} = o;", parserOptions: { ecmaVersion: 6 }, options: ["never"] }
],
Expand Down Expand Up @@ -121,6 +126,10 @@ ruleTester.run("object-shorthand", rule, {
{ code: "var x = {y, a: b, *x(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }, { message: "Expected longform method syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {y: {x}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform property syntax.", type: "Property" }], options: ["never"]},
{ code: "var x = {ConstructorFunction(){}, a: b}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },
{ code: "var x = {notConstructorFunction(){}, b: c}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] }
{ code: "var x = {notConstructorFunction(){}, b: c}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax.", type: "Property" }], options: ["never"] },

// avoidQuotes
{ code: "var x = {'a'(){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax for string literal keys.", type: "Property" }], options: ["always", {avoidQuotes: true}] },
{ code: "var x = {['a'](){}}", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected longform method syntax for string literal keys.", type: "Property" }], options: ["methods", {avoidQuotes: true}] }
]
});

0 comments on commit 3c44c2c

Please sign in to comment.