eslint-plugin-ocavue 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -31
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +2 -0
- package/src/rules/prefer-while-true.test.ts +43 -0
- package/src/rules/prefer-while-true.ts +52 -0
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ export default [
|
|
|
21
21
|
plugins: { ocavue },
|
|
22
22
|
rules: {
|
|
23
23
|
'ocavue/no-implicit-arrow-linebreak': 'error',
|
|
24
|
+
'ocavue/prefer-while-true': 'error',
|
|
24
25
|
},
|
|
25
26
|
},
|
|
26
27
|
]
|
|
@@ -49,6 +50,24 @@ const items = Array.from({ length: count }, (_, index) => {
|
|
|
49
50
|
|
|
50
51
|
When a comment sits between `=>` and the body, the rule reports without autofixing so the fix never drops a comment.
|
|
51
52
|
|
|
53
|
+
### `prefer-while-true`
|
|
54
|
+
|
|
55
|
+
Enforce `while (true)` instead of `for (;;)` for infinite loops. Rules such as [`no-constant-condition`](https://eslint.org/docs/latest/rules/no-constant-condition) (with `checkLoops: "all"`) and [`@typescript-eslint/no-unnecessary-condition`](https://typescript-eslint.io/rules/no-unnecessary-condition) report `while (true)` but not `for (;;)`, so people often rewrite the loop as `for (;;)` to silence them. That only hides the infinite loop from the linter: the code still loops forever. This rule removes that workaround. `while (true)` also reads more clearly than `for (;;)`.
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
// Incorrect
|
|
59
|
+
for (;;) {
|
|
60
|
+
step()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Correct (what the fixer produces)
|
|
64
|
+
while (true) {
|
|
65
|
+
step()
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
When a comment sits inside the loop head, the rule reports without autofixing so the fix never drops a comment.
|
|
70
|
+
|
|
52
71
|
## Sponsors
|
|
53
72
|
|
|
54
73
|
<p align="center">
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";cAOM"}
|
package/dist/index.js
CHANGED
|
@@ -3,41 +3,76 @@
|
|
|
3
3
|
const plugin = {
|
|
4
4
|
meta: {
|
|
5
5
|
name: "eslint-plugin-ocavue",
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.2.0"
|
|
7
7
|
},
|
|
8
|
-
rules: {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
rules: {
|
|
9
|
+
"no-implicit-arrow-linebreak": {
|
|
10
|
+
meta: {
|
|
11
|
+
type: "layout",
|
|
12
|
+
fixable: "code",
|
|
13
|
+
docs: {
|
|
14
|
+
description: "disallow a linebreak between `=>` and an implicit arrow function body, fixing it to a block body with `return`",
|
|
15
|
+
url: "https://github.com/ocavue/eslint-plugin-ocavue#no-implicit-arrow-linebreak"
|
|
16
|
+
},
|
|
17
|
+
messages: { linebreak: "Implicit arrow body must not start on a new line. Use a block body with `return` instead." },
|
|
18
|
+
schema: []
|
|
15
19
|
},
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
create(context) {
|
|
21
|
+
const sourceCode = context.sourceCode;
|
|
22
|
+
return { ArrowFunctionExpression(node) {
|
|
23
|
+
if (node.body.type === "BlockStatement") return;
|
|
24
|
+
const arrowToken = sourceCode.getTokenBefore(node.body, { filter: (token) => token.type === "Punctuator" && token.value === "=>" });
|
|
25
|
+
if (!arrowToken) return;
|
|
26
|
+
const firstBodyToken = sourceCode.getTokenAfter(arrowToken);
|
|
27
|
+
const lastToken = sourceCode.getLastToken(node);
|
|
28
|
+
if (!firstBodyToken || !lastToken) return;
|
|
29
|
+
if (arrowToken.loc.end.line === firstBodyToken.loc.start.line) return;
|
|
30
|
+
const canFix = !sourceCode.commentsExistBetween(arrowToken, firstBodyToken);
|
|
31
|
+
context.report({
|
|
32
|
+
node: node.body,
|
|
33
|
+
messageId: "linebreak",
|
|
34
|
+
fix: canFix ? (fixer) => {
|
|
35
|
+
const bodyText = sourceCode.text.slice(firstBodyToken.range[0], lastToken.range[1]);
|
|
36
|
+
return fixer.replaceTextRange([arrowToken.range[1], lastToken.range[1]], ` { return ${bodyText} }`);
|
|
37
|
+
} : void 0
|
|
38
|
+
});
|
|
39
|
+
} };
|
|
40
|
+
}
|
|
18
41
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
"prefer-while-true": {
|
|
43
|
+
meta: {
|
|
44
|
+
type: "suggestion",
|
|
45
|
+
fixable: "code",
|
|
46
|
+
docs: {
|
|
47
|
+
description: "enforce `while (true)` instead of `for (;;)` for infinite loops",
|
|
48
|
+
url: "https://github.com/ocavue/eslint-plugin-ocavue#prefer-while-true"
|
|
49
|
+
},
|
|
50
|
+
messages: { preferWhileTrue: "Use `while (true)` instead of `for (;;)`." },
|
|
51
|
+
schema: []
|
|
52
|
+
},
|
|
53
|
+
create(context) {
|
|
54
|
+
const sourceCode = context.sourceCode;
|
|
55
|
+
return { ForStatement(node) {
|
|
56
|
+
if (node.init || node.test || node.update) return;
|
|
57
|
+
const forToken = sourceCode.getFirstToken(node);
|
|
58
|
+
const closingParen = sourceCode.getTokenBefore(node.body);
|
|
59
|
+
if (!forToken || !closingParen) return;
|
|
60
|
+
const canFix = !sourceCode.commentsExistBetween(forToken, closingParen);
|
|
61
|
+
context.report({
|
|
62
|
+
node,
|
|
63
|
+
loc: {
|
|
64
|
+
start: forToken.loc.start,
|
|
65
|
+
end: closingParen.loc.end
|
|
66
|
+
},
|
|
67
|
+
messageId: "preferWhileTrue",
|
|
68
|
+
fix: canFix ? (fixer) => {
|
|
69
|
+
return fixer.replaceTextRange([forToken.range[0], closingParen.range[1]], "while (true)");
|
|
70
|
+
} : void 0
|
|
71
|
+
});
|
|
72
|
+
} };
|
|
73
|
+
}
|
|
39
74
|
}
|
|
40
|
-
}
|
|
75
|
+
}
|
|
41
76
|
};
|
|
42
77
|
//#endregion
|
|
43
78
|
export { plugin as default };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["noImplicitArrowLinebreak"],"sources":["../package.json","../src/rules/no-implicit-arrow-linebreak.ts","../src/index.ts"],"sourcesContent":["","import type { Rule } from 'eslint'\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'layout',\n fixable: 'code',\n docs: {\n description:\n 'disallow a linebreak between `=>` and an implicit arrow function body, fixing it to a block body with `return`',\n url: 'https://github.com/ocavue/eslint-plugin-ocavue#no-implicit-arrow-linebreak',\n },\n messages: {\n linebreak:\n 'Implicit arrow body must not start on a new line. Use a block body with `return` instead.',\n },\n schema: [],\n },\n create(context) {\n const sourceCode = context.sourceCode\n return {\n ArrowFunctionExpression(node) {\n if (node.body.type === 'BlockStatement') {\n return\n }\n\n const arrowToken = sourceCode.getTokenBefore(node.body, {\n filter: (token) => token.type === 'Punctuator' && token.value === '=>',\n })\n if (!arrowToken) {\n return\n }\n const firstBodyToken = sourceCode.getTokenAfter(arrowToken)\n // The last token of the arrow function. When the body is wrapped in\n // parentheses, this is the closing `)`, so the fix keeps the parens.\n const lastToken = sourceCode.getLastToken(node)\n if (!firstBodyToken || !lastToken) {\n return\n }\n if (arrowToken.loc.end.line === firstBodyToken.loc.start.line) {\n return\n }\n\n // The fix rewrites the region between `=>` and the body, so bail out\n // of fixing (but still report) if that region contains comments.\n const canFix = !sourceCode.commentsExistBetween(arrowToken, firstBodyToken)\n\n context.report({\n node: node.body,\n messageId: 'linebreak',\n fix: canFix\n ? (fixer) => {\n const bodyText = sourceCode.text.slice(firstBodyToken.range[0], lastToken.range[1])\n return fixer.replaceTextRange(\n [arrowToken.range[1], lastToken.range[1]],\n ` { return ${bodyText} }`,\n )\n }\n : undefined,\n })\n },\n }\n },\n}\n\nexport default rule\n","import type { ESLint } from 'eslint'\n\nimport { version } from '../package.json'\n\nimport noImplicitArrowLinebreak from './rules/no-implicit-arrow-linebreak'\n\nconst plugin = {\n meta: {\n name: 'eslint-plugin-ocavue',\n version,\n },\n rules: {\n 'no-implicit-arrow-linebreak': noImplicitArrowLinebreak,\n },\n} satisfies ESLint.Plugin\n\nexport default plugin\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","names":["rule","noImplicitArrowLinebreak","preferWhileTrue"],"sources":["../package.json","../src/rules/no-implicit-arrow-linebreak.ts","../src/rules/prefer-while-true.ts","../src/index.ts"],"sourcesContent":["","import type { Rule } from 'eslint'\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'layout',\n fixable: 'code',\n docs: {\n description:\n 'disallow a linebreak between `=>` and an implicit arrow function body, fixing it to a block body with `return`',\n url: 'https://github.com/ocavue/eslint-plugin-ocavue#no-implicit-arrow-linebreak',\n },\n messages: {\n linebreak:\n 'Implicit arrow body must not start on a new line. Use a block body with `return` instead.',\n },\n schema: [],\n },\n create(context) {\n const sourceCode = context.sourceCode\n return {\n ArrowFunctionExpression(node) {\n if (node.body.type === 'BlockStatement') {\n return\n }\n\n const arrowToken = sourceCode.getTokenBefore(node.body, {\n filter: (token) => token.type === 'Punctuator' && token.value === '=>',\n })\n if (!arrowToken) {\n return\n }\n const firstBodyToken = sourceCode.getTokenAfter(arrowToken)\n // The last token of the arrow function. When the body is wrapped in\n // parentheses, this is the closing `)`, so the fix keeps the parens.\n const lastToken = sourceCode.getLastToken(node)\n if (!firstBodyToken || !lastToken) {\n return\n }\n if (arrowToken.loc.end.line === firstBodyToken.loc.start.line) {\n return\n }\n\n // The fix rewrites the region between `=>` and the body, so bail out\n // of fixing (but still report) if that region contains comments.\n const canFix = !sourceCode.commentsExistBetween(arrowToken, firstBodyToken)\n\n context.report({\n node: node.body,\n messageId: 'linebreak',\n fix: canFix\n ? (fixer) => {\n const bodyText = sourceCode.text.slice(firstBodyToken.range[0], lastToken.range[1])\n return fixer.replaceTextRange(\n [arrowToken.range[1], lastToken.range[1]],\n ` { return ${bodyText} }`,\n )\n }\n : undefined,\n })\n },\n }\n },\n}\n\nexport default rule\n","import type { Rule } from 'eslint'\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n docs: {\n description: 'enforce `while (true)` instead of `for (;;)` for infinite loops',\n url: 'https://github.com/ocavue/eslint-plugin-ocavue#prefer-while-true',\n },\n messages: {\n preferWhileTrue: 'Use `while (true)` instead of `for (;;)`.',\n },\n schema: [],\n },\n create(context) {\n const sourceCode = context.sourceCode\n return {\n ForStatement(node) {\n if (node.init || node.test || node.update) {\n return\n }\n\n const forToken = sourceCode.getFirstToken(node)\n const closingParen = sourceCode.getTokenBefore(node.body)\n if (!forToken || !closingParen) {\n return\n }\n\n // Bail out of fixing (but still report) if the loop head contains\n // comments, so the fix never drops a comment.\n const canFix = !sourceCode.commentsExistBetween(forToken, closingParen)\n\n context.report({\n node,\n loc: { start: forToken.loc.start, end: closingParen.loc.end },\n messageId: 'preferWhileTrue',\n fix: canFix\n ? (fixer) => {\n return fixer.replaceTextRange(\n [forToken.range[0], closingParen.range[1]],\n 'while (true)',\n )\n }\n : undefined,\n })\n },\n }\n },\n}\n\nexport default rule\n","import type { ESLint } from 'eslint'\n\nimport { version } from '../package.json'\n\nimport noImplicitArrowLinebreak from './rules/no-implicit-arrow-linebreak'\nimport preferWhileTrue from './rules/prefer-while-true'\n\nconst plugin = {\n meta: {\n name: 'eslint-plugin-ocavue',\n version,\n },\n rules: {\n 'no-implicit-arrow-linebreak': noImplicitArrowLinebreak,\n 'prefer-while-true': preferWhileTrue,\n },\n} satisfies ESLint.Plugin\n\nexport default plugin\n"],"mappings":";;AGOA,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN;CACF;CACA,OAAO;EACL,+BAA+BC;GFVjC,MAAM;IACJ,MAAM;IACN,SAAS;IACT,MAAM;KACJ,aACE;KACF,KAAK;IACP;IACA,UAAU,EACR,WACE,4FACJ;IACA,QAAQ,CAAC;GACX;GACA,OAAO,SAAS;IACd,MAAM,aAAa,QAAQ;IAC3B,OAAO,EACL,wBAAwB,MAAM;KAC5B,IAAI,KAAK,KAAK,SAAS,kBACrB;KAGF,MAAM,aAAa,WAAW,eAAe,KAAK,MAAM,EACtD,SAAS,UAAU,MAAM,SAAS,gBAAgB,MAAM,UAAU,KACpE,CAAC;KACD,IAAI,CAAC,YACH;KAEF,MAAM,iBAAiB,WAAW,cAAc,UAAU;KAG1D,MAAM,YAAY,WAAW,aAAa,IAAI;KAC9C,IAAI,CAAC,kBAAkB,CAAC,WACtB;KAEF,IAAI,WAAW,IAAI,IAAI,SAAS,eAAe,IAAI,MAAM,MACvD;KAKF,MAAM,SAAS,CAAC,WAAW,qBAAqB,YAAY,cAAc;KAE1E,QAAQ,OAAO;MACb,MAAM,KAAK;MACX,WAAW;MACX,KAAK,UACA,UAAU;OACT,MAAM,WAAW,WAAW,KAAK,MAAM,eAAe,MAAM,IAAI,UAAU,MAAM,EAAE;OAClF,OAAO,MAAM,iBACX,CAAC,WAAW,MAAM,IAAI,UAAU,MAAM,EAAE,GACxC,aAAa,SAAS,GACxB;MACF,IACA,KAAA;KACN,CAAC;IACH,EACF;GACF;EEhDiCA;EAC/B,qBAAqBC;GDXvB,MAAM;IACJ,MAAM;IACN,SAAS;IACT,MAAM;KACJ,aAAa;KACb,KAAK;IACP;IACA,UAAU,EACR,iBAAiB,4CACnB;IACA,QAAQ,CAAC;GACX;GACA,OAAO,SAAS;IACd,MAAM,aAAa,QAAQ;IAC3B,OAAO,EACL,aAAa,MAAM;KACjB,IAAI,KAAK,QAAQ,KAAK,QAAQ,KAAK,QACjC;KAGF,MAAM,WAAW,WAAW,cAAc,IAAI;KAC9C,MAAM,eAAe,WAAW,eAAe,KAAK,IAAI;KACxD,IAAI,CAAC,YAAY,CAAC,cAChB;KAKF,MAAM,SAAS,CAAC,WAAW,qBAAqB,UAAU,YAAY;KAEtE,QAAQ,OAAO;MACb;MACA,KAAK;OAAE,OAAO,SAAS,IAAI;OAAO,KAAK,aAAa,IAAI;MAAI;MAC5D,WAAW;MACX,KAAK,UACA,UAAU;OACT,OAAO,MAAM,iBACX,CAAC,SAAS,MAAM,IAAI,aAAa,MAAM,EAAE,GACzC,cACF;MACF,IACA,KAAA;KACN,CAAC;IACH,EACF;GACF;EClCuBA;CACvB;AACF"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-ocavue",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"description": "Custom ESLint rules from ocavue",
|
|
6
6
|
"author": "ocavue <ocavue@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -35,15 +35,15 @@
|
|
|
35
35
|
"eslint": "^10.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@ocavue/eslint-config": "^4.
|
|
38
|
+
"@ocavue/eslint-config": "^4.22.0",
|
|
39
39
|
"@ocavue/tsconfig": "^0.7.1",
|
|
40
40
|
"@types/node": "^24.0.0",
|
|
41
|
-
"eslint": "^10.
|
|
42
|
-
"knip": "^6.
|
|
43
|
-
"oxfmt": "^0.
|
|
44
|
-
"tsdown": "^0.
|
|
41
|
+
"eslint": "^10.14.0",
|
|
42
|
+
"knip": "^6.41.0",
|
|
43
|
+
"oxfmt": "^0.73.0",
|
|
44
|
+
"tsdown": "^0.23.1",
|
|
45
45
|
"typescript": "^6.0.3",
|
|
46
|
-
"vitest": "^
|
|
46
|
+
"vitest": "^5.0.5"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsdown",
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { ESLint } from 'eslint'
|
|
|
3
3
|
import { version } from '../package.json'
|
|
4
4
|
|
|
5
5
|
import noImplicitArrowLinebreak from './rules/no-implicit-arrow-linebreak'
|
|
6
|
+
import preferWhileTrue from './rules/prefer-while-true'
|
|
6
7
|
|
|
7
8
|
const plugin = {
|
|
8
9
|
meta: {
|
|
@@ -11,6 +12,7 @@ const plugin = {
|
|
|
11
12
|
},
|
|
12
13
|
rules: {
|
|
13
14
|
'no-implicit-arrow-linebreak': noImplicitArrowLinebreak,
|
|
15
|
+
'prefer-while-true': preferWhileTrue,
|
|
14
16
|
},
|
|
15
17
|
} satisfies ESLint.Plugin
|
|
16
18
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { RuleTester } from 'eslint'
|
|
2
|
+
import { test } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import rule from './prefer-while-true'
|
|
5
|
+
|
|
6
|
+
test('prefer-while-true', () => {
|
|
7
|
+
const tester = new RuleTester({
|
|
8
|
+
languageOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
tester.run('prefer-while-true', rule, {
|
|
12
|
+
valid: [
|
|
13
|
+
'while (true) {}',
|
|
14
|
+
'for (let i = 0; i < 10; i++) {}',
|
|
15
|
+
'for (; i < 10; ) {}',
|
|
16
|
+
'for (let i = 0; ; i++) {}',
|
|
17
|
+
'for (const x of xs) {}',
|
|
18
|
+
],
|
|
19
|
+
invalid: [
|
|
20
|
+
{
|
|
21
|
+
code: 'for (;;) {\n fn()\n}',
|
|
22
|
+
output: 'while (true) {\n fn()\n}',
|
|
23
|
+
errors: [{ messageId: 'preferWhileTrue' }],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
code: 'for ( ; ; ) fn()',
|
|
27
|
+
output: 'while (true) fn()',
|
|
28
|
+
errors: [{ messageId: 'preferWhileTrue' }],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: 'outer: for (;;) {\n for (;;) break outer\n}',
|
|
32
|
+
output: 'outer: while (true) {\n while (true) break outer\n}',
|
|
33
|
+
errors: [{ messageId: 'preferWhileTrue' }, { messageId: 'preferWhileTrue' }],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
// No autofix when a comment sits inside the loop head.
|
|
37
|
+
code: 'for (; /* forever */ ;) {}',
|
|
38
|
+
output: null,
|
|
39
|
+
errors: [{ messageId: 'preferWhileTrue' }],
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Rule } from 'eslint'
|
|
2
|
+
|
|
3
|
+
const rule: Rule.RuleModule = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'suggestion',
|
|
6
|
+
fixable: 'code',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'enforce `while (true)` instead of `for (;;)` for infinite loops',
|
|
9
|
+
url: 'https://github.com/ocavue/eslint-plugin-ocavue#prefer-while-true',
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
preferWhileTrue: 'Use `while (true)` instead of `for (;;)`.',
|
|
13
|
+
},
|
|
14
|
+
schema: [],
|
|
15
|
+
},
|
|
16
|
+
create(context) {
|
|
17
|
+
const sourceCode = context.sourceCode
|
|
18
|
+
return {
|
|
19
|
+
ForStatement(node) {
|
|
20
|
+
if (node.init || node.test || node.update) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const forToken = sourceCode.getFirstToken(node)
|
|
25
|
+
const closingParen = sourceCode.getTokenBefore(node.body)
|
|
26
|
+
if (!forToken || !closingParen) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Bail out of fixing (but still report) if the loop head contains
|
|
31
|
+
// comments, so the fix never drops a comment.
|
|
32
|
+
const canFix = !sourceCode.commentsExistBetween(forToken, closingParen)
|
|
33
|
+
|
|
34
|
+
context.report({
|
|
35
|
+
node,
|
|
36
|
+
loc: { start: forToken.loc.start, end: closingParen.loc.end },
|
|
37
|
+
messageId: 'preferWhileTrue',
|
|
38
|
+
fix: canFix
|
|
39
|
+
? (fixer) => {
|
|
40
|
+
return fixer.replaceTextRange(
|
|
41
|
+
[forToken.range[0], closingParen.range[1]],
|
|
42
|
+
'while (true)',
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
: undefined,
|
|
46
|
+
})
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default rule
|