Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: add option first for VariableDeclarator in indent (fixes #8976) #11193

Merged
merged 3 commits into from Dec 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 35 additions & 1 deletion docs/rules/indent.md
Expand Up @@ -69,7 +69,7 @@ if (a) {
This rule has an object option:

* `"SwitchCase"` (default: 0) enforces indentation level for `case` clauses in `switch` statements
* `"VariableDeclarator"` (default: 1) enforces indentation level for `var` declarators; can also take an object to define separate rules for `var`, `let` and `const` declarations.
* `"VariableDeclarator"` (default: 1) enforces indentation level for `var` declarators; can also take an object to define separate rules for `var`, `let` and `const` declarations. It can also be `"first"`, indicating all the declarators should be aligned with the first declarator.
* `"outerIIFEBody"` (default: 1) enforces indentation level for file-level IIFEs.
* `"MemberExpression"` (default: 1) enforces indentation level for multi-line property chains. This can also be set to `"off"` to disable checking for MemberExpression indentation.
* `"FunctionDeclaration"` takes an object to define rules for function declarations.
Expand Down Expand Up @@ -213,6 +213,40 @@ const a = 1,
c = 3;
```

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

```js
/*eslint indent: ["error", 2, { "VariableDeclarator": "first" }]*/
/*eslint-env es6*/

var a,
b,
c;
let a,
b,
c;
const a = 1,
b = 2,
c = 3;
```

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

```js
/*eslint indent: ["error", 2, { "VariableDeclarator": "first" }]*/
/*eslint-env es6*/

var a,
b,
c;
let a,
b,
c;
const a = 1,
b = 2,
c = 3;
```

Examples of **correct** code for this rule with the `2, { "VariableDeclarator": { "var": 2, "let": 2, "const": 3 } }` options:

```js
Expand Down
46 changes: 24 additions & 22 deletions lib/rules/indent.js
Expand Up @@ -522,25 +522,13 @@ module.exports = {
},
VariableDeclarator: {
oneOf: [
{
type: "integer",
minimum: 0
},
ELEMENT_LIST_SCHEMA,
{
type: "object",
properties: {
var: {
type: "integer",
minimum: 0
},
let: {
type: "integer",
minimum: 0
},
const: {
type: "integer",
minimum: 0
}
var: ELEMENT_LIST_SCHEMA,
let: ELEMENT_LIST_SCHEMA,
const: ELEMENT_LIST_SCHEMA
},
additionalProperties: false
}
Expand Down Expand Up @@ -661,7 +649,7 @@ module.exports = {
if (context.options[1]) {
lodash.merge(options, context.options[1]);

if (typeof options.VariableDeclarator === "number") {
if (typeof options.VariableDeclarator === "number" || options.VariableDeclarator === "first") {
options.VariableDeclarator = {
var: options.VariableDeclarator,
let: options.VariableDeclarator,
Expand Down Expand Up @@ -1349,10 +1337,27 @@ module.exports = {
},

VariableDeclaration(node) {
const variableIndent = Object.prototype.hasOwnProperty.call(options.VariableDeclarator, node.kind)
let variableIndent = Object.prototype.hasOwnProperty.call(options.VariableDeclarator, node.kind)
? options.VariableDeclarator[node.kind]
: DEFAULT_VARIABLE_INDENT;

const firstToken = sourceCode.getFirstToken(node),
lastToken = sourceCode.getLastToken(node);

if (options.VariableDeclarator[node.kind] === "first") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be simplified?

if (variableIndent === "first" && node.declarations.length > 1)

Might also allow the let a few lines up to revert to const.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may not. You can see there is a line (line 1358) after the if statement (node.declarations.length > 1).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did see that, but for some reason I thought the original declaration also covered that case. I see now that it probably doesn't. I have no issue merging this as is.

if (node.declarations.length > 1) {
addElementListIndent(
node.declarations,
firstToken,
lastToken,
"first"
);
return;
}

variableIndent = DEFAULT_VARIABLE_INDENT;
}

if (node.declarations[node.declarations.length - 1].loc.start.line > node.loc.start.line) {

/*
Expand All @@ -1374,13 +1379,10 @@ module.exports = {
* on the same line as the start of the declaration, provided that there are declarators that
* follow this one.
*/
const firstToken = sourceCode.getFirstToken(node);

offsets.setDesiredOffsets(node.range, firstToken, variableIndent, true);
} else {
offsets.setDesiredOffsets(node.range, sourceCode.getFirstToken(node), variableIndent);
offsets.setDesiredOffsets(node.range, firstToken, variableIndent);
}
const lastToken = sourceCode.getLastToken(node);

if (astUtils.isSemicolonToken(lastToken)) {
offsets.ignoreToken(lastToken);
Expand Down
88 changes: 88 additions & 0 deletions tests/lib/rules/indent.js
Expand Up @@ -614,6 +614,24 @@ ruleTester.run("indent", rule, {
`,
options: [2, { VariableDeclarator: 1 }]
},
{
code: unIndent`
let foo = 'foo',
bar = bar;
const a = 'a',
b = 'b';
`,
options: [2, { VariableDeclarator: "first" }]
},
{
code: unIndent`
let foo = 'foo',
bar = bar // <-- no semicolon here
const a = 'a',
b = 'b' // <-- no semicolon here
`,
options: [2, { VariableDeclarator: "first" }]
},
{
code: unIndent`
var foo = 1,
Expand All @@ -632,6 +650,43 @@ ruleTester.run("indent", rule, {
`,
options: [2, { VariableDeclarator: { var: 2 } }]
},
{
code: unIndent`
var foo = 'foo',
bar = bar;
`,
options: [2, { VariableDeclarator: { var: "first" } }]
},
{
code: unIndent`
var foo = 'foo',
bar = 'bar' // <-- no semicolon here
`,
options: [2, { VariableDeclarator: { var: "first" } }]
},
{
code: unIndent`
let foo = 1,
bar = 2,
baz
`,
options: [2, { VariableDeclarator: "first" }]
},
{
code: unIndent`
let
foo
`,
options: [4, { VariableDeclarator: "first" }]
},
{
code: unIndent`
let foo = 1,
bar =
2
`,
options: [2, { VariableDeclarator: "first" }]
},
{
code: unIndent`
var abc =
Expand Down Expand Up @@ -5933,6 +5988,39 @@ ruleTester.run("indent", rule, {
[2, 4, 2, "Identifier"]
])
},
{
code: unIndent`
let foo = 'foo',
bar = bar;
const a = 'a',
b = 'b';
`,
output: unIndent`
let foo = 'foo',
bar = bar;
const a = 'a',
b = 'b';
`,
options: [2, { VariableDeclarator: "first" }],
errors: expectedErrors([
[2, 4, 2, "Identifier"],
[4, 6, 2, "Identifier"]
])
},
{
code: unIndent`
var foo = 'foo',
bar = bar;
`,
output: unIndent`
var foo = 'foo',
bar = bar;
`,
options: [2, { VariableDeclarator: { var: "first" } }],
errors: expectedErrors([
[2, 4, 2, "Identifier"]
])
},
{
code: unIndent`
if(true)
Expand Down