eslint-config-typed 7.3.0 → 7.3.1
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/plugins/total-functions/rules/no-partial-division.d.mts +4 -1
- package/dist/plugins/total-functions/rules/no-partial-division.d.mts.map +1 -1
- package/dist/plugins/total-functions/rules/no-partial-division.mjs +20 -16
- package/dist/plugins/total-functions/rules/no-partial-division.mjs.map +1 -1
- package/package.json +5 -5
- package/src/plugins/total-functions/rules/no-partial-division.mts +36 -27
- package/src/plugins/total-functions/rules/no-partial-division.test.mts +92 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* An ESLint rule to ban partial division: `x / y` and `x /= y` whose
|
|
4
|
+
* denominator is not provably non-zero.
|
|
5
|
+
*/
|
|
3
6
|
export declare const noPartialDivision: ESLintUtils.RuleModule<string, readonly unknown[], unknown, ESLintUtils.RuleListener> & {
|
|
4
7
|
name: string;
|
|
5
8
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-partial-division.d.mts","sourceRoot":"","sources":["../../../../src/plugins/total-functions/rules/no-partial-division.mts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"no-partial-division.d.mts","sourceRoot":"","sources":["../../../../src/plugins/total-functions/rules/no-partial-division.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAEZ,MAAM,0BAA0B,CAAC;AAMlC;;;GAGG;AAEH,eAAO,MAAM,iBAAiB;;CAiFnB,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils, } from '@typescript-eslint/utils';
|
|
2
2
|
import { Arr, isNonNullObject } from 'ts-data-forge';
|
|
3
3
|
import { intersectionTypeParts, unionTypeParts } from 'tsutils';
|
|
4
4
|
import { createRule } from './common.mjs';
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
6
9
|
export const noPartialDivision = createRule({
|
|
7
10
|
name: 'no-partial-division',
|
|
8
11
|
meta: {
|
|
@@ -31,26 +34,27 @@ export const noPartialDivision = createRule({
|
|
|
31
34
|
return ((type.isNumberLiteral() && type.value !== 0) ||
|
|
32
35
|
(isBigIntLiteral(type) && type.value.base10Value !== '0'));
|
|
33
36
|
};
|
|
37
|
+
const isProvablySafeDenominator = (denominator) => {
|
|
38
|
+
if (denominator.type === AST_NODE_TYPES.Literal &&
|
|
39
|
+
denominator.value !== 0 &&
|
|
40
|
+
denominator.value !== 0n) {
|
|
41
|
+
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (denominator.type === AST_NODE_TYPES.Identifier) {
|
|
45
|
+
const denominatorNode = parserServices.esTreeNodeToTSNodeMap.get(denominator);
|
|
46
|
+
return isSafeDenominator(checker.getTypeAtLocation(denominatorNode));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return false;
|
|
50
|
+
};
|
|
34
51
|
return {
|
|
35
|
-
BinaryExpression: (node) => {
|
|
36
|
-
if (node.operator !== '/') {
|
|
37
52
|
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (node.right.type === AST_NODE_TYPES.Literal &&
|
|
41
|
-
node.right.value !== 0 &&
|
|
42
|
-
node.right.value !== 0n) {
|
|
43
53
|
|
|
54
|
+
'BinaryExpression[operator="/"], AssignmentExpression[operator="/="]': (node) => {
|
|
55
|
+
if (isProvablySafeDenominator(node.right)) {
|
|
44
56
|
return;
|
|
45
57
|
}
|
|
46
|
-
if (node.right.type === AST_NODE_TYPES.Identifier) {
|
|
47
|
-
const denominatorNode = parserServices.esTreeNodeToTSNodeMap.get(node.right);
|
|
48
|
-
const denominatorNodeType = checker.getTypeAtLocation(denominatorNode);
|
|
49
|
-
if (isSafeDenominator(denominatorNodeType)) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
58
|
context.report({
|
|
55
59
|
node,
|
|
56
60
|
messageId: 'errorStringGeneric',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-partial-division.mjs","sourceRoot":"","sources":["../../../../src/plugins/total-functions/rules/no-partial-division.mts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"no-partial-division.mjs","sourceRoot":"","sources":["../../../../src/plugins/total-functions/rules/no-partial-division.mts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-config-typed",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript"
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"is-glob": "^4.0.3",
|
|
76
76
|
"is-immutable-type": "^5.0.4",
|
|
77
77
|
"micromatch": "^4.0.8",
|
|
78
|
-
"ts-data-forge": "^14.10.
|
|
78
|
+
"ts-data-forge": "^14.10.2",
|
|
79
79
|
"ts-type-forge": "^9.2.2",
|
|
80
80
|
"tsutils": "^3.21.0"
|
|
81
81
|
},
|
|
@@ -90,8 +90,8 @@
|
|
|
90
90
|
"@vitest/ui": "5.0.5",
|
|
91
91
|
"cspell": "10.4.0",
|
|
92
92
|
"dedent": "1.7.2",
|
|
93
|
-
"eslint-config-typed": "7.3.
|
|
94
|
-
"eslint-plugin-ts-data-forge": "0.10.
|
|
93
|
+
"eslint-config-typed": "7.3.1",
|
|
94
|
+
"eslint-plugin-ts-data-forge": "0.10.8",
|
|
95
95
|
"eslint-plugin-ts-fortress": "1.3.12",
|
|
96
96
|
"eslint-plugin-ts-type-forge": "0.8.17",
|
|
97
97
|
"immer": "11.2.7",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
106
106
|
"prettier-plugin-packagejson": "3.0.2",
|
|
107
107
|
"react": "19.3.1",
|
|
108
|
-
"ts-codemod-lib": "4.0.
|
|
108
|
+
"ts-codemod-lib": "4.0.1",
|
|
109
109
|
"ts-repo-utils": "10.7.1",
|
|
110
110
|
"tsx": "4.23.15",
|
|
111
111
|
"typescript": "6.0.3",
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AST_NODE_TYPES,
|
|
3
|
+
ESLintUtils,
|
|
4
|
+
type TSESTree,
|
|
5
|
+
} from '@typescript-eslint/utils';
|
|
2
6
|
import { Arr, isNonNullObject } from 'ts-data-forge';
|
|
3
7
|
import { intersectionTypeParts, unionTypeParts } from 'tsutils';
|
|
4
8
|
import type { BigIntLiteralType, PseudoBigInt, Type } from 'typescript';
|
|
5
9
|
import { createRule } from './common.mjs';
|
|
6
10
|
|
|
7
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* An ESLint rule to ban partial division: `x / y` and `x /= y` whose
|
|
13
|
+
* denominator is not provably non-zero.
|
|
14
|
+
*/
|
|
8
15
|
|
|
9
16
|
export const noPartialDivision = createRule({
|
|
10
17
|
name: 'no-partial-division',
|
|
@@ -47,37 +54,39 @@ export const noPartialDivision = createRule({
|
|
|
47
54
|
);
|
|
48
55
|
};
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
const isProvablySafeDenominator = (
|
|
58
|
+
denominator: TSESTree.Expression,
|
|
59
|
+
): boolean => {
|
|
60
|
+
if (
|
|
61
|
+
denominator.type === AST_NODE_TYPES.Literal &&
|
|
62
|
+
denominator.value !== 0 &&
|
|
63
|
+
denominator.value !== 0n
|
|
64
|
+
) {
|
|
65
|
+
// Division by a literal that isn't zero is safe.
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
56
68
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
node.right.value !== 0n
|
|
61
|
-
) {
|
|
62
|
-
// Division by a literal that isn't zero is safe.
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
69
|
+
if (denominator.type === AST_NODE_TYPES.Identifier) {
|
|
70
|
+
const denominatorNode =
|
|
71
|
+
parserServices.esTreeNodeToTSNodeMap.get(denominator);
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
node.right,
|
|
69
|
-
);
|
|
73
|
+
return isSafeDenominator(checker.getTypeAtLocation(denominatorNode));
|
|
74
|
+
}
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
// All other division is not provably safe.
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
73
79
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
return {
|
|
81
|
+
// `x /= y` divides as `x = x / y` does, and `unicorn/operator-assignment`
|
|
82
|
+
// autofixes the latter into the former, so both are checked alike.
|
|
83
|
+
'BinaryExpression[operator="/"], AssignmentExpression[operator="/="]': (
|
|
84
|
+
node: TSESTree.AssignmentExpression | TSESTree.BinaryExpression,
|
|
85
|
+
) => {
|
|
86
|
+
if (isProvablySafeDenominator(node.right)) {
|
|
87
|
+
return;
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
// All other division is not provably safe.
|
|
80
|
-
|
|
81
90
|
context.report({
|
|
82
91
|
node,
|
|
83
92
|
messageId: 'errorStringGeneric',
|
|
@@ -86,6 +86,35 @@ ruleTester.run('no-partial-division', noPartialDivision, {
|
|
|
86
86
|
const bar = 1n / foo;
|
|
87
87
|
`,
|
|
88
88
|
},
|
|
89
|
+
{
|
|
90
|
+
filename: 'file.ts',
|
|
91
|
+
code: dedent`
|
|
92
|
+
let mut_x = 6;
|
|
93
|
+
mut_x /= 2;
|
|
94
|
+
`,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
filename: 'file.ts',
|
|
98
|
+
code: dedent`
|
|
99
|
+
let mut_x = 6n;
|
|
100
|
+
mut_x /= 2n;
|
|
101
|
+
`,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
filename: 'file.ts',
|
|
105
|
+
code: dedent`
|
|
106
|
+
declare const foo: 42 | 43;
|
|
107
|
+
let mut_x = 6;
|
|
108
|
+
mut_x /= foo;
|
|
109
|
+
`,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
filename: 'file.ts',
|
|
113
|
+
code: dedent`
|
|
114
|
+
let mut_x = 6;
|
|
115
|
+
mut_x *= 0;
|
|
116
|
+
`,
|
|
117
|
+
},
|
|
89
118
|
],
|
|
90
119
|
invalid: [
|
|
91
120
|
{
|
|
@@ -218,5 +247,68 @@ ruleTester.run('no-partial-division', noPartialDivision, {
|
|
|
218
247
|
},
|
|
219
248
|
],
|
|
220
249
|
},
|
|
250
|
+
{
|
|
251
|
+
filename: 'file.ts',
|
|
252
|
+
code: dedent`
|
|
253
|
+
let mut_x = 6;
|
|
254
|
+
mut_x /= 0;
|
|
255
|
+
`,
|
|
256
|
+
errors: [
|
|
257
|
+
{
|
|
258
|
+
messageId: 'errorStringGeneric',
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
filename: 'file.ts',
|
|
264
|
+
code: dedent`
|
|
265
|
+
let mut_x = 6n;
|
|
266
|
+
mut_x /= 0n;
|
|
267
|
+
`,
|
|
268
|
+
errors: [
|
|
269
|
+
{
|
|
270
|
+
messageId: 'errorStringGeneric',
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
filename: 'file.ts',
|
|
276
|
+
code: dedent`
|
|
277
|
+
declare const y: number;
|
|
278
|
+
let mut_x = 6;
|
|
279
|
+
mut_x /= y;
|
|
280
|
+
`,
|
|
281
|
+
errors: [
|
|
282
|
+
{
|
|
283
|
+
messageId: 'errorStringGeneric',
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
filename: 'file.ts',
|
|
289
|
+
code: dedent`
|
|
290
|
+
declare const foo: 42 | 0;
|
|
291
|
+
let mut_x = 6;
|
|
292
|
+
mut_x /= foo;
|
|
293
|
+
`,
|
|
294
|
+
errors: [
|
|
295
|
+
{
|
|
296
|
+
messageId: 'errorStringGeneric',
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
filename: 'file.ts',
|
|
302
|
+
code: dedent`
|
|
303
|
+
declare const obj: { readonly n: number };
|
|
304
|
+
let mut_x = 6;
|
|
305
|
+
mut_x /= obj.n;
|
|
306
|
+
`,
|
|
307
|
+
errors: [
|
|
308
|
+
{
|
|
309
|
+
messageId: 'errorStringGeneric',
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
},
|
|
221
313
|
],
|
|
222
314
|
} as const);
|