@flint.fyi/ts 0.14.2 → 0.14.4
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 +17 -0
- package/lib/createTypeScriptFileFromProgram.js +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/language.d.ts +1 -0
- package/lib/nodes.d.ts +1 -0
- package/lib/plugin.d.ts +165 -1
- package/lib/plugin.js +82 -0
- package/lib/rules/anyReturns.d.ts +6 -0
- package/lib/rules/anyReturns.js +187 -0
- package/lib/rules/anyReturns.test.d.ts +1 -0
- package/lib/rules/anyReturns.test.js +647 -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/caseDuplicates.d.ts +6 -0
- package/lib/rules/caseDuplicates.js +49 -0
- package/lib/rules/caseDuplicates.test.d.ts +1 -0
- package/lib/rules/caseDuplicates.test.js +307 -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/elseIfDuplicates.d.ts +6 -0
- package/lib/rules/elseIfDuplicates.js +53 -0
- package/lib/rules/elseIfDuplicates.test.d.ts +1 -0
- package/lib/rules/elseIfDuplicates.test.js +176 -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/forDirections.d.ts +6 -0
- package/lib/rules/forDirections.js +124 -0
- package/lib/rules/forDirections.test.d.ts +1 -0
- package/lib/rules/forDirections.test.js +99 -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/functionNewCalls.d.ts +6 -0
- package/lib/rules/functionNewCalls.js +60 -0
- package/lib/rules/functionNewCalls.test.d.ts +1 -0
- package/lib/rules/functionNewCalls.test.js +115 -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 +65 -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/nonOctalDecimalEscapes.d.ts +6 -0
- package/lib/rules/nonOctalDecimalEscapes.js +57 -0
- package/lib/rules/nonOctalDecimalEscapes.test.d.ts +1 -0
- package/lib/rules/nonOctalDecimalEscapes.test.js +69 -0
- package/lib/rules/numericLiteralParsing.d.ts +6 -0
- package/lib/rules/numericLiteralParsing.js +97 -0
- package/lib/rules/numericLiteralParsing.test.d.ts +1 -0
- package/lib/rules/numericLiteralParsing.test.js +99 -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/selfAssignments.d.ts +6 -0
- package/lib/rules/selfAssignments.js +44 -0
- package/lib/rules/selfAssignments.test.d.ts +1 -0
- package/lib/rules/selfAssignments.test.js +66 -0
- package/lib/rules/selfComparisons.d.ts +6 -0
- package/lib/rules/selfComparisons.js +41 -0
- package/lib/rules/selfComparisons.test.d.ts +1 -0
- package/lib/rules/selfComparisons.test.js +297 -0
- package/lib/rules/sequences.d.ts +6 -0
- package/lib/rules/sequences.js +34 -0
- package/lib/rules/sequences.test.d.ts +1 -0
- package/lib/rules/sequences.test.js +48 -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/typeofComparisons.d.ts +6 -0
- package/lib/rules/typeofComparisons.js +78 -0
- package/lib/rules/typeofComparisons.test.d.ts +1 -0
- package/lib/rules/typeofComparisons.test.js +85 -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/utils/discriminateAnyType.d.ts +12 -0
- package/lib/rules/utils/discriminateAnyType.js +41 -0
- package/lib/rules/utils/getThisExpression.d.ts +2 -0
- package/lib/rules/utils/getThisExpression.js +23 -0
- package/lib/rules/utils/isUnsafeAssignment.d.ts +13 -0
- package/lib/rules/utils/isUnsafeAssignment.js +76 -0
- package/lib/rules/utils/operators.d.ts +4 -0
- package/lib/rules/utils/operators.js +36 -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/declarationIncludesGlobal.d.ts +2 -0
- package/lib/utils/declarationIncludesGlobal.js +5 -0
- package/lib/utils/declarationsIncludeGlobal.d.ts +2 -0
- package/lib/utils/declarationsIncludeGlobal.js +4 -0
- package/lib/utils/getModifyingReferences.d.ts +8 -0
- package/lib/utils/getModifyingReferences.js +42 -0
- package/lib/utils/hasSameTokens.d.ts +2 -0
- package/lib/utils/hasSameTokens.js +30 -0
- package/lib/utils/isGlobalDeclaration.d.ts +2 -0
- package/lib/utils/isGlobalDeclaration.js +5 -0
- package/lib/utils/isGlobalDeclarationOfName.d.ts +5 -0
- package/lib/utils/isGlobalDeclarationOfName.js +31 -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/createTypeScriptFileFromProgram.ts +1 -0
- package/src/index.ts +1 -0
- package/src/language.ts +1 -0
- package/src/nodes.ts +1 -0
- package/src/plugin.ts +82 -0
- package/src/rules/anyReturns.test.ts +649 -0
- package/src/rules/anyReturns.ts +263 -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/caseDuplicates.test.ts +308 -0
- package/src/rules/caseDuplicates.ts +57 -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/elseIfDuplicates.test.ts +177 -0
- package/src/rules/elseIfDuplicates.ts +69 -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/forDirections.test.ts +100 -0
- package/src/rules/forDirections.ts +163 -0
- package/src/rules/functionAssignments.test.ts +210 -0
- package/src/rules/functionAssignments.ts +51 -0
- package/src/rules/functionNewCalls.test.ts +116 -0
- package/src/rules/functionNewCalls.ts +75 -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 +87 -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/nonOctalDecimalEscapes.test.ts +70 -0
- package/src/rules/nonOctalDecimalEscapes.ts +70 -0
- package/src/rules/numericLiteralParsing.test.ts +100 -0
- package/src/rules/numericLiteralParsing.ts +116 -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/selfAssignments.test.ts +67 -0
- package/src/rules/selfAssignments.ts +50 -0
- package/src/rules/selfComparisons.test.ts +298 -0
- package/src/rules/selfComparisons.ts +45 -0
- package/src/rules/sequences.test.ts +49 -0
- package/src/rules/sequences.ts +37 -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/typeofComparisons.test.ts +86 -0
- package/src/rules/typeofComparisons.ts +88 -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/utils/discriminateAnyType.ts +66 -0
- package/src/rules/utils/getThisExpression.ts +24 -0
- package/src/rules/utils/isUnsafeAssignment.ts +113 -0
- package/src/rules/utils/operators.ts +39 -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/declarationIncludesGlobal.ts +9 -0
- package/src/utils/declarationsIncludeGlobal.ts +7 -0
- package/src/utils/getModifyingReferences.ts +58 -0
- package/src/utils/hasSameTokens.ts +45 -0
- package/src/utils/isGlobalDeclaration.ts +12 -0
- package/src/utils/isGlobalDeclarationOfName.ts +51 -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,210 @@
|
|
|
1
|
+
import rule from "./negativeZeroComparisons.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
if (value === -0) {}
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
if (value === -0) {}
|
|
12
|
+
~~~~~~~~~~~~
|
|
13
|
+
Comparisons with -0 using === do not distinguish between -0 and +0.
|
|
14
|
+
`,
|
|
15
|
+
suggestions: [
|
|
16
|
+
{
|
|
17
|
+
id: "useObjectIs",
|
|
18
|
+
updated: `
|
|
19
|
+
if (Object.is(value, -0)) {}
|
|
20
|
+
`,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
code: `
|
|
26
|
+
if (-0 === value) {}
|
|
27
|
+
`,
|
|
28
|
+
snapshot: `
|
|
29
|
+
if (-0 === value) {}
|
|
30
|
+
~~~~~~~~~~~~
|
|
31
|
+
Comparisons with -0 using === do not distinguish between -0 and +0.
|
|
32
|
+
`,
|
|
33
|
+
suggestions: [
|
|
34
|
+
{
|
|
35
|
+
id: "useObjectIs",
|
|
36
|
+
updated: `
|
|
37
|
+
if (Object.is(-0, value)) {}
|
|
38
|
+
`,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
code: `
|
|
44
|
+
if (value == -0) {}
|
|
45
|
+
`,
|
|
46
|
+
snapshot: `
|
|
47
|
+
if (value == -0) {}
|
|
48
|
+
~~~~~~~~~~~
|
|
49
|
+
Comparisons with -0 using == do not distinguish between -0 and +0.
|
|
50
|
+
`,
|
|
51
|
+
suggestions: [
|
|
52
|
+
{
|
|
53
|
+
id: "useObjectIs",
|
|
54
|
+
updated: `
|
|
55
|
+
if (Object.is(value, -0)) {}
|
|
56
|
+
`,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
code: `
|
|
62
|
+
if (value !== -0) {}
|
|
63
|
+
`,
|
|
64
|
+
snapshot: `
|
|
65
|
+
if (value !== -0) {}
|
|
66
|
+
~~~~~~~~~~~~
|
|
67
|
+
Comparisons with -0 using !== do not distinguish between -0 and +0.
|
|
68
|
+
`,
|
|
69
|
+
suggestions: [
|
|
70
|
+
{
|
|
71
|
+
id: "useObjectIs",
|
|
72
|
+
updated: `
|
|
73
|
+
if (!Object.is(value, -0)) {}
|
|
74
|
+
`,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
code: `
|
|
80
|
+
if (value != -0) {}
|
|
81
|
+
`,
|
|
82
|
+
snapshot: `
|
|
83
|
+
if (value != -0) {}
|
|
84
|
+
~~~~~~~~~~~
|
|
85
|
+
Comparisons with -0 using != do not distinguish between -0 and +0.
|
|
86
|
+
`,
|
|
87
|
+
suggestions: [
|
|
88
|
+
{
|
|
89
|
+
id: "useObjectIs",
|
|
90
|
+
updated: `
|
|
91
|
+
if (!Object.is(value, -0)) {}
|
|
92
|
+
`,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
code: `
|
|
98
|
+
if (value < -0) {}
|
|
99
|
+
`,
|
|
100
|
+
snapshot: `
|
|
101
|
+
if (value < -0) {}
|
|
102
|
+
~~~~~~~~~~
|
|
103
|
+
Comparisons with -0 using < do not distinguish between -0 and +0.
|
|
104
|
+
`,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
code: `
|
|
108
|
+
if (value <= -0) {}
|
|
109
|
+
`,
|
|
110
|
+
snapshot: `
|
|
111
|
+
if (value <= -0) {}
|
|
112
|
+
~~~~~~~~~~~
|
|
113
|
+
Comparisons with -0 using <= do not distinguish between -0 and +0.
|
|
114
|
+
`,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
code: `
|
|
118
|
+
if (value > -0) {}
|
|
119
|
+
`,
|
|
120
|
+
snapshot: `
|
|
121
|
+
if (value > -0) {}
|
|
122
|
+
~~~~~~~~~~
|
|
123
|
+
Comparisons with -0 using > do not distinguish between -0 and +0.
|
|
124
|
+
`,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
code: `
|
|
128
|
+
if (value >= -0) {}
|
|
129
|
+
`,
|
|
130
|
+
snapshot: `
|
|
131
|
+
if (value >= -0) {}
|
|
132
|
+
~~~~~~~~~~~
|
|
133
|
+
Comparisons with -0 using >= do not distinguish between -0 and +0.
|
|
134
|
+
`,
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
code: `
|
|
138
|
+
const result = value === -0 ? "negative zero" : "other";
|
|
139
|
+
`,
|
|
140
|
+
snapshot: `
|
|
141
|
+
const result = value === -0 ? "negative zero" : "other";
|
|
142
|
+
~~~~~~~~~~~~
|
|
143
|
+
Comparisons with -0 using === do not distinguish between -0 and +0.
|
|
144
|
+
`,
|
|
145
|
+
suggestions: [
|
|
146
|
+
{
|
|
147
|
+
id: "useObjectIs",
|
|
148
|
+
updated: `
|
|
149
|
+
const result = Object.is(value, -0) ? "negative zero" : "other";
|
|
150
|
+
`,
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
code: `
|
|
156
|
+
while (value !== -0) {
|
|
157
|
+
value++;
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
160
|
+
snapshot: `
|
|
161
|
+
while (value !== -0) {
|
|
162
|
+
~~~~~~~~~~~~
|
|
163
|
+
Comparisons with -0 using !== do not distinguish between -0 and +0.
|
|
164
|
+
value++;
|
|
165
|
+
}
|
|
166
|
+
`,
|
|
167
|
+
suggestions: [
|
|
168
|
+
{
|
|
169
|
+
id: "useObjectIs",
|
|
170
|
+
updated: `
|
|
171
|
+
while (!Object.is(value, -0)) {
|
|
172
|
+
value++;
|
|
173
|
+
}
|
|
174
|
+
`,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
code: `
|
|
180
|
+
const isNegativeZero = value === -0;
|
|
181
|
+
`,
|
|
182
|
+
snapshot: `
|
|
183
|
+
const isNegativeZero = value === -0;
|
|
184
|
+
~~~~~~~~~~~~
|
|
185
|
+
Comparisons with -0 using === do not distinguish between -0 and +0.
|
|
186
|
+
`,
|
|
187
|
+
suggestions: [
|
|
188
|
+
{
|
|
189
|
+
id: "useObjectIs",
|
|
190
|
+
updated: `
|
|
191
|
+
const isNegativeZero = Object.is(value, -0);
|
|
192
|
+
`,
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
valid: [
|
|
198
|
+
`if (value === 0) {}`,
|
|
199
|
+
`if (value === -1) {}`,
|
|
200
|
+
`if (value === 1) {}`,
|
|
201
|
+
`if (Object.is(value, -0)) {}`,
|
|
202
|
+
`if (Object.is(-0, value)) {}`,
|
|
203
|
+
`const result = -0;`,
|
|
204
|
+
`const value = -0 + 1;`,
|
|
205
|
+
`const value = -0 * 2;`,
|
|
206
|
+
`const value = Math.abs(-0);`,
|
|
207
|
+
`const value = [-0, 0, 1];`,
|
|
208
|
+
`function test() { return -0; }`,
|
|
209
|
+
],
|
|
210
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { typescriptLanguage } from "../language.js";
|
|
4
|
+
import {
|
|
5
|
+
isComparisonOperator,
|
|
6
|
+
isEqualityOperator,
|
|
7
|
+
isNegatedEqualityOperator,
|
|
8
|
+
} from "./utils/operators.js";
|
|
9
|
+
|
|
10
|
+
function isNegativeZero(node: ts.Node): boolean {
|
|
11
|
+
return (
|
|
12
|
+
ts.isPrefixUnaryExpression(node) &&
|
|
13
|
+
node.operator === ts.SyntaxKind.MinusToken &&
|
|
14
|
+
ts.isNumericLiteral(node.operand) &&
|
|
15
|
+
node.operand.text === "0"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default typescriptLanguage.createRule({
|
|
20
|
+
about: {
|
|
21
|
+
description: "Reports comparisons with -0 that may not behave as expected.",
|
|
22
|
+
id: "negativeZeroComparisons",
|
|
23
|
+
preset: "logical",
|
|
24
|
+
},
|
|
25
|
+
messages: {
|
|
26
|
+
unexpectedNegativeZeroComparison: {
|
|
27
|
+
primary:
|
|
28
|
+
"Comparisons with -0 using {{ operator }} do not distinguish between -0 and +0.",
|
|
29
|
+
secondary: [
|
|
30
|
+
"In JavaScript, -0 and +0 are considered equal when using comparison operators like === or ==, even though they are distinct values.",
|
|
31
|
+
"To properly check for -0, use `Object.is(value, -0)` which correctly distinguishes between -0 and +0.",
|
|
32
|
+
],
|
|
33
|
+
suggestions: ["Use `Object.is()` to reliably check if a value is -0."],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
setup(context) {
|
|
37
|
+
function generateObjectIsText(
|
|
38
|
+
node: ts.BinaryExpression,
|
|
39
|
+
isNegated: boolean,
|
|
40
|
+
) {
|
|
41
|
+
const leftText = node.left.getText(context.sourceFile);
|
|
42
|
+
const rightText = node.right.getText(context.sourceFile);
|
|
43
|
+
const objectIsCall = `Object.is(${leftText}, ${rightText})`;
|
|
44
|
+
|
|
45
|
+
return isNegated ? `!${objectIsCall}` : objectIsCall;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
visitors: {
|
|
50
|
+
BinaryExpression: (node) => {
|
|
51
|
+
if (
|
|
52
|
+
!isComparisonOperator(node.operatorToken) ||
|
|
53
|
+
(!isNegativeZero(node.left) && !isNegativeZero(node.right))
|
|
54
|
+
) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const operator = node.operatorToken.getText(context.sourceFile);
|
|
59
|
+
const range = {
|
|
60
|
+
begin: node.getStart(context.sourceFile),
|
|
61
|
+
end: node.getEnd(),
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
context.report({
|
|
65
|
+
data: {
|
|
66
|
+
operator,
|
|
67
|
+
},
|
|
68
|
+
message: "unexpectedNegativeZeroComparison",
|
|
69
|
+
range,
|
|
70
|
+
suggestions: isEqualityOperator(node.operatorToken)
|
|
71
|
+
? [
|
|
72
|
+
{
|
|
73
|
+
id: "useObjectIs",
|
|
74
|
+
range,
|
|
75
|
+
text: generateObjectIsText(
|
|
76
|
+
node,
|
|
77
|
+
isNegatedEqualityOperator(node.operatorToken),
|
|
78
|
+
),
|
|
79
|
+
},
|
|
80
|
+
]
|
|
81
|
+
: undefined,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import rule from "./newExpressions.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
new MyClass();
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
new MyClass();
|
|
12
|
+
~~~
|
|
13
|
+
Constructors should only be called when their return value is used.
|
|
14
|
+
`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: `
|
|
18
|
+
function process() {
|
|
19
|
+
new EventEmitter();
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
snapshot: `
|
|
23
|
+
function process() {
|
|
24
|
+
new EventEmitter();
|
|
25
|
+
~~~
|
|
26
|
+
Constructors should only be called when their return value is used.
|
|
27
|
+
}
|
|
28
|
+
`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: `
|
|
32
|
+
if (condition) {
|
|
33
|
+
new Logger();
|
|
34
|
+
}
|
|
35
|
+
`,
|
|
36
|
+
snapshot: `
|
|
37
|
+
if (condition) {
|
|
38
|
+
new Logger();
|
|
39
|
+
~~~
|
|
40
|
+
Constructors should only be called when their return value is used.
|
|
41
|
+
}
|
|
42
|
+
`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: `
|
|
46
|
+
new DatabaseConnection(), processData();
|
|
47
|
+
`,
|
|
48
|
+
snapshot: `
|
|
49
|
+
new DatabaseConnection(), processData();
|
|
50
|
+
~~~
|
|
51
|
+
Constructors should only be called when their return value is used.
|
|
52
|
+
`,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
code: `
|
|
56
|
+
someFunction(), new Queue();
|
|
57
|
+
`,
|
|
58
|
+
snapshot: `
|
|
59
|
+
someFunction(), new Queue();
|
|
60
|
+
~~~
|
|
61
|
+
Constructors should only be called when their return value is used.
|
|
62
|
+
`,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
valid: [
|
|
66
|
+
`const instance = new MyClass();`,
|
|
67
|
+
`let value = new MyClass();`,
|
|
68
|
+
`const result = condition ? new MyClass() : new OtherClass();`,
|
|
69
|
+
`return new MyClass();`,
|
|
70
|
+
`throw new Error("message");`,
|
|
71
|
+
`function create() { return new MyClass(); }`,
|
|
72
|
+
`const array = [new MyClass(), new OtherClass()];`,
|
|
73
|
+
`const object = { value: new MyClass() };`,
|
|
74
|
+
`myFunction(new MyClass());`,
|
|
75
|
+
`new MyClass().method();`,
|
|
76
|
+
`const value = new MyClass() || fallback;`,
|
|
77
|
+
`const value = new MyClass() && other;`,
|
|
78
|
+
`const value = new MyClass() ?? fallback;`,
|
|
79
|
+
],
|
|
80
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { getTSNodeRange } from "../getTSNodeRange.js";
|
|
4
|
+
import { typescriptLanguage } from "../language.js";
|
|
5
|
+
|
|
6
|
+
export default typescriptLanguage.createRule({
|
|
7
|
+
about: {
|
|
8
|
+
description:
|
|
9
|
+
"Reports standalone new expressions that don't use the constructed object.",
|
|
10
|
+
id: "newExpressions",
|
|
11
|
+
preset: "logical",
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noStandaloneNew: {
|
|
15
|
+
primary:
|
|
16
|
+
"Constructors should only be called when their return value is used.",
|
|
17
|
+
secondary: [
|
|
18
|
+
"Using `new` to construct an object but not storing or using the result is often a mistake or indicates unclear code intent.",
|
|
19
|
+
"If the constructor has side effects you want to trigger, it's better to make that explicit by calling a separate method rather than relying on constructor side effects.",
|
|
20
|
+
],
|
|
21
|
+
suggestions: [
|
|
22
|
+
"If you need to use the constructed object, assign it to a variable or return it.",
|
|
23
|
+
"If you only need the constructor's side effects, consider refactoring to a function that makes the side effects explicit.",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
setup(context) {
|
|
28
|
+
function isStandaloneExpression(node: ts.Node): boolean {
|
|
29
|
+
const parent = node.parent;
|
|
30
|
+
|
|
31
|
+
// If parent is an ExpressionStatement, it's standalone
|
|
32
|
+
if (parent.kind === ts.SyntaxKind.ExpressionStatement) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If parent is a comma expression, check recursively
|
|
37
|
+
if (
|
|
38
|
+
ts.isBinaryExpression(parent) &&
|
|
39
|
+
parent.operatorToken.kind === ts.SyntaxKind.CommaToken
|
|
40
|
+
) {
|
|
41
|
+
// If this is the last expression in the comma sequence, check if the parent is standalone
|
|
42
|
+
if (parent.right === node) {
|
|
43
|
+
return isStandaloneExpression(parent);
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
visitors: {
|
|
53
|
+
NewExpression: (node) => {
|
|
54
|
+
if (isStandaloneExpression(node)) {
|
|
55
|
+
context.report({
|
|
56
|
+
message: "noStandaloneNew",
|
|
57
|
+
range: getTSNodeRange(
|
|
58
|
+
node.getChildAt(0, context.sourceFile),
|
|
59
|
+
context.sourceFile,
|
|
60
|
+
),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import rule from "./newNativeNonConstructors.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
new Symbol("description");
|
|
9
|
+
`,
|
|
10
|
+
output: `
|
|
11
|
+
Symbol("description");
|
|
12
|
+
`,
|
|
13
|
+
snapshot: `
|
|
14
|
+
new Symbol("description");
|
|
15
|
+
~~~
|
|
16
|
+
Symbol cannot be called with \`new\`.
|
|
17
|
+
`,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
code: `
|
|
21
|
+
new BigInt(42);
|
|
22
|
+
`,
|
|
23
|
+
output: `
|
|
24
|
+
BigInt(42);
|
|
25
|
+
`,
|
|
26
|
+
snapshot: `
|
|
27
|
+
new BigInt(42);
|
|
28
|
+
~~~
|
|
29
|
+
BigInt cannot be called with \`new\`.
|
|
30
|
+
`,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
code: `
|
|
34
|
+
const value = new Symbol();
|
|
35
|
+
`,
|
|
36
|
+
output: `
|
|
37
|
+
const value = Symbol();
|
|
38
|
+
`,
|
|
39
|
+
snapshot: `
|
|
40
|
+
const value = new Symbol();
|
|
41
|
+
~~~
|
|
42
|
+
Symbol cannot be called with \`new\`.
|
|
43
|
+
`,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
code: `
|
|
47
|
+
function create() {
|
|
48
|
+
return new BigInt(100);
|
|
49
|
+
}
|
|
50
|
+
`,
|
|
51
|
+
output: `
|
|
52
|
+
function create() {
|
|
53
|
+
return BigInt(100);
|
|
54
|
+
}
|
|
55
|
+
`,
|
|
56
|
+
snapshot: `
|
|
57
|
+
function create() {
|
|
58
|
+
return new BigInt(100);
|
|
59
|
+
~~~
|
|
60
|
+
BigInt cannot be called with \`new\`.
|
|
61
|
+
}
|
|
62
|
+
`,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
valid: [
|
|
66
|
+
`Symbol("description");`,
|
|
67
|
+
`BigInt(42);`,
|
|
68
|
+
`const value = Symbol();`,
|
|
69
|
+
`const number = BigInt(100);`,
|
|
70
|
+
`function create() { return Symbol("key"); }`,
|
|
71
|
+
`const array = [Symbol("a"), Symbol("b")];`,
|
|
72
|
+
`new String("text");`,
|
|
73
|
+
`new Number(42);`,
|
|
74
|
+
`new Boolean(true);`,
|
|
75
|
+
`new Object();`,
|
|
76
|
+
`new Array();`,
|
|
77
|
+
`new Date();`,
|
|
78
|
+
`new Error("message");`,
|
|
79
|
+
`new Map();`,
|
|
80
|
+
`new Set();`,
|
|
81
|
+
`new Promise((resolve) => resolve());`,
|
|
82
|
+
`new WeakMap();`,
|
|
83
|
+
`new WeakSet();`,
|
|
84
|
+
`
|
|
85
|
+
class BigInt {}
|
|
86
|
+
new BigInt();
|
|
87
|
+
export {}
|
|
88
|
+
`,
|
|
89
|
+
`
|
|
90
|
+
class Symbol {}
|
|
91
|
+
new Symbol();
|
|
92
|
+
export {}
|
|
93
|
+
`,
|
|
94
|
+
],
|
|
95
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { getTSNodeRange } from "../getTSNodeRange.js";
|
|
4
|
+
import { typescriptLanguage } from "../language.js";
|
|
5
|
+
import { isGlobalDeclaration } from "../utils/isGlobalDeclaration.js";
|
|
6
|
+
|
|
7
|
+
export default typescriptLanguage.createRule({
|
|
8
|
+
about: {
|
|
9
|
+
description:
|
|
10
|
+
"Disallows using `new` with global non-constructor functions like Symbol and BigInt.",
|
|
11
|
+
id: "newNativeNonConstructors",
|
|
12
|
+
preset: "untyped",
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
noNewNonConstructor: {
|
|
16
|
+
primary: "{{ name }} cannot be called with `new`.",
|
|
17
|
+
secondary: [
|
|
18
|
+
"`Symbol` and `BigInt` are not constructors and will throw a `TypeError` when called with `new`.",
|
|
19
|
+
"These functions should be called directly without the `new` keyword to create their respective values.",
|
|
20
|
+
],
|
|
21
|
+
suggestions: ["Remove the `new` keyword and call the function directly."],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
setup(context) {
|
|
25
|
+
return {
|
|
26
|
+
visitors: {
|
|
27
|
+
NewExpression: (node) => {
|
|
28
|
+
if (!ts.isIdentifier(node.expression)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const name = node.expression.text;
|
|
33
|
+
if (
|
|
34
|
+
!["BigInt", "Symbol"].includes(name) ||
|
|
35
|
+
!isGlobalDeclaration(node.expression, context.typeChecker)
|
|
36
|
+
) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
context.report({
|
|
41
|
+
data: { name },
|
|
42
|
+
fix: {
|
|
43
|
+
range: {
|
|
44
|
+
begin: node.getStart(context.sourceFile),
|
|
45
|
+
end: node.expression.getStart(context.sourceFile),
|
|
46
|
+
},
|
|
47
|
+
text: "",
|
|
48
|
+
},
|
|
49
|
+
message: "noNewNonConstructor",
|
|
50
|
+
range: getTSNodeRange(
|
|
51
|
+
node.getChildAt(0, context.sourceFile),
|
|
52
|
+
context.sourceFile,
|
|
53
|
+
),
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import rule from "./nonOctalDecimalEscapes.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
"\\8"
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
"\\8"
|
|
12
|
+
~~
|
|
13
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
14
|
+
`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: `
|
|
18
|
+
"\\9"
|
|
19
|
+
`,
|
|
20
|
+
snapshot: `
|
|
21
|
+
"\\9"
|
|
22
|
+
~~
|
|
23
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
24
|
+
`,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: `
|
|
28
|
+
"w\\8less"
|
|
29
|
+
`,
|
|
30
|
+
snapshot: `
|
|
31
|
+
"w\\8less"
|
|
32
|
+
~~
|
|
33
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
34
|
+
`,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: `
|
|
38
|
+
"December 1\\9"
|
|
39
|
+
`,
|
|
40
|
+
snapshot: `
|
|
41
|
+
"December 1\\9"
|
|
42
|
+
~~
|
|
43
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
44
|
+
`,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
code: `
|
|
48
|
+
"Don't use \\8 and \\9 escapes."
|
|
49
|
+
`,
|
|
50
|
+
snapshot: `
|
|
51
|
+
"Don't use \\8 and \\9 escapes."
|
|
52
|
+
~~
|
|
53
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
54
|
+
~~
|
|
55
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
56
|
+
`,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
code: `
|
|
60
|
+
"\\0\\8"
|
|
61
|
+
`,
|
|
62
|
+
snapshot: `
|
|
63
|
+
"\\0\\8"
|
|
64
|
+
~~
|
|
65
|
+
Non-octal decimal escape sequences (\\8 and \\9) should not be used in string literals.
|
|
66
|
+
`,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
valid: ['"8"', '"9"', '"w8less"', '"December 19"', '"\\\\8"', '"\\0\\u0038"'],
|
|
70
|
+
});
|