Skip to content

Commit

Permalink
Fix: support boundary spread elements in sort-keys
Browse files Browse the repository at this point in the history
  • Loading branch information
P0lip committed Dec 4, 2018
1 parent 62fd2b9 commit 25c0224
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/rules/sort-keys.md
Expand Up @@ -53,7 +53,7 @@ let obj = {a: 1, ["c" + "d"]: 3, b: 2};
let obj = {a: 1, [`${c}`]: 3, b: 2};
let obj = {a: 1, [tag`c`]: 3, b: 2};

// This rule ignores objects that have a spread operator in them.
// This rule ignores objects that have a non-boundary spread operator in them.
let obj = {b: 1, ...c, a: 2};
```

Expand Down
40 changes: 37 additions & 3 deletions lib/rules/sort-keys.js
Expand Up @@ -115,11 +115,45 @@ module.exports = {
// The stack to save the previous property's name for each object literals.
let stack = null;

/**
* Checks if object contains non-boundary spread elements
* @param {ASTNode} node - The node to check.
* @returns {boolean} node has non-boundary spread elements
* @private
*/
function hasNonBoundarySpreadElement(node) {

// if object contains 2 or fewer properties a spread element will always be boundary
if (node.properties.length < 3) {
return false;
}

let previousType = node.properties[0].type;
let mustBeSpread = false;

for (let i = 1; i < node.properties.length; i++) {
const property = node.properties[i];

if (mustBeSpread && property.type !== "SpreadElement") {
return true;
}

if (!mustBeSpread && previousType !== "SpreadElement" && property.type === "SpreadElement") {
mustBeSpread = true;
}

previousType = property.type;
}

return false;
}

return {
ObjectExpression() {
ObjectExpression(node) {
stack = {
upper: stack,
prevName: null
prevName: null,
hasNonBoundarySpread: hasNonBoundarySpreadElement(node)
};
},

Expand All @@ -128,7 +162,7 @@ module.exports = {
},

Property(node) {
if (node.parent.type === "ObjectPattern" || node.parent.properties.some(n => n.type === "SpreadElement")) {
if (node.parent.type === "ObjectPattern" || stack.hasNonBoundarySpread || node.type === "SpreadElement") {
return;
}

Expand Down
39 changes: 38 additions & 1 deletion tests/lib/rules/sort-keys.js
Expand Up @@ -33,10 +33,15 @@ ruleTester.run("sort-keys", rule, {
// ignore non-simple computed properties.
{ code: "var obj = {a:1, b:3, [a + b]: -1, c:2}", options: [], parserOptions: { ecmaVersion: 6 } },

// ignore spread properties.
// ignore non-boundary spread properties.
{ code: "var obj = {a:1, ...z, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
{ code: "var obj = {b:1, ...z, a:1}", options: [], parserOptions: { ecmaVersion: 2018 } },

// boundary spread properties
{ code: "var obj = {...z, a:1, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
{ code: "var obj = {...z, ...c, a:1, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
{ code: "var obj = {a:1, b:1, ...z}", options: [], parserOptions: { ecmaVersion: 2018 } },

// ignore destructuring patterns.
{ code: "let {a, b} = {}", options: [], parserOptions: { ecmaVersion: 6 } },

Expand Down Expand Up @@ -151,6 +156,38 @@ ruleTester.run("sort-keys", rule, {
errors: ["Expected object keys to be in ascending order. 'Z' should be before 'À'."]
},

// not ignore boundary spread properties
{
code: "var obj = {...z, c:1, b:1}",
options: [],
parserOptions: { ecmaVersion: 2018 },
errors: ["Expected object keys to be in ascending order. 'b' should be before 'c'."]
},
{
code: "var obj = {c:1, b:1, ...a}",
options: [],
parserOptions: { ecmaVersion: 2018 },
errors: ["Expected object keys to be in ascending order. 'b' should be before 'c'."]
},
{
code: "var obj = {...z, ...a, c:1, b:1}",
options: [],
parserOptions: { ecmaVersion: 2018 },
errors: ["Expected object keys to be in ascending order. 'b' should be before 'c'."]
},
{
code: "var obj = {...z, b:1, a:1, ...d, ...c}",
options: [],
parserOptions: { ecmaVersion: 2018 },
errors: ["Expected object keys to be in ascending order. 'a' should be before 'b'."]
},
{
code: "var obj = {...z, a:2, b:0, ...x, ...c}",
options: ["desc"],
parserOptions: { ecmaVersion: 2018 },
errors: ["Expected object keys to be in descending order. 'b' should be before 'a'."]
},

// not ignore simple computed properties.
{
code: "var obj = {a:1, b:3, [a]: -1, c:2}",
Expand Down

0 comments on commit 25c0224

Please sign in to comment.