Skip to content

Commit b0d72c9

Browse files
DMartensmdjermanovic
andauthoredSep 16, 2022
feat: add rule logical-assignment-operators (#16102)
* feat: add rule logical-assignment-operators Fixes #13689 * docs: update rule documentation - State the concept of the rule clearer - Increase the heading level for options * chore: unify ast-utils import * fix: only check for void 0 in undefined checks * fix: always fix for the logical pattern * feat: support yoda conditions in if conditions * fix: remove parenthesis around assignment target if necessary * fix: parenthesize logical pattern if needed * fix: add semicolon for if patterns with a body if needed * fix: remove file extension from import Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> * fix: check strictness of global scope instead of current scope to avoid checking for with * fix: check for mixed ?? and ||/&& operators in the fix for never * fix: check previous token for continuation problems in the if fix * feat: support else if (and fix suggest cases for if) * fix: do not remove else keyword for else if * fix: if cases also suggest based on potential getter * fix: also fix if only a single property is accessed for the if pattern * fix: do not fix logical patterns with a deeper access * fix: check whether Boolean references a global * fix: allow test conditions to access the same static property (a.b <=> a['b']) * fix: use the whole assignment operator with equals in the message and add operator for 'if' messages * docs: remove edit_link * docs: remove description from docs as it is autogenerated from rule.meta.docs.description * docs: move introductory text before rule details * docs: add missing 'logical' to rule description * docs: fix formatting for options * docs: include all logical operators for option 'never' * docs: add examples for option 'always' * docs: add examples of for the 'enforceForIfStatements' option and swap correct with incorrect sections * fix: disallow optional chaining for the logical pattern * fix: fixer does not delete parenthesis around the right operand in the assignment pattern * fix: remove multiple parenthesis around the right operand in the logical pattern * test: add data property for suggestions * docs: add missing comma in description Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> * test: clean up unnecessary data, add missing data and pass missing options for test case * fix: do not allow property accesses in a computed property when checking for a single property access * test: add test cases for private identifiers Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
1 parent f02bcd9 commit b0d72c9

File tree

5 files changed

+2067
-0
lines changed

5 files changed

+2067
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
title: logical-assignment-operators
3+
layout: doc
4+
rule_type: suggestion
5+
---
6+
7+
ES2021 introduces the assignment operator shorthand for the logical operators `||`, `&&` and `??`.
8+
Before, this was only allowed for mathematical operations such as `+` or `*` (see the rule [operator-assignment](./operator-assignment)).
9+
The shorthand can be used if the assignment target and the left expression of a logical expression are the same.
10+
For example `a = a || b` can be shortened to `a ||= b`.
11+
12+
## Rule Details
13+
14+
This rule requires or disallows logical assignment operator shorthand.
15+
16+
### Options
17+
18+
This rule has a string and an object option.
19+
String option:
20+
21+
* `"always"` (default)
22+
* `"never"`
23+
24+
Object option (only available if string option is set to `"always"`):
25+
26+
* `"enforceForIfStatements": false`(default) Do *not* check for equivalent `if` statements
27+
* `"enforceForIfStatements": true` Check for equivalent `if` statements
28+
29+
#### always
30+
31+
Examples of **incorrect** code for this rule with the default `"always"` option:
32+
33+
::: incorrect
34+
35+
```js
36+
/*eslint logical-assignment-operators: ["error", "always"]*/
37+
38+
a = a || b
39+
a = a && b
40+
a = a ?? b
41+
a || (a = b)
42+
a && (a = b)
43+
a ?? (a = b)
44+
```
45+
46+
:::
47+
48+
Examples of **correct** code for this rule with the default `"always"` option:
49+
50+
::: correct
51+
52+
```js
53+
/*eslint logical-assignment-operators: ["error", "always"]*/
54+
55+
a = b
56+
a += b
57+
a ||= b
58+
a = b || c
59+
a || (b = c)
60+
61+
if (a) a = b
62+
```
63+
64+
:::
65+
66+
#### never
67+
68+
Examples of **incorrect** code for this rule with the `"never"` option:
69+
70+
::: incorrect
71+
72+
```js
73+
/*eslint logical-assignment-operators: ["error", "never"]*/
74+
75+
a ||= b
76+
a &&= b
77+
a ??= b
78+
```
79+
80+
:::
81+
82+
Examples of **correct** code for this rule with the `"never"` option:
83+
84+
::: correct
85+
86+
```js
87+
/*eslint logical-assignment-operators: ["error", "never"]*/
88+
89+
a = a || b
90+
a = a && b
91+
a = a ?? b
92+
```
93+
94+
:::
95+
96+
#### enforceForIfStatements
97+
98+
This option checks for additional patterns with if statements which could be expressed with the logical assignment operator.
99+
100+
::: incorrect
101+
102+
Examples of **incorrect** code for this rule with the `["always", { enforceIfStatements: true }]` option:
103+
104+
```js
105+
/*eslint logical-assignment-operators: ["error", "always", { enforceForIfStatements: true }]*/
106+
107+
if (a) a = b // <=> a &&= b
108+
if (!a) a = b // <=> a ||= b
109+
110+
if (a == null) a = b // <=> a ??= b
111+
if (a === null || a === undefined) a = b // <=> a ??= b
112+
```
113+
114+
:::
115+
116+
Examples of **correct** code for this rule with the `["always", { enforceIfStatements: true }]` option:
117+
118+
::: correct
119+
120+
```js
121+
/*eslint logical-assignment-operators: ["error", "always", { enforceForIfStatements: true }]*/
122+
123+
if (a) b = c
124+
if (a === 0) a = b
125+
```
126+
127+
:::
128+
129+
## When Not To Use It
130+
131+
Use of logical operator assignment shorthand is a stylistic choice. Leaving this rule turned off would allow developers to choose which style is more readable on a case-by-case basis.

‎lib/rules/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
7272
"lines-around-comment": () => require("./lines-around-comment"),
7373
"lines-around-directive": () => require("./lines-around-directive"),
7474
"lines-between-class-members": () => require("./lines-between-class-members"),
75+
"logical-assignment-operators": () => require("./logical-assignment-operators"),
7576
"max-classes-per-file": () => require("./max-classes-per-file"),
7677
"max-depth": () => require("./max-depth"),
7778
"max-len": () => require("./max-len"),

0 commit comments

Comments
 (0)
Please sign in to comment.