@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,71 @@
|
|
|
1
|
+
import rule from "./asyncPromiseExecutors.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
ruleTester.describe(rule, {
|
|
4
|
+
invalid: [
|
|
5
|
+
{
|
|
6
|
+
code: `
|
|
7
|
+
new Promise(async (resolve, reject) => {
|
|
8
|
+
resolve(42);
|
|
9
|
+
});
|
|
10
|
+
`,
|
|
11
|
+
snapshot: `
|
|
12
|
+
new Promise(async (resolve, reject) => {
|
|
13
|
+
~~~~~
|
|
14
|
+
Async Promise executor functions are not able to properly catch thrown errors and often indicate unnecessarily complex logic.
|
|
15
|
+
resolve(42);
|
|
16
|
+
});
|
|
17
|
+
`,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
code: `
|
|
21
|
+
new Promise(async function(resolve, reject) {
|
|
22
|
+
resolve(42);
|
|
23
|
+
});
|
|
24
|
+
`,
|
|
25
|
+
snapshot: `
|
|
26
|
+
new Promise(async function(resolve, reject) {
|
|
27
|
+
~~~~~
|
|
28
|
+
Async Promise executor functions are not able to properly catch thrown errors and often indicate unnecessarily complex logic.
|
|
29
|
+
resolve(42);
|
|
30
|
+
});
|
|
31
|
+
`,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
code: `
|
|
35
|
+
const p = new Promise(async (resolve) => {
|
|
36
|
+
resolve();
|
|
37
|
+
});
|
|
38
|
+
`,
|
|
39
|
+
snapshot: `
|
|
40
|
+
const p = new Promise(async (resolve) => {
|
|
41
|
+
~~~~~
|
|
42
|
+
Async Promise executor functions are not able to properly catch thrown errors and often indicate unnecessarily complex logic.
|
|
43
|
+
resolve();
|
|
44
|
+
});
|
|
45
|
+
`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
valid: [
|
|
49
|
+
`
|
|
50
|
+
new Promise((resolve, reject) => {
|
|
51
|
+
resolve(42);
|
|
52
|
+
});
|
|
53
|
+
`,
|
|
54
|
+
`
|
|
55
|
+
new Promise(function(resolve, reject) {
|
|
56
|
+
resolve(42);
|
|
57
|
+
});
|
|
58
|
+
`,
|
|
59
|
+
`
|
|
60
|
+
const p = new Promise((resolve) => {
|
|
61
|
+
doSomething().then(resolve);
|
|
62
|
+
});
|
|
63
|
+
`,
|
|
64
|
+
`
|
|
65
|
+
// Not a Promise constructor
|
|
66
|
+
new SomethingElse(async (resolve) => {
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
`,
|
|
70
|
+
],
|
|
71
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports lexical declarations in case clauses without wrapping them in blocks.";
|
|
3
|
+
readonly id: "caseDeclarations";
|
|
4
|
+
readonly preset: "untyped";
|
|
5
|
+
}, import("../nodes.js").TSNodesByName, import("../language.js").TypeScriptServices, "unexpectedLexicalDeclaration", undefined>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
export default typescriptLanguage.createRule({
|
|
6
|
+
about: {
|
|
7
|
+
description: "Reports lexical declarations in case clauses without wrapping them in blocks.",
|
|
8
|
+
id: "caseDeclarations",
|
|
9
|
+
preset: "untyped",
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
unexpectedLexicalDeclaration: {
|
|
13
|
+
primary: "Variables declared in case clauses without braces leak into the surrounding scope.",
|
|
14
|
+
secondary: [
|
|
15
|
+
"Lexical declarations (let, const, function, class) are scoped to the entire switch statement, not just the case clause where they are declared.",
|
|
16
|
+
"This can lead to unexpected behavior when the same variable name is used in multiple case clauses, as they will conflict in the same scope.",
|
|
17
|
+
],
|
|
18
|
+
suggestions: [
|
|
19
|
+
"Wrap the case clause contents in curly braces {} to create a block scope.",
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
setup(context) {
|
|
24
|
+
function getLexicalDeclaration(statements) {
|
|
25
|
+
for (const statement of statements) {
|
|
26
|
+
if (ts.isVariableStatement(statement) &&
|
|
27
|
+
tsutils.isNodeFlagSet(statement.declarationList, ts.NodeFlags.Let | ts.NodeFlags.Const)) {
|
|
28
|
+
return statement.declarationList.getChildAt(0, context.sourceFile);
|
|
29
|
+
}
|
|
30
|
+
if (ts.isClassDeclaration(statement) ||
|
|
31
|
+
ts.isFunctionDeclaration(statement)) {
|
|
32
|
+
return statement.getChildAt(0, context.sourceFile);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
function checkClause(node) {
|
|
38
|
+
const declarationNode = getLexicalDeclaration(node.statements);
|
|
39
|
+
if (declarationNode) {
|
|
40
|
+
context.report({
|
|
41
|
+
message: "unexpectedLexicalDeclaration",
|
|
42
|
+
range: getTSNodeRange(declarationNode, context.sourceFile),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
visitors: {
|
|
48
|
+
CaseClause: checkClause,
|
|
49
|
+
DefaultClause: checkClause,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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 switch statements with duplicate case clause test expressions.";
|
|
3
|
+
readonly id: "caseDuplicates";
|
|
4
|
+
readonly preset: "logical";
|
|
5
|
+
}, import("../nodes.js").TSNodesByName, import("../language.js").TypeScriptServices, "duplicateCase", undefined>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
import { typescriptLanguage } from "../language.js";
|
|
3
|
+
import { hasSameTokens } from "../utils/hasSameTokens.js";
|
|
4
|
+
export default typescriptLanguage.createRule({
|
|
5
|
+
about: {
|
|
6
|
+
description: "Reports switch statements with duplicate case clause test expressions.",
|
|
7
|
+
id: "caseDuplicates",
|
|
8
|
+
preset: "logical",
|
|
9
|
+
},
|
|
10
|
+
messages: {
|
|
11
|
+
duplicateCase: {
|
|
12
|
+
primary: "This case duplicates a previous case, so it will never be reached.",
|
|
13
|
+
secondary: [
|
|
14
|
+
"Having duplicate case clauses in a switch statement is a logic error.",
|
|
15
|
+
"The second case clause will never be reached because the first matching case will always execute first.",
|
|
16
|
+
],
|
|
17
|
+
suggestions: [
|
|
18
|
+
"Remove the duplicate case clause or modify its test expression to be unique.",
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
setup(context) {
|
|
23
|
+
return {
|
|
24
|
+
visitors: {
|
|
25
|
+
SwitchStatement: (node) => {
|
|
26
|
+
const seenCases = [];
|
|
27
|
+
for (const clause of node.caseBlock.clauses) {
|
|
28
|
+
if (!ts.isCaseClause(clause)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const isDuplicate = seenCases.some((seenCase) => hasSameTokens(seenCase, clause.expression, context.sourceFile));
|
|
32
|
+
if (isDuplicate) {
|
|
33
|
+
context.report({
|
|
34
|
+
message: "duplicateCase",
|
|
35
|
+
range: {
|
|
36
|
+
begin: clause.getStart(context.sourceFile),
|
|
37
|
+
end: clause.expression.getEnd(),
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
seenCases.push(clause.expression);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|