Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update: add indent options for array and object literals (fixes #7473
…) (#7681)

* Update: add `indent` options for array and object literals (fixes #7473)

* Fix crash with empty arrays
  • Loading branch information
not-an-aardvark committed Dec 8, 2016
1 parent 7079c89 commit b921d1f
Show file tree
Hide file tree
Showing 3 changed files with 383 additions and 15 deletions.
95 changes: 95 additions & 0 deletions docs/rules/indent.md
Expand Up @@ -82,6 +82,8 @@ This rule has an object option:
* `body` (default: 1) enforces indentation level for the body of a function expression.
* `"CallExpression"` takes an object to define rules for function call expressions.
* `arguments` (off by default) enforces indentation level for arguments in a call expression. This can either be a number indicating indentation level, or the string `"first"` indicating that all arguments of the expression must be aligned with the first argument.
* `"ArrayExpression"` (default: 1) enforces indentation level for elements in arrays. It can also be set to the string `"first"`, indicating that all the elements in the array should be aligned with the first element.
* `"ObjectExpression"` (default: 1) enforces indentation level for properties in objects. It can be set to the string `"first"`, indicating that all properties in the object should be aligned with the first property.

Level of indentation denotes the multiple of the indent specified. Example:

Expand Down Expand Up @@ -430,6 +432,99 @@ foo(bar, baz,
baz, boop, beep);
```

### ArrayExpression

Examples of **incorrect** code for this rule with the `2, { "ArrayExpression": 1 }` option:

```js
/*eslint indent: ["error", 2, { "ArrayExpression": 1 }]*/

var foo = [
bar,
baz,
qux
];
```

Examples of **correct** code for this rule with the `2, { "ArrayExpression": 1 }` option:

```js
/*eslint indent: ["error", 2, { "ArrayExpression": 1 }]*/

var foo = [
bar,
baz,
qux
];
```

Examples of **incorrect** code for this rule with the `2, { "ArrayExpression": "first" }` option:

```js
/*eslint indent: ["error", 2, {"ArrayExpression": "first"}]*/

var foo = [bar,
baz,
qux
];
```

Examples of **correct** code for this rule with the `2, { "ArrayExpression": "first" }` option:

```js
/*eslint indent: ["error", 2, {"ArrayExpression": "first"}]*/

var foo = [bar,
baz,
qux
];
```

### ObjectExpression

Examples of **incorrect** code for this rule with the `2, { "ObjectExpression": 1 }` option:

```js
/*eslint indent: ["error", 2, { "ObjectExpression": 1 }]*/

var foo = {
bar: 1,
baz: 2,
qux: 3
};
```

Examples of **correct** code for this rule with the `2, { "ObjectExpression": 1 }` option:

```js
/*eslint indent: ["error", 2, { "ObjectExpression": 1 }]*/

var foo = {
bar: 1,
baz: 2,
qux: 3
};
```

Examples of **incorrect** code for this rule with the `2, { "ObjectExpression": "first" }` option:

```js
/*eslint indent: ["error", 2, {"ObjectExpression": "first"}]*/

var foo = { bar: 1,
baz: 2 };
```

Examples of **correct** code for this rule with the `2, { "ObjectExpression": "first" }` option:

```js
/*eslint indent: ["error", 2, {"ObjectExpression": "first"}]*/

var foo = { bar: 1,
baz: 2 };
```


## Compatibility

* **JSHint**: `indent`
Expand Down
60 changes: 46 additions & 14 deletions lib/rules/indent.js
Expand Up @@ -129,6 +129,28 @@ module.exports = {
]
}
}
},
ArrayExpression: {
oneOf: [
{
type: "integer",
minimum: 0
},
{
enum: ["first"]
}
]
},
ObjectExpression: {
oneOf: [
{
type: "integer",
minimum: 0
},
{
enum: ["first"]
}
]
}
},
additionalProperties: false
Expand Down Expand Up @@ -161,7 +183,9 @@ module.exports = {
},
CallExpression: {
arguments: DEFAULT_PARAMETER_INDENT
}
},
ArrayExpression: 1,
ObjectExpression: 1
};

const sourceCode = context.getSourceCode();
Expand Down Expand Up @@ -210,6 +234,14 @@ module.exports = {
if (typeof opts.CallExpression === "object") {
Object.assign(options.CallExpression, opts.CallExpression);
}

if (typeof opts.ArrayExpression === "number" || typeof opts.ArrayExpression === "string") {
options.ArrayExpression = opts.ArrayExpression;
}

if (typeof opts.ObjectExpression === "number" || typeof opts.ObjectExpression === "string") {
options.ObjectExpression = opts.ObjectExpression;
}
}
}

Expand Down Expand Up @@ -694,27 +726,27 @@ module.exports = {
if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) {
nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
} else if (
parent.type === "ObjectExpression" ||
parent.type === "ArrayExpression" ||
parent.type === "CallExpression" ||
parent.type === "ArrowFunctionExpression" ||
parent.type === "NewExpression" ||
parent.type === "LogicalExpression"
) {
nodeIndent = nodeIndent + indentSize;
} else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") {
nodeIndent += options[parent.type] * indentSize;
} else if (parent.type === "CallExpression" || parent.type === "NewExpression") {
nodeIndent += (typeof options.CallExpression.arguments === "number" ? options.CallExpression.arguments : 1) * indentSize;
} else if (parent.type === "LogicalExpression" || parent.type === "ArrowFunctionExpression") {
nodeIndent += indentSize;
}
}
} else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") {
nodeIndent = nodeIndent + indentSize;
}

elementsIndent = nodeIndent + indentSize;

checkFirstNodeLineIndent(node, nodeIndent);
} else {
nodeIndent = getNodeIndent(node).goodChar;
elementsIndent = nodeIndent + indentSize;
}

if (options[node.type] === "first") {
elementsIndent = elements.length ? elements[0].loc.start.column : 0; // If there are no elements, elementsIndent doesn't matter.
} else {
elementsIndent = nodeIndent + indentSize * options[node.type];
}

/*
Expand All @@ -735,7 +767,7 @@ module.exports = {
}
}

checkLastNodeLineIndent(node, elementsIndent - indentSize);
checkLastNodeLineIndent(node, nodeIndent + (isNodeInVarOnTop(node, parentVarNode) ? options.VariableDeclarator[parentVarNode.parent.kind] * indentSize : 0));
}

/**
Expand Down

0 comments on commit b921d1f

Please sign in to comment.