@flint.fyi/ts 0.14.2 → 0.14.3
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/CHANGELOG.md +7 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/nodes.d.ts +1 -0
- package/lib/plugin.d.ts +121 -1
- package/lib/plugin.js +60 -0
- package/lib/rules/asyncPromiseExecutors.d.ts +6 -0
- package/lib/rules/asyncPromiseExecutors.js +51 -0
- package/lib/rules/asyncPromiseExecutors.test.d.ts +1 -0
- package/lib/rules/asyncPromiseExecutors.test.js +71 -0
- package/lib/rules/caseDeclarations.d.ts +6 -0
- package/lib/rules/caseDeclarations.js +53 -0
- package/lib/rules/caseDeclarations.test.d.ts +1 -0
- package/lib/rules/caseDeclarations.test.js +227 -0
- package/lib/rules/chainedAssignments.d.ts +6 -0
- package/lib/rules/chainedAssignments.js +48 -0
- package/lib/rules/chainedAssignments.test.d.ts +1 -0
- package/lib/rules/chainedAssignments.test.js +238 -0
- package/lib/rules/classAssignments.d.ts +6 -0
- package/lib/rules/classAssignments.js +42 -0
- package/lib/rules/classAssignments.test.d.ts +1 -0
- package/lib/rules/classAssignments.test.js +156 -0
- package/lib/rules/constantAssignments.d.ts +6 -0
- package/lib/rules/constantAssignments.js +61 -0
- package/lib/rules/constantAssignments.test.d.ts +1 -0
- package/lib/rules/constantAssignments.test.js +221 -0
- package/lib/rules/constructorReturns.d.ts +6 -0
- package/lib/rules/constructorReturns.js +52 -0
- package/lib/rules/constructorReturns.test.d.ts +1 -0
- package/lib/rules/constructorReturns.test.js +96 -0
- package/lib/rules/defaultCaseLast.d.ts +6 -0
- package/lib/rules/defaultCaseLast.js +43 -0
- package/lib/rules/defaultCaseLast.test.d.ts +1 -0
- package/lib/rules/defaultCaseLast.test.js +195 -0
- package/lib/rules/duplicateArguments.d.ts +6 -0
- package/lib/rules/duplicateArguments.js +51 -0
- package/lib/rules/duplicateArguments.test.d.ts +1 -0
- package/lib/rules/duplicateArguments.test.js +139 -0
- package/lib/rules/emptyDestructures.d.ts +6 -0
- package/lib/rules/emptyDestructures.js +40 -0
- package/lib/rules/emptyDestructures.test.d.ts +1 -0
- package/lib/rules/emptyDestructures.test.js +186 -0
- package/lib/rules/emptyStaticBlocks.d.ts +6 -0
- package/lib/rules/emptyStaticBlocks.js +54 -0
- package/lib/rules/emptyStaticBlocks.test.d.ts +1 -0
- package/lib/rules/emptyStaticBlocks.test.js +167 -0
- package/lib/rules/exceptionAssignments.d.ts +6 -0
- package/lib/rules/exceptionAssignments.js +61 -0
- package/lib/rules/exceptionAssignments.test.d.ts +1 -0
- package/lib/rules/exceptionAssignments.test.js +264 -0
- package/lib/rules/functionAssignments.d.ts +6 -0
- package/lib/rules/functionAssignments.js +42 -0
- package/lib/rules/functionAssignments.test.d.ts +1 -0
- package/lib/rules/functionAssignments.test.js +209 -0
- package/lib/rules/generatorFunctionYields.d.ts +6 -0
- package/lib/rules/generatorFunctionYields.js +57 -0
- package/lib/rules/generatorFunctionYields.test.d.ts +1 -0
- package/lib/rules/generatorFunctionYields.test.js +151 -0
- package/lib/rules/globalAssignments.d.ts +6 -0
- package/lib/rules/globalAssignments.js +59 -0
- package/lib/rules/globalAssignments.test.d.ts +1 -0
- package/lib/rules/globalAssignments.test.js +215 -0
- package/lib/rules/globalObjectCalls.d.ts +6 -0
- package/lib/rules/globalObjectCalls.js +43 -0
- package/lib/rules/globalObjectCalls.test.d.ts +1 -0
- package/lib/rules/globalObjectCalls.test.js +93 -0
- package/lib/rules/negativeZeroComparisons.d.ts +6 -0
- package/lib/rules/negativeZeroComparisons.js +83 -0
- package/lib/rules/negativeZeroComparisons.test.d.ts +1 -0
- package/lib/rules/negativeZeroComparisons.test.js +209 -0
- package/lib/rules/newExpressions.d.ts +6 -0
- package/lib/rules/newExpressions.js +54 -0
- package/lib/rules/newExpressions.test.d.ts +1 -0
- package/lib/rules/newExpressions.test.js +79 -0
- package/lib/rules/newNativeNonConstructors.d.ts +6 -0
- package/lib/rules/newNativeNonConstructors.js +49 -0
- package/lib/rules/newNativeNonConstructors.test.d.ts +1 -0
- package/lib/rules/newNativeNonConstructors.test.js +94 -0
- package/lib/rules/objectProto.d.ts +6 -0
- package/lib/rules/objectProto.js +54 -0
- package/lib/rules/objectProto.test.d.ts +1 -0
- package/lib/rules/objectProto.test.js +96 -0
- package/lib/rules/octalNumbers.d.ts +6 -0
- package/lib/rules/octalNumbers.js +68 -0
- package/lib/rules/octalNumbers.test.d.ts +1 -0
- package/lib/rules/octalNumbers.test.js +245 -0
- package/lib/rules/returnAssignments.d.ts +6 -0
- package/lib/rules/returnAssignments.js +50 -0
- package/lib/rules/returnAssignments.test.d.ts +1 -0
- package/lib/rules/returnAssignments.test.js +185 -0
- package/lib/rules/sparseArrays.d.ts +6 -0
- package/lib/rules/sparseArrays.js +54 -0
- package/lib/rules/sparseArrays.test.d.ts +1 -0
- package/lib/rules/sparseArrays.test.js +110 -0
- package/lib/rules/symbolDescriptions.d.ts +6 -0
- package/lib/rules/symbolDescriptions.js +41 -0
- package/lib/rules/symbolDescriptions.test.d.ts +1 -0
- package/lib/rules/symbolDescriptions.test.js +89 -0
- package/lib/rules/unassignedVariables.d.ts +6 -0
- package/lib/rules/unassignedVariables.js +55 -0
- package/lib/rules/unassignedVariables.test.d.ts +1 -0
- package/lib/rules/unassignedVariables.test.js +72 -0
- package/lib/rules/undefinedVariables.d.ts +6 -0
- package/lib/rules/undefinedVariables.js +76 -0
- package/lib/rules/undefinedVariables.test.d.ts +1 -0
- package/lib/rules/undefinedVariables.test.js +80 -0
- package/lib/rules/unicodeBOMs.d.ts +6 -0
- package/lib/rules/unicodeBOMs.js +41 -0
- package/lib/rules/unicodeBOMs.test.d.ts +1 -0
- package/lib/rules/unicodeBOMs.test.js +65 -0
- package/lib/rules/unnecessaryCatches.d.ts +6 -0
- package/lib/rules/unnecessaryCatches.js +68 -0
- package/lib/rules/unnecessaryCatches.test.d.ts +1 -0
- package/lib/rules/unnecessaryCatches.test.js +210 -0
- package/lib/rules/unsafeNegations.d.ts +6 -0
- package/lib/rules/unsafeNegations.js +50 -0
- package/lib/rules/unsafeNegations.test.d.ts +1 -0
- package/lib/rules/unsafeNegations.test.js +63 -0
- package/lib/rules/variableDeletions.d.ts +6 -0
- package/lib/rules/variableDeletions.js +39 -0
- package/lib/rules/variableDeletions.test.d.ts +1 -0
- package/lib/rules/variableDeletions.test.js +75 -0
- package/lib/rules/voidOperator.d.ts +6 -0
- package/lib/rules/voidOperator.js +36 -0
- package/lib/rules/voidOperator.test.d.ts +1 -0
- package/lib/rules/voidOperator.test.js +98 -0
- package/lib/utils/declarationsIncludeGlobal.d.ts +2 -0
- package/lib/utils/declarationsIncludeGlobal.js +7 -0
- package/lib/utils/getModifyingReferences.d.ts +8 -0
- package/lib/utils/getModifyingReferences.js +42 -0
- package/lib/utils/isGlobalDeclaration.d.ts +2 -0
- package/lib/utils/isGlobalDeclaration.js +5 -0
- package/lib/utils/isGlobalVariable.d.ts +8 -0
- package/lib/utils/isGlobalVariable.js +21 -0
- package/lib/utils/unwrapParentParenthesizedExpressions.d.ts +2 -0
- package/lib/utils/unwrapParentParenthesizedExpressions.js +6 -0
- package/lib/utils/unwrapParenthesizedExpression.d.ts +2 -0
- package/lib/utils/unwrapParenthesizedExpression.js +6 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/nodes.ts +1 -0
- package/src/plugin.ts +60 -0
- package/src/rules/asyncPromiseExecutors.test.ts +72 -0
- package/src/rules/asyncPromiseExecutors.ts +61 -0
- package/src/rules/caseDeclarations.test.ts +228 -0
- package/src/rules/caseDeclarations.ts +70 -0
- package/src/rules/chainedAssignments.test.ts +239 -0
- package/src/rules/chainedAssignments.ts +55 -0
- package/src/rules/classAssignments.test.ts +157 -0
- package/src/rules/classAssignments.ts +50 -0
- package/src/rules/constantAssignments.test.ts +222 -0
- package/src/rules/constantAssignments.ts +78 -0
- package/src/rules/constructorReturns.test.ts +97 -0
- package/src/rules/constructorReturns.ts +59 -0
- package/src/rules/defaultCaseLast.test.ts +196 -0
- package/src/rules/defaultCaseLast.ts +54 -0
- package/src/rules/duplicateArguments.test.ts +140 -0
- package/src/rules/duplicateArguments.ts +58 -0
- package/src/rules/emptyDestructures.test.ts +187 -0
- package/src/rules/emptyDestructures.ts +48 -0
- package/src/rules/emptyStaticBlocks.test.ts +168 -0
- package/src/rules/emptyStaticBlocks.ts +60 -0
- package/src/rules/exceptionAssignments.test.ts +265 -0
- package/src/rules/exceptionAssignments.ts +77 -0
- package/src/rules/functionAssignments.test.ts +210 -0
- package/src/rules/functionAssignments.ts +51 -0
- package/src/rules/generatorFunctionYields.test.ts +152 -0
- package/src/rules/generatorFunctionYields.ts +71 -0
- package/src/rules/globalAssignments.test.ts +216 -0
- package/src/rules/globalAssignments.ts +67 -0
- package/src/rules/globalObjectCalls.test.ts +94 -0
- package/src/rules/globalObjectCalls.ts +52 -0
- package/src/rules/negativeZeroComparisons.test.ts +210 -0
- package/src/rules/negativeZeroComparisons.ts +106 -0
- package/src/rules/newExpressions.test.ts +80 -0
- package/src/rules/newExpressions.ts +67 -0
- package/src/rules/newNativeNonConstructors.test.ts +95 -0
- package/src/rules/newNativeNonConstructors.ts +59 -0
- package/src/rules/objectProto.test.ts +97 -0
- package/src/rules/objectProto.ts +62 -0
- package/src/rules/octalNumbers.test.ts +246 -0
- package/src/rules/octalNumbers.ts +75 -0
- package/src/rules/returnAssignments.test.ts +186 -0
- package/src/rules/returnAssignments.ts +57 -0
- package/src/rules/sparseArrays.test.ts +111 -0
- package/src/rules/sparseArrays.ts +61 -0
- package/src/rules/symbolDescriptions.test.ts +90 -0
- package/src/rules/symbolDescriptions.ts +47 -0
- package/src/rules/unassignedVariables.test.ts +73 -0
- package/src/rules/unassignedVariables.ts +69 -0
- package/src/rules/undefinedVariables.test.ts +81 -0
- package/src/rules/undefinedVariables.ts +97 -0
- package/src/rules/unicodeBOMs.test.ts +66 -0
- package/src/rules/unicodeBOMs.ts +44 -0
- package/src/rules/unnecessaryCatches.test.ts +211 -0
- package/src/rules/unnecessaryCatches.ts +84 -0
- package/src/rules/unsafeNegations.test.ts +64 -0
- package/src/rules/unsafeNegations.ts +59 -0
- package/src/rules/variableDeletions.test.ts +76 -0
- package/src/rules/variableDeletions.ts +43 -0
- package/src/rules/voidOperator.test.ts +99 -0
- package/src/rules/voidOperator.ts +38 -0
- package/src/utils/declarationsIncludeGlobal.ts +11 -0
- package/src/utils/getModifyingReferences.ts +58 -0
- package/src/utils/isGlobalDeclaration.ts +12 -0
- package/src/utils/isGlobalVariable.ts +30 -0
- package/src/utils/unwrapParentParenthesizedExpressions.ts +7 -0
- package/src/utils/unwrapParenthesizedExpression.ts +9 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import rule from "./caseDeclarations.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
ruleTester.describe(rule, {
|
|
4
|
+
invalid: [
|
|
5
|
+
{
|
|
6
|
+
code: `
|
|
7
|
+
switch (value) {
|
|
8
|
+
case 1:
|
|
9
|
+
let x = 1;
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
`,
|
|
13
|
+
snapshot: `
|
|
14
|
+
switch (value) {
|
|
15
|
+
case 1:
|
|
16
|
+
let x = 1;
|
|
17
|
+
~~~
|
|
18
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
code: `
|
|
25
|
+
switch (value) {
|
|
26
|
+
case 1:
|
|
27
|
+
const x = 1;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
`,
|
|
31
|
+
snapshot: `
|
|
32
|
+
switch (value) {
|
|
33
|
+
case 1:
|
|
34
|
+
const x = 1;
|
|
35
|
+
~~~~~
|
|
36
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
`,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
code: `
|
|
43
|
+
switch (value) {
|
|
44
|
+
case 1:
|
|
45
|
+
function foo() {}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
`,
|
|
49
|
+
snapshot: `
|
|
50
|
+
switch (value) {
|
|
51
|
+
case 1:
|
|
52
|
+
function foo() {}
|
|
53
|
+
~~~~~~~~
|
|
54
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
`,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
code: `
|
|
61
|
+
switch (value) {
|
|
62
|
+
case 1:
|
|
63
|
+
class Foo {}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
`,
|
|
67
|
+
snapshot: `
|
|
68
|
+
switch (value) {
|
|
69
|
+
case 1:
|
|
70
|
+
class Foo {}
|
|
71
|
+
~~~~~
|
|
72
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
`,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
code: `
|
|
79
|
+
switch (value) {
|
|
80
|
+
default:
|
|
81
|
+
let x = 1;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
`,
|
|
85
|
+
snapshot: `
|
|
86
|
+
switch (value) {
|
|
87
|
+
default:
|
|
88
|
+
let x = 1;
|
|
89
|
+
~~~
|
|
90
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
`,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
code: `
|
|
97
|
+
switch (value) {
|
|
98
|
+
default:
|
|
99
|
+
const x = 1;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
`,
|
|
103
|
+
snapshot: `
|
|
104
|
+
switch (value) {
|
|
105
|
+
default:
|
|
106
|
+
const x = 1;
|
|
107
|
+
~~~~~
|
|
108
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
`,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
code: `
|
|
115
|
+
switch (value) {
|
|
116
|
+
case 1:
|
|
117
|
+
let x = 1;
|
|
118
|
+
case 2:
|
|
119
|
+
let y = 2;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
`,
|
|
123
|
+
snapshot: `
|
|
124
|
+
switch (value) {
|
|
125
|
+
case 1:
|
|
126
|
+
let x = 1;
|
|
127
|
+
~~~
|
|
128
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
129
|
+
case 2:
|
|
130
|
+
let y = 2;
|
|
131
|
+
~~~
|
|
132
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
`,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
code: `
|
|
139
|
+
switch (value) {
|
|
140
|
+
case 1:
|
|
141
|
+
const x = 1;
|
|
142
|
+
console.log(x);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
`,
|
|
146
|
+
snapshot: `
|
|
147
|
+
switch (value) {
|
|
148
|
+
case 1:
|
|
149
|
+
const x = 1;
|
|
150
|
+
~~~~~
|
|
151
|
+
Variables declared in case clauses without braces leak into the surrounding scope.
|
|
152
|
+
console.log(x);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
`,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
valid: [
|
|
159
|
+
`switch (value) { case 1: { let x = 1; break; } }`,
|
|
160
|
+
`switch (value) { case 1: { const x = 1; break; } }`,
|
|
161
|
+
`switch (value) { case 1: { function foo() {} break; } }`,
|
|
162
|
+
`switch (value) { case 1: { class Foo {} break; } }`,
|
|
163
|
+
`switch (value) { default: { let x = 1; break; } }`,
|
|
164
|
+
`switch (value) { default: { const x = 1; break; } }`,
|
|
165
|
+
`switch (value) { case 1: var x = 1; break; }`,
|
|
166
|
+
`switch (value) { case 1: break; }`,
|
|
167
|
+
`switch (value) { case 1: console.log("test"); break; }`,
|
|
168
|
+
`
|
|
169
|
+
switch (value) {
|
|
170
|
+
case 1: {
|
|
171
|
+
let x = 1;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
`,
|
|
176
|
+
`
|
|
177
|
+
switch (value) {
|
|
178
|
+
case 1: {
|
|
179
|
+
const x = 1;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
`,
|
|
184
|
+
`
|
|
185
|
+
switch (value) {
|
|
186
|
+
case 1: {
|
|
187
|
+
function foo() {}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
`,
|
|
192
|
+
`
|
|
193
|
+
switch (value) {
|
|
194
|
+
case 1: {
|
|
195
|
+
class Foo {}
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
`,
|
|
200
|
+
`
|
|
201
|
+
switch (value) {
|
|
202
|
+
case 1:
|
|
203
|
+
var x = 1;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
`,
|
|
207
|
+
`
|
|
208
|
+
switch (value) {
|
|
209
|
+
case 1: {
|
|
210
|
+
let x = 1;
|
|
211
|
+
}
|
|
212
|
+
case 2: {
|
|
213
|
+
let y = 2;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
`,
|
|
218
|
+
`
|
|
219
|
+
switch (value) {
|
|
220
|
+
default: {
|
|
221
|
+
let x = 1;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
`,
|
|
226
|
+
],
|
|
227
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports using chained assignment expressions (e.g., a = b = c).";
|
|
3
|
+
readonly id: "chainedAssignments";
|
|
4
|
+
readonly preset: "stylistic";
|
|
5
|
+
}, import("../nodes.js").TSNodesByName, import("../language.js").TypeScriptServices, "noChainedAssignment", undefined>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as tsutils from "ts-api-utils";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
import { getTSNodeRange } from "../getTSNodeRange.js";
|
|
4
|
+
import { typescriptLanguage } from "../language.js";
|
|
5
|
+
import { unwrapParenthesizedExpression } from "../utils/unwrapParenthesizedExpression.js";
|
|
6
|
+
import { unwrapParenthesizedExpressionsParent } from "../utils/unwrapParentParenthesizedExpressions.js";
|
|
7
|
+
export default typescriptLanguage.createRule({
|
|
8
|
+
about: {
|
|
9
|
+
description: "Reports using chained assignment expressions (e.g., a = b = c).",
|
|
10
|
+
id: "chainedAssignments",
|
|
11
|
+
preset: "stylistic",
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noChainedAssignment: {
|
|
15
|
+
primary: "Prefer separate assignment statements for readability instead of chaining assignments.",
|
|
16
|
+
secondary: [
|
|
17
|
+
"Chained assignments can be hard to read and can lead to unexpected behavior with variable scoping and type inference.",
|
|
18
|
+
"Each assignment creates a reference to the same value, which may cause confusion when dealing with mutable values.",
|
|
19
|
+
],
|
|
20
|
+
suggestions: [
|
|
21
|
+
"Break the chained assignment into separate assignment statements, one for each variable.",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
setup(context) {
|
|
26
|
+
return {
|
|
27
|
+
visitors: {
|
|
28
|
+
BinaryExpression: (node) => {
|
|
29
|
+
if (!tsutils.isAssignmentKind(node.operatorToken.kind)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const rightSide = unwrapParenthesizedExpression(node.right);
|
|
33
|
+
if (!ts.isBinaryExpression(rightSide)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const parent = unwrapParenthesizedExpressionsParent(node);
|
|
37
|
+
if (ts.isBinaryExpression(parent)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
context.report({
|
|
41
|
+
message: "noChainedAssignment",
|
|
42
|
+
range: getTSNodeRange(node.operatorToken, context.sourceFile),
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import rule from "./chainedAssignments.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
ruleTester.describe(rule, {
|
|
4
|
+
invalid: [
|
|
5
|
+
{
|
|
6
|
+
code: `
|
|
7
|
+
let first;
|
|
8
|
+
let second;
|
|
9
|
+
first = second = 1;
|
|
10
|
+
`,
|
|
11
|
+
snapshot: `
|
|
12
|
+
let first;
|
|
13
|
+
let second;
|
|
14
|
+
first = second = 1;
|
|
15
|
+
~
|
|
16
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
17
|
+
`,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
code: `
|
|
21
|
+
let first;
|
|
22
|
+
let second;
|
|
23
|
+
let third;
|
|
24
|
+
first = second = third = 0;
|
|
25
|
+
`,
|
|
26
|
+
snapshot: `
|
|
27
|
+
let first;
|
|
28
|
+
let second;
|
|
29
|
+
let third;
|
|
30
|
+
first = second = third = 0;
|
|
31
|
+
~
|
|
32
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
33
|
+
`,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
code: `
|
|
37
|
+
let value;
|
|
38
|
+
let another;
|
|
39
|
+
value = another = getValue();
|
|
40
|
+
`,
|
|
41
|
+
snapshot: `
|
|
42
|
+
let value;
|
|
43
|
+
let another;
|
|
44
|
+
value = another = getValue();
|
|
45
|
+
~
|
|
46
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
47
|
+
`,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
code: `
|
|
51
|
+
let first;
|
|
52
|
+
let second;
|
|
53
|
+
(first = second = 1);
|
|
54
|
+
`,
|
|
55
|
+
snapshot: `
|
|
56
|
+
let first;
|
|
57
|
+
let second;
|
|
58
|
+
(first = second = 1);
|
|
59
|
+
~
|
|
60
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
61
|
+
`,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
code: `
|
|
65
|
+
const calculate = (value: number) => {
|
|
66
|
+
let first;
|
|
67
|
+
let second;
|
|
68
|
+
first = second = value;
|
|
69
|
+
return first + second;
|
|
70
|
+
};
|
|
71
|
+
`,
|
|
72
|
+
snapshot: `
|
|
73
|
+
const calculate = (value: number) => {
|
|
74
|
+
let first;
|
|
75
|
+
let second;
|
|
76
|
+
first = second = value;
|
|
77
|
+
~
|
|
78
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
79
|
+
return first + second;
|
|
80
|
+
};
|
|
81
|
+
`,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
code: `
|
|
85
|
+
let first;
|
|
86
|
+
let second;
|
|
87
|
+
if (true) {
|
|
88
|
+
first = second = 10;
|
|
89
|
+
}
|
|
90
|
+
`,
|
|
91
|
+
snapshot: `
|
|
92
|
+
let first;
|
|
93
|
+
let second;
|
|
94
|
+
if (true) {
|
|
95
|
+
first = second = 10;
|
|
96
|
+
~
|
|
97
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
98
|
+
}
|
|
99
|
+
`,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
code: `
|
|
103
|
+
class MyClass {
|
|
104
|
+
method() {
|
|
105
|
+
let first;
|
|
106
|
+
let second;
|
|
107
|
+
first = second = 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
`,
|
|
111
|
+
snapshot: `
|
|
112
|
+
class MyClass {
|
|
113
|
+
method() {
|
|
114
|
+
let first;
|
|
115
|
+
let second;
|
|
116
|
+
first = second = 0;
|
|
117
|
+
~
|
|
118
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
`,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
code: `
|
|
125
|
+
let first;
|
|
126
|
+
let second;
|
|
127
|
+
let third;
|
|
128
|
+
first = (second = third = 5);
|
|
129
|
+
`,
|
|
130
|
+
snapshot: `
|
|
131
|
+
let first;
|
|
132
|
+
let second;
|
|
133
|
+
let third;
|
|
134
|
+
first = (second = third = 5);
|
|
135
|
+
~
|
|
136
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
137
|
+
`,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
code: `
|
|
141
|
+
let first;
|
|
142
|
+
let second;
|
|
143
|
+
first ||= second ||= 1;
|
|
144
|
+
`,
|
|
145
|
+
snapshot: `
|
|
146
|
+
let first;
|
|
147
|
+
let second;
|
|
148
|
+
first ||= second ||= 1;
|
|
149
|
+
~~~
|
|
150
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
151
|
+
`,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
code: `
|
|
155
|
+
let first;
|
|
156
|
+
let second;
|
|
157
|
+
first ??= second ??= 0;
|
|
158
|
+
`,
|
|
159
|
+
snapshot: `
|
|
160
|
+
let first;
|
|
161
|
+
let second;
|
|
162
|
+
first ??= second ??= 0;
|
|
163
|
+
~~~
|
|
164
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
165
|
+
`,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
code: `
|
|
169
|
+
let first;
|
|
170
|
+
let second;
|
|
171
|
+
first += second += 5;
|
|
172
|
+
`,
|
|
173
|
+
snapshot: `
|
|
174
|
+
let first;
|
|
175
|
+
let second;
|
|
176
|
+
first += second += 5;
|
|
177
|
+
~~
|
|
178
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
179
|
+
`,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
code: `
|
|
183
|
+
let first;
|
|
184
|
+
let second;
|
|
185
|
+
first |= second |= 3;
|
|
186
|
+
`,
|
|
187
|
+
snapshot: `
|
|
188
|
+
let first;
|
|
189
|
+
let second;
|
|
190
|
+
first |= second |= 3;
|
|
191
|
+
~~
|
|
192
|
+
Prefer separate assignment statements for readability instead of chaining assignments.
|
|
193
|
+
`,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
valid: [
|
|
197
|
+
`let first = 1;`,
|
|
198
|
+
`let first = 1, second = 2;`,
|
|
199
|
+
`let first = 1; let second = 2;`,
|
|
200
|
+
`let first; let second; first = 1; second = 2;`,
|
|
201
|
+
`let first; let second; first = 1; second = first;`,
|
|
202
|
+
`const value = getValue();`,
|
|
203
|
+
`let first; first = 1;`,
|
|
204
|
+
`
|
|
205
|
+
let first;
|
|
206
|
+
let second;
|
|
207
|
+
first = 1;
|
|
208
|
+
second = 2;
|
|
209
|
+
`,
|
|
210
|
+
`
|
|
211
|
+
let first;
|
|
212
|
+
let second;
|
|
213
|
+
let third;
|
|
214
|
+
first = 1;
|
|
215
|
+
second = 2;
|
|
216
|
+
third = 3;
|
|
217
|
+
`,
|
|
218
|
+
`
|
|
219
|
+
const calculate = (value: number) => {
|
|
220
|
+
let first;
|
|
221
|
+
let second;
|
|
222
|
+
first = value;
|
|
223
|
+
second = value;
|
|
224
|
+
return first + second;
|
|
225
|
+
};
|
|
226
|
+
`,
|
|
227
|
+
`
|
|
228
|
+
class MyClass {
|
|
229
|
+
method() {
|
|
230
|
+
let first;
|
|
231
|
+
let second;
|
|
232
|
+
first = 0;
|
|
233
|
+
second = 0;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
`,
|
|
237
|
+
],
|
|
238
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports reassigning class declarations.";
|
|
3
|
+
readonly id: "classAssignments";
|
|
4
|
+
readonly preset: "untyped";
|
|
5
|
+
}, import("../nodes.js").TSNodesByName, import("../language.js").TypeScriptServices, "noClassAssign", undefined>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { typescriptLanguage } from "../language.js";
|
|
2
|
+
import { getModifyingReferences } from "../utils/getModifyingReferences.js";
|
|
3
|
+
export default typescriptLanguage.createRule({
|
|
4
|
+
about: {
|
|
5
|
+
description: "Reports reassigning class declarations.",
|
|
6
|
+
id: "classAssignments",
|
|
7
|
+
preset: "untyped",
|
|
8
|
+
},
|
|
9
|
+
messages: {
|
|
10
|
+
noClassAssign: {
|
|
11
|
+
primary: "Reassigning a class declaration is misleading and makes the class harder to use.",
|
|
12
|
+
secondary: [
|
|
13
|
+
"Reassigning a class declaration can lead to unexpected behavior and makes code harder to understand.",
|
|
14
|
+
"Class declarations are typically intended to be immutable references, and reassigning them can cause confusion about which class is being used.",
|
|
15
|
+
],
|
|
16
|
+
suggestions: [
|
|
17
|
+
"Use a different variable name if you need to store a modified reference to a class.",
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
setup(context) {
|
|
22
|
+
return {
|
|
23
|
+
visitors: {
|
|
24
|
+
ClassDeclaration: (node) => {
|
|
25
|
+
if (!node.name) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const modifyingReferences = getModifyingReferences(node.name, context.sourceFile, context.typeChecker);
|
|
29
|
+
for (const reference of modifyingReferences) {
|
|
30
|
+
context.report({
|
|
31
|
+
message: "noClassAssign",
|
|
32
|
+
range: {
|
|
33
|
+
begin: reference.getStart(context.sourceFile),
|
|
34
|
+
end: reference.getEnd(),
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|