@eslint-react/ast 2.0.0-beta.44 → 2.0.0-beta.48
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/index.d.ts +50 -89
- package/dist/index.js +483 -450
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { unit } from
|
|
3
|
-
import { TSESTree as TSESTree$1 } from
|
|
1
|
+
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
|
|
2
|
+
import { unit } from "@eslint-react/eff";
|
|
3
|
+
import { TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
|
|
4
4
|
|
|
5
|
+
//#region src/ast-array-method.d.ts
|
|
5
6
|
declare function isArrayFromCall(node: TSESTree.Node, loose?: boolean): node is TSESTree.CallExpression;
|
|
6
7
|
declare function isArrayMapCall(node: TSESTree.Node, loose?: boolean): node is TSESTree.CallExpression;
|
|
7
|
-
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/ast-array-method-callback.d.ts
|
|
8
10
|
declare function getArrayMethodCallbackIndexParamPosition(methodName: string): number;
|
|
9
|
-
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/ast-node-types.d.ts
|
|
10
13
|
type TSESTreeFunction = TSESTree$1.ArrowFunctionExpression | TSESTree$1.FunctionDeclaration | TSESTree$1.FunctionExpression;
|
|
11
14
|
type TSESTreeFunctionType = TSESTree$1.TSCallSignatureDeclaration | TSESTree$1.TSConstructSignatureDeclaration | TSESTree$1.TSDeclareFunction | TSESTree$1.TSEmptyBodyFunctionExpression | TSESTree$1.TSFunctionType | TSESTree$1.TSMethodSignature | TSESTreeFunction;
|
|
12
15
|
type TSESTreeClass = TSESTree$1.ClassDeclaration | TSESTree$1.ClassExpression;
|
|
@@ -19,9 +22,11 @@ type TSESTreeDestructuringPattern = TSESTree$1.ArrayPattern | TSESTree$1.Assignm
|
|
|
19
22
|
type TSESTreeTypeDeclaration = TSESTree$1.TSInterfaceDeclaration | TSESTree$1.TSTypeAliasDeclaration;
|
|
20
23
|
type TSESTreeTypeExpression = TSESTree$1.TSAsExpression | TSESTree$1.TSNonNullExpression | TSESTree$1.TSSatisfiesExpression | TSESTree$1.TSTypeAssertion | TSESTree$1.TSInstantiationExpression;
|
|
21
24
|
type TSESTreeTypeAssertionExpression = TSESTree$1.TSAsExpression | TSESTree$1.TSNonNullExpression | TSESTree$1.TSSatisfiesExpression | TSESTree$1.TSTypeAssertion;
|
|
22
|
-
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/ast-class-id.d.ts
|
|
23
27
|
declare function getClassId(node: TSESTreeClass): TSESTree.Identifier | unit;
|
|
24
|
-
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/ast-expression.d.ts
|
|
25
30
|
/**
|
|
26
31
|
* Recursively get the inner expression until it's not a TypeExpression
|
|
27
32
|
* @param node - The node to get the expression from
|
|
@@ -29,7 +34,8 @@ declare function getClassId(node: TSESTreeClass): TSESTree.Identifier | unit;
|
|
|
29
34
|
*/
|
|
30
35
|
declare function getJSExpression(node: TSESTree.Node): Exclude<TSESTree.Node, TSESTreeTypeExpression>;
|
|
31
36
|
declare function isThisExpression(node: TSESTree.Expression): boolean;
|
|
32
|
-
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/ast-function-id.d.ts
|
|
33
39
|
/**
|
|
34
40
|
* Gets the static name of a function AST node. For function declarations it is
|
|
35
41
|
* easy. For anonymous function expressions it is much harder. If you search for
|
|
@@ -38,8 +44,9 @@ declare function isThisExpression(node: TSESTree.Expression): boolean;
|
|
|
38
44
|
* same AST nodes with some exceptions to better fit our use case.
|
|
39
45
|
*/
|
|
40
46
|
declare function getFunctionId(node: TSESTree.Expression | TSESTreeFunction): TSESTree.Identifier | unit;
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/ast-function-init-path.d.ts
|
|
49
|
+
type FunctionInitPath =
|
|
43
50
|
/**
|
|
44
51
|
* function Comp() { return <div />; }
|
|
45
52
|
*/
|
|
@@ -47,102 +54,50 @@ readonly [TSESTree.FunctionDeclaration]
|
|
|
47
54
|
/**
|
|
48
55
|
* const Comp = () => <div />;
|
|
49
56
|
* const Comp = function () { return <div />; };
|
|
50
|
-
*/
|
|
51
|
-
| readonly [
|
|
52
|
-
TSESTree.VariableDeclaration,
|
|
53
|
-
TSESTree.VariableDeclarator,
|
|
54
|
-
TSESTreeFunction
|
|
55
|
-
]
|
|
57
|
+
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTreeFunction]
|
|
56
58
|
/**
|
|
57
59
|
* const Comp = React.memo(() => <div />);
|
|
58
60
|
* const Comp = React.forwardRef(() => <div />);
|
|
59
|
-
*/
|
|
60
|
-
| readonly [
|
|
61
|
-
TSESTree.VariableDeclaration,
|
|
62
|
-
TSESTree.VariableDeclarator,
|
|
63
|
-
TSESTree.CallExpression,
|
|
64
|
-
TSESTreeFunction
|
|
65
|
-
]
|
|
61
|
+
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTreeFunction]
|
|
66
62
|
/**
|
|
67
63
|
* const Comp = React.memo(React.forwardRef(() => <div />));
|
|
68
|
-
*/
|
|
69
|
-
| readonly [
|
|
70
|
-
TSESTree.VariableDeclaration,
|
|
71
|
-
TSESTree.VariableDeclarator,
|
|
72
|
-
TSESTree.CallExpression,
|
|
73
|
-
TSESTree.CallExpression,
|
|
74
|
-
TSESTreeFunction
|
|
75
|
-
]
|
|
64
|
+
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTree.CallExpression, TSESTreeFunction]
|
|
76
65
|
/**
|
|
77
66
|
* const Comps = {
|
|
78
67
|
* TopNav() { return <div />; },
|
|
79
68
|
* SidPanel: () => <div />,
|
|
80
69
|
* }
|
|
81
|
-
*/
|
|
82
|
-
| readonly [
|
|
83
|
-
TSESTree.VariableDeclaration,
|
|
84
|
-
TSESTree.VariableDeclarator,
|
|
85
|
-
TSESTree.ObjectExpression,
|
|
86
|
-
TSESTree.Property,
|
|
87
|
-
TSESTreeFunction
|
|
88
|
-
]
|
|
70
|
+
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTreeFunction]
|
|
89
71
|
/**
|
|
90
72
|
* const Comps = {
|
|
91
73
|
* TopNav: React.memo(() => <div />),
|
|
92
74
|
* SidPanel: React.forwardRef(() => <div />),
|
|
93
75
|
* }
|
|
94
|
-
*/
|
|
95
|
-
| readonly [
|
|
96
|
-
TSESTree.VariableDeclaration,
|
|
97
|
-
TSESTree.VariableDeclarator,
|
|
98
|
-
TSESTree.ObjectExpression,
|
|
99
|
-
TSESTree.Property,
|
|
100
|
-
TSESTree.CallExpression,
|
|
101
|
-
TSESTreeFunction
|
|
102
|
-
]
|
|
76
|
+
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTreeFunction]
|
|
103
77
|
/**
|
|
104
78
|
* const Comps = {
|
|
105
79
|
* TopNav: React.memo(React.forwardRef(() => <div />)),
|
|
106
80
|
* SidPanel: React.forwardRef(React.memo(() => <div />)),
|
|
107
81
|
* }
|
|
108
|
-
*/
|
|
109
|
-
| readonly [
|
|
110
|
-
TSESTree.VariableDeclaration,
|
|
111
|
-
TSESTree.VariableDeclarator,
|
|
112
|
-
TSESTree.ObjectExpression,
|
|
113
|
-
TSESTree.Property,
|
|
114
|
-
TSESTree.CallExpression,
|
|
115
|
-
TSESTree.CallExpression,
|
|
116
|
-
TSESTreeFunction
|
|
117
|
-
]
|
|
82
|
+
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTree.CallExpression, TSESTreeFunction]
|
|
118
83
|
/**
|
|
119
84
|
* class Comp {
|
|
120
85
|
* TopNav() { return <div />; }
|
|
121
86
|
* }
|
|
122
|
-
*/
|
|
123
|
-
| readonly [
|
|
124
|
-
TSESTree.ClassDeclaration,
|
|
125
|
-
TSESTree.ClassBody,
|
|
126
|
-
TSESTree.MethodDefinition,
|
|
127
|
-
TSESTreeFunction
|
|
128
|
-
]
|
|
87
|
+
*/ | readonly [TSESTree.ClassDeclaration, TSESTree.ClassBody, TSESTree.MethodDefinition, TSESTreeFunction]
|
|
129
88
|
/**
|
|
130
89
|
* class Comp {
|
|
131
90
|
* TopNav = () => <div />;
|
|
132
91
|
* }
|
|
133
|
-
*/
|
|
134
|
-
| readonly [
|
|
135
|
-
TSESTree.ClassDeclaration,
|
|
136
|
-
TSESTree.ClassBody,
|
|
137
|
-
TSESTree.PropertyDefinition,
|
|
138
|
-
TSESTreeFunction
|
|
139
|
-
];
|
|
92
|
+
*/ | readonly [TSESTree.ClassDeclaration, TSESTree.ClassBody, TSESTree.PropertyDefinition, TSESTreeFunction];
|
|
140
93
|
declare function getFunctionInitPath(node: TSESTreeFunction): unit | FunctionInitPath;
|
|
141
94
|
declare function hasCallInFunctionInitPath(callName: string, initPath: FunctionInitPath): boolean;
|
|
142
|
-
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/ast-function-is.d.ts
|
|
143
97
|
declare function isEmptyFunction(node: TSESTreeFunction): boolean;
|
|
144
98
|
declare function isImmediatelyInvokedFunction(node: TSESTreeFunction): boolean;
|
|
145
|
-
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/ast-hierarchy.d.ts
|
|
146
101
|
/**
|
|
147
102
|
* Find the parent node that satisfies the test function
|
|
148
103
|
* @param node The AST node
|
|
@@ -157,7 +112,6 @@ declare function findParentNode<A extends TSESTree.Node>(node: TSESTree.Node | u
|
|
|
157
112
|
* @returns The parent node that satisfies the test function
|
|
158
113
|
*/
|
|
159
114
|
declare function findParentNode(node: TSESTree.Node | unit, test: (node: TSESTree.Node) => boolean): TSESTree.Node | unit;
|
|
160
|
-
|
|
161
115
|
/**
|
|
162
116
|
* Get all nested identifiers in a expression like node
|
|
163
117
|
* @param node The node to get the nested identifiers from
|
|
@@ -177,7 +131,7 @@ declare function getNestedReturnStatements(node: TSESTree.Node): readonly TSESTr
|
|
|
177
131
|
* node, and it will return an array of all nested expressions of type T.
|
|
178
132
|
*/
|
|
179
133
|
declare function getNestedExpressionsOfType<TNodeType extends AST_NODE_TYPES>(type: TNodeType): (node: TSESTree.Node) => Extract<TSESTree.Node, {
|
|
180
|
-
|
|
134
|
+
type: TNodeType;
|
|
181
135
|
}>[];
|
|
182
136
|
/**
|
|
183
137
|
* Get all nested new expressions in an expression like node
|
|
@@ -191,7 +145,8 @@ declare const getNestedNewExpressions: (node: TSESTree.Node) => TSESTree.NewExpr
|
|
|
191
145
|
* @returns All nested call expressions
|
|
192
146
|
*/
|
|
193
147
|
declare const getNestedCallExpressions: (node: TSESTree.Node) => TSESTree.CallExpression[];
|
|
194
|
-
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/ast-line.d.ts
|
|
195
150
|
/**
|
|
196
151
|
* Check if a node is multiline
|
|
197
152
|
* @param node The AST node to check
|
|
@@ -204,14 +159,16 @@ declare function isMultiLine(node: TSESTree.Node): boolean;
|
|
|
204
159
|
* @returns boolean
|
|
205
160
|
*/
|
|
206
161
|
declare function isLineBreak(node: TSESTree.Node): boolean;
|
|
207
|
-
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/ast-literal-is.d.ts
|
|
208
164
|
declare function isLiteral(node: TSESTree.Node): node is TSESTree.Literal;
|
|
209
165
|
declare function isLiteral(node: TSESTree.Node, type: "boolean"): node is TSESTree.BooleanLiteral;
|
|
210
166
|
declare function isLiteral(node: TSESTree.Node, type: "null"): node is TSESTree.NullLiteral;
|
|
211
167
|
declare function isLiteral(node: TSESTree.Node, type: "number"): node is TSESTree.NumberLiteral;
|
|
212
168
|
declare function isLiteral(node: TSESTree.Node, type: "regexp"): node is TSESTree.RegExpLiteral;
|
|
213
169
|
declare function isLiteral(node: TSESTree.Node, type: "string"): node is TSESTree.StringLiteral;
|
|
214
|
-
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region src/ast-node-equal.d.ts
|
|
215
172
|
/**
|
|
216
173
|
* Determines whether node equals to another node
|
|
217
174
|
* @param a node to compare
|
|
@@ -220,10 +177,11 @@ declare function isLiteral(node: TSESTree.Node, type: "string"): node is TSESTre
|
|
|
220
177
|
* @see https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/util/isNodeEqual.ts
|
|
221
178
|
*/
|
|
222
179
|
declare const isNodeEqual: {
|
|
223
|
-
|
|
224
|
-
|
|
180
|
+
(a: TSESTree.Node): (b: TSESTree.Node) => boolean;
|
|
181
|
+
(a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
225
182
|
};
|
|
226
|
-
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/ast-node-format.d.ts
|
|
227
185
|
/**
|
|
228
186
|
* @internal
|
|
229
187
|
*/
|
|
@@ -232,12 +190,13 @@ declare function toDelimiterFormat(node: TSESTree.Node, delimiter?: string): "Re
|
|
|
232
190
|
* @internal
|
|
233
191
|
*/
|
|
234
192
|
declare function toStringFormat(node: TSESTree.Node, getText: (node: TSESTree.Node) => string): string;
|
|
235
|
-
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/ast-node-is.d.ts
|
|
236
195
|
declare const is: <NodeType extends TSESTree.AST_NODE_TYPES>(nodeType: NodeType) => (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, {
|
|
237
|
-
|
|
196
|
+
type: NodeType;
|
|
238
197
|
}>;
|
|
239
198
|
declare const isOneOf: <NodeTypes extends readonly TSESTree.AST_NODE_TYPES[]>(nodeTypes: NodeTypes) => (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, {
|
|
240
|
-
|
|
199
|
+
type: NodeTypes[number];
|
|
241
200
|
}>;
|
|
242
201
|
declare const isFunction: (node: TSESTree.Node | null | undefined) => node is TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.FunctionExpression;
|
|
243
202
|
declare const isFunctionType: (node: TSESTree.Node | null | undefined) => node is TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.FunctionExpression | TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructSignatureDeclaration | TSESTree.TSDeclareFunctionNoDeclare | TSESTree.TSDeclareFunctionWithDeclare | TSESTree.TSEmptyBodyFunctionExpression | TSESTree.TSFunctionType | TSESTree.TSMethodSignatureComputedName | TSESTree.TSMethodSignatureNonComputedName;
|
|
@@ -251,9 +210,11 @@ declare const isJSX: (node: TSESTree.Node | null | undefined) => node is TSESTre
|
|
|
251
210
|
declare const isLoop: (node: TSESTree.Node | null | undefined) => node is TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.WhileStatement;
|
|
252
211
|
declare const isTypeExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
253
212
|
declare const isTypeAssertionExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
254
|
-
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/ast-property-name.d.ts
|
|
255
215
|
declare function getPropertyName(node: TSESTree.Node): string | unit;
|
|
256
|
-
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/ast-then.d.ts
|
|
257
218
|
declare function isThenCall(node: TSESTree.CallExpression): boolean;
|
|
258
|
-
|
|
259
|
-
export {
|
|
219
|
+
//#endregion
|
|
220
|
+
export { FunctionInitPath, TSESTreeArrayTupleType, TSESTreeClass, TSESTreeDestructuringPattern, TSESTreeFunction, TSESTreeFunctionType, TSESTreeJSX, TSESTreeLoop, TSESTreeMethodOrProperty, TSESTreeProperty, TSESTreeTypeAssertionExpression, TSESTreeTypeDeclaration, TSESTreeTypeExpression, findParentNode, getArrayMethodCallbackIndexParamPosition, getClassId, getFunctionId, getFunctionInitPath, getJSExpression, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, hasCallInFunctionInitPath, is, isArrayFromCall, isArrayMapCall, isClass, isEmptyFunction, isFunction, isFunctionType, isImmediatelyInvokedFunction, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProperty, isThenCall, isThisExpression, isTypeAssertionExpression, isTypeExpression, toDelimiterFormat, toStringFormat };
|
package/dist/index.js
CHANGED
|
@@ -1,510 +1,543 @@
|
|
|
1
|
-
import { AST_NODE_TYPES } from
|
|
2
|
-
import { dual, unit } from
|
|
3
|
-
import { ASTUtils } from
|
|
4
|
-
import { simpleTraverse } from
|
|
5
|
-
import {
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
2
|
+
import { dual, unit } from "@eslint-react/eff";
|
|
3
|
+
import { ASTUtils } from "@typescript-eslint/utils";
|
|
4
|
+
import { simpleTraverse } from "@typescript-eslint/typescript-estree";
|
|
5
|
+
import { delimiterCase, replace, toLowerCase } from "string-ts";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
//#region src/ast-array-method.ts
|
|
8
8
|
function isArrayFromCall(node, loose = true) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
10
|
+
if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
11
|
+
if (node.callee.property.type !== AST_NODE_TYPES.Identifier) return false;
|
|
12
|
+
const name = node.callee.property.name;
|
|
13
|
+
return name === "from" || loose && name.startsWith("from");
|
|
14
14
|
}
|
|
15
15
|
function isArrayMapCall(node, loose = true) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
17
|
+
if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
18
|
+
if (node.callee.property.type !== AST_NODE_TYPES.Identifier) return false;
|
|
19
|
+
const name = node.callee.property.name;
|
|
20
|
+
return name === "map" || loose && name.endsWith("Map");
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/ast-array-method-callback.ts
|
|
25
|
+
const indexParamPosition = new Map([
|
|
26
|
+
["every", 1],
|
|
27
|
+
["filter", 1],
|
|
28
|
+
["find", 1],
|
|
29
|
+
["findIndex", 1],
|
|
30
|
+
["findLast", 1],
|
|
31
|
+
["findLastIndex", 1],
|
|
32
|
+
["flatMap", 1],
|
|
33
|
+
["forEach", 1],
|
|
34
|
+
["map", 1],
|
|
35
|
+
["reduce", 2],
|
|
36
|
+
["reduceRight", 2],
|
|
37
|
+
["some", 1]
|
|
37
38
|
]);
|
|
38
39
|
function getArrayMethodCallbackIndexParamPosition(methodName) {
|
|
39
|
-
|
|
40
|
+
return indexParamPosition.get(methodName) ?? -1;
|
|
40
41
|
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/ast-class-id.ts
|
|
41
45
|
function getClassId(node) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
return unit;
|
|
46
|
+
if (node.id != null) return node.id;
|
|
47
|
+
if (node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES.Identifier) return node.parent.id;
|
|
48
|
+
return unit;
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
AST_NODE_TYPES.FunctionDeclaration,
|
|
58
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
59
|
-
AST_NODE_TYPES.TSCallSignatureDeclaration,
|
|
60
|
-
AST_NODE_TYPES.TSConstructSignatureDeclaration,
|
|
61
|
-
AST_NODE_TYPES.TSDeclareFunction,
|
|
62
|
-
AST_NODE_TYPES.TSEmptyBodyFunctionExpression,
|
|
63
|
-
AST_NODE_TYPES.TSFunctionType,
|
|
64
|
-
AST_NODE_TYPES.TSMethodSignature
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/ast-node-is.ts
|
|
53
|
+
const is = ASTUtils.isNodeOfType;
|
|
54
|
+
const isOneOf = ASTUtils.isNodeOfTypes;
|
|
55
|
+
const isFunction = isOneOf([
|
|
56
|
+
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
57
|
+
AST_NODE_TYPES.FunctionDeclaration,
|
|
58
|
+
AST_NODE_TYPES.FunctionExpression
|
|
65
59
|
]);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
const isFunctionType = isOneOf([
|
|
61
|
+
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
62
|
+
AST_NODE_TYPES.FunctionDeclaration,
|
|
63
|
+
AST_NODE_TYPES.FunctionExpression,
|
|
64
|
+
AST_NODE_TYPES.TSCallSignatureDeclaration,
|
|
65
|
+
AST_NODE_TYPES.TSConstructSignatureDeclaration,
|
|
66
|
+
AST_NODE_TYPES.TSDeclareFunction,
|
|
67
|
+
AST_NODE_TYPES.TSEmptyBodyFunctionExpression,
|
|
68
|
+
AST_NODE_TYPES.TSFunctionType,
|
|
69
|
+
AST_NODE_TYPES.TSMethodSignature
|
|
70
70
|
]);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
const isClass = isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression]);
|
|
72
|
+
const isMethodOrProperty = isOneOf([AST_NODE_TYPES.PropertyDefinition, AST_NODE_TYPES.MethodDefinition]);
|
|
73
|
+
const isProperty = isOneOf([
|
|
74
|
+
AST_NODE_TYPES.PropertyDefinition,
|
|
75
|
+
AST_NODE_TYPES.TSIndexSignature,
|
|
76
|
+
AST_NODE_TYPES.TSParameterProperty,
|
|
77
|
+
AST_NODE_TYPES.TSPropertySignature
|
|
76
78
|
]);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
const isJSXElement = is(AST_NODE_TYPES.JSXElement);
|
|
80
|
+
const isJSXFragment = is(AST_NODE_TYPES.JSXFragment);
|
|
81
|
+
const isJSXTagNameExpression = isOneOf([
|
|
82
|
+
AST_NODE_TYPES.JSXIdentifier,
|
|
83
|
+
AST_NODE_TYPES.JSXMemberExpression,
|
|
84
|
+
AST_NODE_TYPES.JSXNamespacedName
|
|
83
85
|
]);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
const isJSX = isOneOf([
|
|
87
|
+
AST_NODE_TYPES.JSXAttribute,
|
|
88
|
+
AST_NODE_TYPES.JSXClosingElement,
|
|
89
|
+
AST_NODE_TYPES.JSXClosingFragment,
|
|
90
|
+
AST_NODE_TYPES.JSXElement,
|
|
91
|
+
AST_NODE_TYPES.JSXEmptyExpression,
|
|
92
|
+
AST_NODE_TYPES.JSXExpressionContainer,
|
|
93
|
+
AST_NODE_TYPES.JSXFragment,
|
|
94
|
+
AST_NODE_TYPES.JSXIdentifier,
|
|
95
|
+
AST_NODE_TYPES.JSXMemberExpression,
|
|
96
|
+
AST_NODE_TYPES.JSXNamespacedName,
|
|
97
|
+
AST_NODE_TYPES.JSXOpeningElement,
|
|
98
|
+
AST_NODE_TYPES.JSXOpeningFragment,
|
|
99
|
+
AST_NODE_TYPES.JSXSpreadAttribute,
|
|
100
|
+
AST_NODE_TYPES.JSXSpreadChild,
|
|
101
|
+
AST_NODE_TYPES.JSXText
|
|
100
102
|
]);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
const isLoop = isOneOf([
|
|
104
|
+
AST_NODE_TYPES.DoWhileStatement,
|
|
105
|
+
AST_NODE_TYPES.ForInStatement,
|
|
106
|
+
AST_NODE_TYPES.ForOfStatement,
|
|
107
|
+
AST_NODE_TYPES.ForStatement,
|
|
108
|
+
AST_NODE_TYPES.WhileStatement
|
|
107
109
|
]);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const isTypeExpression = isOneOf([
|
|
111
|
+
AST_NODE_TYPES.TSAsExpression,
|
|
112
|
+
AST_NODE_TYPES.TSTypeAssertion,
|
|
113
|
+
AST_NODE_TYPES.TSNonNullExpression,
|
|
114
|
+
AST_NODE_TYPES.TSSatisfiesExpression,
|
|
115
|
+
AST_NODE_TYPES.TSInstantiationExpression
|
|
114
116
|
]);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
const isTypeAssertionExpression = isOneOf([
|
|
118
|
+
AST_NODE_TYPES.TSAsExpression,
|
|
119
|
+
AST_NODE_TYPES.TSTypeAssertion,
|
|
120
|
+
AST_NODE_TYPES.TSNonNullExpression,
|
|
121
|
+
AST_NODE_TYPES.TSSatisfiesExpression
|
|
120
122
|
]);
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/ast-expression.ts
|
|
126
|
+
/**
|
|
127
|
+
* Recursively get the inner expression until it's not a TypeExpression
|
|
128
|
+
* @param node - The node to get the expression from
|
|
129
|
+
* @returns The inner expression
|
|
130
|
+
*/
|
|
123
131
|
function getJSExpression(node) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
return node;
|
|
132
|
+
if (isTypeExpression(node)) return getJSExpression(node.expression);
|
|
133
|
+
return node;
|
|
128
134
|
}
|
|
129
135
|
function isThisExpression(node) {
|
|
130
|
-
|
|
136
|
+
return getJSExpression(node).type === AST_NODE_TYPES.ThisExpression;
|
|
131
137
|
}
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/ast-function-id.ts
|
|
141
|
+
/**
|
|
142
|
+
* Gets the static name of a function AST node. For function declarations it is
|
|
143
|
+
* easy. For anonymous function expressions it is much harder. If you search for
|
|
144
|
+
* `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
|
|
145
|
+
* where JS gives anonymous function expressions names. We roughly detect the
|
|
146
|
+
* same AST nodes with some exceptions to better fit our use case.
|
|
147
|
+
*/
|
|
132
148
|
function getFunctionId(node) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// {MaybeComponent: () => {}}
|
|
144
|
-
// {MaybeComponent() {}}
|
|
145
|
-
case (node.parent.type === AST_NODE_TYPES.Property && node.parent.value === node && !node.parent.computed && node.parent.key.type === AST_NODE_TYPES.Identifier):
|
|
146
|
-
return node.parent.key;
|
|
147
|
-
// class {MaybeComponent = () => {}}
|
|
148
|
-
// class {MaybeComponent() {}}
|
|
149
|
-
case (isMethodOrProperty(node.parent) && node.parent.value === node && node.parent.key.type === AST_NODE_TYPES.Identifier):
|
|
150
|
-
return node.parent.key;
|
|
151
|
-
// Follow spec convention for `IsAnonymousFunctionDefinition()` usage.
|
|
152
|
-
//
|
|
153
|
-
// const {MaybeComponent = () => {}} = {};
|
|
154
|
-
// ({MaybeComponent = () => {}} = {});
|
|
155
|
-
case (node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node && node.parent.left.type === AST_NODE_TYPES.Identifier):
|
|
156
|
-
return node.parent.left;
|
|
157
|
-
// const MaybeComponent = (() => {})!;
|
|
158
|
-
// const MaybeComponent = (() => {}) as FunctionComponent;
|
|
159
|
-
// const MaybeComponent = (() => {}) satisfies FunctionComponent;
|
|
160
|
-
case isTypeAssertionExpression(node.parent):
|
|
161
|
-
return getFunctionId(node.parent);
|
|
162
|
-
}
|
|
163
|
-
return unit;
|
|
149
|
+
switch (true) {
|
|
150
|
+
case "id" in node && node.id != null: return node.id;
|
|
151
|
+
case node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node && node.parent.id.type === AST_NODE_TYPES.Identifier: return node.parent.id;
|
|
152
|
+
case node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.right === node && node.parent.operator === "=" && node.parent.left.type === AST_NODE_TYPES.Identifier: return node.parent.left;
|
|
153
|
+
case node.parent.type === AST_NODE_TYPES.Property && node.parent.value === node && !node.parent.computed && node.parent.key.type === AST_NODE_TYPES.Identifier: return node.parent.key;
|
|
154
|
+
case isMethodOrProperty(node.parent) && node.parent.value === node && node.parent.key.type === AST_NODE_TYPES.Identifier: return node.parent.key;
|
|
155
|
+
case node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node && node.parent.left.type === AST_NODE_TYPES.Identifier: return node.parent.left;
|
|
156
|
+
case isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
|
|
157
|
+
}
|
|
158
|
+
return unit;
|
|
164
159
|
}
|
|
160
|
+
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/ast-function-init-path.ts
|
|
165
163
|
function getFunctionInitPath(node) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
164
|
+
if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
|
|
165
|
+
const { parent } = node;
|
|
166
|
+
switch (true) {
|
|
167
|
+
case parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
168
|
+
parent.parent,
|
|
169
|
+
parent,
|
|
170
|
+
node
|
|
171
|
+
];
|
|
172
|
+
case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
173
|
+
parent.parent.parent,
|
|
174
|
+
parent.parent,
|
|
175
|
+
parent,
|
|
176
|
+
node
|
|
177
|
+
];
|
|
178
|
+
case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
179
|
+
parent.parent.parent.parent,
|
|
180
|
+
parent.parent.parent,
|
|
181
|
+
parent.parent,
|
|
182
|
+
parent,
|
|
183
|
+
node
|
|
184
|
+
];
|
|
185
|
+
case parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
186
|
+
parent.parent.parent.parent,
|
|
187
|
+
parent.parent.parent,
|
|
188
|
+
parent.parent,
|
|
189
|
+
parent,
|
|
190
|
+
node
|
|
191
|
+
];
|
|
192
|
+
case parent.type === AST_NODE_TYPES.MethodDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
|
|
193
|
+
parent.parent.parent,
|
|
194
|
+
parent.parent,
|
|
195
|
+
parent,
|
|
196
|
+
node
|
|
197
|
+
];
|
|
198
|
+
case parent.type === AST_NODE_TYPES.PropertyDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
|
|
199
|
+
parent.parent.parent,
|
|
200
|
+
parent.parent,
|
|
201
|
+
parent,
|
|
202
|
+
node
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
return unit;
|
|
185
206
|
}
|
|
186
207
|
function hasCallInFunctionInitPath(callName, initPath) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return "name" in n.callee.property && n.callee.property.name === callName;
|
|
196
|
-
default:
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
});
|
|
208
|
+
return initPath.some((n) => {
|
|
209
|
+
if (n.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
210
|
+
switch (n.callee.type) {
|
|
211
|
+
case AST_NODE_TYPES.Identifier: return n.callee.name === callName;
|
|
212
|
+
case AST_NODE_TYPES.MemberExpression: return "name" in n.callee.property && n.callee.property.name === callName;
|
|
213
|
+
default: return false;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
200
216
|
}
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/ast-function-is.ts
|
|
201
220
|
function isEmptyFunction(node) {
|
|
202
|
-
|
|
221
|
+
return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
|
|
203
222
|
}
|
|
204
223
|
function isImmediatelyInvokedFunction(node) {
|
|
205
|
-
|
|
224
|
+
return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
|
|
206
225
|
}
|
|
226
|
+
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/ast-hierarchy.ts
|
|
207
229
|
function findParentNode(node, test) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
return unit;
|
|
230
|
+
if (node == null) return unit;
|
|
231
|
+
let parent = node.parent;
|
|
232
|
+
while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
|
|
233
|
+
if (test(parent)) return parent;
|
|
234
|
+
parent = parent.parent;
|
|
235
|
+
}
|
|
236
|
+
return unit;
|
|
217
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Get all nested identifiers in a expression like node
|
|
240
|
+
* @param node The node to get the nested identifiers from
|
|
241
|
+
* @returns All nested identifiers
|
|
242
|
+
*/
|
|
218
243
|
function getNestedIdentifiers(node) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
return identifiers;
|
|
244
|
+
const identifiers = [];
|
|
245
|
+
if (node.type === AST_NODE_TYPES.Identifier) identifiers.push(node);
|
|
246
|
+
if ("arguments" in node) {
|
|
247
|
+
const chunk = node.arguments.map(getNestedIdentifiers).flat(1);
|
|
248
|
+
identifiers.push(...chunk);
|
|
249
|
+
}
|
|
250
|
+
if ("elements" in node) {
|
|
251
|
+
const chunk = node.elements.filter((x) => x != null).map(getNestedIdentifiers).flat(1);
|
|
252
|
+
identifiers.push(...chunk);
|
|
253
|
+
}
|
|
254
|
+
if ("properties" in node) {
|
|
255
|
+
const chunk = node.properties.map(getNestedIdentifiers).flat(1);
|
|
256
|
+
identifiers.push(...chunk);
|
|
257
|
+
}
|
|
258
|
+
if ("expressions" in node) {
|
|
259
|
+
const chunk = node.expressions.map(getNestedIdentifiers).flat(1);
|
|
260
|
+
identifiers.push(...chunk);
|
|
261
|
+
}
|
|
262
|
+
if ("left" in node) {
|
|
263
|
+
const chunk = getNestedIdentifiers(node.left);
|
|
264
|
+
identifiers.push(...chunk);
|
|
265
|
+
}
|
|
266
|
+
if ("right" in node) {
|
|
267
|
+
const chunk = getNestedIdentifiers(node.right);
|
|
268
|
+
identifiers.push(...chunk);
|
|
269
|
+
}
|
|
270
|
+
if (node.type === AST_NODE_TYPES.Property) {
|
|
271
|
+
const chunk = getNestedIdentifiers(node.value);
|
|
272
|
+
identifiers.push(...chunk);
|
|
273
|
+
}
|
|
274
|
+
if (node.type === AST_NODE_TYPES.SpreadElement) {
|
|
275
|
+
const chunk = getNestedIdentifiers(node.argument);
|
|
276
|
+
identifiers.push(...chunk);
|
|
277
|
+
}
|
|
278
|
+
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
279
|
+
const chunk = getNestedIdentifiers(node.object);
|
|
280
|
+
identifiers.push(...chunk);
|
|
281
|
+
}
|
|
282
|
+
if (node.type === AST_NODE_TYPES.UnaryExpression) {
|
|
283
|
+
const chunk = getNestedIdentifiers(node.argument);
|
|
284
|
+
identifiers.push(...chunk);
|
|
285
|
+
}
|
|
286
|
+
if (node.type === AST_NODE_TYPES.ChainExpression) {
|
|
287
|
+
const chunk = getNestedIdentifiers(node.expression);
|
|
288
|
+
identifiers.push(...chunk);
|
|
289
|
+
}
|
|
290
|
+
if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
|
|
291
|
+
const chunk = getNestedIdentifiers(node.expression);
|
|
292
|
+
identifiers.push(...chunk);
|
|
293
|
+
}
|
|
294
|
+
if (node.type === AST_NODE_TYPES.TSAsExpression) {
|
|
295
|
+
const chunk = getNestedIdentifiers(node.expression);
|
|
296
|
+
identifiers.push(...chunk);
|
|
297
|
+
}
|
|
298
|
+
if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
|
|
299
|
+
const chunk = getNestedIdentifiers(node.expression);
|
|
300
|
+
identifiers.push(...chunk);
|
|
301
|
+
}
|
|
302
|
+
return identifiers;
|
|
280
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Gets the nested return statements in the node that are within the same function
|
|
306
|
+
* @param node The AST node
|
|
307
|
+
* @returns The nested return statements in the node
|
|
308
|
+
*/
|
|
281
309
|
function getNestedReturnStatements(node) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
statements.push(node2);
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
return statements;
|
|
310
|
+
const statements = [];
|
|
311
|
+
const boundaryNode = isFunction(node) ? node : findParentNode(node, isFunction);
|
|
312
|
+
simpleTraverse(node, { enter(node$1) {
|
|
313
|
+
if (node$1.type !== AST_NODE_TYPES.ReturnStatement) return;
|
|
314
|
+
const parentFunction = findParentNode(node$1, isFunction);
|
|
315
|
+
if (parentFunction !== boundaryNode) return;
|
|
316
|
+
statements.push(node$1);
|
|
317
|
+
} });
|
|
318
|
+
return statements;
|
|
297
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Get all nested expressions of type T in an expression like node
|
|
322
|
+
* @param type The type of the expression to retrieve within the node
|
|
323
|
+
* @returns A partially applied function bound to a predicate of type T. The returned function can be called passing a
|
|
324
|
+
* node, and it will return an array of all nested expressions of type T.
|
|
325
|
+
*/
|
|
298
326
|
function getNestedExpressionsOfType(type) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
return expressions;
|
|
379
|
-
};
|
|
327
|
+
const isNodeOfType = is(type);
|
|
328
|
+
return function(node) {
|
|
329
|
+
const boundGetNestedExpressionsOfType = getNestedExpressionsOfType(type);
|
|
330
|
+
const expressions = [];
|
|
331
|
+
if (isNodeOfType(node)) expressions.push(node);
|
|
332
|
+
if ("arguments" in node) {
|
|
333
|
+
const chunk = node.arguments.map(getNestedExpressionsOfType(type)).flat(1);
|
|
334
|
+
expressions.push(...chunk);
|
|
335
|
+
}
|
|
336
|
+
if ("expression" in node && node.expression !== true && node.expression !== false) {
|
|
337
|
+
const chunk = boundGetNestedExpressionsOfType(node.expression);
|
|
338
|
+
expressions.push(...chunk);
|
|
339
|
+
}
|
|
340
|
+
if ("left" in node) {
|
|
341
|
+
const chunk = boundGetNestedExpressionsOfType(node.left);
|
|
342
|
+
expressions.push(...chunk);
|
|
343
|
+
}
|
|
344
|
+
if ("right" in node) {
|
|
345
|
+
const chunk = boundGetNestedExpressionsOfType(node.right);
|
|
346
|
+
expressions.push(...chunk);
|
|
347
|
+
}
|
|
348
|
+
if ("test" in node && node.test != null) {
|
|
349
|
+
const chunk = boundGetNestedExpressionsOfType(node.test);
|
|
350
|
+
expressions.push(...chunk);
|
|
351
|
+
}
|
|
352
|
+
if ("consequent" in node) {
|
|
353
|
+
const chunk = Array.isArray(node.consequent) ? node.consequent.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.consequent);
|
|
354
|
+
expressions.push(...chunk);
|
|
355
|
+
}
|
|
356
|
+
if ("alternate" in node && node.alternate != null) {
|
|
357
|
+
const chunk = Array.isArray(node.alternate) ? node.alternate.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.alternate);
|
|
358
|
+
expressions.push(...chunk);
|
|
359
|
+
}
|
|
360
|
+
if ("elements" in node) {
|
|
361
|
+
const chunk = node.elements.filter((x) => x != null).map(getNestedExpressionsOfType(type)).flat(1);
|
|
362
|
+
expressions.push(...chunk);
|
|
363
|
+
}
|
|
364
|
+
if ("properties" in node) {
|
|
365
|
+
const chunk = node.properties.map(boundGetNestedExpressionsOfType).flat(1);
|
|
366
|
+
expressions.push(...chunk);
|
|
367
|
+
}
|
|
368
|
+
if ("expressions" in node) {
|
|
369
|
+
const chunk = node.expressions.map(boundGetNestedExpressionsOfType).flat(1);
|
|
370
|
+
expressions.push(...chunk);
|
|
371
|
+
}
|
|
372
|
+
if (node.type === AST_NODE_TYPES.Property) {
|
|
373
|
+
const chunk = boundGetNestedExpressionsOfType(node.value);
|
|
374
|
+
expressions.push(...chunk);
|
|
375
|
+
}
|
|
376
|
+
if (node.type === AST_NODE_TYPES.SpreadElement) {
|
|
377
|
+
const chunk = boundGetNestedExpressionsOfType(node.argument);
|
|
378
|
+
expressions.push(...chunk);
|
|
379
|
+
}
|
|
380
|
+
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
381
|
+
const chunk = boundGetNestedExpressionsOfType(node.object);
|
|
382
|
+
expressions.push(...chunk);
|
|
383
|
+
}
|
|
384
|
+
if (node.type === AST_NODE_TYPES.UnaryExpression) {
|
|
385
|
+
const chunk = boundGetNestedExpressionsOfType(node.argument);
|
|
386
|
+
expressions.push(...chunk);
|
|
387
|
+
}
|
|
388
|
+
if (node.type === AST_NODE_TYPES.ChainExpression) {
|
|
389
|
+
const chunk = boundGetNestedExpressionsOfType(node.expression);
|
|
390
|
+
expressions.push(...chunk);
|
|
391
|
+
}
|
|
392
|
+
if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
|
|
393
|
+
const chunk = boundGetNestedExpressionsOfType(node.expression);
|
|
394
|
+
expressions.push(...chunk);
|
|
395
|
+
}
|
|
396
|
+
if (node.type === AST_NODE_TYPES.TSAsExpression) {
|
|
397
|
+
const chunk = boundGetNestedExpressionsOfType(node.expression);
|
|
398
|
+
expressions.push(...chunk);
|
|
399
|
+
}
|
|
400
|
+
if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
|
|
401
|
+
const chunk = boundGetNestedExpressionsOfType(node.expression);
|
|
402
|
+
expressions.push(...chunk);
|
|
403
|
+
}
|
|
404
|
+
return expressions;
|
|
405
|
+
};
|
|
380
406
|
}
|
|
381
|
-
|
|
382
|
-
|
|
407
|
+
/**
|
|
408
|
+
* Get all nested new expressions in an expression like node
|
|
409
|
+
* @param node The node to get the nested new expressions from
|
|
410
|
+
* @returns All nested new expressions
|
|
411
|
+
*/
|
|
412
|
+
const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
|
|
413
|
+
/**
|
|
414
|
+
* Get all nested call expressions in a expression like node
|
|
415
|
+
* @param node The node to get the nested call expressions from
|
|
416
|
+
* @returns All nested call expressions
|
|
417
|
+
*/
|
|
418
|
+
const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
|
|
419
|
+
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/ast-line.ts
|
|
422
|
+
/**
|
|
423
|
+
* Check if a node is multiline
|
|
424
|
+
* @param node The AST node to check
|
|
425
|
+
* @returns `true` if the node is multiline
|
|
426
|
+
*/
|
|
383
427
|
function isMultiLine(node) {
|
|
384
|
-
|
|
428
|
+
return node.loc.start.line !== node.loc.end.line;
|
|
385
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Check if a node is a line break
|
|
432
|
+
* @param node The AST node to check
|
|
433
|
+
* @returns boolean
|
|
434
|
+
*/
|
|
386
435
|
function isLineBreak(node) {
|
|
387
|
-
|
|
436
|
+
return isOneOf([AST_NODE_TYPES.Literal, AST_NODE_TYPES.JSXText])(node) && typeof node.value === "string" && node.value.trim() === "" && isMultiLine(node);
|
|
388
437
|
}
|
|
438
|
+
|
|
439
|
+
//#endregion
|
|
440
|
+
//#region src/ast-literal-is.ts
|
|
389
441
|
function isLiteral(node, type) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
case "regexp":
|
|
400
|
-
return "regex" in node;
|
|
401
|
-
case "string":
|
|
402
|
-
return typeof node.value === "string";
|
|
403
|
-
}
|
|
442
|
+
if (node.type !== AST_NODE_TYPES.Literal) return false;
|
|
443
|
+
if (type == null) return true;
|
|
444
|
+
switch (type) {
|
|
445
|
+
case "boolean": return typeof node.value === "boolean";
|
|
446
|
+
case "null": return node.value === null;
|
|
447
|
+
case "number": return typeof node.value === "number";
|
|
448
|
+
case "regexp": return "regex" in node;
|
|
449
|
+
case "string": return typeof node.value === "string";
|
|
450
|
+
}
|
|
404
451
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
return false;
|
|
444
|
-
}
|
|
445
|
-
if (a.value == null || b.value == null) {
|
|
446
|
-
return a.value === b.value;
|
|
447
|
-
}
|
|
448
|
-
return isNodeEqual(a.value, b.value);
|
|
449
|
-
}
|
|
450
|
-
case (a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression):
|
|
451
|
-
return true;
|
|
452
|
-
default:
|
|
453
|
-
return false;
|
|
454
|
-
}
|
|
452
|
+
|
|
453
|
+
//#endregion
|
|
454
|
+
//#region src/ast-node-equal.ts
|
|
455
|
+
/**
|
|
456
|
+
* Determines whether node equals to another node
|
|
457
|
+
* @param a node to compare
|
|
458
|
+
* @param b node to compare
|
|
459
|
+
* @returns `true` if node equal
|
|
460
|
+
* @see https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/util/isNodeEqual.ts
|
|
461
|
+
*/
|
|
462
|
+
const isNodeEqual = dual(2, (a, b) => {
|
|
463
|
+
switch (true) {
|
|
464
|
+
case a === b: return true;
|
|
465
|
+
case a.type !== b.type: return false;
|
|
466
|
+
case a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal: return a.value === b.value;
|
|
467
|
+
case a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement: return a.value.raw === b.value.raw;
|
|
468
|
+
case a.type === AST_NODE_TYPES.TemplateLiteral && b.type === AST_NODE_TYPES.TemplateLiteral: {
|
|
469
|
+
if (a.quasis.length !== b.quasis.length || a.expressions.length !== b.expressions.length) return false;
|
|
470
|
+
let i = a.quasis.length;
|
|
471
|
+
while (i--) if (a.quasis[i]?.value.raw !== b.quasis[i]?.value.raw) return false;
|
|
472
|
+
i = a.expressions.length;
|
|
473
|
+
while (i--) {
|
|
474
|
+
const exprA = a.expressions[i];
|
|
475
|
+
const exprB = b.expressions[i];
|
|
476
|
+
if (!isNodeEqual(exprA, exprB)) return false;
|
|
477
|
+
}
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
case a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier: return a.name === b.name;
|
|
481
|
+
case a.type === AST_NODE_TYPES.PrivateIdentifier && b.type === AST_NODE_TYPES.PrivateIdentifier: return a.name === b.name;
|
|
482
|
+
case a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression: return isNodeEqual(a.property, b.property) && isNodeEqual(a.object, b.object);
|
|
483
|
+
case a.type === AST_NODE_TYPES.JSXAttribute && b.type === AST_NODE_TYPES.JSXAttribute:
|
|
484
|
+
if (a.name.name !== b.name.name) return false;
|
|
485
|
+
if (a.value == null || b.value == null) return a.value === b.value;
|
|
486
|
+
return isNodeEqual(a.value, b.value);
|
|
487
|
+
case a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression: return true;
|
|
488
|
+
default: return false;
|
|
489
|
+
}
|
|
455
490
|
});
|
|
491
|
+
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/ast-node-format.ts
|
|
456
494
|
function getLiteralValueType(input) {
|
|
457
|
-
|
|
458
|
-
|
|
495
|
+
if (input === null) return "null";
|
|
496
|
+
return typeof input;
|
|
459
497
|
}
|
|
498
|
+
/**
|
|
499
|
+
* @internal
|
|
500
|
+
*/
|
|
460
501
|
function toDelimiterFormat(node, delimiter = " ") {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (isJSX(node)) {
|
|
468
|
-
return `JSX ${toLowerCase(delimiterCase(replace(node.type, "JSX", ""), delimiter))}`;
|
|
469
|
-
}
|
|
470
|
-
return toLowerCase(delimiterCase(node.type, delimiter));
|
|
502
|
+
if (node.type === AST_NODE_TYPES.Literal) {
|
|
503
|
+
if ("regex" in node) return "RegExp literal";
|
|
504
|
+
return `${getLiteralValueType(node.value)} literal`;
|
|
505
|
+
}
|
|
506
|
+
if (isJSX(node)) return `JSX ${toLowerCase(delimiterCase(replace(node.type, "JSX", ""), delimiter))}`;
|
|
507
|
+
return toLowerCase(delimiterCase(node.type, delimiter));
|
|
471
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* @internal
|
|
511
|
+
*/
|
|
472
512
|
function toStringFormat(node, getText) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return node.value;
|
|
485
|
-
case AST_NODE_TYPES.Literal:
|
|
486
|
-
return node.raw;
|
|
487
|
-
default:
|
|
488
|
-
return getText(node);
|
|
489
|
-
}
|
|
513
|
+
switch (node.type) {
|
|
514
|
+
case AST_NODE_TYPES.Identifier:
|
|
515
|
+
case AST_NODE_TYPES.JSXIdentifier:
|
|
516
|
+
case AST_NODE_TYPES.PrivateIdentifier: return node.name;
|
|
517
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
518
|
+
case AST_NODE_TYPES.JSXMemberExpression: return `${toStringFormat(node.object, getText)}.${toStringFormat(node.property, getText)}`;
|
|
519
|
+
case AST_NODE_TYPES.JSXNamespacedName: return `${node.namespace.name}:${node.name.name}`;
|
|
520
|
+
case AST_NODE_TYPES.JSXText: return node.value;
|
|
521
|
+
case AST_NODE_TYPES.Literal: return node.raw;
|
|
522
|
+
default: return getText(node);
|
|
523
|
+
}
|
|
490
524
|
}
|
|
525
|
+
|
|
526
|
+
//#endregion
|
|
527
|
+
//#region src/ast-property-name.ts
|
|
491
528
|
function getPropertyName(node) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
if (node.type === AST_NODE_TYPES.Literal) {
|
|
499
|
-
return String(node.value);
|
|
500
|
-
}
|
|
501
|
-
if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) {
|
|
502
|
-
return node.quasis[0]?.value.raw;
|
|
503
|
-
}
|
|
504
|
-
return unit;
|
|
529
|
+
if (isTypeExpression(node)) return getPropertyName(getJSExpression(node));
|
|
530
|
+
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
|
|
531
|
+
if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
|
|
532
|
+
if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.raw;
|
|
533
|
+
return unit;
|
|
505
534
|
}
|
|
535
|
+
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/ast-then.ts
|
|
506
538
|
function isThenCall(node) {
|
|
507
|
-
|
|
539
|
+
return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
|
|
508
540
|
}
|
|
509
541
|
|
|
510
|
-
|
|
542
|
+
//#endregion
|
|
543
|
+
export { findParentNode, getArrayMethodCallbackIndexParamPosition, getClassId, getFunctionId, getFunctionInitPath, getJSExpression, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, hasCallInFunctionInitPath, is, isArrayFromCall, isArrayMapCall, isClass, isEmptyFunction, isFunction, isFunctionType, isImmediatelyInvokedFunction, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProperty, isThenCall, isThisExpression, isTypeAssertionExpression, isTypeExpression, toDelimiterFormat, toStringFormat };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/ast",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.48",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -27,22 +27,22 @@
|
|
|
27
27
|
"./package.json"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@typescript-eslint/types": "^8.
|
|
31
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
32
|
-
"@typescript-eslint/utils": "^8.
|
|
30
|
+
"@typescript-eslint/types": "^8.41.0",
|
|
31
|
+
"@typescript-eslint/typescript-estree": "^8.41.0",
|
|
32
|
+
"@typescript-eslint/utils": "^8.41.0",
|
|
33
33
|
"string-ts": "^2.2.1",
|
|
34
34
|
"ts-pattern": "^5.8.0",
|
|
35
|
-
"@eslint-react/eff": "2.0.0-beta.
|
|
35
|
+
"@eslint-react/eff": "2.0.0-beta.48"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"
|
|
38
|
+
"tsdown": "^0.14.2",
|
|
39
39
|
"@local/configs": "0.0.0"
|
|
40
40
|
},
|
|
41
41
|
"engines": {
|
|
42
42
|
"node": ">=20.19.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
|
-
"build": "
|
|
45
|
+
"build": "tsdown --dts-resolve",
|
|
46
46
|
"lint:publish": "publint",
|
|
47
47
|
"lint:ts": "tsc --noEmit"
|
|
48
48
|
}
|