@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,76 @@
|
|
|
1
|
+
import { ruleTester } from "./ruleTester.js";
|
|
2
|
+
import rule from "./variableDeletions.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
delete value;
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
delete value;
|
|
12
|
+
~~~~~~~~~~~~
|
|
13
|
+
Deleting a variable with the delete operator outside of strict mode will silently fail and return false.
|
|
14
|
+
`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: `
|
|
18
|
+
let x = 5;
|
|
19
|
+
delete x;
|
|
20
|
+
`,
|
|
21
|
+
snapshot: `
|
|
22
|
+
let x = 5;
|
|
23
|
+
delete x;
|
|
24
|
+
~~~~~~~~
|
|
25
|
+
Deleting a variable with the delete operator outside of strict mode will silently fail and return false.
|
|
26
|
+
`,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
code: `
|
|
30
|
+
const variable = 10;
|
|
31
|
+
delete variable;
|
|
32
|
+
`,
|
|
33
|
+
snapshot: `
|
|
34
|
+
const variable = 10;
|
|
35
|
+
delete variable;
|
|
36
|
+
~~~~~~~~~~~~~~~
|
|
37
|
+
Deleting a variable with the delete operator outside of strict mode will silently fail and return false.
|
|
38
|
+
`,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
code: `
|
|
42
|
+
function test(parameter: number) {
|
|
43
|
+
delete parameter;
|
|
44
|
+
}
|
|
45
|
+
`,
|
|
46
|
+
snapshot: `
|
|
47
|
+
function test(parameter: number) {
|
|
48
|
+
delete parameter;
|
|
49
|
+
~~~~~~~~~~~~~~~~
|
|
50
|
+
Deleting a variable with the delete operator outside of strict mode will silently fail and return false.
|
|
51
|
+
}
|
|
52
|
+
`,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
code: `
|
|
56
|
+
for (let index = 0; index < 10; index++) {
|
|
57
|
+
delete index;
|
|
58
|
+
}
|
|
59
|
+
`,
|
|
60
|
+
snapshot: `
|
|
61
|
+
for (let index = 0; index < 10; index++) {
|
|
62
|
+
delete index;
|
|
63
|
+
~~~~~~~~~~~~
|
|
64
|
+
Deleting a variable with the delete operator outside of strict mode will silently fail and return false.
|
|
65
|
+
}
|
|
66
|
+
`,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
valid: [
|
|
70
|
+
`const obj = { prop: 1 }; delete obj.prop;`,
|
|
71
|
+
`delete obj.property;`,
|
|
72
|
+
`delete obj["property"];`,
|
|
73
|
+
`const obj = { nested: { prop: 1 } }; delete obj.nested.prop;`,
|
|
74
|
+
`const array = [1, 2, 3]; delete array[0];`,
|
|
75
|
+
],
|
|
76
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { typescriptLanguage } from "../language.js";
|
|
4
|
+
|
|
5
|
+
export default typescriptLanguage.createRule({
|
|
6
|
+
about: {
|
|
7
|
+
description:
|
|
8
|
+
"Reports attempting to delete variables with the delete operator.",
|
|
9
|
+
id: "variableDeletions",
|
|
10
|
+
preset: "untyped",
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
noDeleteVar: {
|
|
14
|
+
primary:
|
|
15
|
+
"Deleting a variable with the delete operator outside of strict mode will silently fail and return false.",
|
|
16
|
+
secondary: [
|
|
17
|
+
"The delete operator is only meant to remove properties from objects, not variables.",
|
|
18
|
+
"Attempting to delete a variable in strict mode will cause a syntax error.",
|
|
19
|
+
"In non-strict mode, it will silently fail and return false without actually deleting the variable.",
|
|
20
|
+
],
|
|
21
|
+
suggestions: [
|
|
22
|
+
"Remove the delete statement, or if you need to unset the value, assign undefined instead.",
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
setup(context) {
|
|
27
|
+
return {
|
|
28
|
+
visitors: {
|
|
29
|
+
DeleteExpression: (node) => {
|
|
30
|
+
if (node.expression.kind === ts.SyntaxKind.Identifier) {
|
|
31
|
+
context.report({
|
|
32
|
+
message: "noDeleteVar",
|
|
33
|
+
range: {
|
|
34
|
+
begin: node.getStart(context.sourceFile),
|
|
35
|
+
end: node.getEnd(),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ruleTester } from "./ruleTester.js";
|
|
2
|
+
import rule from "./voidOperator.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
void 0;
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
void 0;
|
|
12
|
+
~~~~~~
|
|
13
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
14
|
+
`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: `
|
|
18
|
+
const value = void 0;
|
|
19
|
+
`,
|
|
20
|
+
snapshot: `
|
|
21
|
+
const value = void 0;
|
|
22
|
+
~~~~~~
|
|
23
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
24
|
+
`,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: `
|
|
28
|
+
void someFunction();
|
|
29
|
+
`,
|
|
30
|
+
snapshot: `
|
|
31
|
+
void someFunction();
|
|
32
|
+
~~~~~~~~~~~~~~~~~~~
|
|
33
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
34
|
+
`,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: `
|
|
38
|
+
return void calculate();
|
|
39
|
+
`,
|
|
40
|
+
snapshot: `
|
|
41
|
+
return void calculate();
|
|
42
|
+
~~~~~~~~~~~~~~~~
|
|
43
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
44
|
+
`,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
code: `
|
|
48
|
+
const result = void (a + b);
|
|
49
|
+
`,
|
|
50
|
+
snapshot: `
|
|
51
|
+
const result = void (a + b);
|
|
52
|
+
~~~~~~~~~~~~
|
|
53
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
54
|
+
`,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
code: `
|
|
58
|
+
void expression, anotherExpression;
|
|
59
|
+
`,
|
|
60
|
+
snapshot: `
|
|
61
|
+
void expression, anotherExpression;
|
|
62
|
+
~~~~~~~~~~~~~~~
|
|
63
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
64
|
+
`,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
code: `
|
|
68
|
+
function process() {
|
|
69
|
+
void doSomething();
|
|
70
|
+
}
|
|
71
|
+
`,
|
|
72
|
+
snapshot: `
|
|
73
|
+
function process() {
|
|
74
|
+
void doSomething();
|
|
75
|
+
~~~~~~~~~~~~~~~~~~
|
|
76
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
77
|
+
}
|
|
78
|
+
`,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
code: `
|
|
82
|
+
const callback = () => void action();
|
|
83
|
+
`,
|
|
84
|
+
snapshot: `
|
|
85
|
+
const callback = () => void action();
|
|
86
|
+
~~~~~~~~~~~~~
|
|
87
|
+
Prefer an explicit value over using the void operator to produce undefined.
|
|
88
|
+
`,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
valid: [
|
|
92
|
+
`const value = undefined;`,
|
|
93
|
+
`return undefined;`,
|
|
94
|
+
`someFunction();`,
|
|
95
|
+
`const result = doSomething();`,
|
|
96
|
+
`if (value === undefined) {}`,
|
|
97
|
+
`function returns() { return; }`,
|
|
98
|
+
],
|
|
99
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { typescriptLanguage } from "../language.js";
|
|
2
|
+
|
|
3
|
+
export default typescriptLanguage.createRule({
|
|
4
|
+
about: {
|
|
5
|
+
description: "Reports using the void operator.",
|
|
6
|
+
id: "voidOperator",
|
|
7
|
+
preset: "stylistic",
|
|
8
|
+
},
|
|
9
|
+
messages: {
|
|
10
|
+
noVoid: {
|
|
11
|
+
primary:
|
|
12
|
+
"Prefer an explicit value over using the void operator to produce undefined.",
|
|
13
|
+
secondary: [
|
|
14
|
+
"The void operator evaluates an expression and returns undefined, regardless of the expression's value.",
|
|
15
|
+
"This is often confusing and can be replaced with more explicit code.",
|
|
16
|
+
"Instead of using void, return or assign undefined directly.",
|
|
17
|
+
],
|
|
18
|
+
suggestions: [
|
|
19
|
+
"Replace void expressions with undefined or restructure the code to be more explicit.",
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
setup(context) {
|
|
24
|
+
return {
|
|
25
|
+
visitors: {
|
|
26
|
+
VoidExpression: (node) => {
|
|
27
|
+
context.report({
|
|
28
|
+
message: "noVoid",
|
|
29
|
+
range: {
|
|
30
|
+
begin: node.getStart(context.sourceFile),
|
|
31
|
+
end: node.getEnd(),
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as tsutils from "ts-api-utils";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Gets all references to a variable that modify it (assignments, increments, decrements).
|
|
6
|
+
*
|
|
7
|
+
* TODO: Replace with a proper scope manager when available (see #400).
|
|
8
|
+
* @returns An array of identifier nodes that modify the variable.
|
|
9
|
+
*/
|
|
10
|
+
export function getModifyingReferences(
|
|
11
|
+
identifier: ts.Identifier,
|
|
12
|
+
sourceFile: ts.SourceFile,
|
|
13
|
+
typeChecker: ts.TypeChecker,
|
|
14
|
+
): ts.Identifier[] {
|
|
15
|
+
const symbol = typeChecker.getSymbolAtLocation(identifier);
|
|
16
|
+
if (!symbol?.valueDeclaration) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const valueDeclaration = symbol.valueDeclaration;
|
|
21
|
+
const modifyingReferences: ts.Identifier[] = [];
|
|
22
|
+
|
|
23
|
+
function visit(node: ts.Node): void {
|
|
24
|
+
// Check if this is an identifier that refers to the same symbol
|
|
25
|
+
if (ts.isIdentifier(node)) {
|
|
26
|
+
const nodeSymbol = typeChecker.getSymbolAtLocation(node);
|
|
27
|
+
if (
|
|
28
|
+
nodeSymbol?.valueDeclaration &&
|
|
29
|
+
nodeSymbol.valueDeclaration === valueDeclaration
|
|
30
|
+
) {
|
|
31
|
+
// Check if this identifier is being modified
|
|
32
|
+
const parent = node.parent;
|
|
33
|
+
|
|
34
|
+
// Assignment expressions (=, +=, -=, etc.)
|
|
35
|
+
if (
|
|
36
|
+
ts.isBinaryExpression(parent) &&
|
|
37
|
+
tsutils.isAssignmentKind(parent.operatorToken.kind) &&
|
|
38
|
+
parent.left === node
|
|
39
|
+
) {
|
|
40
|
+
modifyingReferences.push(node);
|
|
41
|
+
}
|
|
42
|
+
// Unary expressions (++, --)
|
|
43
|
+
else if (
|
|
44
|
+
(ts.isPostfixUnaryExpression(parent) ||
|
|
45
|
+
ts.isPrefixUnaryExpression(parent)) &&
|
|
46
|
+
parent.operand === node
|
|
47
|
+
) {
|
|
48
|
+
modifyingReferences.push(node);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
ts.forEachChild(node, visit);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
visit(sourceFile);
|
|
57
|
+
return modifyingReferences;
|
|
58
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
export function hasSameTokens(
|
|
4
|
+
nodeA: ts.Node,
|
|
5
|
+
nodeB: ts.Node,
|
|
6
|
+
sourceFile: ts.SourceFile,
|
|
7
|
+
): boolean {
|
|
8
|
+
const queueA: ts.Node[] = [nodeA];
|
|
9
|
+
const queueB: ts.Node[] = [nodeB];
|
|
10
|
+
|
|
11
|
+
while (true) {
|
|
12
|
+
const currentA = queueA.shift();
|
|
13
|
+
const currentB = queueB.shift();
|
|
14
|
+
|
|
15
|
+
if (!currentA || !currentB) {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (currentA.kind !== currentB.kind) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (
|
|
24
|
+
currentA.kind >= ts.SyntaxKind.FirstToken &&
|
|
25
|
+
currentA.kind <= ts.SyntaxKind.LastToken
|
|
26
|
+
) {
|
|
27
|
+
if (currentA.getText(sourceFile) !== currentB.getText(sourceFile)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const childrenA = currentA.getChildren(sourceFile);
|
|
34
|
+
const childrenB = currentB.getChildren(sourceFile);
|
|
35
|
+
|
|
36
|
+
if (childrenA.length !== childrenB.length) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
queueA.push(...childrenA);
|
|
41
|
+
queueB.push(...childrenB);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return queueA.length === queueB.length;
|
|
45
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { declarationsIncludeGlobal } from "./declarationsIncludeGlobal.js";
|
|
4
|
+
|
|
5
|
+
export function isGlobalDeclaration(
|
|
6
|
+
node: ts.Expression,
|
|
7
|
+
typeChecker: ts.TypeChecker,
|
|
8
|
+
): boolean {
|
|
9
|
+
const declarations = typeChecker.getSymbolAtLocation(node)?.getDeclarations();
|
|
10
|
+
|
|
11
|
+
return !!declarations && declarationsIncludeGlobal(declarations);
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { declarationIncludesGlobal } from "./declarationIncludesGlobal.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* TODO: Use a scope analyzer (#400).
|
|
7
|
+
*/
|
|
8
|
+
export function isGlobalDeclarationOfName(
|
|
9
|
+
node: ts.Expression,
|
|
10
|
+
name: string,
|
|
11
|
+
typeChecker: ts.TypeChecker,
|
|
12
|
+
): boolean {
|
|
13
|
+
const declarations = typeChecker.getSymbolAtLocation(node)?.getDeclarations();
|
|
14
|
+
if (!declarations) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return declarations.every((declaration) => {
|
|
19
|
+
// Special case: a variable set to a known identifier. E.g.:
|
|
20
|
+
// const CustomFunction = Function;
|
|
21
|
+
if (
|
|
22
|
+
ts.isVariableDeclaration(declaration) &&
|
|
23
|
+
declaration.initializer &&
|
|
24
|
+
declaration.initializer.kind === ts.SyntaxKind.Identifier
|
|
25
|
+
) {
|
|
26
|
+
return isGlobalDeclarationOfName(
|
|
27
|
+
declaration.initializer,
|
|
28
|
+
name,
|
|
29
|
+
typeChecker,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
isDeclarationOfName(declaration, name) &&
|
|
35
|
+
declarationIncludesGlobal(declaration)
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isDeclarationOfName(node: ts.Node, name: string) {
|
|
41
|
+
if (
|
|
42
|
+
ts.isClassDeclaration(node) ||
|
|
43
|
+
ts.isFunctionDeclaration(node) ||
|
|
44
|
+
ts.isInterfaceDeclaration(node) ||
|
|
45
|
+
ts.isVariableDeclaration(node)
|
|
46
|
+
) {
|
|
47
|
+
return node.name && ts.isIdentifier(node.name) && node.name.text === name;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { declarationsIncludeGlobal } from "./declarationsIncludeGlobal.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Checks if a node is a reference to a global variable (e.g., Object, undefined, NaN).
|
|
7
|
+
* Global variables are those declared in TypeScript's lib files or are global identifiers
|
|
8
|
+
* like undefined which have symbols but no user-defined declarations.
|
|
9
|
+
* TODO: Use a scope manager (#400).
|
|
10
|
+
*/
|
|
11
|
+
export function isGlobalVariable(
|
|
12
|
+
node: ts.Expression,
|
|
13
|
+
typeChecker: ts.TypeChecker,
|
|
14
|
+
): boolean {
|
|
15
|
+
const symbol = typeChecker.getSymbolAtLocation(node);
|
|
16
|
+
if (!symbol) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const declarations = symbol.getDeclarations();
|
|
21
|
+
|
|
22
|
+
// undefined, NaN, Infinity etc. may have no declarations in some contexts
|
|
23
|
+
// but are still global identifiers. Check if they're global scope symbols.
|
|
24
|
+
if (!declarations?.length) {
|
|
25
|
+
// If there are no declarations, it's likely a built-in global like undefined
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return declarationsIncludeGlobal(declarations);
|
|
30
|
+
}
|