eslint-plugin-ts-std-forge 0.1.17 → 0.1.19
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/dist/rules/prefer-safe-array-length-guard.d.mts.map +1 -1
- package/dist/rules/prefer-safe-array-length-guard.mjs +5 -6
- package/dist/rules/prefer-safe-array-length-guard.mjs.map +1 -1
- package/package.json +7 -7
- package/src/rules/prefer-safe-array-length-guard.mts +7 -14
- package/src/rules/prefer-safe-array-length-guard.test.mts +59 -0
- package/src/rules/prefer-safe-number-parse.test.mts +36 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-array-length-guard.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-safe-array-length-guard.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAUlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,YAAY,GAAG,eAAe,CAAC;AAwCjD,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,UAAU,CAC1D,UAAU,EACV,OAAO,CAwGC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { bindValueImportsAt, getArgumentText, skipTypeWrappers, typeHoldsAtEveryLayer, } from 'eslint-rule-forge';
|
|
3
3
|
import { TS_STD_FORGE_MODULE } from './constants.mjs';
|
|
4
4
|
|
|
5
5
|
|
|
@@ -73,17 +73,16 @@ export const preferSafeArrayLengthGuard = {
|
|
|
73
73
|
if (mut_nodesToFix.length === 0) {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
const
|
|
76
|
+
const bindingAt = bindValueImportsAt(sourceCode, TS_STD_FORGE_MODULE, [
|
|
77
77
|
'SafeArray',
|
|
78
78
|
]);
|
|
79
|
-
const localName = binding?.localNames[0];
|
|
80
79
|
|
|
81
80
|
|
|
82
81
|
for (const { node, arrayExpression, guard } of mut_nodesToFix) {
|
|
82
|
+
const binding = bindingAt(node);
|
|
83
|
+
const localName = binding?.localNames[0];
|
|
83
84
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
84
|
-
const writable = binding !== undefined &&
|
|
85
|
-
localName !== undefined &&
|
|
86
|
-
!hasForeignBinding(sourceCode, node, localName, TS_STD_FORGE_MODULE);
|
|
85
|
+
const writable = binding !== undefined && localName !== undefined;
|
|
87
86
|
context.report({
|
|
88
87
|
node,
|
|
89
88
|
messageId: MESSAGE_IDS[guard],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-array-length-guard.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"prefer-safe-array-length-guard.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-array-length-guard.mts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-ts-std-forge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "ESLint rules that steer code toward ts-std-forge idioms.",
|
|
6
6
|
"keywords": [
|
|
@@ -35,21 +35,21 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@typescript-eslint/utils": "^8.72.0",
|
|
38
|
-
"eslint-rule-forge": "^0.
|
|
39
|
-
"ts-std-forge": "0.5.
|
|
38
|
+
"eslint-rule-forge": "^0.6.0",
|
|
39
|
+
"ts-std-forge": "0.5.3",
|
|
40
40
|
"ts-type-forge": "~9.2.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@typescript-eslint/parser": "8.72.0",
|
|
44
44
|
"@typescript-eslint/rule-tester": "8.72.0",
|
|
45
45
|
"dedent": "1.7.2",
|
|
46
|
-
"eslint-config-typed": "7.
|
|
47
|
-
"eslint-plugin-ts-fortress": "1.3.
|
|
48
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
46
|
+
"eslint-config-typed": "7.5.0",
|
|
47
|
+
"eslint-plugin-ts-fortress": "1.3.14",
|
|
48
|
+
"eslint-plugin-ts-type-forge": "0.8.19",
|
|
49
49
|
"prettier": "3.9.10",
|
|
50
50
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
51
51
|
"prettier-plugin-packagejson": "3.0.2",
|
|
52
|
-
"ts-repo-utils": "10.7.
|
|
52
|
+
"ts-repo-utils": "10.7.3"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"eslint": ">=9.0.0",
|
|
@@ -4,9 +4,8 @@ import {
|
|
|
4
4
|
type TSESTree,
|
|
5
5
|
} from '@typescript-eslint/utils';
|
|
6
6
|
import {
|
|
7
|
-
|
|
7
|
+
bindValueImportsAt,
|
|
8
8
|
getArgumentText,
|
|
9
|
-
hasForeignBinding,
|
|
10
9
|
skipTypeWrappers,
|
|
11
10
|
typeHoldsAtEveryLayer,
|
|
12
11
|
} from 'eslint-rule-forge';
|
|
@@ -123,26 +122,20 @@ export const preferSafeArrayLengthGuard: TSESLint.RuleModule<
|
|
|
123
122
|
return;
|
|
124
123
|
}
|
|
125
124
|
|
|
126
|
-
const
|
|
125
|
+
const bindingAt = bindValueImportsAt(sourceCode, TS_STD_FORGE_MODULE, [
|
|
127
126
|
'SafeArray',
|
|
128
127
|
]);
|
|
129
128
|
|
|
130
|
-
const localName = binding?.localNames[0];
|
|
131
|
-
|
|
132
129
|
// Every fix brings `SafeArray` into scope itself, so that one applied
|
|
133
130
|
// alone (an editor's quick fix) is complete.
|
|
134
131
|
for (const { node, arrayExpression, guard } of mut_nodesToFix) {
|
|
132
|
+
const binding = bindingAt(node);
|
|
133
|
+
|
|
134
|
+
const localName = binding?.localNames[0];
|
|
135
|
+
|
|
135
136
|
const arrayText = getArgumentText(sourceCode, arrayExpression);
|
|
136
137
|
|
|
137
|
-
const writable =
|
|
138
|
-
binding !== undefined &&
|
|
139
|
-
localName !== undefined &&
|
|
140
|
-
!hasForeignBinding(
|
|
141
|
-
sourceCode,
|
|
142
|
-
node,
|
|
143
|
-
localName,
|
|
144
|
-
TS_STD_FORGE_MODULE,
|
|
145
|
-
);
|
|
138
|
+
const writable = binding !== undefined && localName !== undefined;
|
|
146
139
|
|
|
147
140
|
context.report({
|
|
148
141
|
node,
|
|
@@ -78,6 +78,29 @@ describe('prefer-safe-array-length-guard', () => {
|
|
|
78
78
|
`,
|
|
79
79
|
errors: [{ messageId: 'useIsNonEmpty' }],
|
|
80
80
|
},
|
|
81
|
+
{
|
|
82
|
+
name: 'writes through a namespace import, and names what it writes',
|
|
83
|
+
code: dedent`
|
|
84
|
+
import * as tsf from 'ts-std-forge';
|
|
85
|
+
declare const xs: readonly number[];
|
|
86
|
+
const ok = xs.length === 0;
|
|
87
|
+
`,
|
|
88
|
+
output: dedent`
|
|
89
|
+
import * as tsf from 'ts-std-forge';
|
|
90
|
+
declare const xs: readonly number[];
|
|
91
|
+
const ok = tsf.SafeArray.isEmpty(xs);
|
|
92
|
+
`,
|
|
93
|
+
errors: [
|
|
94
|
+
{
|
|
95
|
+
messageId: 'useIsEmpty',
|
|
96
|
+
data: {
|
|
97
|
+
original: 'xs.length === 0',
|
|
98
|
+
arrayName: 'xs',
|
|
99
|
+
safeArray: 'tsf.SafeArray',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
},
|
|
81
104
|
{
|
|
82
105
|
name: 'xs.length >= 1 becomes isNonEmpty',
|
|
83
106
|
code: dedent`
|
|
@@ -399,6 +422,42 @@ describe('prefer-safe-array-length-guard and the import it adds', () => {
|
|
|
399
422
|
output: null,
|
|
400
423
|
errors: [{ messageId: 'useIsNonEmpty' }],
|
|
401
424
|
},
|
|
425
|
+
{
|
|
426
|
+
name: 'a type parameter of the name does not take the value',
|
|
427
|
+
code: dedent`
|
|
428
|
+
declare const xs: readonly number[];
|
|
429
|
+
function f<SafeArray>() {
|
|
430
|
+
return xs.length > 0;
|
|
431
|
+
}
|
|
432
|
+
`,
|
|
433
|
+
output: dedent`
|
|
434
|
+
import { SafeArray } from 'ts-std-forge';
|
|
435
|
+
declare const xs: readonly number[];
|
|
436
|
+
function f<SafeArray>() {
|
|
437
|
+
return SafeArray.isNonEmpty(xs);
|
|
438
|
+
}
|
|
439
|
+
`,
|
|
440
|
+
errors: [{ messageId: 'useIsNonEmpty' }],
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: 'a local type alias of the name does not take the value',
|
|
444
|
+
code: dedent`
|
|
445
|
+
declare const xs: readonly number[];
|
|
446
|
+
function f() {
|
|
447
|
+
type SafeArray = number;
|
|
448
|
+
return xs.length > 0;
|
|
449
|
+
}
|
|
450
|
+
`,
|
|
451
|
+
output: dedent`
|
|
452
|
+
import { SafeArray } from 'ts-std-forge';
|
|
453
|
+
declare const xs: readonly number[];
|
|
454
|
+
function f() {
|
|
455
|
+
type SafeArray = number;
|
|
456
|
+
return SafeArray.isNonEmpty(xs);
|
|
457
|
+
}
|
|
458
|
+
`,
|
|
459
|
+
errors: [{ messageId: 'useIsNonEmpty' }],
|
|
460
|
+
},
|
|
402
461
|
],
|
|
403
462
|
});
|
|
404
463
|
});
|
|
@@ -17,6 +17,15 @@ const tester = new RuleTester({
|
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
+
// What the report and its suggestion name when the file imports the module as a
|
|
21
|
+
// namespace.
|
|
22
|
+
const namespaceData = {
|
|
23
|
+
original: 'parseFloat(s)',
|
|
24
|
+
argName: 's',
|
|
25
|
+
namespaceName: 'tsf.SafeNumber',
|
|
26
|
+
resultName: 'tsf.Result',
|
|
27
|
+
} as const;
|
|
28
|
+
|
|
20
29
|
describe('prefer-safe-number-parse', () => {
|
|
21
30
|
tester.run('prefer-safe-number-parse', preferSafeNumberParse, {
|
|
22
31
|
valid: [
|
|
@@ -119,6 +128,33 @@ describe('prefer-safe-number-parse', () => {
|
|
|
119
128
|
},
|
|
120
129
|
],
|
|
121
130
|
},
|
|
131
|
+
{
|
|
132
|
+
name: 'writes through a namespace import, and names what it writes',
|
|
133
|
+
code: dedent`
|
|
134
|
+
import * as tsf from 'ts-std-forge';
|
|
135
|
+
|
|
136
|
+
declare const s: string;
|
|
137
|
+
const n = parseFloat(s);
|
|
138
|
+
`,
|
|
139
|
+
errors: [
|
|
140
|
+
{
|
|
141
|
+
messageId: 'useSafeParseFloat',
|
|
142
|
+
data: namespaceData,
|
|
143
|
+
suggestions: [
|
|
144
|
+
{
|
|
145
|
+
messageId: 'replaceWithSafeParse',
|
|
146
|
+
data: namespaceData,
|
|
147
|
+
output: dedent`
|
|
148
|
+
import * as tsf from 'ts-std-forge';
|
|
149
|
+
|
|
150
|
+
declare const s: string;
|
|
151
|
+
const n = tsf.Result.unwrapOkOr(tsf.SafeNumber.parse(s), Number.NaN);
|
|
152
|
+
`,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
122
158
|
{
|
|
123
159
|
name: 'rewrites parseFloat on a string',
|
|
124
160
|
code: dedent`
|