@flint.fyi/ts 0.14.1 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/nodes.d.ts +1 -0
- package/lib/plugin.d.ts +132 -4
- package/lib/plugin.js +69 -1
- package/lib/rules/asyncPromiseExecutors.d.ts +6 -0
- package/lib/rules/asyncPromiseExecutors.js +51 -0
- package/lib/rules/asyncPromiseExecutors.test.d.ts +1 -0
- package/lib/rules/asyncPromiseExecutors.test.js +71 -0
- package/lib/rules/caseDeclarations.d.ts +6 -0
- package/lib/rules/caseDeclarations.js +53 -0
- package/lib/rules/caseDeclarations.test.d.ts +1 -0
- package/lib/rules/caseDeclarations.test.js +227 -0
- package/lib/rules/chainedAssignments.d.ts +6 -0
- package/lib/rules/chainedAssignments.js +48 -0
- package/lib/rules/chainedAssignments.test.d.ts +1 -0
- package/lib/rules/chainedAssignments.test.js +238 -0
- package/lib/rules/classAssignments.d.ts +6 -0
- package/lib/rules/classAssignments.js +42 -0
- package/lib/rules/classAssignments.test.d.ts +1 -0
- package/lib/rules/classAssignments.test.js +156 -0
- package/lib/rules/constantAssignments.d.ts +6 -0
- package/lib/rules/constantAssignments.js +61 -0
- package/lib/rules/constantAssignments.test.d.ts +1 -0
- package/lib/rules/constantAssignments.test.js +221 -0
- package/lib/rules/constructorReturns.d.ts +6 -0
- package/lib/rules/constructorReturns.js +52 -0
- package/lib/rules/constructorReturns.test.d.ts +1 -0
- package/lib/rules/constructorReturns.test.js +96 -0
- package/lib/rules/debuggerStatements.d.ts +6 -0
- package/lib/rules/debuggerStatements.js +43 -0
- package/lib/rules/debuggerStatements.test.d.ts +1 -0
- package/lib/rules/debuggerStatements.test.js +80 -0
- package/lib/rules/defaultCaseLast.d.ts +6 -0
- package/lib/rules/defaultCaseLast.js +43 -0
- package/lib/rules/defaultCaseLast.test.d.ts +1 -0
- package/lib/rules/defaultCaseLast.test.js +195 -0
- package/lib/rules/duplicateArguments.d.ts +6 -0
- package/lib/rules/duplicateArguments.js +51 -0
- package/lib/rules/duplicateArguments.test.d.ts +1 -0
- package/lib/rules/duplicateArguments.test.js +139 -0
- package/lib/rules/emptyDestructures.d.ts +6 -0
- package/lib/rules/emptyDestructures.js +40 -0
- package/lib/rules/emptyDestructures.test.d.ts +1 -0
- package/lib/rules/emptyDestructures.test.js +186 -0
- package/lib/rules/emptyStaticBlocks.d.ts +6 -0
- package/lib/rules/emptyStaticBlocks.js +54 -0
- package/lib/rules/emptyStaticBlocks.test.d.ts +1 -0
- package/lib/rules/emptyStaticBlocks.test.js +167 -0
- package/lib/rules/exceptionAssignments.d.ts +6 -0
- package/lib/rules/exceptionAssignments.js +61 -0
- package/lib/rules/exceptionAssignments.test.d.ts +1 -0
- package/lib/rules/exceptionAssignments.test.js +264 -0
- package/lib/rules/functionAssignments.d.ts +6 -0
- package/lib/rules/functionAssignments.js +42 -0
- package/lib/rules/functionAssignments.test.d.ts +1 -0
- package/lib/rules/functionAssignments.test.js +209 -0
- package/lib/rules/generatorFunctionYields.d.ts +6 -0
- package/lib/rules/generatorFunctionYields.js +57 -0
- package/lib/rules/generatorFunctionYields.test.d.ts +1 -0
- package/lib/rules/generatorFunctionYields.test.js +151 -0
- package/lib/rules/globalAssignments.d.ts +6 -0
- package/lib/rules/globalAssignments.js +59 -0
- package/lib/rules/globalAssignments.test.d.ts +1 -0
- package/lib/rules/globalAssignments.test.js +215 -0
- package/lib/rules/globalObjectCalls.d.ts +6 -0
- package/lib/rules/globalObjectCalls.js +43 -0
- package/lib/rules/globalObjectCalls.test.d.ts +1 -0
- package/lib/rules/globalObjectCalls.test.js +93 -0
- package/lib/rules/negativeZeroComparisons.d.ts +6 -0
- package/lib/rules/negativeZeroComparisons.js +83 -0
- package/lib/rules/negativeZeroComparisons.test.d.ts +1 -0
- package/lib/rules/negativeZeroComparisons.test.js +209 -0
- package/lib/rules/newExpressions.d.ts +6 -0
- package/lib/rules/newExpressions.js +54 -0
- package/lib/rules/newExpressions.test.d.ts +1 -0
- package/lib/rules/newExpressions.test.js +79 -0
- package/lib/rules/newNativeNonConstructors.d.ts +6 -0
- package/lib/rules/newNativeNonConstructors.js +49 -0
- package/lib/rules/newNativeNonConstructors.test.d.ts +1 -0
- package/lib/rules/newNativeNonConstructors.test.js +94 -0
- package/lib/rules/objectProto.d.ts +6 -0
- package/lib/rules/objectProto.js +54 -0
- package/lib/rules/objectProto.test.d.ts +1 -0
- package/lib/rules/objectProto.test.js +96 -0
- package/lib/rules/octalEscapes.d.ts +6 -0
- package/lib/rules/octalEscapes.js +71 -0
- package/lib/rules/octalEscapes.test.d.ts +1 -0
- package/lib/rules/octalEscapes.test.js +213 -0
- package/lib/rules/octalNumbers.d.ts +6 -0
- package/lib/rules/octalNumbers.js +68 -0
- package/lib/rules/octalNumbers.test.d.ts +1 -0
- package/lib/rules/octalNumbers.test.js +245 -0
- package/lib/rules/returnAssignments.d.ts +6 -0
- package/lib/rules/returnAssignments.js +50 -0
- package/lib/rules/returnAssignments.test.d.ts +1 -0
- package/lib/rules/returnAssignments.test.js +185 -0
- package/lib/rules/sparseArrays.d.ts +6 -0
- package/lib/rules/sparseArrays.js +54 -0
- package/lib/rules/sparseArrays.test.d.ts +1 -0
- package/lib/rules/sparseArrays.test.js +110 -0
- package/lib/rules/symbolDescriptions.d.ts +6 -0
- package/lib/rules/symbolDescriptions.js +41 -0
- package/lib/rules/symbolDescriptions.test.d.ts +1 -0
- package/lib/rules/symbolDescriptions.test.js +89 -0
- package/lib/rules/unassignedVariables.d.ts +6 -0
- package/lib/rules/unassignedVariables.js +55 -0
- package/lib/rules/unassignedVariables.test.d.ts +1 -0
- package/lib/rules/unassignedVariables.test.js +72 -0
- package/lib/rules/undefinedVariables.d.ts +6 -0
- package/lib/rules/undefinedVariables.js +76 -0
- package/lib/rules/undefinedVariables.test.d.ts +1 -0
- package/lib/rules/undefinedVariables.test.js +80 -0
- package/lib/rules/unicodeBOMs.d.ts +6 -0
- package/lib/rules/unicodeBOMs.js +41 -0
- package/lib/rules/unicodeBOMs.test.d.ts +1 -0
- package/lib/rules/unicodeBOMs.test.js +65 -0
- package/lib/rules/unnecessaryCatches.d.ts +6 -0
- package/lib/rules/unnecessaryCatches.js +68 -0
- package/lib/rules/unnecessaryCatches.test.d.ts +1 -0
- package/lib/rules/unnecessaryCatches.test.js +210 -0
- package/lib/rules/unsafeNegations.d.ts +6 -0
- package/lib/rules/unsafeNegations.js +50 -0
- package/lib/rules/unsafeNegations.test.d.ts +1 -0
- package/lib/rules/unsafeNegations.test.js +63 -0
- package/lib/rules/variableDeletions.d.ts +6 -0
- package/lib/rules/variableDeletions.js +39 -0
- package/lib/rules/variableDeletions.test.d.ts +1 -0
- package/lib/rules/variableDeletions.test.js +75 -0
- package/lib/rules/voidOperator.d.ts +6 -0
- package/lib/rules/voidOperator.js +36 -0
- package/lib/rules/voidOperator.test.d.ts +1 -0
- package/lib/rules/voidOperator.test.js +98 -0
- package/lib/utils/declarationsIncludeGlobal.d.ts +2 -0
- package/lib/utils/declarationsIncludeGlobal.js +7 -0
- package/lib/utils/getModifyingReferences.d.ts +8 -0
- package/lib/utils/getModifyingReferences.js +42 -0
- package/lib/utils/isGlobalDeclaration.d.ts +2 -0
- package/lib/utils/isGlobalDeclaration.js +5 -0
- package/lib/utils/isGlobalVariable.d.ts +8 -0
- package/lib/utils/isGlobalVariable.js +21 -0
- package/lib/utils/unwrapParentParenthesizedExpressions.d.ts +2 -0
- package/lib/utils/unwrapParentParenthesizedExpressions.js +6 -0
- package/lib/utils/unwrapParenthesizedExpression.d.ts +2 -0
- package/lib/utils/unwrapParenthesizedExpression.js +6 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/nodes.ts +1 -0
- package/src/plugin.ts +69 -1
- package/src/rules/asyncPromiseExecutors.test.ts +72 -0
- package/src/rules/asyncPromiseExecutors.ts +61 -0
- package/src/rules/caseDeclarations.test.ts +228 -0
- package/src/rules/caseDeclarations.ts +70 -0
- package/src/rules/chainedAssignments.test.ts +239 -0
- package/src/rules/chainedAssignments.ts +55 -0
- package/src/rules/classAssignments.test.ts +157 -0
- package/src/rules/classAssignments.ts +50 -0
- package/src/rules/constantAssignments.test.ts +222 -0
- package/src/rules/constantAssignments.ts +78 -0
- package/src/rules/constructorReturns.test.ts +97 -0
- package/src/rules/constructorReturns.ts +59 -0
- package/src/rules/debuggerStatements.test.ts +81 -0
- package/src/rules/debuggerStatements.ts +45 -0
- package/src/rules/defaultCaseLast.test.ts +196 -0
- package/src/rules/defaultCaseLast.ts +54 -0
- package/src/rules/duplicateArguments.test.ts +140 -0
- package/src/rules/duplicateArguments.ts +58 -0
- package/src/rules/emptyDestructures.test.ts +187 -0
- package/src/rules/emptyDestructures.ts +48 -0
- package/src/rules/emptyStaticBlocks.test.ts +168 -0
- package/src/rules/emptyStaticBlocks.ts +60 -0
- package/src/rules/exceptionAssignments.test.ts +265 -0
- package/src/rules/exceptionAssignments.ts +77 -0
- package/src/rules/functionAssignments.test.ts +210 -0
- package/src/rules/functionAssignments.ts +51 -0
- package/src/rules/generatorFunctionYields.test.ts +152 -0
- package/src/rules/generatorFunctionYields.ts +71 -0
- package/src/rules/globalAssignments.test.ts +216 -0
- package/src/rules/globalAssignments.ts +67 -0
- package/src/rules/globalObjectCalls.test.ts +94 -0
- package/src/rules/globalObjectCalls.ts +52 -0
- package/src/rules/negativeZeroComparisons.test.ts +210 -0
- package/src/rules/negativeZeroComparisons.ts +106 -0
- package/src/rules/newExpressions.test.ts +80 -0
- package/src/rules/newExpressions.ts +67 -0
- package/src/rules/newNativeNonConstructors.test.ts +95 -0
- package/src/rules/newNativeNonConstructors.ts +59 -0
- package/src/rules/objectProto.test.ts +97 -0
- package/src/rules/objectProto.ts +62 -0
- package/src/rules/octalEscapes.test.ts +214 -0
- package/src/rules/octalEscapes.ts +85 -0
- package/src/rules/octalNumbers.test.ts +246 -0
- package/src/rules/octalNumbers.ts +75 -0
- package/src/rules/returnAssignments.test.ts +186 -0
- package/src/rules/returnAssignments.ts +57 -0
- package/src/rules/sparseArrays.test.ts +111 -0
- package/src/rules/sparseArrays.ts +61 -0
- package/src/rules/symbolDescriptions.test.ts +90 -0
- package/src/rules/symbolDescriptions.ts +47 -0
- package/src/rules/unassignedVariables.test.ts +73 -0
- package/src/rules/unassignedVariables.ts +69 -0
- package/src/rules/undefinedVariables.test.ts +81 -0
- package/src/rules/undefinedVariables.ts +97 -0
- package/src/rules/unicodeBOMs.test.ts +66 -0
- package/src/rules/unicodeBOMs.ts +44 -0
- package/src/rules/unnecessaryCatches.test.ts +211 -0
- package/src/rules/unnecessaryCatches.ts +84 -0
- package/src/rules/unsafeNegations.test.ts +64 -0
- package/src/rules/unsafeNegations.ts +59 -0
- package/src/rules/variableDeletions.test.ts +76 -0
- package/src/rules/variableDeletions.ts +43 -0
- package/src/rules/voidOperator.test.ts +99 -0
- package/src/rules/voidOperator.ts +38 -0
- package/src/utils/declarationsIncludeGlobal.ts +11 -0
- package/src/utils/getModifyingReferences.ts +58 -0
- package/src/utils/isGlobalDeclaration.ts +12 -0
- package/src/utils/isGlobalVariable.ts +30 -0
- package/src/utils/unwrapParentParenthesizedExpressions.ts +7 -0
- package/src/utils/unwrapParenthesizedExpression.ts +9 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import rule from "./octalEscapes.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
const a = "\\1";
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
const a = "\\1";
|
|
12
|
+
~~
|
|
13
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
14
|
+
`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: `
|
|
18
|
+
const a = "\\2";
|
|
19
|
+
`,
|
|
20
|
+
snapshot: `
|
|
21
|
+
const a = "\\2";
|
|
22
|
+
~~
|
|
23
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
24
|
+
`,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: `
|
|
28
|
+
const a = "\\7";
|
|
29
|
+
`,
|
|
30
|
+
snapshot: `
|
|
31
|
+
const a = "\\7";
|
|
32
|
+
~~
|
|
33
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
34
|
+
`,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: `
|
|
38
|
+
const a = "\\00";
|
|
39
|
+
`,
|
|
40
|
+
snapshot: `
|
|
41
|
+
const a = "\\00";
|
|
42
|
+
~~~
|
|
43
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
44
|
+
`,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
code: `
|
|
48
|
+
const a = "\\01";
|
|
49
|
+
`,
|
|
50
|
+
snapshot: `
|
|
51
|
+
const a = "\\01";
|
|
52
|
+
~~~
|
|
53
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
54
|
+
`,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
code: `
|
|
58
|
+
const a = "\\02";
|
|
59
|
+
`,
|
|
60
|
+
snapshot: `
|
|
61
|
+
const a = "\\02";
|
|
62
|
+
~~~
|
|
63
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
64
|
+
`,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
code: `
|
|
68
|
+
const a = "\\07";
|
|
69
|
+
`,
|
|
70
|
+
snapshot: `
|
|
71
|
+
const a = "\\07";
|
|
72
|
+
~~~
|
|
73
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
74
|
+
`,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
code: `
|
|
78
|
+
const a = "\\377";
|
|
79
|
+
`,
|
|
80
|
+
snapshot: `
|
|
81
|
+
const a = "\\377";
|
|
82
|
+
~~~~
|
|
83
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
84
|
+
`,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
code: `
|
|
88
|
+
const a = "\\12";
|
|
89
|
+
`,
|
|
90
|
+
snapshot: `
|
|
91
|
+
const a = "\\12";
|
|
92
|
+
~~~
|
|
93
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
94
|
+
`,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
code: `
|
|
98
|
+
const a = "before\\1after";
|
|
99
|
+
`,
|
|
100
|
+
snapshot: `
|
|
101
|
+
const a = "before\\1after";
|
|
102
|
+
~~
|
|
103
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
104
|
+
`,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
code: `
|
|
108
|
+
const a = "before\\01after";
|
|
109
|
+
`,
|
|
110
|
+
snapshot: `
|
|
111
|
+
const a = "before\\01after";
|
|
112
|
+
~~~
|
|
113
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
114
|
+
`,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
code: `
|
|
118
|
+
const a = '\\1';
|
|
119
|
+
`,
|
|
120
|
+
snapshot: `
|
|
121
|
+
const a = '\\1';
|
|
122
|
+
~~
|
|
123
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
124
|
+
`,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
code: `
|
|
128
|
+
const a = '\\01';
|
|
129
|
+
`,
|
|
130
|
+
snapshot: `
|
|
131
|
+
const a = '\\01';
|
|
132
|
+
~~~
|
|
133
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
134
|
+
`,
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
code: `
|
|
138
|
+
const a = \`\\1\`;
|
|
139
|
+
`,
|
|
140
|
+
snapshot: `
|
|
141
|
+
const a = \`\\1\`;
|
|
142
|
+
~~
|
|
143
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
144
|
+
`,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
code: `
|
|
148
|
+
const a = \`\\01\`;
|
|
149
|
+
`,
|
|
150
|
+
snapshot: `
|
|
151
|
+
const a = \`\\01\`;
|
|
152
|
+
~~~
|
|
153
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
154
|
+
`,
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
code: `
|
|
158
|
+
const a = \`before\\1after\`;
|
|
159
|
+
`,
|
|
160
|
+
snapshot: `
|
|
161
|
+
const a = \`before\\1after\`;
|
|
162
|
+
~~
|
|
163
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
164
|
+
`,
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
code: `
|
|
168
|
+
const x = 5;
|
|
169
|
+
const a = \`value: \${x} \\1\`;
|
|
170
|
+
`,
|
|
171
|
+
snapshot: `
|
|
172
|
+
const x = 5;
|
|
173
|
+
const a = \`value: \${x} \\1\`;
|
|
174
|
+
~~
|
|
175
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
176
|
+
`,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
code: `
|
|
180
|
+
const x = 5;
|
|
181
|
+
const a = \`\\01 value: \${x}\`;
|
|
182
|
+
`,
|
|
183
|
+
snapshot: `
|
|
184
|
+
const x = 5;
|
|
185
|
+
const a = \`\\01 value: \${x}\`;
|
|
186
|
+
~~~
|
|
187
|
+
Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.
|
|
188
|
+
`,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
valid: [
|
|
192
|
+
`const a = "\\0";`,
|
|
193
|
+
`const a = "\\8";`,
|
|
194
|
+
`const a = "\\9";`,
|
|
195
|
+
`const a = "\\x01";`,
|
|
196
|
+
`const a = "\\u0001";`,
|
|
197
|
+
`const a = "\\n";`,
|
|
198
|
+
`const a = "\\t";`,
|
|
199
|
+
`const a = "\\\\0";`,
|
|
200
|
+
`const a = "\\\\1";`,
|
|
201
|
+
`const a = "before\\0after";`,
|
|
202
|
+
`const a = "before\\8after";`,
|
|
203
|
+
`const a = "before\\9after";`,
|
|
204
|
+
`const a = '\\0';`,
|
|
205
|
+
`const a = '\\8';`,
|
|
206
|
+
`const a = '\\9';`,
|
|
207
|
+
`const a = \`\\0\`;`,
|
|
208
|
+
`const a = \`\\8\`;`,
|
|
209
|
+
`const a = \`\\9\`;`,
|
|
210
|
+
`const x = 5; const a = \`value: \${x} \\0\`;`,
|
|
211
|
+
`const x = 5; const a = \`\\0 value: \${x}\`;`,
|
|
212
|
+
`const x = 5; const a = \`\\8 \${x} \\9\`;`,
|
|
213
|
+
],
|
|
214
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { typescriptLanguage } from "../language.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Finds the position and length of an octal escape sequence in a string.
|
|
7
|
+
* Returns undefined if no octal escape is found.
|
|
8
|
+
*/
|
|
9
|
+
function findOctalEscape(
|
|
10
|
+
text: string,
|
|
11
|
+
): undefined | { index: number; length: number } {
|
|
12
|
+
// Remove quotes from the string literal
|
|
13
|
+
const content = text.slice(1, -1);
|
|
14
|
+
|
|
15
|
+
// Match octal escapes: \0 followed by [0-7], or \1-7 optionally followed by [0-7]
|
|
16
|
+
// But exclude escaped backslashes (\\)
|
|
17
|
+
const octalEscapePattern = /(?<!\\)\\0[0-7]|(?<!\\)\\[1-7][0-7]*/;
|
|
18
|
+
const match = octalEscapePattern.exec(content);
|
|
19
|
+
|
|
20
|
+
if (!match) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Add 1 to account for the opening quote
|
|
25
|
+
return {
|
|
26
|
+
index: match.index + 1,
|
|
27
|
+
length: match[0].length,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default typescriptLanguage.createRule({
|
|
32
|
+
about: {
|
|
33
|
+
description: "Reports using octal escape sequences in string literals.",
|
|
34
|
+
id: "octalEscapes",
|
|
35
|
+
preset: "logical",
|
|
36
|
+
},
|
|
37
|
+
messages: {
|
|
38
|
+
noOctalEscape: {
|
|
39
|
+
primary:
|
|
40
|
+
"Prefer hexadecimal or Unicode escape sequences over legacy octal escape sequences.",
|
|
41
|
+
secondary: [
|
|
42
|
+
"Octal escape sequences (e.g., `\\01`, `\\02`, `\\377`) are a deprecated feature in JavaScript that can lead to confusion and are forbidden in strict mode and template literals.",
|
|
43
|
+
"They are less readable than their modern alternatives and can cause portability issues.",
|
|
44
|
+
],
|
|
45
|
+
suggestions: [
|
|
46
|
+
"Use hexadecimal escape sequences (e.g., `\\x01`) or Unicode escape sequences (e.g., `\\u0001`) instead.",
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
setup(context) {
|
|
51
|
+
function checkNode(node: ts.Node) {
|
|
52
|
+
const text = node.getText(context.sourceFile);
|
|
53
|
+
const octalEscape = findOctalEscape(text);
|
|
54
|
+
|
|
55
|
+
if (!octalEscape) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const nodeStart = node.getStart(context.sourceFile);
|
|
60
|
+
context.report({
|
|
61
|
+
message: "noOctalEscape",
|
|
62
|
+
range: {
|
|
63
|
+
begin: nodeStart + octalEscape.index,
|
|
64
|
+
end: nodeStart + octalEscape.index + octalEscape.length,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
visitors: {
|
|
71
|
+
NoSubstitutionTemplateLiteral: checkNode,
|
|
72
|
+
StringLiteral: checkNode,
|
|
73
|
+
TemplateExpression: (node) => {
|
|
74
|
+
// Check the head of the template
|
|
75
|
+
checkNode(node.head);
|
|
76
|
+
|
|
77
|
+
// Check each template span
|
|
78
|
+
for (const span of node.templateSpans) {
|
|
79
|
+
checkNode(span.literal);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import rule from "./octalNumbers.js";
|
|
2
|
+
import { ruleTester } from "./ruleTester.js";
|
|
3
|
+
|
|
4
|
+
ruleTester.describe(rule, {
|
|
5
|
+
invalid: [
|
|
6
|
+
{
|
|
7
|
+
code: `
|
|
8
|
+
const value = 07;
|
|
9
|
+
`,
|
|
10
|
+
snapshot: `
|
|
11
|
+
const value = 07;
|
|
12
|
+
~~
|
|
13
|
+
This legacy octal numeric literal evaluates to 7. Did you mean that value, or to use a modern octal syntax such as 0o7?
|
|
14
|
+
`,
|
|
15
|
+
suggestions: [
|
|
16
|
+
{
|
|
17
|
+
id: "useModernOctalSyntax",
|
|
18
|
+
updated: `
|
|
19
|
+
const value = 0o7;
|
|
20
|
+
`,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: "removeLeadingZero",
|
|
24
|
+
updated: `
|
|
25
|
+
const value = 7;
|
|
26
|
+
`,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: `
|
|
32
|
+
const value = 077;
|
|
33
|
+
`,
|
|
34
|
+
snapshot: `
|
|
35
|
+
const value = 077;
|
|
36
|
+
~~~
|
|
37
|
+
This legacy octal numeric literal evaluates to 63. Did you mean that value, or to use a modern octal syntax such as 0o77?
|
|
38
|
+
`,
|
|
39
|
+
suggestions: [
|
|
40
|
+
{
|
|
41
|
+
id: "useModernOctalSyntax",
|
|
42
|
+
updated: `
|
|
43
|
+
const value = 0o77;
|
|
44
|
+
`,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "removeLeadingZero",
|
|
48
|
+
updated: `
|
|
49
|
+
const value = 77;
|
|
50
|
+
`,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
code: `
|
|
56
|
+
const value = 0123;
|
|
57
|
+
`,
|
|
58
|
+
snapshot: `
|
|
59
|
+
const value = 0123;
|
|
60
|
+
~~~~
|
|
61
|
+
This legacy octal numeric literal evaluates to 83. Did you mean that value, or to use a modern octal syntax such as 0o123?
|
|
62
|
+
`,
|
|
63
|
+
suggestions: [
|
|
64
|
+
{
|
|
65
|
+
id: "useModernOctalSyntax",
|
|
66
|
+
updated: `
|
|
67
|
+
const value = 0o123;
|
|
68
|
+
`,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "removeLeadingZero",
|
|
72
|
+
updated: `
|
|
73
|
+
const value = 123;
|
|
74
|
+
`,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
code: `
|
|
80
|
+
const value = 01234567;
|
|
81
|
+
`,
|
|
82
|
+
snapshot: `
|
|
83
|
+
const value = 01234567;
|
|
84
|
+
~~~~~~~~
|
|
85
|
+
This legacy octal numeric literal evaluates to 342391. Did you mean that value, or to use a modern octal syntax such as 0o1234567?
|
|
86
|
+
`,
|
|
87
|
+
suggestions: [
|
|
88
|
+
{
|
|
89
|
+
id: "useModernOctalSyntax",
|
|
90
|
+
updated: `
|
|
91
|
+
const value = 0o1234567;
|
|
92
|
+
`,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: "removeLeadingZero",
|
|
96
|
+
updated: `
|
|
97
|
+
const value = 1234567;
|
|
98
|
+
`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
code: `
|
|
104
|
+
const values = [01, 02, 03];
|
|
105
|
+
`,
|
|
106
|
+
snapshot: `
|
|
107
|
+
const values = [01, 02, 03];
|
|
108
|
+
~~
|
|
109
|
+
This legacy octal numeric literal evaluates to 1. Did you mean that value, or to use a modern octal syntax such as 0o1?
|
|
110
|
+
~~
|
|
111
|
+
This legacy octal numeric literal evaluates to 2. Did you mean that value, or to use a modern octal syntax such as 0o2?
|
|
112
|
+
~~
|
|
113
|
+
This legacy octal numeric literal evaluates to 3. Did you mean that value, or to use a modern octal syntax such as 0o3?
|
|
114
|
+
`,
|
|
115
|
+
suggestions: [
|
|
116
|
+
{
|
|
117
|
+
id: "useModernOctalSyntax",
|
|
118
|
+
updated: `
|
|
119
|
+
const values = [0o1, 02, 03];
|
|
120
|
+
`,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "removeLeadingZero",
|
|
124
|
+
updated: `
|
|
125
|
+
const values = [1, 02, 03];
|
|
126
|
+
`,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "useModernOctalSyntax",
|
|
130
|
+
updated: `
|
|
131
|
+
const values = [01, 0o2, 03];
|
|
132
|
+
`,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: "removeLeadingZero",
|
|
136
|
+
updated: `
|
|
137
|
+
const values = [01, 2, 03];
|
|
138
|
+
`,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: "useModernOctalSyntax",
|
|
142
|
+
updated: `
|
|
143
|
+
const values = [01, 02, 0o3];
|
|
144
|
+
`,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: "removeLeadingZero",
|
|
148
|
+
updated: `
|
|
149
|
+
const values = [01, 02, 3];
|
|
150
|
+
`,
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
code: `
|
|
156
|
+
function calculate() {
|
|
157
|
+
return 077;
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
160
|
+
snapshot: `
|
|
161
|
+
function calculate() {
|
|
162
|
+
return 077;
|
|
163
|
+
~~~
|
|
164
|
+
This legacy octal numeric literal evaluates to 63. Did you mean that value, or to use a modern octal syntax such as 0o77?
|
|
165
|
+
}
|
|
166
|
+
`,
|
|
167
|
+
suggestions: [
|
|
168
|
+
{
|
|
169
|
+
id: "useModernOctalSyntax",
|
|
170
|
+
updated: `
|
|
171
|
+
function calculate() {
|
|
172
|
+
return 0o77;
|
|
173
|
+
}
|
|
174
|
+
`,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: "removeLeadingZero",
|
|
178
|
+
updated: `
|
|
179
|
+
function calculate() {
|
|
180
|
+
return 77;
|
|
181
|
+
}
|
|
182
|
+
`,
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
code: `
|
|
188
|
+
const result = 010 + 020;
|
|
189
|
+
`,
|
|
190
|
+
snapshot: `
|
|
191
|
+
const result = 010 + 020;
|
|
192
|
+
~~~
|
|
193
|
+
This legacy octal numeric literal evaluates to 8. Did you mean that value, or to use a modern octal syntax such as 0o10?
|
|
194
|
+
~~~
|
|
195
|
+
This legacy octal numeric literal evaluates to 16. Did you mean that value, or to use a modern octal syntax such as 0o20?
|
|
196
|
+
`,
|
|
197
|
+
suggestions: [
|
|
198
|
+
{
|
|
199
|
+
id: "useModernOctalSyntax",
|
|
200
|
+
updated: `
|
|
201
|
+
const result = 0o10 + 020;
|
|
202
|
+
`,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: "removeLeadingZero",
|
|
206
|
+
updated: `
|
|
207
|
+
const result = 10 + 020;
|
|
208
|
+
`,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: "useModernOctalSyntax",
|
|
212
|
+
updated: `
|
|
213
|
+
const result = 010 + 0o20;
|
|
214
|
+
`,
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: "removeLeadingZero",
|
|
218
|
+
updated: `
|
|
219
|
+
const result = 010 + 20;
|
|
220
|
+
`,
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
valid: [
|
|
226
|
+
`const value = 0;`,
|
|
227
|
+
`const value = 1;`,
|
|
228
|
+
`const value = 10;`,
|
|
229
|
+
`const value = 100;`,
|
|
230
|
+
`const value = 0x7F;`,
|
|
231
|
+
`const value = 0o77;`,
|
|
232
|
+
`const value = 0O77;`,
|
|
233
|
+
`const value = 0b111;`,
|
|
234
|
+
`const value = 0B111;`,
|
|
235
|
+
`const value = 0.8;`,
|
|
236
|
+
`const value = 8;`,
|
|
237
|
+
`const value = 9;`,
|
|
238
|
+
`const value = 123;`,
|
|
239
|
+
`const values = [0, 1, 10, 100];`,
|
|
240
|
+
`const hex = 0xFF;`,
|
|
241
|
+
`const binary = 0b1010;`,
|
|
242
|
+
`const octal = 0o755;`,
|
|
243
|
+
`const notOctal = 08;`,
|
|
244
|
+
`const alsoNotOctal = 09;`,
|
|
245
|
+
],
|
|
246
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { typescriptLanguage } from "../language.js";
|
|
2
|
+
|
|
3
|
+
export default typescriptLanguage.createRule({
|
|
4
|
+
about: {
|
|
5
|
+
description: "Reports using legacy octal numeric literals.",
|
|
6
|
+
id: "octalNumbers",
|
|
7
|
+
preset: "untyped",
|
|
8
|
+
},
|
|
9
|
+
messages: {
|
|
10
|
+
noOctalNumber: {
|
|
11
|
+
primary:
|
|
12
|
+
"This legacy octal numeric literal evaluates to {{ raw }}. Did you mean that value, or to use a modern octal syntax such as {{ equivalent }}?",
|
|
13
|
+
secondary: [
|
|
14
|
+
"Legacy octal numeric literals (e.g., `077`, `0123`) are a deprecated feature in JavaScript that can lead to confusion and errors.",
|
|
15
|
+
"They are forbidden in strict mode and are less readable than their modern alternatives.",
|
|
16
|
+
"The digit `0` by itself is allowed as it represents zero, not an octal literal.",
|
|
17
|
+
],
|
|
18
|
+
suggestions: [
|
|
19
|
+
"Use the explicit octal syntax (e.g., `0o77`) introduced in ES6, which is clearer and works in both strict and non-strict modes.",
|
|
20
|
+
"Remove the leading `0` if you intended to use the decimal value.",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
setup(context) {
|
|
25
|
+
return {
|
|
26
|
+
visitors: {
|
|
27
|
+
NumericLiteral: (node) => {
|
|
28
|
+
const text = node.getText(context.sourceFile);
|
|
29
|
+
|
|
30
|
+
// Check for legacy octal literal: starts with 0 followed by octal digits (0-7)
|
|
31
|
+
// But not just "0" alone, and not modern formats like 0x, 0o, 0b
|
|
32
|
+
// cspell:ignore xobi
|
|
33
|
+
if (
|
|
34
|
+
text.length > 1 &&
|
|
35
|
+
text.startsWith("0") &&
|
|
36
|
+
text[1] >= "0" &&
|
|
37
|
+
text[1] <= "7" &&
|
|
38
|
+
!/^0[xobi]/i.test(text)
|
|
39
|
+
) {
|
|
40
|
+
const range = {
|
|
41
|
+
begin: node.getStart(context.sourceFile),
|
|
42
|
+
end: node.getEnd(),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Parse the octal value
|
|
46
|
+
const octalValue = parseInt(text, 8);
|
|
47
|
+
const modernOctalSyntax = `0o${text.slice(1)}`;
|
|
48
|
+
const decimalWithoutLeadingZero = text.slice(1);
|
|
49
|
+
|
|
50
|
+
context.report({
|
|
51
|
+
data: {
|
|
52
|
+
equivalent: modernOctalSyntax,
|
|
53
|
+
raw: octalValue.toString(),
|
|
54
|
+
},
|
|
55
|
+
message: "noOctalNumber",
|
|
56
|
+
range,
|
|
57
|
+
suggestions: [
|
|
58
|
+
{
|
|
59
|
+
id: "useModernOctalSyntax",
|
|
60
|
+
range,
|
|
61
|
+
text: modernOctalSyntax,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "removeLeadingZero",
|
|
65
|
+
range,
|
|
66
|
+
text: decimalWithoutLeadingZero,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
});
|