Skip to content

Commit

Permalink
Fix: handle computed class fields in operator-linebreak (refs #14857) (
Browse files Browse the repository at this point in the history
  • Loading branch information
mdjermanovic committed Aug 12, 2021
1 parent 3b6cd89 commit af96584
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 14 deletions.
70 changes: 70 additions & 0 deletions docs/rules/operator-linebreak.md
Expand Up @@ -60,6 +60,16 @@ if (someCondition
answer = everything
? 42
: foo;

class Foo {
a
= 1;
[b]
= 2;
[c
]
= 3;
}
```

Examples of **correct** code for this rule with the `"after"` option:
Expand All @@ -82,6 +92,17 @@ if (someCondition ||
answer = everything ?
42 :
foo;

class Foo {
a =
1;
[b] =
2;
[c
] =
3;
d = 4;
}
```

### before
Expand All @@ -104,6 +125,16 @@ if (someCondition ||
answer = everything ?
42 :
foo;

class Foo {
a =
1;
[b] =
2;
[c
] =
3;
}
```

Examples of **correct** code for this rule with the `"before"` option:
Expand All @@ -126,6 +157,17 @@ if (someCondition
answer = everything
? 42
: foo;

class Foo {
a
= 1;
[b]
= 2;
[c
]
= 3;
d = 4;
}
```

### none
Expand Down Expand Up @@ -156,6 +198,23 @@ answer = everything
answer = everything ?
42 :
foo;

class Foo {
a =
1;
[b] =
2;
[c
] =
3;
d
= 4;
[e]
= 5;
[f
]
= 6;
}
```

Examples of **correct** code for this rule with the `"none"` option:
Expand All @@ -171,6 +230,17 @@ if (someCondition || otherCondition) {
}

answer = everything ? 42 : foo;

class Foo {
a = 1;
[b] = 2;
[c
] = 3;
d = 4;
[e] = 5;
[f
] = 6;
}
```

### overrides
Expand Down
26 changes: 12 additions & 14 deletions lib/rules/operator-linebreak.js
Expand Up @@ -136,23 +136,21 @@ module.exports = {
/**
* Checks the operator placement
* @param {ASTNode} node The node to check
* @param {ASTNode} leftSide The node that comes before the operator in `node`
* @param {ASTNode} rightSide The node that comes after the operator in `node`
* @param {string} operator The operator
* @private
* @returns {void}
*/
function validateNode(node, leftSide) {
function validateNode(node, rightSide, operator) {

/*
* When the left part of a binary expression is a single expression wrapped in
* parentheses (ex: `(a) + b`), leftToken will be the last token of the expression
* and operatorToken will be the closing parenthesis.
* The leftToken should be the last closing parenthesis, and the operatorToken
* should be the token right after that.
* Find the operator token by searching from the right side, because between the left side and the operator
* there could be additional tokens from type annotations. Search specifically for the token which
* value equals the operator, in order to skip possible opening parentheses before the right side node.
*/
const operatorToken = sourceCode.getTokenAfter(leftSide, astUtils.isNotClosingParenToken);
const operatorToken = sourceCode.getTokenBefore(rightSide, token => token.value === operator);
const leftToken = sourceCode.getTokenBefore(operatorToken);
const rightToken = sourceCode.getTokenAfter(operatorToken);
const operator = operatorToken.value;
const operatorStyleOverride = styleOverrides[operator];
const style = operatorStyleOverride || globalStyle;
const fix = getFixer(operatorToken, style);
Expand Down Expand Up @@ -222,7 +220,7 @@ module.exports = {
* @returns {void}
*/
function validateBinaryExpression(node) {
validateNode(node, node.left);
validateNode(node, node.right, node.operator);
}

//--------------------------------------------------------------------------
Expand All @@ -235,17 +233,17 @@ module.exports = {
AssignmentExpression: validateBinaryExpression,
VariableDeclarator(node) {
if (node.init) {
validateNode(node, node.id);
validateNode(node, node.init, "=");
}
},
PropertyDefinition(node) {
if (node.value) {
validateNode(node, node.key);
validateNode(node, node.value, "=");
}
},
ConditionalExpression(node) {
validateNode(node, node.test);
validateNode(node, node.consequent);
validateNode(node, node.consequent, "?");
validateNode(node, node.alternate, ":");
}
};
}
Expand Down
83 changes: 83 additions & 0 deletions tests/lib/rules/operator-linebreak.js
Expand Up @@ -56,6 +56,7 @@ ruleTester.run("operator-linebreak", rule, {
{ code: "\n1 + 1", options: ["none"] },
{ code: "1 + 1\n", options: ["none"] },
{ code: "answer = everything ? 42 : foo;", options: ["none"] },
{ code: "(a\n) + (\nb)", options: ["none"] },
{ code: "answer = everything \n?\n 42 : foo;", options: [null, { overrides: { "?": "ignore" } }] },
{ code: "answer = everything ? 42 \n:\n foo;", options: [null, { overrides: { ":": "ignore" } }] },

Expand Down Expand Up @@ -100,6 +101,7 @@ ruleTester.run("operator-linebreak", rule, {
parserOptions: { ecmaVersion: 2021 }
},

// class fields
{
code: "class C { foo =\n0 }",
parserOptions: { ecmaVersion: 2022 }
Expand All @@ -108,6 +110,41 @@ ruleTester.run("operator-linebreak", rule, {
code: "class C { foo\n= 0 }",
options: ["before"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { [foo\n]= 0 }",
options: ["before"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { [foo]\n= 0 }",
options: ["before"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { [foo\n]\n= 0 }",
options: ["before"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { [foo\n]= 0 }",
options: ["after"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { [foo\n]=\n0 }",
options: ["after"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { [foo\n]= 0 }",
options: ["none"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { foo\n=\n0 }",
options: ["none", { overrides: { "=": "ignore" } }],
parserOptions: { ecmaVersion: 2022 }
}
],

Expand Down Expand Up @@ -782,6 +819,7 @@ ruleTester.run("operator-linebreak", rule, {
}]
},

// class fields
{
code: "class C { a\n= 0; }",
output: "class C { a =\n0; }",
Expand Down Expand Up @@ -826,6 +864,51 @@ ruleTester.run("operator-linebreak", rule, {
endLine: 1,
endColumn: 14
}]
},
{
code: "class C { [a]\n= 0; }",
output: "class C { [a] =\n0; }",
options: ["after"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "operatorAtEnd",
data: { operator: "=" },
type: "PropertyDefinition",
line: 2,
column: 1,
endLine: 2,
endColumn: 2
}]
},
{
code: "class C { [a] =\n0; }",
output: "class C { [a]\n= 0; }",
options: ["before"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "operatorAtBeginning",
data: { operator: "=" },
type: "PropertyDefinition",
line: 1,
column: 15,
endLine: 1,
endColumn: 16
}]
},
{
code: "class C { [a]\n =0; }",
output: "class C { [a] =0; }",
options: ["none"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "noLinebreak",
data: { operator: "=" },
type: "PropertyDefinition",
line: 2,
column: 2,
endLine: 2,
endColumn: 3
}]
}
]
});

0 comments on commit af96584

Please sign in to comment.