eslint-config-typed 4.2.1 → 4.3.0
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/README.md +4 -0
- package/dist/configs/immer.d.mts +3 -0
- package/dist/configs/immer.d.mts.map +1 -0
- package/dist/configs/immer.mjs +11 -0
- package/dist/configs/immer.mjs.map +1 -0
- package/dist/configs/index.d.mts +2 -0
- package/dist/configs/index.d.mts.map +1 -1
- package/dist/configs/index.mjs +2 -0
- package/dist/configs/index.mjs.map +1 -1
- package/dist/configs/plugins.d.mts +1 -1
- package/dist/configs/plugins.d.mts.map +1 -1
- package/dist/configs/plugins.mjs +2 -0
- package/dist/configs/plugins.mjs.map +1 -1
- package/dist/configs/ts-data-forge.d.mts +3 -0
- package/dist/configs/ts-data-forge.d.mts.map +1 -0
- package/dist/configs/ts-data-forge.mjs +11 -0
- package/dist/configs/ts-data-forge.mjs.map +1 -0
- package/dist/configs/typescript.d.mts.map +1 -1
- package/dist/configs/typescript.mjs +0 -2
- package/dist/configs/typescript.mjs.map +1 -1
- package/dist/entry-point.mjs +4 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -1
- package/dist/plugins/index.d.mts +1 -0
- package/dist/plugins/index.d.mts.map +1 -1
- package/dist/plugins/index.mjs +1 -0
- package/dist/plugins/index.mjs.map +1 -1
- package/dist/plugins/ts-data-forge/index.d.mts +2 -0
- package/dist/plugins/ts-data-forge/index.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/index.mjs +2 -0
- package/dist/plugins/ts-data-forge/index.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/plugin.d.mts +3 -0
- package/dist/plugins/ts-data-forge/plugin.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/plugin.mjs +8 -0
- package/dist/plugins/ts-data-forge/plugin.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/branded-number-types.d.mts +5 -0
- package/dist/plugins/ts-data-forge/rules/branded-number-types.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/branded-number-types.mjs +35 -0
- package/dist/plugins/ts-data-forge/rules/branded-number-types.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/constants.d.mts +2 -0
- package/dist/plugins/ts-data-forge/rules/constants.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/constants.mjs +4 -0
- package/dist/plugins/ts-data-forge/rules/constants.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/import-utils.d.mts +5 -0
- package/dist/plugins/ts-data-forge/rules/import-utils.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/import-utils.mjs +31 -0
- package/dist/plugins/ts-data-forge/rules/import-utils.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/index.d.mts +2 -0
- package/dist/plugins/ts-data-forge/rules/index.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/index.mjs +2 -0
- package/dist/plugins/ts-data-forge/rules/index.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-at-least-length.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-at-least-length.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-at-least-length.mjs +94 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-at-least-length.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.mjs +95 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array.mjs +72 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-array.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.mjs +71 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-sum.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-sum.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-sum.mjs +183 -0
- package/dist/plugins/ts-data-forge/rules/prefer-arr-sum.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-as-int.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-as-int.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-as-int.mjs +86 -0
- package/dist/plugins/ts-data-forge/rules/prefer-as-int.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-non-null-object.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-non-null-object.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-non-null-object.mjs +103 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-non-null-object.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-record-and-has-key.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-record-and-has-key.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-record-and-has-key.mjs +105 -0
- package/dist/plugins/ts-data-forge/rules/prefer-is-record-and-has-key.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-range-for-loop.d.mts +6 -0
- package/dist/plugins/ts-data-forge/rules/prefer-range-for-loop.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-range-for-loop.mjs +130 -0
- package/dist/plugins/ts-data-forge/rules/prefer-range-for-loop.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/rules.d.mts +12 -0
- package/dist/plugins/ts-data-forge/rules/rules.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/rules.mjs +24 -0
- package/dist/plugins/ts-data-forge/rules/rules.mjs.map +1 -0
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.d.mts.map +1 -1
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.mjs +6 -8
- package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.mjs.map +1 -1
- package/dist/plugins/ts-restrictions/rules/no-restricted-cast-name.d.mts.map +1 -1
- package/dist/plugins/ts-restrictions/rules/no-restricted-cast-name.mjs +11 -15
- package/dist/plugins/ts-restrictions/rules/no-restricted-cast-name.mjs.map +1 -1
- package/dist/rules/eslint-jest-rules.d.mts +3 -0
- package/dist/rules/eslint-jest-rules.d.mts.map +1 -1
- package/dist/rules/eslint-jest-rules.mjs +3 -0
- package/dist/rules/eslint-jest-rules.mjs.map +1 -1
- package/dist/rules/eslint-ts-data-forge-rules.d.mts +12 -0
- package/dist/rules/eslint-ts-data-forge-rules.d.mts.map +1 -0
- package/dist/rules/eslint-ts-data-forge-rules.mjs +14 -0
- package/dist/rules/eslint-ts-data-forge-rules.mjs.map +1 -0
- package/dist/rules/eslint-vitest-rules.d.mts +2 -2
- package/dist/rules/eslint-vitest-rules.mjs +2 -2
- package/dist/rules/eslint-vitest-rules.mjs.map +1 -1
- package/dist/rules/index.d.mts +1 -0
- package/dist/rules/index.d.mts.map +1 -1
- package/dist/rules/index.mjs +1 -0
- package/dist/rules/index.mjs.map +1 -1
- package/dist/types/define-known-rules.d.mts +2 -2
- package/dist/types/define-known-rules.d.mts.map +1 -1
- package/dist/types/define-known-rules.mjs.map +1 -1
- package/dist/types/rules/eslint-jest-rules.d.mts +119 -67
- package/dist/types/rules/eslint-jest-rules.d.mts.map +1 -1
- package/dist/types/rules/eslint-ts-data-forge-rules.d.mts +147 -0
- package/dist/types/rules/eslint-ts-data-forge-rules.d.mts.map +1 -0
- package/dist/types/rules/eslint-ts-data-forge-rules.mjs +2 -0
- package/dist/types/rules/eslint-ts-data-forge-rules.mjs.map +1 -0
- package/dist/types/rules/eslint-vitest-rules.d.mts +41 -20
- package/dist/types/rules/eslint-vitest-rules.d.mts.map +1 -1
- package/dist/types/rules/index.d.mts +1 -0
- package/dist/types/rules/index.d.mts.map +1 -1
- package/package.json +14 -14
- package/src/configs/immer.mts +9 -0
- package/src/configs/index.mts +2 -0
- package/src/configs/plugins.mts +3 -0
- package/src/configs/ts-data-forge.mts +11 -0
- package/src/configs/typescript.mts +0 -2
- package/src/plugins/index.mts +1 -0
- package/src/plugins/strict-dependencies/rules/resolve-import-path.test.mts +7 -9
- package/src/plugins/ts-data-forge/index.mts +1 -0
- package/src/plugins/ts-data-forge/plugin.mts +6 -0
- package/src/plugins/ts-data-forge/rules/branded-number-types.mts +36 -0
- package/src/plugins/ts-data-forge/rules/constants.mts +1 -0
- package/src/plugins/ts-data-forge/rules/import-utils.mts +56 -0
- package/src/plugins/ts-data-forge/rules/index.mts +1 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-array-at-least-length.mts +140 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-array-at-least-length.test.mts +175 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.mts +144 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.test.mts +183 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-array.mts +97 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-array.test.mts +62 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.mts +106 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.test.mts +83 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-sum.mts +269 -0
- package/src/plugins/ts-data-forge/rules/prefer-arr-sum.test.mts +171 -0
- package/src/plugins/ts-data-forge/rules/prefer-as-int.mts +130 -0
- package/src/plugins/ts-data-forge/rules/prefer-as-int.test.mts +267 -0
- package/src/plugins/ts-data-forge/rules/prefer-is-non-null-object.mts +144 -0
- package/src/plugins/ts-data-forge/rules/prefer-is-non-null-object.test.mts +156 -0
- package/src/plugins/ts-data-forge/rules/prefer-is-record-and-has-key.mts +158 -0
- package/src/plugins/ts-data-forge/rules/prefer-is-record-and-has-key.test.mts +191 -0
- package/src/plugins/ts-data-forge/rules/prefer-range-for-loop.mts +181 -0
- package/src/plugins/ts-data-forge/rules/prefer-range-for-loop.test.mts +156 -0
- package/src/plugins/ts-data-forge/rules/rules.mts +22 -0
- package/src/plugins/ts-restrictions/rules/check-destructuring-completeness.mts +6 -8
- package/src/plugins/ts-restrictions/rules/no-restricted-cast-name.mts +11 -15
- package/src/rules/eslint-jest-rules.mts +3 -0
- package/src/rules/eslint-ts-data-forge-rules.mts +13 -0
- package/src/rules/eslint-vitest-rules.mts +2 -2
- package/src/rules/index.mts +1 -0
- package/src/types/define-known-rules.mts +2 -0
- package/src/types/rules/eslint-jest-rules.mts +122 -67
- package/src/types/rules/eslint-ts-data-forge-rules.mts +156 -0
- package/src/types/rules/eslint-vitest-rules.mts +46 -21
- package/src/types/rules/index.mts +1 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const preferArrIsArrayOfLength = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Replace `xs.length === n` with `Arr.isArrayOfLength(xs, n)` from ts-data-forge.',
|
|
9
|
+
},
|
|
10
|
+
fixable: 'code',
|
|
11
|
+
schema: [],
|
|
12
|
+
messages: {
|
|
13
|
+
useIsArrayOfLength: 'Replace `{{original}}` with `Arr.isArrayOfLength({{arrayName}}, {{length}})` from ts-data-forge.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
create: (context) => {
|
|
17
|
+
const sourceCode = context.sourceCode;
|
|
18
|
+
const program = sourceCode.ast;
|
|
19
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
20
|
+
const services = context.sourceCode.parserServices;
|
|
21
|
+
const mut_nodesToFix = [];
|
|
22
|
+
return {
|
|
23
|
+
BinaryExpression: (node) => {
|
|
24
|
+
// Check for `xs.length === n` or `n === xs.length` or `xs.length !== n`
|
|
25
|
+
if (node.operator !== '===' && node.operator !== '!==')
|
|
26
|
+
return;
|
|
27
|
+
const isNegated = node.operator === '!==';
|
|
28
|
+
const isLengthOnLeft = isLengthAccess(node.left);
|
|
29
|
+
const lengthSide = isLengthOnLeft ? node.left : node.right;
|
|
30
|
+
const valueSide = isLengthOnLeft ? node.right : node.left;
|
|
31
|
+
if (!isLengthAccess(lengthSide))
|
|
32
|
+
return;
|
|
33
|
+
// lengthSide is MemberExpression accessing .length
|
|
34
|
+
const arrayExpression = lengthSide.object;
|
|
35
|
+
// Check if arrayExpression is actually an array type
|
|
36
|
+
if (services?.program !== undefined && services.program !== null) {
|
|
37
|
+
const checker = services.program.getTypeChecker();
|
|
38
|
+
const tsNode = services.esTreeNodeToTSNodeMap?.get(arrayExpression);
|
|
39
|
+
if (tsNode !== undefined) {
|
|
40
|
+
const type = checker.getTypeAtLocation(tsNode);
|
|
41
|
+
// Check if it's an array type or tuple type
|
|
42
|
+
const isArrayType = checker.isArrayType(type) || checker.isTupleType(type);
|
|
43
|
+
if (!isArrayType)
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
mut_nodesToFix.push({
|
|
54
|
+
node,
|
|
55
|
+
arrayExpression,
|
|
56
|
+
lengthExpression: valueSide,
|
|
57
|
+
isNegated,
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
'Program:exit': () => {
|
|
61
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
62
|
+
const hasArrImport = namedImports.includes('Arr');
|
|
63
|
+
for (const [index, { node, arrayExpression, lengthExpression, isNegated },] of mut_nodesToFix.entries()) {
|
|
64
|
+
const arrayText = sourceCode.getText(arrayExpression);
|
|
65
|
+
const lengthText = sourceCode.getText(lengthExpression);
|
|
66
|
+
const originalText = sourceCode.getText(node);
|
|
67
|
+
context.report({
|
|
68
|
+
node,
|
|
69
|
+
messageId: 'useIsArrayOfLength',
|
|
70
|
+
data: {
|
|
71
|
+
original: originalText,
|
|
72
|
+
arrayName: arrayText,
|
|
73
|
+
length: lengthText,
|
|
74
|
+
},
|
|
75
|
+
fix: (fixer) => {
|
|
76
|
+
const baseCall = `Arr.isArrayOfLength(${arrayText}, ${lengthText})`;
|
|
77
|
+
const replacement = isNegated ? `!${baseCall}` : baseCall;
|
|
78
|
+
const importFixes = index === 0 && !hasArrImport
|
|
79
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, ['Arr'])
|
|
80
|
+
: [];
|
|
81
|
+
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
defaultOptions: [],
|
|
89
|
+
};
|
|
90
|
+
const isLengthAccess = (node) => node.type === AST_NODE_TYPES.MemberExpression &&
|
|
91
|
+
node.property.type === AST_NODE_TYPES.Identifier &&
|
|
92
|
+
node.property.name === 'length';
|
|
93
|
+
|
|
94
|
+
export { preferArrIsArrayOfLength };
|
|
95
|
+
//# sourceMappingURL=prefer-arr-is-array-of-length.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-is-array-of-length.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-is-array-of-length.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useArrIsArray';
|
|
4
|
+
export declare const preferArrIsArray: TSESLint.RuleModule<MessageIds, Options>;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=prefer-arr-is-array.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-is-array.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-is-array.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAOlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,eAAe,CAAC;AAElC,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA+DrE,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const preferArrIsArray = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Replace `Array.isArray` with `Arr.isArray` from ts-data-forge.',
|
|
9
|
+
},
|
|
10
|
+
fixable: 'code',
|
|
11
|
+
schema: [],
|
|
12
|
+
messages: {
|
|
13
|
+
useArrIsArray: 'Replace `Array.isArray` with `Arr.isArray` from ts-data-forge.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
create: (context) => {
|
|
17
|
+
const sourceCode = context.sourceCode;
|
|
18
|
+
const program = sourceCode.ast;
|
|
19
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
20
|
+
const mut_nodesToFix = [];
|
|
21
|
+
return {
|
|
22
|
+
CallExpression: (node) => {
|
|
23
|
+
if (!isArrayIsArrayCall(node))
|
|
24
|
+
return;
|
|
25
|
+
mut_nodesToFix.push(node);
|
|
26
|
+
},
|
|
27
|
+
'Program:exit': () => {
|
|
28
|
+
// Check if Arr is already imported
|
|
29
|
+
const hasArrImport = getNamedImports(tsDataForgeImport).includes('Arr');
|
|
30
|
+
// Note: We add import only for the first node to avoid conflicts when
|
|
31
|
+
// multiple fixes try to insert at the same position. This means if the
|
|
32
|
+
// first node is disabled via eslint-disable comment, no import will be
|
|
33
|
+
// added.
|
|
34
|
+
for (const [index, node] of mut_nodesToFix.entries()) {
|
|
35
|
+
context.report({
|
|
36
|
+
node,
|
|
37
|
+
messageId: 'useArrIsArray',
|
|
38
|
+
fix: (fixer) => {
|
|
39
|
+
const callee = node.callee;
|
|
40
|
+
if (callee.type !== AST_NODE_TYPES.MemberExpression)
|
|
41
|
+
return [];
|
|
42
|
+
const replacement = `Arr.isArray${sourceCode.getText(node).slice(sourceCode.getText(callee).length)}`;
|
|
43
|
+
// Add import only for the first node and only if not already imported
|
|
44
|
+
const importFixes = index === 0 && !hasArrImport
|
|
45
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, ['Arr'])
|
|
46
|
+
: [];
|
|
47
|
+
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
defaultOptions: [],
|
|
55
|
+
};
|
|
56
|
+
const isArrayIsArrayCall = (node) => {
|
|
57
|
+
if (node.callee.type !== AST_NODE_TYPES.MemberExpression)
|
|
58
|
+
return false;
|
|
59
|
+
const { object, property } = node.callee;
|
|
60
|
+
if (object.type !== AST_NODE_TYPES.Identifier)
|
|
61
|
+
return false;
|
|
62
|
+
if (object.name !== 'Array')
|
|
63
|
+
return false;
|
|
64
|
+
if (property.type !== AST_NODE_TYPES.Identifier)
|
|
65
|
+
return false;
|
|
66
|
+
if (property.name !== 'isArray')
|
|
67
|
+
return false;
|
|
68
|
+
return true;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export { preferArrIsArray };
|
|
72
|
+
//# sourceMappingURL=prefer-arr-is-array.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-is-array.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-is-array.mts"],"sourcesContent":[null],"names":[],"mappings":";;;AAeO,MAAM,gBAAgB,GAA6C;AACxE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,gEAAgE;AACnE,SAAA;AACD,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,aAAa,EACX,gEAAgE;AACnE,SAAA;AACF,KAAA;AAED,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;AAClB,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU;AAErC,QAAA,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG;AAE9B,QAAA,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,CAAC;QAEvD,MAAM,cAAc,GAA8B,EAAE;QAEpD,OAAO;AACL,YAAA,cAAc,EAAE,CAAC,IAAI,KAAI;AACvB,gBAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;oBAAE;AAE/B,gBAAA,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;YAC3B,CAAC;YACD,cAAc,EAAE,MAAK;;gBAEnB,MAAM,YAAY,GAAG,eAAe,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;;;;;AAMvE,gBAAA,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,EAAE;oBACpD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;AACJ,wBAAA,SAAS,EAAE,eAAe;AAC1B,wBAAA,GAAG,EAAE,CAAC,KAAK,KAAI;AACb,4BAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;AAE1B,4BAAA,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;AAAE,gCAAA,OAAO,EAAE;4BAE9D,MAAM,WAAW,GAAG,CAAA,WAAA,EAAc,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA,CAAE;;AAGrG,4BAAA,MAAM,WAAW,GACf,KAAK,KAAK,CAAC,IAAI,CAAC;AACd,kCAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,KAAK,CAAC;kCAC3D,EAAE;AAER,4BAAA,OAAO,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;wBAC/D,CAAC;AACF,qBAAA,CAAC;gBACJ;YACF,CAAC;SACF;IACH,CAAC;AACD,IAAA,cAAc,EAAE,EAAE;;AAGpB,MAAM,kBAAkB,GAAG,CACzB,IAA2C,KAChC;IACX,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;AAAE,QAAA,OAAO,KAAK;IAEtE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM;AAExC,IAAA,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAAE,QAAA,OAAO,KAAK;AAE3D,IAAA,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;AAAE,QAAA,OAAO,KAAK;AAEzC,IAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAAE,QAAA,OAAO,KAAK;AAE7D,IAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS;AAAE,QAAA,OAAO,KAAK;AAE7C,IAAA,OAAO,IAAI;AACb,CAAC;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useIsNonEmpty';
|
|
4
|
+
export declare const preferArrIsNonEmpty: TSESLint.RuleModule<MessageIds, Options>;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=prefer-arr-is-non-empty.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-is-non-empty.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAOlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,eAAe,CAAC;AAElC,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA0FxE,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const preferArrIsNonEmpty = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Replace `xs.length > 0` with `Arr.isNonEmpty(xs)` from ts-data-forge.',
|
|
9
|
+
},
|
|
10
|
+
fixable: 'code',
|
|
11
|
+
schema: [],
|
|
12
|
+
messages: {
|
|
13
|
+
useIsNonEmpty: 'Replace `{{original}}` with `Arr.isNonEmpty({{arrayName}})` from ts-data-forge.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
create: (context) => {
|
|
17
|
+
const sourceCode = context.sourceCode;
|
|
18
|
+
const program = sourceCode.ast;
|
|
19
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
20
|
+
const mut_nodesToFix = [];
|
|
21
|
+
return {
|
|
22
|
+
BinaryExpression: (node) => {
|
|
23
|
+
// Check for `xs.length > 0` or `0 < xs.length`
|
|
24
|
+
if (node.operator !== '>' && node.operator !== '<')
|
|
25
|
+
return;
|
|
26
|
+
const isLengthOnLeft = node.operator === '>';
|
|
27
|
+
const lengthSide = isLengthOnLeft ? node.left : node.right;
|
|
28
|
+
const numberSide = isLengthOnLeft ? node.right : node.left;
|
|
29
|
+
// Check if one side is `.length` and the other is 0
|
|
30
|
+
if (lengthSide.type !== AST_NODE_TYPES.MemberExpression ||
|
|
31
|
+
lengthSide.property.type !== AST_NODE_TYPES.Identifier ||
|
|
32
|
+
lengthSide.property.name !== 'length' ||
|
|
33
|
+
numberSide.type !== AST_NODE_TYPES.Literal ||
|
|
34
|
+
numberSide.value !== 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
mut_nodesToFix.push({
|
|
38
|
+
node,
|
|
39
|
+
arrayExpression: lengthSide.object,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
'Program:exit': () => {
|
|
43
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
44
|
+
const hasArrImport = namedImports.includes('Arr');
|
|
45
|
+
for (const [index, { node, arrayExpression },] of mut_nodesToFix.entries()) {
|
|
46
|
+
const arrayText = sourceCode.getText(arrayExpression);
|
|
47
|
+
const originalText = sourceCode.getText(node);
|
|
48
|
+
context.report({
|
|
49
|
+
node,
|
|
50
|
+
messageId: 'useIsNonEmpty',
|
|
51
|
+
data: {
|
|
52
|
+
original: originalText,
|
|
53
|
+
arrayName: arrayText,
|
|
54
|
+
},
|
|
55
|
+
fix: (fixer) => {
|
|
56
|
+
const replacement = `Arr.isNonEmpty(${arrayText})`;
|
|
57
|
+
const importFixes = index === 0 && !hasArrImport
|
|
58
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, ['Arr'])
|
|
59
|
+
: [];
|
|
60
|
+
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
defaultOptions: [],
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { preferArrIsNonEmpty };
|
|
71
|
+
//# sourceMappingURL=prefer-arr-is-non-empty.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-is-non-empty.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-is-non-empty.mts"],"sourcesContent":[null],"names":[],"mappings":";;;AAeO,MAAM,mBAAmB,GAA6C;AAC3E,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,uEAAuE;AAC1E,SAAA;AACD,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,aAAa,EACX,iFAAiF;AACpF,SAAA;AACF,KAAA;AAED,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;AAClB,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU;AAErC,QAAA,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG;AAE9B,QAAA,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,CAAC;QAEvD,MAAM,cAAc,GAGd,EAAE;QAER,OAAO;AACL,YAAA,gBAAgB,EAAE,CAAC,IAAI,KAAI;;gBAEzB,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG;oBAAE;AAEpD,gBAAA,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,KAAK,GAAG;AAE5C,gBAAA,MAAM,UAAU,GAAG,cAAc,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;AAE1D,gBAAA,MAAM,UAAU,GAAG,cAAc,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI;;AAG1D,gBAAA,IACE,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;AACnD,oBAAA,UAAU,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AACtD,oBAAA,UAAU,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ;AACrC,oBAAA,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;AAC1C,oBAAA,UAAU,CAAC,KAAK,KAAK,CAAC,EACtB;oBACA;gBACF;gBAEA,cAAc,CAAC,IAAI,CAAC;oBAClB,IAAI;oBACJ,eAAe,EAAE,UAAU,CAAC,MAAM;AACnC,iBAAA,CAAC;YACJ,CAAC;YACD,cAAc,EAAE,MAAK;AACnB,gBAAA,MAAM,YAAY,GAAG,eAAe,CAAC,iBAAiB,CAAC;gBAEvD,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;AAEjD,gBAAA,KAAK,MAAM,CACT,KAAK,EACL,EAAE,IAAI,EAAE,eAAe,EAAE,EAC1B,IAAI,cAAc,CAAC,OAAO,EAAE,EAAE;oBAC7B,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC;oBAErD,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;oBAE7C,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;AACJ,wBAAA,SAAS,EAAE,eAAe;AAC1B,wBAAA,IAAI,EAAE;AACJ,4BAAA,QAAQ,EAAE,YAAY;AACtB,4BAAA,SAAS,EAAE,SAAS;AACrB,yBAAA;AACD,wBAAA,GAAG,EAAE,CAAC,KAAK,KAAI;AACb,4BAAA,MAAM,WAAW,GAAG,CAAA,eAAA,EAAkB,SAAS,GAAG;AAElD,4BAAA,MAAM,WAAW,GACf,KAAK,KAAK,CAAC,IAAI,CAAC;AACd,kCAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,KAAK,CAAC;kCAC3D,EAAE;AAER,4BAAA,OAAO,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;wBAC/D,CAAC;AACF,qBAAA,CAAC;gBACJ;YACF,CAAC;SACF;IACH,CAAC;AACD,IAAA,cAAc,EAAE,EAAE;;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useArrSum' | 'useArrSumBy';
|
|
4
|
+
export declare const preferArrSum: TSESLint.RuleModule<MessageIds, Options>;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=prefer-arr-sum.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-sum.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-sum.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AASlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;AAE9C,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA2PjE,CAAC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { Arr, pipe } from 'ts-data-forge';
|
|
3
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
4
|
+
|
|
5
|
+
const preferArrSum = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'suggestion',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Replace `xs.reduce((a, b) => a + b, 0)` with `Arr.sum(xs)` or `Arr.sumBy(xs, fn)` from ts-data-forge.',
|
|
10
|
+
},
|
|
11
|
+
fixable: 'code',
|
|
12
|
+
schema: [],
|
|
13
|
+
messages: {
|
|
14
|
+
useArrSum: 'Replace with `Arr.sum({{arrayName}})` from ts-data-forge.',
|
|
15
|
+
useArrSumBy: 'Replace with `Arr.sumBy({{arrayName}}, {{mapper}})` from ts-data-forge.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
create: (context) => {
|
|
19
|
+
const sourceCode = context.sourceCode;
|
|
20
|
+
const program = sourceCode.ast;
|
|
21
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
22
|
+
const services = context.sourceCode.parserServices;
|
|
23
|
+
const mut_nodesToFix = [];
|
|
24
|
+
return {
|
|
25
|
+
CallExpression: (node) => {
|
|
26
|
+
// Check for xs.reduce(...)
|
|
27
|
+
if (node.callee.type !== AST_NODE_TYPES.MemberExpression ||
|
|
28
|
+
node.callee.property.type !== AST_NODE_TYPES.Identifier ||
|
|
29
|
+
node.callee.property.name !== 'reduce') {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const arrayExpression = node.callee.object;
|
|
33
|
+
// Check if we have 2 arguments: reducer function and initial value 0
|
|
34
|
+
if (!Arr.isArrayOfLength(node.arguments, 2))
|
|
35
|
+
return;
|
|
36
|
+
const reducer = node.arguments[0];
|
|
37
|
+
const initialValue = node.arguments[1];
|
|
38
|
+
// Check initial value is 0
|
|
39
|
+
if (initialValue.type !== AST_NODE_TYPES.Literal ||
|
|
40
|
+
initialValue.value !== 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Check if reducer is an arrow function with 2 parameters
|
|
44
|
+
if (reducer.type !== AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
45
|
+
!Arr.isArrayOfLength(reducer.params, 2)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const [param1, param2] = reducer.params;
|
|
49
|
+
if (param1.type !== AST_NODE_TYPES.Identifier ||
|
|
50
|
+
param2.type !== AST_NODE_TYPES.Identifier) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const body = reducer.body;
|
|
54
|
+
const checker = services?.program?.getTypeChecker();
|
|
55
|
+
if (checker === undefined)
|
|
56
|
+
return;
|
|
57
|
+
// Case 1: (a, b) => a + b
|
|
58
|
+
if (body.type === AST_NODE_TYPES.BinaryExpression &&
|
|
59
|
+
body.operator === '+' &&
|
|
60
|
+
body.left.type === AST_NODE_TYPES.Identifier &&
|
|
61
|
+
body.left.name === param1.name &&
|
|
62
|
+
body.right.type === AST_NODE_TYPES.Identifier &&
|
|
63
|
+
body.right.name === param2.name) {
|
|
64
|
+
// Check if arrayExpression type is number[] or compatible
|
|
65
|
+
const type = pipe(services?.esTreeNodeToTSNodeMap?.get(arrayExpression)).mapNullable((tsNode) => checker.getTypeAtLocation(tsNode)).value;
|
|
66
|
+
if (type !== undefined && // Check if it's an array type or tuple type
|
|
67
|
+
(checker.isArrayType(type) || checker.isTupleType(type))) {
|
|
68
|
+
// Get type arguments using the official API
|
|
69
|
+
// TypeReference has typeArguments that we can access
|
|
70
|
+
const typeArguments = checker.getTypeArguments(
|
|
71
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
72
|
+
type);
|
|
73
|
+
if (Arr.isNonEmpty(typeArguments)) {
|
|
74
|
+
const elementType = typeArguments[0];
|
|
75
|
+
const numberType = checker.getNumberType();
|
|
76
|
+
// Check if element type is assignable to number
|
|
77
|
+
if (checker.isTypeAssignableTo(elementType, numberType)) {
|
|
78
|
+
mut_nodesToFix.push({
|
|
79
|
+
node,
|
|
80
|
+
arrayExpression,
|
|
81
|
+
messageId: 'useArrSum',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Case 2: (a, b) => a.prop + b.prop or a['prop'] + b['prop']
|
|
89
|
+
if (body.type === AST_NODE_TYPES.BinaryExpression &&
|
|
90
|
+
body.operator === '+' &&
|
|
91
|
+
body.left.type === AST_NODE_TYPES.MemberExpression &&
|
|
92
|
+
body.right.type === AST_NODE_TYPES.MemberExpression) {
|
|
93
|
+
const leftObj = body.left.object;
|
|
94
|
+
const rightObj = body.right.object;
|
|
95
|
+
if (leftObj.type !== AST_NODE_TYPES.Identifier ||
|
|
96
|
+
leftObj.name !== param1.name ||
|
|
97
|
+
rightObj.type !== AST_NODE_TYPES.Identifier ||
|
|
98
|
+
rightObj.name !== param2.name) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Check if both access the same property
|
|
102
|
+
const leftProp = body.left.property;
|
|
103
|
+
const rightProp = body.right.property;
|
|
104
|
+
let mut_propName;
|
|
105
|
+
if (leftProp.type === AST_NODE_TYPES.Identifier &&
|
|
106
|
+
!body.left.computed &&
|
|
107
|
+
rightProp.type === AST_NODE_TYPES.Identifier &&
|
|
108
|
+
!body.right.computed &&
|
|
109
|
+
leftProp.name === rightProp.name) {
|
|
110
|
+
mut_propName = leftProp.name;
|
|
111
|
+
}
|
|
112
|
+
else if (leftProp.type === AST_NODE_TYPES.Literal &&
|
|
113
|
+
body.left.computed &&
|
|
114
|
+
rightProp.type === AST_NODE_TYPES.Literal &&
|
|
115
|
+
body.right.computed &&
|
|
116
|
+
leftProp.value === rightProp.value &&
|
|
117
|
+
typeof leftProp.value === 'string') {
|
|
118
|
+
mut_propName = leftProp.value;
|
|
119
|
+
}
|
|
120
|
+
if (mut_propName === undefined)
|
|
121
|
+
return;
|
|
122
|
+
// Check if property type is number
|
|
123
|
+
if (services?.program !== undefined && services.program !== null) {
|
|
124
|
+
const tsLeftProp = services.esTreeNodeToTSNodeMap?.get(body.left);
|
|
125
|
+
const tsRightProp = services.esTreeNodeToTSNodeMap?.get(body.right);
|
|
126
|
+
if (tsLeftProp !== undefined && tsRightProp !== undefined) {
|
|
127
|
+
const leftPropType = checker.getTypeAtLocation(tsLeftProp);
|
|
128
|
+
const rightPropType = checker.getTypeAtLocation(tsRightProp);
|
|
129
|
+
const numberType = checker.getNumberType();
|
|
130
|
+
// Check if property type is assignable to number
|
|
131
|
+
if (!checker.isTypeAssignableTo(leftPropType, numberType) ||
|
|
132
|
+
!checker.isTypeAssignableTo(rightPropType, numberType)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Generate mapper function
|
|
138
|
+
const mapperParam = param1.name;
|
|
139
|
+
const mapper = body.left.computed
|
|
140
|
+
? `${mapperParam} => ${mapperParam}['${mut_propName}']`
|
|
141
|
+
: `${mapperParam} => ${mapperParam}.${mut_propName}`;
|
|
142
|
+
mut_nodesToFix.push({
|
|
143
|
+
node,
|
|
144
|
+
arrayExpression,
|
|
145
|
+
messageId: 'useArrSumBy',
|
|
146
|
+
mapper,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
'Program:exit': () => {
|
|
151
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
152
|
+
const hasArrImport = namedImports.includes('Arr');
|
|
153
|
+
for (const [index, nodeInfo] of mut_nodesToFix.entries()) {
|
|
154
|
+
const arrayText = sourceCode.getText(nodeInfo.arrayExpression);
|
|
155
|
+
context.report({
|
|
156
|
+
node: nodeInfo.node,
|
|
157
|
+
messageId: nodeInfo.messageId,
|
|
158
|
+
data: {
|
|
159
|
+
arrayName: arrayText,
|
|
160
|
+
mapper: nodeInfo.mapper ?? '',
|
|
161
|
+
},
|
|
162
|
+
fix: (fixer) => {
|
|
163
|
+
const replacement = nodeInfo.messageId === 'useArrSum'
|
|
164
|
+
? `Arr.sum(${arrayText})`
|
|
165
|
+
: `Arr.sumBy(${arrayText}, ${nodeInfo.mapper})`;
|
|
166
|
+
const importFixes = index === 0 && !hasArrImport
|
|
167
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, ['Arr'])
|
|
168
|
+
: [];
|
|
169
|
+
return [
|
|
170
|
+
...importFixes,
|
|
171
|
+
fixer.replaceText(nodeInfo.node, replacement),
|
|
172
|
+
];
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
defaultOptions: [],
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export { preferArrSum };
|
|
183
|
+
//# sourceMappingURL=prefer-arr-sum.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-arr-sum.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-arr-sum.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAiBO,MAAM,YAAY,GAA6C;AACpE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,uGAAuG;AAC1G,SAAA;AACD,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,SAAS,EAAE,2DAA2D;AACtE,YAAA,WAAW,EACT,yEAAyE;AAC5E,SAAA;AACF,KAAA;AAED,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;AAClB,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU;AAErC,QAAA,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG;AAE9B,QAAA,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,CAAC;AAEvD,QAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,cAAc;QAElD,MAAM,cAAc,GAKd,EAAE;QAER,OAAO;AACL,YAAA,cAAc,EAAE,CAAC,IAAI,KAAI;;gBAEvB,IACE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;oBACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;oBACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,EACtC;oBACA;gBACF;AAEA,gBAAA,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM;;gBAG1C,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;oBAAE;gBAE7C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;gBAEjC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;;AAGtC,gBAAA,IACE,YAAY,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;AAC5C,oBAAA,YAAY,CAAC,KAAK,KAAK,CAAC,EACxB;oBACA;gBACF;;AAGA,gBAAA,IACE,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,uBAAuB;oBACvD,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EACvC;oBACA;gBACF;gBAEA,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM;AAEvC,gBAAA,IACE,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AACzC,oBAAA,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EACzC;oBACA;gBACF;AAEA,gBAAA,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI;gBAEzB,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE;gBAEnD,IAAI,OAAO,KAAK,SAAS;oBAAE;;AAG3B,gBAAA,IACE,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;oBAC7C,IAAI,CAAC,QAAQ,KAAK,GAAG;AACrB,oBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC5C,oBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI;AAC9B,oBAAA,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;oBAC7C,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,EAC/B;;AAGA,oBAAA,MAAM,IAAI,GAAG,IAAI,CACf,QAAQ,EAAE,qBAAqB,EAAE,GAAG,CAAC,eAAe,CAAC,CACtD,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;AAElE,oBAAA,IACE,IAAI,KAAK,SAAS;AAClB,yBAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EACxD;;;AAGA,wBAAA,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB;;AAE5C,wBAAA,IAAqB,CACtB;AAED,wBAAA,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;AACjC,4BAAA,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC;AAEpC,4BAAA,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE;;4BAG1C,IAAI,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE;gCACvD,cAAc,CAAC,IAAI,CAAC;oCAClB,IAAI;oCACJ,eAAe;AACf,oCAAA,SAAS,EAAE,WAAW;AACvB,iCAAA,CAAC;4BACJ;wBACF;oBACF;oBAEA;gBACF;;AAGA,gBAAA,IACE,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;oBAC7C,IAAI,CAAC,QAAQ,KAAK,GAAG;AACrB,oBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;oBAClD,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,EACnD;AACA,oBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM;AAEhC,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM;AAElC,oBAAA,IACE,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC1C,wBAAA,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI;AAC5B,wBAAA,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC3C,wBAAA,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,EAC7B;wBACA;oBACF;;AAGA,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ;AAEnC,oBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ;AAErC,oBAAA,IAAI,YAAgC;AAEpC,oBAAA,IACE,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC3C,wBAAA,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;AACnB,wBAAA,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC5C,wBAAA,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;AACpB,wBAAA,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,EAChC;AACA,wBAAA,YAAY,GAAG,QAAQ,CAAC,IAAI;oBAC9B;AAAO,yBAAA,IACL,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;wBACxC,IAAI,CAAC,IAAI,CAAC,QAAQ;AAClB,wBAAA,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;wBACzC,IAAI,CAAC,KAAK,CAAC,QAAQ;AACnB,wBAAA,QAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK;AAClC,wBAAA,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAClC;AACA,wBAAA,YAAY,GAAG,QAAQ,CAAC,KAAK;oBAC/B;oBAEA,IAAI,YAAY,KAAK,SAAS;wBAAE;;AAGhC,oBAAA,IAAI,QAAQ,EAAE,OAAO,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,IAAI,EAAE;AAChE,wBAAA,MAAM,UAAU,GAAG,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AAEjE,wBAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;wBAEnE,IAAI,UAAU,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,EAAE;4BACzD,MAAM,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC;4BAE1D,MAAM,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC;AAE5D,4BAAA,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE;;4BAG1C,IACE,CAAC,OAAO,CAAC,kBAAkB,CAAC,YAAY,EAAE,UAAU,CAAC;gCACrD,CAAC,OAAO,CAAC,kBAAkB,CAAC,aAAa,EAAE,UAAU,CAAC,EACtD;gCACA;4BACF;wBACF;oBACF;;AAGA,oBAAA,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI;AAE/B,oBAAA,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;AACvB,0BAAE,CAAA,EAAG,WAAW,OAAO,WAAW,CAAA,EAAA,EAAK,YAAY,CAAA,EAAA;0BACjD,GAAG,WAAW,CAAA,IAAA,EAAO,WAAW,CAAA,CAAA,EAAI,YAAY,EAAE;oBAEtD,cAAc,CAAC,IAAI,CAAC;wBAClB,IAAI;wBACJ,eAAe;AACf,wBAAA,SAAS,EAAE,aAAa;wBACxB,MAAM;AACP,qBAAA,CAAC;gBACJ;YACF,CAAC;YACD,cAAc,EAAE,MAAK;AACnB,gBAAA,MAAM,YAAY,GAAG,eAAe,CAAC,iBAAiB,CAAC;gBAEvD,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;AAEjD,gBAAA,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,EAAE;oBACxD,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;oBAE9D,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;AAC7B,wBAAA,IAAI,EAAE;AACJ,4BAAA,SAAS,EAAE,SAAS;AACpB,4BAAA,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE;AAC9B,yBAAA;AACD,wBAAA,GAAG,EAAE,CAAC,KAAK,KAAI;AACb,4BAAA,MAAM,WAAW,GACf,QAAQ,CAAC,SAAS,KAAK;kCACnB,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA;kCACpB,aAAa,SAAS,CAAA,EAAA,EAAK,QAAQ,CAAC,MAAM,GAAG;AAEnD,4BAAA,MAAM,WAAW,GACf,KAAK,KAAK,CAAC,IAAI,CAAC;AACd,kCAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,KAAK,CAAC;kCAC3D,EAAE;4BAER,OAAO;AACL,gCAAA,GAAG,WAAW;gCACd,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;6BAC9C;wBACH,CAAC;AACF,qBAAA,CAAC;gBACJ;YACF,CAAC;SACF;IACH,CAAC;AACD,IAAA,cAAc,EAAE,EAAE;;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useBrandedNumberCastFunction';
|
|
4
|
+
export declare const preferAsInt: TSESLint.RuleModule<MessageIds, Options>;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=prefer-as-int.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-as-int.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-as-int.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAQlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,8BAA8B,CAAC;AAEjD,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA8FhE,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import { brandedNumberTypeNameToFunctionName } from './branded-number-types.mjs';
|
|
3
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
4
|
+
|
|
5
|
+
const preferAsInt = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'suggestion',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Replace branded number type assertions (e.g., `as Int`) with corresponding functions (e.g., `asInt()`) from ts-data-forge.',
|
|
10
|
+
},
|
|
11
|
+
fixable: 'code',
|
|
12
|
+
schema: [],
|
|
13
|
+
messages: {
|
|
14
|
+
useBrandedNumberCastFunction: 'Replace `as {{typeName}}` with `{{functionName}}()` from ts-data-forge.',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
create: (context) => {
|
|
18
|
+
const sourceCode = context.sourceCode;
|
|
19
|
+
const program = sourceCode.ast;
|
|
20
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
21
|
+
const mut_nodesToFix = [];
|
|
22
|
+
return {
|
|
23
|
+
TSAsExpression: (node) => {
|
|
24
|
+
const typeInfo = getBrandedNumberTypeInfo(node.typeAnnotation);
|
|
25
|
+
if (typeInfo === undefined)
|
|
26
|
+
return;
|
|
27
|
+
mut_nodesToFix.push({
|
|
28
|
+
node,
|
|
29
|
+
typeName: typeInfo.typeName,
|
|
30
|
+
functionName: typeInfo.functionName,
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
'Program:exit': () => {
|
|
34
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
35
|
+
// Group nodes by function name to handle imports efficiently
|
|
36
|
+
const mut_functionNameToNodes = new Map();
|
|
37
|
+
for (const nodeInfo of mut_nodesToFix) {
|
|
38
|
+
const mut_nodes = mut_functionNameToNodes.get(nodeInfo.functionName) ?? [];
|
|
39
|
+
mut_nodes.push(nodeInfo);
|
|
40
|
+
mut_functionNameToNodes.set(nodeInfo.functionName, mut_nodes);
|
|
41
|
+
}
|
|
42
|
+
// Process each group
|
|
43
|
+
for (const [functionName, nodes] of mut_functionNameToNodes) {
|
|
44
|
+
const hasImport = namedImports.includes(functionName);
|
|
45
|
+
for (const [index, { node, typeName }] of nodes.entries()) {
|
|
46
|
+
context.report({
|
|
47
|
+
node,
|
|
48
|
+
messageId: 'useBrandedNumberCastFunction',
|
|
49
|
+
data: {
|
|
50
|
+
typeName,
|
|
51
|
+
functionName,
|
|
52
|
+
},
|
|
53
|
+
fix: (fixer) => {
|
|
54
|
+
const replacement = `${functionName}(${sourceCode.getText(node.expression)})`;
|
|
55
|
+
// Add import only for the first node of this function and only if not already imported
|
|
56
|
+
const importFixes = index === 0 && !hasImport
|
|
57
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, [
|
|
58
|
+
functionName,
|
|
59
|
+
])
|
|
60
|
+
: [];
|
|
61
|
+
return [...importFixes, fixer.replaceText(node, replacement)];
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
defaultOptions: [],
|
|
70
|
+
};
|
|
71
|
+
const getBrandedNumberTypeInfo = (typeAnnotation) => {
|
|
72
|
+
if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (typeAnnotation.typeName.type !== AST_NODE_TYPES.Identifier)
|
|
75
|
+
return undefined;
|
|
76
|
+
const typeName = typeAnnotation.typeName.name;
|
|
77
|
+
if (!brandedNumberTypeNameToFunctionName.has(typeName))
|
|
78
|
+
return undefined;
|
|
79
|
+
const functionName = brandedNumberTypeNameToFunctionName.get(typeName);
|
|
80
|
+
if (functionName === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
return { typeName, functionName };
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export { preferAsInt };
|
|
86
|
+
//# sourceMappingURL=prefer-as-int.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-as-int.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-as-int.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useIsNonNullObject';
|
|
4
|
+
export declare const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options>;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=prefer-is-non-null-object.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-is-non-null-object.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-is-non-null-object.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAOlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,oBAAoB,CAAC;AAEvC,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAsE1E,CAAC"}
|