Skip to content

Commit d3e4b80

Browse files
axetroyfisker
andauthoredSep 9, 2024··
Add consistent-existence-index-check rule (#2425)
Co-authored-by: fisker <lionkay@gmail.com>
1 parent 461b01c commit d3e4b80

11 files changed

+764
-4
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Enforce consistent style for element existence checks with `indexOf()`, `lastIndexOf()`, `findIndex()`, and `findLastIndex()`
2+
3+
💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs-eslintconfigjs).
4+
5+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
6+
7+
<!-- end auto-generated rule header -->
8+
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->
9+
10+
Enforce consistent style for element existence checks with `indexOf()`, `lastIndexOf()`, `findIndex()`, and `findLastIndex()`.
11+
12+
Prefer using `index === -1` to check if an element does not exist and `index !== -1` to check if an element does exist.
13+
14+
Similar to the [`explicit-length-check`](explicit-length-check.md) rule.
15+
16+
## Examples
17+
18+
```js
19+
const index = foo.indexOf('bar');
20+
21+
//
22+
if (index < 0) {}
23+
24+
//
25+
if (index === -1) {}
26+
```
27+
28+
```js
29+
const index = foo.indexOf('bar');
30+
31+
//
32+
if (index >= 0) {}
33+
34+
//
35+
if (index !== -1) {}
36+
```
37+
38+
```js
39+
const index = foo.indexOf('bar');
40+
41+
//
42+
if (index > -1) {}
43+
44+
//
45+
if (index !== -1) {}
46+
```
47+
48+
```js
49+
const index = foo.lastIndexOf('bar');
50+
51+
//
52+
if (index >= 0) {}
53+
54+
//
55+
if (index !== -1) {}
56+
```
57+
58+
```js
59+
const index = array.findIndex(element => element > 10);
60+
61+
//
62+
if (index < 0) {}
63+
64+
//
65+
if (index === -1) {}
66+
```
67+
68+
```js
69+
const index = array.findLastIndex(element => element > 10);
70+
71+
//
72+
if (index < 0) {}
73+
74+
//
75+
if (index === -1) {}
76+
```

‎readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c
114114
| [catch-error-name](docs/rules/catch-error-name.md) | Enforce a specific parameter name in catch clauses. || 🔧 | |
115115
| [consistent-destructuring](docs/rules/consistent-destructuring.md) | Use destructured variables over properties. | | 🔧 | 💡 |
116116
| [consistent-empty-array-spread](docs/rules/consistent-empty-array-spread.md) | Prefer consistent types when spreading a ternary in an array literal. || 🔧 | |
117+
| [consistent-existence-index-check](docs/rules/consistent-existence-index-check.md) | Enforce consistent style for element existence checks with `indexOf()`, `lastIndexOf()`, `findIndex()`, and `findLastIndex()`. || 🔧 | |
117118
| [consistent-function-scoping](docs/rules/consistent-function-scoping.md) | Move function definitions to the highest possible scope. || | |
118119
| [custom-error-definition](docs/rules/custom-error-definition.md) | Enforce correct `Error` subclassing. | | 🔧 | |
119120
| [empty-brace-spaces](docs/rules/empty-brace-spaces.md) | Enforce no spaces between braces. || 🔧 | |

‎rules/ast/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
isFunction: require('./is-function.js'),
3232
isMemberExpression: require('./is-member-expression.js'),
3333
isMethodCall: require('./is-method-call.js'),
34+
isNegativeOne: require('./is-negative-one.js'),
3435
isNewExpression,
3536
isReferenceIdentifier: require('./is-reference-identifier.js'),
3637
isStaticRequire: require('./is-static-require.js'),

‎rules/ast/is-negative-one.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
const {isNumberLiteral} = require('./literal.js');
4+
5+
function isNegativeOne(node) {
6+
return node?.type === 'UnaryExpression'
7+
&& node.operator === '-'
8+
&& isNumberLiteral(node.argument)
9+
&& node.argument.value === 1;
10+
}
11+
12+
module.exports = isNegativeOne;
+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
'use strict';
2+
const toLocation = require('./utils/to-location.js');
3+
const {isMethodCall, isNegativeOne, isNumberLiteral} = require('./ast/index.js');
4+
5+
const MESSAGE_ID = 'consistent-existence-index-check';
6+
const messages = {
7+
[MESSAGE_ID]: 'Prefer `{{replacementOperator}} {{replacementValue}}` over `{{originalOperator}} {{originalValue}}` to check {{existenceOrNonExistence}}.',
8+
};
9+
10+
const isZero = node => isNumberLiteral(node) && node.value === 0;
11+
12+
/**
13+
@param {parent: import('estree').BinaryExpression} binaryExpression
14+
@returns {{
15+
replacementOperator: string,
16+
replacementValue: string,
17+
originalOperator: string,
18+
originalValue: string,
19+
} | undefined}
20+
*/
21+
function getReplacement(binaryExpression) {
22+
const {operator, right} = binaryExpression;
23+
24+
if (operator === '<' && isZero(right)) {
25+
return {
26+
replacementOperator: '===',
27+
replacementValue: '-1',
28+
originalOperator: operator,
29+
originalValue: '0',
30+
};
31+
}
32+
33+
if (operator === '>' && isNegativeOne(right)) {
34+
return {
35+
replacementOperator: '!==',
36+
replacementValue: '-1',
37+
originalOperator: operator,
38+
originalValue: '-1',
39+
};
40+
}
41+
42+
if (operator === '>=' && isZero(right)) {
43+
return {
44+
replacementOperator: '!==',
45+
replacementValue: '-1',
46+
originalOperator: operator,
47+
originalValue: '0',
48+
};
49+
}
50+
}
51+
52+
/** @param {import('eslint').Rule.RuleContext} context */
53+
const create = context => ({
54+
/** @param {import('estree').VariableDeclarator} variableDeclarator */
55+
* VariableDeclarator(variableDeclarator) {
56+
if (!(
57+
variableDeclarator.parent.type === 'VariableDeclaration'
58+
&& variableDeclarator.parent.kind === 'const'
59+
&& variableDeclarator.id.type === 'Identifier'
60+
&& isMethodCall(variableDeclarator.init, {methods: ['indexOf', 'lastIndexOf', 'findIndex', 'findLastIndex']})
61+
)) {
62+
return;
63+
}
64+
65+
const variableIdentifier = variableDeclarator.id;
66+
const variables = context.sourceCode.getDeclaredVariables(variableDeclarator);
67+
const [variable] = variables;
68+
69+
// Just for safety
70+
if (
71+
variables.length !== 1
72+
|| variable.identifiers.length !== 1
73+
|| variable.identifiers[0] !== variableIdentifier
74+
) {
75+
return;
76+
}
77+
78+
for (const {identifier} of variable.references) {
79+
/** @type {{parent: import('estree').BinaryExpression}} */
80+
const binaryExpression = identifier.parent;
81+
82+
if (binaryExpression.type !== 'BinaryExpression' || binaryExpression.left !== identifier) {
83+
continue;
84+
}
85+
86+
const replacement = getReplacement(binaryExpression);
87+
88+
if (!replacement) {
89+
return;
90+
}
91+
92+
const {left, operator, right} = binaryExpression;
93+
const {sourceCode} = context;
94+
95+
const operatorToken = sourceCode.getTokenAfter(
96+
left,
97+
token => token.type === 'Punctuator' && token.value === operator,
98+
);
99+
100+
yield {
101+
node: binaryExpression,
102+
loc: toLocation([operatorToken.range[0], right.range[1]], sourceCode),
103+
messageId: MESSAGE_ID,
104+
data: {
105+
...replacement,
106+
existenceOrNonExistence: `${replacement.replacementOperator === '===' ? 'non-' : ''}existence`,
107+
},
108+
* fix(fixer) {
109+
yield fixer.replaceText(operatorToken, replacement.replacementOperator);
110+
111+
if (replacement.replacementValue !== replacement.originalValue) {
112+
yield fixer.replaceText(right, replacement.replacementValue);
113+
}
114+
},
115+
};
116+
}
117+
},
118+
});
119+
120+
/** @type {import('eslint').Rule.RuleModule} */
121+
module.exports = {
122+
create,
123+
meta: {
124+
type: 'problem',
125+
docs: {
126+
description:
127+
'Enforce consistent style for element existence checks with `indexOf()`, `lastIndexOf()`, `findIndex()`, and `findLastIndex()`.',
128+
recommended: true,
129+
},
130+
fixable: 'code',
131+
messages,
132+
},
133+
};

‎rules/prefer-includes.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22
const isMethodNamed = require('./utils/is-method-named.js');
33
const simpleArraySearchRule = require('./shared/simple-array-search-rule.js');
4-
const {isLiteral} = require('./ast/index.js');
4+
const {isLiteral, isNegativeOne} = require('./ast/index.js');
55

66
const MESSAGE_ID = 'prefer-includes';
77
const messages = {
@@ -10,7 +10,6 @@ const messages = {
1010
// Ignore `{_,lodash,underscore}.{indexOf,lastIndexOf}`
1111
const ignoredVariables = new Set(['_', 'lodash', 'underscore']);
1212
const isIgnoredTarget = node => node.type === 'Identifier' && ignoredVariables.has(node.name);
13-
const isNegativeOne = node => node.type === 'UnaryExpression' && node.operator === '-' && node.argument && node.argument.type === 'Literal' && node.argument.value === 1;
1413
const isLiteralZero = node => isLiteral(node, 0);
1514
const isNegativeResult = node => ['===', '==', '<'].includes(node.operator);
1615

‎rules/utils/resolve-variable-name.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
Finds a variable named `name` in the scope `scope` (or it's parents).
55
66
@param {string} name - The variable name to be resolve.
7-
@param {Scope} scope - The scope to look for the variable in.
8-
@returns {Variable?} - The found variable, if any.
7+
@param {import('eslint').Scope.Scope} scope - The scope to look for the variable in.
8+
@returns {import('eslint').Scope.Variable | void} - The found variable, if any.
99
*/
1010
module.exports = function resolveVariableName(name, scope) {
1111
while (scope) {
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import outdent from 'outdent';
2+
import {getTester} from './utils/test.mjs';
3+
4+
const {test} = getTester(import.meta);
5+
6+
test.snapshot({
7+
valid: [
8+
// Skip checking if indexOf() method is not a method call from a object
9+
outdent`
10+
const index = indexOf('bar');
11+
12+
if (index > -1) {}
13+
`,
14+
outdent`
15+
const index = foo.indexOf('bar');
16+
17+
if (index === -1) {}
18+
`,
19+
outdent`
20+
const index = foo.indexOf('bar');
21+
22+
if (-1 === index) {}
23+
`,
24+
outdent`
25+
const index = foo.indexOf('bar');
26+
27+
if (index !== -1) {}
28+
`,
29+
outdent`
30+
const index = foo.indexOf('bar');
31+
32+
if (-1 !== index) {}
33+
`,
34+
// Variable index is not from indexOf
35+
outdent`
36+
const index = 0;
37+
38+
if (index < 0) {}
39+
`,
40+
// If index is not declared via VariableDeclarator, it will not be check here.
41+
outdent`
42+
function foo (index) {
43+
if (index < 0) {}
44+
}
45+
`,
46+
// Since the variable is references from function parameter, it will not be checked here
47+
outdent`
48+
const index = foo.indexOf('bar');
49+
50+
function foo (index) {
51+
if (index < 0) {}
52+
}
53+
`,
54+
// To prevent false positives, it will not check if the index is not declared via const
55+
outdent`
56+
let index = foo.indexOf("bar");
57+
58+
index < 0
59+
`,
60+
// To prevent false positives, it will not check if the index is not declared via const
61+
outdent`
62+
var index = foo.indexOf("bar");
63+
64+
index < 0
65+
`,
66+
// To prevent false positives, it will not check if the index is not declared via const
67+
outdent`
68+
let index;
69+
70+
// do stuff
71+
72+
index = arr.findLastIndex(element => element > 10);
73+
74+
index < 0;
75+
`,
76+
'const indexOf = "indexOf"; const index = foo[indexOf](foo); index < 0;',
77+
'const index = foo.indexOf?.(foo); index < 0;',
78+
'const index = foo?.indexOf(foo); index < 0;',
79+
],
80+
invalid: [
81+
...[
82+
'index < 0',
83+
'index >= 0',
84+
'index > -1',
85+
].map(code => `const index = foo.indexOf(bar); ${code}`),
86+
...[
87+
'foo.indexOf(bar)',
88+
'foo.lastIndexOf(bar)',
89+
'foo.findIndex(bar)',
90+
'foo.findLastIndex(bar)',
91+
].map(code => `const index = ${code}; index < 0`),
92+
// It will search the scope chain for 'index' and find the 'index' variable declared above.
93+
outdent`
94+
const index = foo.indexOf(bar);
95+
96+
function foo () {
97+
if (index < 0) {}
98+
}
99+
`,
100+
outdent`
101+
const index1 = foo.indexOf("1"),
102+
index2 = foo.indexOf("2");
103+
index1 < 0;
104+
index2 >= 0;
105+
`,
106+
outdent`
107+
const index = foo.indexOf('1');
108+
((
109+
/* comment 1 */
110+
((
111+
/* comment 2 */
112+
index
113+
/* comment 3 */
114+
))
115+
/* comment 4 */
116+
<
117+
/* comment 5 */
118+
((
119+
/* comment 6 */
120+
0
121+
/* comment 7 */
122+
))
123+
/* comment 8 */
124+
));
125+
`,
126+
outdent`
127+
const index = foo.indexOf('1');
128+
((
129+
/* comment 1 */
130+
((
131+
/* comment 2 */
132+
index
133+
/* comment 3 */
134+
))
135+
/* comment 4 */
136+
>
137+
((
138+
/* comment 5 */
139+
- /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ ))
140+
/* comment 9 */
141+
))
142+
));
143+
`,
144+
'const index = _.indexOf([1, 2, 1, 2], 2); index < 0;',
145+
],
146+
});

‎test/package.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const RULES_WITHOUT_PASS_FAIL_SECTIONS = new Set([
3131
// Intended to not use `pass`/`fail` section in this rule.
3232
'prefer-modern-math-apis',
3333
'prefer-math-min-max',
34+
'consistent-existence-index-check',
3435
]);
3536

3637
test('Every rule is defined in index file in alphabetical order', t => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
# Snapshot report for `test/consistent-existence-index-check.mjs`
2+
3+
The actual snapshot is saved in `consistent-existence-index-check.mjs.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## invalid(1): const index = foo.indexOf(bar); index < 0
8+
9+
> Input
10+
11+
`␊
12+
1 | const index = foo.indexOf(bar); index < 0␊
13+
`
14+
15+
> Output
16+
17+
`␊
18+
1 | const index = foo.indexOf(bar); index === -1␊
19+
`
20+
21+
> Error 1/1
22+
23+
`␊
24+
> 1 | const index = foo.indexOf(bar); index < 0␊
25+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
26+
`
27+
28+
## invalid(2): const index = foo.indexOf(bar); index >= 0
29+
30+
> Input
31+
32+
`␊
33+
1 | const index = foo.indexOf(bar); index >= 0␊
34+
`
35+
36+
> Output
37+
38+
`␊
39+
1 | const index = foo.indexOf(bar); index !== -1␊
40+
`
41+
42+
> Error 1/1
43+
44+
`␊
45+
> 1 | const index = foo.indexOf(bar); index >= 0␊
46+
| ^^^^ Prefer \`!== -1\` over \`>= 0\` to check existence.␊
47+
`
48+
49+
## invalid(3): const index = foo.indexOf(bar); index > -1
50+
51+
> Input
52+
53+
`␊
54+
1 | const index = foo.indexOf(bar); index > -1␊
55+
`
56+
57+
> Output
58+
59+
`␊
60+
1 | const index = foo.indexOf(bar); index !== -1␊
61+
`
62+
63+
> Error 1/1
64+
65+
`␊
66+
> 1 | const index = foo.indexOf(bar); index > -1␊
67+
| ^^^^ Prefer \`!== -1\` over \`> -1\` to check existence.␊
68+
`
69+
70+
## invalid(4): const index = foo.indexOf(bar); index < 0
71+
72+
> Input
73+
74+
`␊
75+
1 | const index = foo.indexOf(bar); index < 0␊
76+
`
77+
78+
> Output
79+
80+
`␊
81+
1 | const index = foo.indexOf(bar); index === -1␊
82+
`
83+
84+
> Error 1/1
85+
86+
`␊
87+
> 1 | const index = foo.indexOf(bar); index < 0␊
88+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
89+
`
90+
91+
## invalid(5): const index = foo.lastIndexOf(bar); index < 0
92+
93+
> Input
94+
95+
`␊
96+
1 | const index = foo.lastIndexOf(bar); index < 0␊
97+
`
98+
99+
> Output
100+
101+
`␊
102+
1 | const index = foo.lastIndexOf(bar); index === -1␊
103+
`
104+
105+
> Error 1/1
106+
107+
`␊
108+
> 1 | const index = foo.lastIndexOf(bar); index < 0␊
109+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
110+
`
111+
112+
## invalid(6): const index = foo.findIndex(bar); index < 0
113+
114+
> Input
115+
116+
`␊
117+
1 | const index = foo.findIndex(bar); index < 0␊
118+
`
119+
120+
> Output
121+
122+
`␊
123+
1 | const index = foo.findIndex(bar); index === -1␊
124+
`
125+
126+
> Error 1/1
127+
128+
`␊
129+
> 1 | const index = foo.findIndex(bar); index < 0␊
130+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
131+
`
132+
133+
## invalid(7): const index = foo.findLastIndex(bar); index < 0
134+
135+
> Input
136+
137+
`␊
138+
1 | const index = foo.findLastIndex(bar); index < 0␊
139+
`
140+
141+
> Output
142+
143+
`␊
144+
1 | const index = foo.findLastIndex(bar); index === -1␊
145+
`
146+
147+
> Error 1/1
148+
149+
`␊
150+
> 1 | const index = foo.findLastIndex(bar); index < 0␊
151+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
152+
`
153+
154+
## invalid(8): const index = foo.indexOf(bar); function foo () { if (index < 0) {} }
155+
156+
> Input
157+
158+
`␊
159+
1 | const index = foo.indexOf(bar);␊
160+
2 |␊
161+
3 | function foo () {␊
162+
4 | if (index < 0) {}␊
163+
5 | }␊
164+
`
165+
166+
> Output
167+
168+
`␊
169+
1 | const index = foo.indexOf(bar);␊
170+
2 |␊
171+
3 | function foo () {␊
172+
4 | if (index === -1) {}␊
173+
5 | }␊
174+
`
175+
176+
> Error 1/1
177+
178+
`␊
179+
1 | const index = foo.indexOf(bar);␊
180+
2 |␊
181+
3 | function foo () {␊
182+
> 4 | if (index < 0) {}␊
183+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
184+
5 | }␊
185+
`
186+
187+
## invalid(9): const index1 = foo.indexOf("1"), index2 = foo.indexOf("2"); index1 < 0; index2 >= 0;
188+
189+
> Input
190+
191+
`␊
192+
1 | const index1 = foo.indexOf("1"),␊
193+
2 | index2 = foo.indexOf("2");␊
194+
3 | index1 < 0;␊
195+
4 | index2 >= 0;␊
196+
`
197+
198+
> Output
199+
200+
`␊
201+
1 | const index1 = foo.indexOf("1"),␊
202+
2 | index2 = foo.indexOf("2");␊
203+
3 | index1 === -1;␊
204+
4 | index2 !== -1;␊
205+
`
206+
207+
> Error 1/2
208+
209+
`␊
210+
1 | const index1 = foo.indexOf("1"),␊
211+
2 | index2 = foo.indexOf("2");␊
212+
> 3 | index1 < 0;␊
213+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
214+
4 | index2 >= 0;␊
215+
`
216+
217+
> Error 2/2
218+
219+
`␊
220+
1 | const index1 = foo.indexOf("1"),␊
221+
2 | index2 = foo.indexOf("2");␊
222+
3 | index1 < 0;␊
223+
> 4 | index2 >= 0;␊
224+
| ^^^^ Prefer \`!== -1\` over \`>= 0\` to check existence.␊
225+
`
226+
227+
## invalid(10): const index = foo.indexOf('1'); (( /* comment 1 */ (( /* comment 2 */ index /* comment 3 */ )) /* comment 4 */ < /* comment 5 */ (( /* comment 6 */ 0 /* comment 7 */ )) /* comment 8 */ ));
228+
229+
> Input
230+
231+
`␊
232+
1 | const index = foo.indexOf('1');␊
233+
2 | ((␊
234+
3 | /* comment 1 */␊
235+
4 | ((␊
236+
5 | /* comment 2 */␊
237+
6 | index␊
238+
7 | /* comment 3 */␊
239+
8 | ))␊
240+
9 | /* comment 4 */␊
241+
10 | <␊
242+
11 | /* comment 5 */␊
243+
12 | ((␊
244+
13 | /* comment 6 */␊
245+
14 | 0␊
246+
15 | /* comment 7 */␊
247+
16 | ))␊
248+
17 | /* comment 8 */␊
249+
18 | ));␊
250+
`
251+
252+
> Output
253+
254+
`␊
255+
1 | const index = foo.indexOf('1');␊
256+
2 | ((␊
257+
3 | /* comment 1 */␊
258+
4 | ((␊
259+
5 | /* comment 2 */␊
260+
6 | index␊
261+
7 | /* comment 3 */␊
262+
8 | ))␊
263+
9 | /* comment 4 */␊
264+
10 | ===␊
265+
11 | /* comment 5 */␊
266+
12 | ((␊
267+
13 | /* comment 6 */␊
268+
14 | -1␊
269+
15 | /* comment 7 */␊
270+
16 | ))␊
271+
17 | /* comment 8 */␊
272+
18 | ));␊
273+
`
274+
275+
> Error 1/1
276+
277+
`␊
278+
1 | const index = foo.indexOf('1');␊
279+
2 | ((␊
280+
3 | /* comment 1 */␊
281+
4 | ((␊
282+
5 | /* comment 2 */␊
283+
6 | index␊
284+
7 | /* comment 3 */␊
285+
8 | ))␊
286+
9 | /* comment 4 */␊
287+
> 10 | <␊
288+
| ^␊
289+
> 11 | /* comment 5 */␊
290+
| ^^^^^^^^^^^^^^^^␊
291+
> 12 | ((␊
292+
| ^^^^^^^^^^^^^^^^␊
293+
> 13 | /* comment 6 */␊
294+
| ^^^^^^^^^^^^^^^^␊
295+
> 14 | 0␊
296+
| ^^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
297+
15 | /* comment 7 */␊
298+
16 | ))␊
299+
17 | /* comment 8 */␊
300+
18 | ));␊
301+
`
302+
303+
## invalid(11): const index = foo.indexOf('1'); (( /* comment 1 */ (( /* comment 2 */ index /* comment 3 */ )) /* comment 4 */ > (( /* comment 5 */ - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ )) /* comment 9 */ )) ));
304+
305+
> Input
306+
307+
`␊
308+
1 | const index = foo.indexOf('1');␊
309+
2 | ((␊
310+
3 | /* comment 1 */␊
311+
4 | ((␊
312+
5 | /* comment 2 */␊
313+
6 | index␊
314+
7 | /* comment 3 */␊
315+
8 | ))␊
316+
9 | /* comment 4 */␊
317+
10 | >␊
318+
11 | ((␊
319+
12 | /* comment 5 */␊
320+
13 | - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ ))␊
321+
14 | /* comment 9 */␊
322+
15 | ))␊
323+
16 | ));␊
324+
`
325+
326+
> Output
327+
328+
`␊
329+
1 | const index = foo.indexOf('1');␊
330+
2 | ((␊
331+
3 | /* comment 1 */␊
332+
4 | ((␊
333+
5 | /* comment 2 */␊
334+
6 | index␊
335+
7 | /* comment 3 */␊
336+
8 | ))␊
337+
9 | /* comment 4 */␊
338+
10 | !==␊
339+
11 | ((␊
340+
12 | /* comment 5 */␊
341+
13 | - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ ))␊
342+
14 | /* comment 9 */␊
343+
15 | ))␊
344+
16 | ));␊
345+
`
346+
347+
> Error 1/1
348+
349+
`␊
350+
1 | const index = foo.indexOf('1');␊
351+
2 | ((␊
352+
3 | /* comment 1 */␊
353+
4 | ((␊
354+
5 | /* comment 2 */␊
355+
6 | index␊
356+
7 | /* comment 3 */␊
357+
8 | ))␊
358+
9 | /* comment 4 */␊
359+
> 10 | >␊
360+
| ^␊
361+
> 11 | ((␊
362+
| ^^^␊
363+
> 12 | /* comment 5 */␊
364+
| ^^^␊
365+
> 13 | - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ ))␊
366+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer \`!== -1\` over \`> -1\` to check existence.␊
367+
14 | /* comment 9 */␊
368+
15 | ))␊
369+
16 | ));␊
370+
`
371+
372+
## invalid(12): const index = _.indexOf([1, 2, 1, 2], 2); index < 0;
373+
374+
> Input
375+
376+
`␊
377+
1 | const index = _.indexOf([1, 2, 1, 2], 2); index < 0;␊
378+
`
379+
380+
> Output
381+
382+
`␊
383+
1 | const index = _.indexOf([1, 2, 1, 2], 2); index === -1;␊
384+
`
385+
386+
> Error 1/1
387+
388+
`␊
389+
> 1 | const index = _.indexOf([1, 2, 1, 2], 2); index < 0;␊
390+
| ^^^ Prefer \`=== -1\` over \`< 0\` to check non-existence.␊
391+
`
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.