@eslint-react/ast 5.2.0-next.0 → 5.2.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +45 -303
- package/dist/index.js +155 -659
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,121 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TSESTree } from "@typescript-eslint/types";
|
|
2
2
|
|
|
3
|
-
//#region src/node-types.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Represents function expressions and declarations in TSESTree
|
|
6
|
-
*/
|
|
7
|
-
type TSESTreeFunction = TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression;
|
|
8
|
-
/**
|
|
9
|
-
* Represents all function-related types including TypeScript function types
|
|
10
|
-
*/
|
|
11
|
-
type TSESTreeFunctionType = TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructSignatureDeclaration | TSESTree.TSDeclareFunction | TSESTree.TSEmptyBodyFunctionExpression | TSESTree.TSFunctionType | TSESTree.TSMethodSignature | TSESTreeFunction;
|
|
12
|
-
/**
|
|
13
|
-
* Represents class declarations and expressions in TSESTree
|
|
14
|
-
*/
|
|
15
|
-
type TSESTreeClass = TSESTree.ClassDeclaration | TSESTree.ClassExpression;
|
|
16
|
-
/**
|
|
17
|
-
* Represents method definitions and property definitions in classes
|
|
18
|
-
*/
|
|
19
|
-
type TSESTreeMethodOrProperty = TSESTree.PropertyDefinition | TSESTree.MethodDefinition;
|
|
20
|
-
/**
|
|
21
|
-
* Represents loop statements in TSESTree
|
|
22
|
-
*/
|
|
23
|
-
type TSESTreeLoop = TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.WhileStatement;
|
|
24
|
-
/**
|
|
25
|
-
* Represents TypeScript array and tuple types
|
|
26
|
-
*/
|
|
27
|
-
type TSESTreeArrayTupleType = TSESTree.TSArrayType | TSESTree.TSTupleType;
|
|
28
|
-
/**
|
|
29
|
-
* Represents property-like nodes in TSESTree
|
|
30
|
-
*/
|
|
31
|
-
type TSESTreeProperty = TSESTree.PropertyDefinition | TSESTree.TSIndexSignature | TSESTree.TSParameterProperty | TSESTree.TSPropertySignature;
|
|
32
|
-
/**
|
|
33
|
-
* Represents all JSX-related nodes in TSESTree
|
|
34
|
-
* Note: This type is for type-level operations. The isJSX() runtime guard in node-is.ts
|
|
35
|
-
* has a slightly different set of nodes as it includes JSXExpressionContainer which is
|
|
36
|
-
* commonly needed for runtime checks but not included in this type union.
|
|
37
|
-
*/
|
|
38
|
-
type TSESTreeJSX = TSESTree.JSXAttribute | TSESTree.JSXChild | TSESTree.JSXClosingElement | TSESTree.JSXClosingFragment | TSESTree.JSXEmptyExpression | TSESTree.JSXIdentifierToken | TSESTree.JSXOpeningElement | TSESTree.JSXOpeningFragment | TSESTree.JSXSpreadAttribute | TSESTree.JSXTagNameExpression | TSESTree.JSXTextToken;
|
|
39
|
-
type TSESTreeJSXElementLike = TSESTree.JSXElement | TSESTree.JSXFragment;
|
|
40
|
-
/**
|
|
41
|
-
* Represents JSX attribute-like nodes (attributes and spread attributes)
|
|
42
|
-
*/
|
|
43
|
-
type TSESTreeJSXAttributeLike = TSESTree.JSXAttribute | TSESTree.JSXSpreadAttribute;
|
|
44
|
-
/**
|
|
45
|
-
* Represents destructuring patterns in variable declarations
|
|
46
|
-
*/
|
|
47
|
-
type TSESTreeDestructuringPattern = TSESTree.ArrayPattern | TSESTree.AssignmentPattern | TSESTree.ObjectPattern | TSESTree.RestElement;
|
|
48
|
-
/**
|
|
49
|
-
* Represents TypeScript type declaration nodes
|
|
50
|
-
*/
|
|
51
|
-
type TSESTreeTypeDeclaration = TSESTree.TSInterfaceDeclaration | TSESTree.TSTypeAliasDeclaration;
|
|
52
|
-
/**
|
|
53
|
-
* Represents TypeScript type expression nodes (type assertions, non-null expressions, etc.)
|
|
54
|
-
*/
|
|
55
|
-
type TSESTreeTypeExpression = TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.TSInstantiationExpression;
|
|
56
|
-
/**
|
|
57
|
-
* Represents TypeScript type assertion expressions (excluding instantiation expressions)
|
|
58
|
-
*/
|
|
59
|
-
type TSESTreeTypeAssertionExpression = TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
60
|
-
/**
|
|
61
|
-
* Represents a directive expression statement in TSESTree (ex: "use strict";)
|
|
62
|
-
*/
|
|
63
|
-
type TSESTreeDirective = TSESTree.ExpressionStatement & {
|
|
64
|
-
directive: string;
|
|
65
|
-
expression: TSESTree.StringLiteral;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Represents a directive-like expression statement in TSESTree
|
|
69
|
-
*/
|
|
70
|
-
type TSESTreeDirectiveLike = TSESTree.ExpressionStatement & {
|
|
71
|
-
expression: TSESTree.StringLiteral;
|
|
72
|
-
};
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/class-id.d.ts
|
|
75
|
-
/**
|
|
76
|
-
* Get the class identifier of a class node
|
|
77
|
-
* @param node The class node to get the identifier from
|
|
78
|
-
* @returns The class identifier or null if not found
|
|
79
|
-
*/
|
|
80
|
-
declare function getClassId(node: TSESTreeClass): TSESTree.BindingName | null;
|
|
81
|
-
//#endregion
|
|
82
|
-
//#region src/directive-is.d.ts
|
|
83
|
-
/**
|
|
84
|
-
* Check if a node is a directive expression statement
|
|
85
|
-
* @param node The node to check
|
|
86
|
-
* @returns True if the node is a directive, false otherwise
|
|
87
|
-
*/
|
|
88
|
-
declare function isDirective(node: TSESTree.Node): node is TSESTreeDirective;
|
|
89
|
-
/**
|
|
90
|
-
* Check if a node is a directive-like expression statement
|
|
91
|
-
* @param node The node to check
|
|
92
|
-
* @returns True if the node is a directive, false otherwise
|
|
93
|
-
*/
|
|
94
|
-
declare function isDirectiveLike(node: TSESTree.Node): node is TSESTreeDirectiveLike;
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region src/directive-kind.d.ts
|
|
97
|
-
/**
|
|
98
|
-
* Known directive kinds in React
|
|
99
|
-
*/
|
|
100
|
-
type DirectiveKind = "use client" | "use server" | "use memo" | "use no memo";
|
|
101
|
-
/**
|
|
102
|
-
* Check if a node is a directive kind
|
|
103
|
-
* @param kind The kind to check
|
|
104
|
-
* @returns True if the kind is a directive kind, false otherwise
|
|
105
|
-
*/
|
|
106
|
-
declare function isDirectiveKind(kind: string): kind is DirectiveKind;
|
|
107
|
-
//#endregion
|
|
108
|
-
//#region src/directive-name.d.ts
|
|
109
|
-
/**
|
|
110
|
-
* Check if a string is a directive name (heuristic check)
|
|
111
|
-
* Note: This is a broad check that matches any string starting with "use ".
|
|
112
|
-
* For strict validation against known directives, use isDirectiveKind.
|
|
113
|
-
* @param name The string to check
|
|
114
|
-
* @returns True if the string looks like a directive name, false otherwise
|
|
115
|
-
* @see isDirectiveKind
|
|
116
|
-
*/
|
|
117
|
-
declare function isDirectiveName(name: string): boolean;
|
|
118
|
-
//#endregion
|
|
119
3
|
//#region src/expression-is.d.ts
|
|
120
4
|
/**
|
|
121
5
|
* Check if the given expression is a 'this' expression
|
|
@@ -126,122 +10,14 @@ declare function isDirectiveName(name: string): boolean;
|
|
|
126
10
|
*/
|
|
127
11
|
declare function isThisExpressionLoose(node: TSESTree.Expression): boolean;
|
|
128
12
|
//#endregion
|
|
129
|
-
//#region src/
|
|
130
|
-
/**
|
|
131
|
-
* Get all nested identifiers in a expression like node
|
|
132
|
-
* @param node The node to get the nested identifiers from
|
|
133
|
-
* @returns All nested identifiers
|
|
134
|
-
*/
|
|
135
|
-
declare function getNestedIdentifiers(node: TSESTree.Node): readonly TSESTree.Identifier[];
|
|
136
|
-
/**
|
|
137
|
-
* Gets the nested return statements in the node that are within the same function
|
|
138
|
-
* @param node The AST node
|
|
139
|
-
* @returns The nested return statements in the node
|
|
140
|
-
*/
|
|
141
|
-
declare function getNestedReturnStatements(node: TSESTree.Node): readonly TSESTree.ReturnStatement[];
|
|
142
|
-
/**
|
|
143
|
-
* Get all nested expressions of type T in an expression like node
|
|
144
|
-
* @param type The type of the expression to retrieve within the node
|
|
145
|
-
* @returns A partially applied function bound to a predicate of type AST. The returned function can be called passing a
|
|
146
|
-
* node, and it will return an array of all nested expressions of type AST.
|
|
147
|
-
*/
|
|
148
|
-
declare function getNestedExpressionsOfType<TNodeType extends AST_NODE_TYPES>(type: TNodeType): (node: TSESTree.Node) => Extract<TSESTree.Node, {
|
|
149
|
-
type: TNodeType;
|
|
150
|
-
}>[];
|
|
151
|
-
/**
|
|
152
|
-
* Get all nested new expressions in an expression like node
|
|
153
|
-
* @param node The node to get the nested new expressions from
|
|
154
|
-
* @returns All nested new expressions
|
|
155
|
-
*/
|
|
156
|
-
declare const getNestedNewExpressions: (node: TSESTree.Node) => TSESTree.NewExpression[];
|
|
157
|
-
/**
|
|
158
|
-
* Get all nested call expressions in a expression like node
|
|
159
|
-
* @param node The node to get the nested call expressions from
|
|
160
|
-
* @returns All nested call expressions
|
|
161
|
-
*/
|
|
162
|
-
declare const getNestedCallExpressions: (node: TSESTree.Node) => TSESTree.CallExpression[];
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region src/file-directive.d.ts
|
|
165
|
-
/**
|
|
166
|
-
* Get all directive expression statements from the top of a program AST node
|
|
167
|
-
* @param node The program AST node
|
|
168
|
-
* @returns The array of directive string literals (ex: "use strict")
|
|
169
|
-
*/
|
|
170
|
-
declare function getFileDirectives(node: TSESTree.Program): TSESTreeDirective[];
|
|
13
|
+
//#region src/file.d.ts
|
|
171
14
|
/**
|
|
172
15
|
* Check if a directive with the given name exists in the file directives
|
|
173
16
|
* @param node The program AST node
|
|
174
17
|
* @param name The directive name to check (ex: "use strict", "use memo", "use no memo")
|
|
175
18
|
* @returns True if the directive exists, false otherwise
|
|
176
19
|
*/
|
|
177
|
-
declare function
|
|
178
|
-
//#endregion
|
|
179
|
-
//#region src/function-directive.d.ts
|
|
180
|
-
/**
|
|
181
|
-
* Get all directive expression statements from the top of a function AST node
|
|
182
|
-
* @param node The function AST node
|
|
183
|
-
* @returns The array of directive string literals (ex: "use memo", "use no memo")
|
|
184
|
-
*/
|
|
185
|
-
declare function getFunctionDirectives(node: TSESTreeFunction): TSESTreeDirective[];
|
|
186
|
-
/**
|
|
187
|
-
* Check if a directive with the given name exists in the function directives
|
|
188
|
-
* @param node The function AST node
|
|
189
|
-
* @param name The directive name to check (ex: "use memo", "use no memo")
|
|
190
|
-
* @returns True if the directive exists, false otherwise
|
|
191
|
-
*/
|
|
192
|
-
declare function isDirectiveInFunction(node: TSESTreeFunction, name: string): boolean;
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/function-id.d.ts
|
|
195
|
-
/**
|
|
196
|
-
* Gets the static name of a function AST node. For function declarations it is
|
|
197
|
-
* easy. For anonymous function expressions it is much harder. If you search for
|
|
198
|
-
* `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
|
|
199
|
-
* where JS gives anonymous function expressions names. We roughly detect the
|
|
200
|
-
* same AST nodes with some exceptions to better fit our use case.
|
|
201
|
-
*/
|
|
202
|
-
declare function getFunctionId(node: TSESTree.Expression | TSESTreeFunction): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | null;
|
|
203
|
-
/**
|
|
204
|
-
* Type representing the return type of getFunctionId
|
|
205
|
-
*/
|
|
206
|
-
type FunctionID = ReturnType<typeof getFunctionId>;
|
|
207
|
-
//#endregion
|
|
208
|
-
//#region src/function-init-path.d.ts
|
|
209
|
-
/**
|
|
210
|
-
* Represents various AST paths for React component function declarations
|
|
211
|
-
* Each tuple type represents a specific component definition pattern
|
|
212
|
-
*/
|
|
213
|
-
type FunctionInitPath = readonly [TSESTree.FunctionDeclaration] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTreeFunction] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTreeFunction] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTree.CallExpression, TSESTreeFunction] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTreeFunction] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTreeFunction] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTree.CallExpression, TSESTreeFunction] | readonly [TSESTree.ClassDeclaration | TSESTree.ClassExpression, TSESTree.ClassBody, TSESTree.MethodDefinition, TSESTreeFunction] | readonly [TSESTree.ClassDeclaration | TSESTree.ClassExpression, TSESTree.ClassBody, TSESTree.PropertyDefinition, TSESTreeFunction];
|
|
214
|
-
/**
|
|
215
|
-
* Identifies the initialization path of a function node in the ast.
|
|
216
|
-
* Determine what kind of component declaration pattern the function belongs to.
|
|
217
|
-
*
|
|
218
|
-
* @param node The function node to analyze
|
|
219
|
-
* @returns The function initialization path or null if not identifiable
|
|
220
|
-
*/
|
|
221
|
-
declare function getFunctionInitPath(node: TSESTreeFunction): null | FunctionInitPath;
|
|
222
|
-
/**
|
|
223
|
-
* Check if a specific function call exists in the function initialization path.
|
|
224
|
-
* Useful for detecting HOCs like React.memo, React.forwardRef, etc.
|
|
225
|
-
*
|
|
226
|
-
* @param callName The name of the call to check for (ex: "memo", "forwardRef")
|
|
227
|
-
* @param initPath The function initialization path to search in
|
|
228
|
-
* @returns True if the call exists in the path, false otherwise
|
|
229
|
-
*/
|
|
230
|
-
declare function hasCallInFunctionInitPath(callName: string, initPath: FunctionInitPath): boolean;
|
|
231
|
-
//#endregion
|
|
232
|
-
//#region src/function-is.d.ts
|
|
233
|
-
/**
|
|
234
|
-
* Check if a function is empty
|
|
235
|
-
* @param node The function node to check
|
|
236
|
-
* @returns True if the function is empty, false otherwise
|
|
237
|
-
*/
|
|
238
|
-
declare function isFunctionEmpty(node: TSESTreeFunction): boolean;
|
|
239
|
-
/**
|
|
240
|
-
* Check if a function is immediately invoked
|
|
241
|
-
* @param node The function node to check
|
|
242
|
-
* @returns True if the function is immediately invoked, false otherwise
|
|
243
|
-
*/
|
|
244
|
-
declare function isFunctionImmediatelyInvoked(node: TSESTreeFunction): boolean;
|
|
20
|
+
declare function isFileHasDirective(node: TSESTree.Program, name: string): boolean;
|
|
245
21
|
//#endregion
|
|
246
22
|
//#region src/identifier-is.d.ts
|
|
247
23
|
/**
|
|
@@ -252,16 +28,6 @@ declare function isFunctionImmediatelyInvoked(node: TSESTreeFunction): boolean;
|
|
|
252
28
|
*/
|
|
253
29
|
declare function isIdentifier(node: TSESTree.Node | null, name?: string): node is TSESTree.Identifier;
|
|
254
30
|
//#endregion
|
|
255
|
-
//#region src/identifier-name.d.ts
|
|
256
|
-
/**
|
|
257
|
-
* Check if a string is a valid JavaScript identifier name
|
|
258
|
-
* Note: This only checks for ASCII identifiers. Unicode identifiers (e.g., `const 变量 = 1`)
|
|
259
|
-
* are not supported by this simple regex check.
|
|
260
|
-
* @param name The string to check
|
|
261
|
-
* @returns True if the string is a valid ASCII identifier name
|
|
262
|
-
*/
|
|
263
|
-
declare function isIdentifierName(name: string): boolean;
|
|
264
|
-
//#endregion
|
|
265
31
|
//#region src/identifier-traverse.d.ts
|
|
266
32
|
/**
|
|
267
33
|
* Get the root identifier of a (possibly nested) member expression.
|
|
@@ -297,6 +63,40 @@ declare const isNodeEqual: {
|
|
|
297
63
|
(a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
298
64
|
};
|
|
299
65
|
//#endregion
|
|
66
|
+
//#region src/node-types.d.ts
|
|
67
|
+
/**
|
|
68
|
+
* Represents function expressions and declarations in TSESTree
|
|
69
|
+
*/
|
|
70
|
+
type TSESTreeFunction = TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression;
|
|
71
|
+
/**
|
|
72
|
+
* Represents class declarations and expressions in TSESTree
|
|
73
|
+
*/
|
|
74
|
+
type TSESTreeClass = TSESTree.ClassDeclaration | TSESTree.ClassExpression;
|
|
75
|
+
/**
|
|
76
|
+
* Represents method definitions and property definitions in classes
|
|
77
|
+
*/
|
|
78
|
+
type TSESTreeMethodOrProperty = TSESTree.PropertyDefinition | TSESTree.MethodDefinition;
|
|
79
|
+
/**
|
|
80
|
+
* Represents all JSX-related nodes in TSESTree
|
|
81
|
+
* Note: This type is for type-level operations. The isJSX() runtime guard in node-is.ts
|
|
82
|
+
* has a slightly different set of nodes as it includes JSXExpressionContainer which is
|
|
83
|
+
* commonly needed for runtime checks but not included in this type union.
|
|
84
|
+
*/
|
|
85
|
+
type TSESTreeJSX = TSESTree.JSXAttribute | TSESTree.JSXChild | TSESTree.JSXClosingElement | TSESTree.JSXClosingFragment | TSESTree.JSXEmptyExpression | TSESTree.JSXIdentifierToken | TSESTree.JSXOpeningElement | TSESTree.JSXOpeningFragment | TSESTree.JSXSpreadAttribute | TSESTree.JSXTagNameExpression | TSESTree.JSXTextToken;
|
|
86
|
+
type TSESTreeJSXElementLike = TSESTree.JSXElement | TSESTree.JSXFragment;
|
|
87
|
+
/**
|
|
88
|
+
* Represents JSX attribute-like nodes (attributes and spread attributes)
|
|
89
|
+
*/
|
|
90
|
+
type TSESTreeJSXAttributeLike = TSESTree.JSXAttribute | TSESTree.JSXSpreadAttribute;
|
|
91
|
+
/**
|
|
92
|
+
* Represents a directive expression statement in TSESTree (ex: "use strict";)
|
|
93
|
+
*/
|
|
94
|
+
type TSESTreeDirective = TSESTree.ExpressionStatement & {
|
|
95
|
+
directive: string;
|
|
96
|
+
expression: TSESTree.StringLiteral;
|
|
97
|
+
};
|
|
98
|
+
type TSESTreeTypeExpression = TSESTree.TSAsExpression | TSESTree.TSTypeAssertion | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSInstantiationExpression;
|
|
99
|
+
//#endregion
|
|
300
100
|
//#region src/node-is.d.ts
|
|
301
101
|
/**
|
|
302
102
|
* Type guard to check if a node is of a specific AST node type
|
|
@@ -320,12 +120,6 @@ declare const isOneOf: <NodeTypes extends readonly TSESTree.AST_NODE_TYPES[]>(no
|
|
|
320
120
|
* @returns True if the node is a function
|
|
321
121
|
*/
|
|
322
122
|
declare const isFunction: (node: TSESTree.Node | null | undefined) => node is TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.FunctionExpression;
|
|
323
|
-
/**
|
|
324
|
-
* Check if a node is a function type (including TypeScript function types)
|
|
325
|
-
* @param node The node to check
|
|
326
|
-
* @returns True if the node is a function type
|
|
327
|
-
*/
|
|
328
|
-
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;
|
|
329
123
|
/**
|
|
330
124
|
* Check if a node is a class declaration or expression
|
|
331
125
|
* @param node The node to check
|
|
@@ -350,16 +144,10 @@ declare const isProperty: (node: TSESTree.Node | null | undefined) => node is TS
|
|
|
350
144
|
* @returns True if the node is a JSX element
|
|
351
145
|
*/
|
|
352
146
|
declare const isJSXElement: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXElement;
|
|
353
|
-
/**
|
|
354
|
-
* Check if a node is a JSX fragment
|
|
355
|
-
* @param node The node to check
|
|
356
|
-
* @returns True if the node is a JSX fragment
|
|
357
|
-
*/
|
|
358
|
-
declare const isJSXFragment: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXFragment;
|
|
359
147
|
/**
|
|
360
148
|
* Check if a node is a JSX element or JSX fragment
|
|
361
149
|
*/
|
|
362
|
-
declare const isJSXElementLike: (
|
|
150
|
+
declare const isJSXElementLike: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXElement | TSESTree.JSXFragment;
|
|
363
151
|
/**
|
|
364
152
|
* Check if a node is a JSX tag name expression (identifier, member expression, or namespaced name)
|
|
365
153
|
* @param node The node to check
|
|
@@ -375,24 +163,6 @@ declare const isJSXTagNameExpression: (node: TSESTree.Node | null | undefined) =
|
|
|
375
163
|
* @see TSESTreeJSX
|
|
376
164
|
*/
|
|
377
165
|
declare const isJSX: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXAttribute | TSESTree.JSXClosingElement | TSESTree.JSXClosingFragment | TSESTree.JSXElement | TSESTree.JSXEmptyExpression | TSESTree.JSXExpressionContainer | TSESTree.JSXFragment | TSESTree.JSXIdentifier | TSESTree.JSXMemberExpression | TSESTree.JSXNamespacedName | TSESTree.JSXOpeningElement | TSESTree.JSXOpeningFragment | TSESTree.JSXSpreadAttribute | TSESTree.JSXSpreadChild | TSESTree.JSXText;
|
|
378
|
-
/**
|
|
379
|
-
* Check if a node is a loop statement
|
|
380
|
-
* @param node The node to check
|
|
381
|
-
* @returns True if the node is a loop
|
|
382
|
-
*/
|
|
383
|
-
declare const isLoop: (node: TSESTree.Node | null | undefined) => node is TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.WhileStatement;
|
|
384
|
-
/**
|
|
385
|
-
* Check if a node is a control flow statement (loop, if, or switch)
|
|
386
|
-
* @param node The node to check
|
|
387
|
-
* @returns True if the node is a control flow statement
|
|
388
|
-
*/
|
|
389
|
-
declare const isControlFlow: (data: TSESTree.Node | null | undefined) => data is TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.IfStatement | TSESTree.SwitchStatement | TSESTree.WhileStatement;
|
|
390
|
-
/**
|
|
391
|
-
* Check if a node is a conditional expression or control flow statement
|
|
392
|
-
* @param node The node to check
|
|
393
|
-
* @returns True if the node is conditional
|
|
394
|
-
*/
|
|
395
|
-
declare const isConditional: (data: TSESTree.Node | null | undefined) => data is TSESTree.ConditionalExpression | TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.IfStatement | TSESTree.LogicalExpression | TSESTree.SwitchStatement | TSESTree.WhileStatement;
|
|
396
166
|
/**
|
|
397
167
|
* Check if a node is a TypeScript type expression
|
|
398
168
|
* @param node The node to check
|
|
@@ -405,24 +175,20 @@ declare const isTypeExpression: (node: TSESTree.Node | null | undefined) => node
|
|
|
405
175
|
* @returns True if the node is a type assertion expression
|
|
406
176
|
*/
|
|
407
177
|
declare const isTypeAssertionExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
178
|
+
/**
|
|
179
|
+
* Check if a node is a directive expression statement
|
|
180
|
+
* @param node The node to check
|
|
181
|
+
* @returns True if the node is a directive, false otherwise
|
|
182
|
+
*/
|
|
183
|
+
declare function isDirective(node: TSESTree.Node): node is TSESTreeDirective;
|
|
408
184
|
//#endregion
|
|
409
185
|
//#region src/node-kind.d.ts
|
|
410
186
|
declare function getHumanReadableKind(node: TSESTree.Node, delimiter?: string): "RegExp literal" | Lowercase<string> | `JSX ${Lowercase<string>}`;
|
|
411
187
|
//#endregion
|
|
412
|
-
//#region src/node-line.d.ts
|
|
413
|
-
declare function isMultiLine(node: TSESTree.Node): boolean;
|
|
414
|
-
declare function isLineBreak(node: TSESTree.Node): boolean;
|
|
415
|
-
//#endregion
|
|
416
188
|
//#region src/node-name.d.ts
|
|
417
189
|
declare function getFullyQualifiedName(node: TSESTree.Node, getText: (node: TSESTree.Node) => string): string;
|
|
418
190
|
//#endregion
|
|
419
191
|
//#region src/node-selectors.d.ts
|
|
420
|
-
/**
|
|
421
|
-
* Represents an arrow function expression with an implicit return
|
|
422
|
-
*/
|
|
423
|
-
type ImplicitReturnArrowFunctionExpression = TSESTree.ArrowFunctionExpression & {
|
|
424
|
-
body: TSESTree.Expression;
|
|
425
|
-
};
|
|
426
192
|
/**
|
|
427
193
|
* Represents a variable declarator with object destructuring and an identifier initializer
|
|
428
194
|
*/
|
|
@@ -442,10 +208,6 @@ type DisplayNameAssignmentExpression = TSESTree.AssignmentExpression & {
|
|
|
442
208
|
operator: "=";
|
|
443
209
|
right: TSESTree.Literal;
|
|
444
210
|
};
|
|
445
|
-
/**
|
|
446
|
-
* Selector for arrow function expressions with implicit return
|
|
447
|
-
*/
|
|
448
|
-
declare const SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION = "ArrowFunctionExpression[body.type!='BlockStatement']";
|
|
449
211
|
/**
|
|
450
212
|
* Selector for variable declarators with object destructuring
|
|
451
213
|
*/
|
|
@@ -480,26 +242,6 @@ declare function findParent(node: TSESTree.Node | null, test: (node: TSESTree.No
|
|
|
480
242
|
*/
|
|
481
243
|
declare function getUnderlyingExpression(node: TSESTree.Node): Exclude<TSESTree.Node, TSESTreeTypeExpression>;
|
|
482
244
|
//#endregion
|
|
483
|
-
//#region src/pattern-process-env-node-env.d.ts
|
|
484
|
-
/**
|
|
485
|
-
* Check if the given node is a member expression that accesses `process.env.NODE_ENV`
|
|
486
|
-
* @param node The AST node
|
|
487
|
-
* @returns True if the node is a member expression that accesses `process.env.NODE_ENV`, false otherwise
|
|
488
|
-
*/
|
|
489
|
-
declare function isProcessEnvNodeEnv(node: TSESTree.Node | null): node is TSESTree.MemberExpression;
|
|
490
|
-
/**
|
|
491
|
-
* Check if the given node is a binary expression that compares `process.env.NODE_ENV` with a string literal.
|
|
492
|
-
* @param node The AST node
|
|
493
|
-
* @param operator The operator used in the comparison
|
|
494
|
-
* @param value The string literal value to compare against
|
|
495
|
-
* @returns True if the node is a binary expression that compares `process.env.NODE_ENV` with the specified value, false otherwise
|
|
496
|
-
*/
|
|
497
|
-
declare function isProcessEnvNodeEnvCompare(node: TSESTree.Node | null, operator: "===" | "!==", value: "development" | "production"): node is TSESTree.BinaryExpression;
|
|
498
|
-
//#endregion
|
|
499
|
-
//#region src/pattern-test-mock.d.ts
|
|
500
|
-
declare function isTestMock(node: TSESTree.Node | null): node is TSESTree.MemberExpression;
|
|
501
|
-
declare function isTestMockCallback(node: TSESTree.Node | null): boolean;
|
|
502
|
-
//#endregion
|
|
503
245
|
//#region src/property-name.d.ts
|
|
504
246
|
/**
|
|
505
247
|
* Get the name of a property from a node
|
|
@@ -520,4 +262,4 @@ declare function getPropertyName(node: TSESTree.Node): string | null;
|
|
|
520
262
|
*/
|
|
521
263
|
declare function findProperty(properties: TSESTree.ObjectLiteralElement[], name: string): TSESTree.Property | null;
|
|
522
264
|
//#endregion
|
|
523
|
-
export {
|
|
265
|
+
export { DisplayNameAssignmentExpression, ObjectDestructuringVariableDeclarator, SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, TSESTreeClass, TSESTreeDirective, TSESTreeFunction, TSESTreeJSX, TSESTreeJSXAttributeLike, TSESTreeJSXElementLike, TSESTreeMethodOrProperty, TSESTreeTypeExpression, findParent, findProperty, getFullyQualifiedName, getHumanReadableKind, getPropertyName, getRootIdentifier, getUnderlyingExpression, is, isClass, isDirective, isFileHasDirective, isFunction, isIdentifier, isJSX, isJSXElement, isJSXElementLike, isJSXTagNameExpression, isLiteral, isMethodOrProperty, isNodeEqual, isOneOf, isProperty, isThisExpressionLoose, isTypeAssertionExpression, isTypeExpression };
|
package/dist/index.js
CHANGED
|
@@ -1,200 +1,7 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
|
|
2
2
|
import { ASTUtils } from "@typescript-eslint/utils";
|
|
3
|
-
import { simpleTraverse } from "@typescript-eslint/typescript-estree";
|
|
4
3
|
import { delimiterCase, replace, toLowerCase } from "string-ts";
|
|
5
4
|
|
|
6
|
-
//#region src/class-id.ts
|
|
7
|
-
/**
|
|
8
|
-
* Get the class identifier of a class node
|
|
9
|
-
* @param node The class node to get the identifier from
|
|
10
|
-
* @returns The class identifier or null if not found
|
|
11
|
-
*/
|
|
12
|
-
function getClassId(node) {
|
|
13
|
-
if (node.id != null) return node.id;
|
|
14
|
-
if (node.parent.type === AST_NODE_TYPES.VariableDeclarator) return node.parent.id;
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/directive-name.ts
|
|
20
|
-
/**
|
|
21
|
-
* Check if a string is a directive name (heuristic check)
|
|
22
|
-
* Note: This is a broad check that matches any string starting with "use ".
|
|
23
|
-
* For strict validation against known directives, use isDirectiveKind.
|
|
24
|
-
* @param name The string to check
|
|
25
|
-
* @returns True if the string looks like a directive name, false otherwise
|
|
26
|
-
* @see isDirectiveKind
|
|
27
|
-
*/
|
|
28
|
-
function isDirectiveName(name) {
|
|
29
|
-
return name.startsWith("use ") && name.length > 4;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/literal-is.ts
|
|
34
|
-
function isLiteral(node, type) {
|
|
35
|
-
if (node.type !== AST_NODE_TYPES.Literal) return false;
|
|
36
|
-
if (type == null) return true;
|
|
37
|
-
switch (type) {
|
|
38
|
-
case "boolean": return typeof node.value === "boolean";
|
|
39
|
-
case "null": return node.value === null;
|
|
40
|
-
case "number": return typeof node.value === "number";
|
|
41
|
-
case "regexp": return "regex" in node;
|
|
42
|
-
case "string": return typeof node.value === "string";
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region src/directive-is.ts
|
|
48
|
-
/**
|
|
49
|
-
* Check if a node is a directive expression statement
|
|
50
|
-
* @param node The node to check
|
|
51
|
-
* @returns True if the node is a directive, false otherwise
|
|
52
|
-
*/
|
|
53
|
-
function isDirective(node) {
|
|
54
|
-
return node.type === AST_NODE_TYPES.ExpressionStatement && node.directive != null;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Check if a node is a directive-like expression statement
|
|
58
|
-
* @param node The node to check
|
|
59
|
-
* @returns True if the node is a directive, false otherwise
|
|
60
|
-
*/
|
|
61
|
-
function isDirectiveLike(node) {
|
|
62
|
-
return node.type === AST_NODE_TYPES.ExpressionStatement && isLiteral(node.expression, "string") && isDirectiveName(node.expression.value);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
//#endregion
|
|
66
|
-
//#region src/directive-kind.ts
|
|
67
|
-
/**
|
|
68
|
-
* Check if a node is a directive kind
|
|
69
|
-
* @param kind The kind to check
|
|
70
|
-
* @returns True if the kind is a directive kind, false otherwise
|
|
71
|
-
*/
|
|
72
|
-
function isDirectiveKind(kind) {
|
|
73
|
-
return kind === "use client" || kind === "use server" || kind === "use memo" || kind === "use no memo";
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
//#endregion
|
|
77
|
-
//#region ../../../.pkgs/eff/dist/index.js
|
|
78
|
-
function or(a, b) {
|
|
79
|
-
return (data) => a(data) || b(data);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Creates a function that can be used in a data-last (aka `pipe`able) or
|
|
83
|
-
* data-first style.
|
|
84
|
-
*
|
|
85
|
-
* The first parameter to `dual` is either the arity of the uncurried function
|
|
86
|
-
* or a predicate that determines if the function is being used in a data-first
|
|
87
|
-
* or data-last style.
|
|
88
|
-
*
|
|
89
|
-
* Using the arity is the most common use case, but there are some cases where
|
|
90
|
-
* you may want to use a predicate. For example, if you have a function that
|
|
91
|
-
* takes an optional argument, you can use a predicate to determine if the
|
|
92
|
-
* function is being used in a data-first or data-last style.
|
|
93
|
-
*
|
|
94
|
-
* You can pass either the arity of the uncurried function or a predicate
|
|
95
|
-
* which determines if the function is being used in a data-first or
|
|
96
|
-
* data-last style.
|
|
97
|
-
*
|
|
98
|
-
* **Example** (Using arity to determine data-first or data-last style)
|
|
99
|
-
*
|
|
100
|
-
* ```ts
|
|
101
|
-
* import { dual, pipe } from "effect/Function"
|
|
102
|
-
*
|
|
103
|
-
* const sum = dual<
|
|
104
|
-
* (that: number) => (self: number) => number,
|
|
105
|
-
* (self: number, that: number) => number
|
|
106
|
-
* >(2, (self, that) => self + that)
|
|
107
|
-
*
|
|
108
|
-
* console.log(sum(2, 3)) // 5
|
|
109
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
110
|
-
* ```
|
|
111
|
-
*
|
|
112
|
-
* **Example** (Using call signatures to define the overloads)
|
|
113
|
-
*
|
|
114
|
-
* ```ts
|
|
115
|
-
* import { dual, pipe } from "effect/Function"
|
|
116
|
-
*
|
|
117
|
-
* const sum: {
|
|
118
|
-
* (that: number): (self: number) => number
|
|
119
|
-
* (self: number, that: number): number
|
|
120
|
-
* } = dual(2, (self: number, that: number): number => self + that)
|
|
121
|
-
*
|
|
122
|
-
* console.log(sum(2, 3)) // 5
|
|
123
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
124
|
-
* ```
|
|
125
|
-
*
|
|
126
|
-
* **Example** (Using a predicate to determine data-first or data-last style)
|
|
127
|
-
*
|
|
128
|
-
* ```ts
|
|
129
|
-
* import { dual, pipe } from "effect/Function"
|
|
130
|
-
*
|
|
131
|
-
* const sum = dual<
|
|
132
|
-
* (that: number) => (self: number) => number,
|
|
133
|
-
* (self: number, that: number) => number
|
|
134
|
-
* >(
|
|
135
|
-
* (args) => args.length === 2,
|
|
136
|
-
* (self, that) => self + that
|
|
137
|
-
* )
|
|
138
|
-
*
|
|
139
|
-
* console.log(sum(2, 3)) // 5
|
|
140
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
141
|
-
* ```
|
|
142
|
-
*
|
|
143
|
-
* @param arity - The arity of the uncurried function or a predicate that determines if the function is being used in a data-first or data-last style.
|
|
144
|
-
* @param body - The function to be curried.
|
|
145
|
-
* @since 1.0.0
|
|
146
|
-
*/
|
|
147
|
-
const dual = function(arity, body) {
|
|
148
|
-
if (typeof arity === "function") return function() {
|
|
149
|
-
return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
|
|
150
|
-
};
|
|
151
|
-
switch (arity) {
|
|
152
|
-
case 0:
|
|
153
|
-
case 1: throw new RangeError(`Invalid arity ${arity}`);
|
|
154
|
-
case 2: return function(a, b) {
|
|
155
|
-
if (arguments.length >= 2) return body(a, b);
|
|
156
|
-
return function(self) {
|
|
157
|
-
return body(self, a);
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
|
-
case 3: return function(a, b, c) {
|
|
161
|
-
if (arguments.length >= 3) return body(a, b, c);
|
|
162
|
-
return function(self) {
|
|
163
|
-
return body(self, a, b);
|
|
164
|
-
};
|
|
165
|
-
};
|
|
166
|
-
default: return function() {
|
|
167
|
-
if (arguments.length >= arity) return body.apply(this, arguments);
|
|
168
|
-
const args = arguments;
|
|
169
|
-
return function(self) {
|
|
170
|
-
return body(self, ...args);
|
|
171
|
-
};
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
/**
|
|
176
|
-
* Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
|
|
177
|
-
* The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
|
|
178
|
-
*
|
|
179
|
-
* @param self - The first function to apply (or the composed function in data-last style).
|
|
180
|
-
* @param bc - The second function to apply.
|
|
181
|
-
* @returns A composed function that applies both functions in sequence.
|
|
182
|
-
* @example
|
|
183
|
-
* ```ts
|
|
184
|
-
* import * as assert from "node:assert"
|
|
185
|
-
* import { compose } from "effect/Function"
|
|
186
|
-
*
|
|
187
|
-
* const increment = (n: number) => n + 1;
|
|
188
|
-
* const square = (n: number) => n * n;
|
|
189
|
-
*
|
|
190
|
-
* assert.strictEqual(compose(increment, square)(2), 9);
|
|
191
|
-
* ```
|
|
192
|
-
*
|
|
193
|
-
* @since 1.0.0
|
|
194
|
-
*/
|
|
195
|
-
const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
|
|
196
|
-
|
|
197
|
-
//#endregion
|
|
198
5
|
//#region src/node-is.ts
|
|
199
6
|
/**
|
|
200
7
|
* Type guard to check if a node is of a specific AST node type
|
|
@@ -219,22 +26,6 @@ const isFunction = isOneOf([
|
|
|
219
26
|
AST_NODE_TYPES.FunctionExpression
|
|
220
27
|
]);
|
|
221
28
|
/**
|
|
222
|
-
* Check if a node is a function type (including TypeScript function types)
|
|
223
|
-
* @param node The node to check
|
|
224
|
-
* @returns True if the node is a function type
|
|
225
|
-
*/
|
|
226
|
-
const isFunctionType = isOneOf([
|
|
227
|
-
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
228
|
-
AST_NODE_TYPES.FunctionDeclaration,
|
|
229
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
230
|
-
AST_NODE_TYPES.TSCallSignatureDeclaration,
|
|
231
|
-
AST_NODE_TYPES.TSConstructSignatureDeclaration,
|
|
232
|
-
AST_NODE_TYPES.TSDeclareFunction,
|
|
233
|
-
AST_NODE_TYPES.TSEmptyBodyFunctionExpression,
|
|
234
|
-
AST_NODE_TYPES.TSFunctionType,
|
|
235
|
-
AST_NODE_TYPES.TSMethodSignature
|
|
236
|
-
]);
|
|
237
|
-
/**
|
|
238
29
|
* Check if a node is a class declaration or expression
|
|
239
30
|
* @param node The node to check
|
|
240
31
|
* @returns True if the node is a class
|
|
@@ -264,15 +55,9 @@ const isProperty = isOneOf([
|
|
|
264
55
|
*/
|
|
265
56
|
const isJSXElement = is(AST_NODE_TYPES.JSXElement);
|
|
266
57
|
/**
|
|
267
|
-
* Check if a node is a JSX fragment
|
|
268
|
-
* @param node The node to check
|
|
269
|
-
* @returns True if the node is a JSX fragment
|
|
270
|
-
*/
|
|
271
|
-
const isJSXFragment = is(AST_NODE_TYPES.JSXFragment);
|
|
272
|
-
/**
|
|
273
58
|
* Check if a node is a JSX element or JSX fragment
|
|
274
59
|
*/
|
|
275
|
-
const isJSXElementLike =
|
|
60
|
+
const isJSXElementLike = isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment]);
|
|
276
61
|
/**
|
|
277
62
|
* Check if a node is a JSX tag name expression (identifier, member expression, or namespaced name)
|
|
278
63
|
* @param node The node to check
|
|
@@ -309,30 +94,6 @@ const isJSX = isOneOf([
|
|
|
309
94
|
AST_NODE_TYPES.JSXText
|
|
310
95
|
]);
|
|
311
96
|
/**
|
|
312
|
-
* Check if a node is a loop statement
|
|
313
|
-
* @param node The node to check
|
|
314
|
-
* @returns True if the node is a loop
|
|
315
|
-
*/
|
|
316
|
-
const isLoop = isOneOf([
|
|
317
|
-
AST_NODE_TYPES.DoWhileStatement,
|
|
318
|
-
AST_NODE_TYPES.ForInStatement,
|
|
319
|
-
AST_NODE_TYPES.ForOfStatement,
|
|
320
|
-
AST_NODE_TYPES.ForStatement,
|
|
321
|
-
AST_NODE_TYPES.WhileStatement
|
|
322
|
-
]);
|
|
323
|
-
/**
|
|
324
|
-
* Check if a node is a control flow statement (loop, if, or switch)
|
|
325
|
-
* @param node The node to check
|
|
326
|
-
* @returns True if the node is a control flow statement
|
|
327
|
-
*/
|
|
328
|
-
const isControlFlow = or(isLoop, isOneOf([AST_NODE_TYPES.IfStatement, AST_NODE_TYPES.SwitchStatement]));
|
|
329
|
-
/**
|
|
330
|
-
* Check if a node is a conditional expression or control flow statement
|
|
331
|
-
* @param node The node to check
|
|
332
|
-
* @returns True if the node is conditional
|
|
333
|
-
*/
|
|
334
|
-
const isConditional = or(isControlFlow, isOneOf([AST_NODE_TYPES.LogicalExpression, AST_NODE_TYPES.ConditionalExpression]));
|
|
335
|
-
/**
|
|
336
97
|
* Check if a node is a TypeScript type expression
|
|
337
98
|
* @param node The node to check
|
|
338
99
|
* @returns True if the node is a type expression
|
|
@@ -355,6 +116,14 @@ const isTypeAssertionExpression = isOneOf([
|
|
|
355
116
|
AST_NODE_TYPES.TSNonNullExpression,
|
|
356
117
|
AST_NODE_TYPES.TSSatisfiesExpression
|
|
357
118
|
]);
|
|
119
|
+
/**
|
|
120
|
+
* Check if a node is a directive expression statement
|
|
121
|
+
* @param node The node to check
|
|
122
|
+
* @returns True if the node is a directive, false otherwise
|
|
123
|
+
*/
|
|
124
|
+
function isDirective(node) {
|
|
125
|
+
return node.type === AST_NODE_TYPES.ExpressionStatement && node.directive != null;
|
|
126
|
+
}
|
|
358
127
|
|
|
359
128
|
//#endregion
|
|
360
129
|
//#region src/node-unwrap.ts
|
|
@@ -383,372 +152,16 @@ function isThisExpressionLoose(node) {
|
|
|
383
152
|
}
|
|
384
153
|
|
|
385
154
|
//#endregion
|
|
386
|
-
//#region src/
|
|
387
|
-
function findParent(node, test) {
|
|
388
|
-
if (node == null) return null;
|
|
389
|
-
let parent = node.parent;
|
|
390
|
-
while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
|
|
391
|
-
if (test(parent)) return parent;
|
|
392
|
-
parent = parent.parent;
|
|
393
|
-
}
|
|
394
|
-
return null;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
//#endregion
|
|
398
|
-
//#region src/expression-nested.ts
|
|
399
|
-
/**
|
|
400
|
-
* Get all nested identifiers in a expression like node
|
|
401
|
-
* @param node The node to get the nested identifiers from
|
|
402
|
-
* @returns All nested identifiers
|
|
403
|
-
*/
|
|
404
|
-
function getNestedIdentifiers(node) {
|
|
405
|
-
const identifiers = [];
|
|
406
|
-
if (node.type === AST_NODE_TYPES.Identifier) identifiers.push(node);
|
|
407
|
-
if ("arguments" in node) {
|
|
408
|
-
const chunk = node.arguments.flatMap(getNestedIdentifiers);
|
|
409
|
-
identifiers.push(...chunk);
|
|
410
|
-
}
|
|
411
|
-
if ("elements" in node) {
|
|
412
|
-
const chunk = node.elements.filter((x) => x != null).flatMap(getNestedIdentifiers);
|
|
413
|
-
identifiers.push(...chunk);
|
|
414
|
-
}
|
|
415
|
-
if ("properties" in node) {
|
|
416
|
-
const chunk = node.properties.flatMap(getNestedIdentifiers);
|
|
417
|
-
identifiers.push(...chunk);
|
|
418
|
-
}
|
|
419
|
-
if ("expressions" in node) {
|
|
420
|
-
const chunk = node.expressions.flatMap(getNestedIdentifiers);
|
|
421
|
-
identifiers.push(...chunk);
|
|
422
|
-
}
|
|
423
|
-
if ("left" in node) {
|
|
424
|
-
const chunk = getNestedIdentifiers(node.left);
|
|
425
|
-
identifiers.push(...chunk);
|
|
426
|
-
}
|
|
427
|
-
if ("right" in node) {
|
|
428
|
-
const chunk = getNestedIdentifiers(node.right);
|
|
429
|
-
identifiers.push(...chunk);
|
|
430
|
-
}
|
|
431
|
-
if (node.type === AST_NODE_TYPES.Property) {
|
|
432
|
-
const chunk = getNestedIdentifiers(node.value);
|
|
433
|
-
identifiers.push(...chunk);
|
|
434
|
-
}
|
|
435
|
-
if (node.type === AST_NODE_TYPES.SpreadElement) {
|
|
436
|
-
const chunk = getNestedIdentifiers(node.argument);
|
|
437
|
-
identifiers.push(...chunk);
|
|
438
|
-
}
|
|
439
|
-
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
440
|
-
identifiers.push(...getNestedIdentifiers(node.object));
|
|
441
|
-
if (node.computed) identifiers.push(...getNestedIdentifiers(node.property));
|
|
442
|
-
}
|
|
443
|
-
if (node.type === AST_NODE_TYPES.UnaryExpression) {
|
|
444
|
-
const chunk = getNestedIdentifiers(node.argument);
|
|
445
|
-
identifiers.push(...chunk);
|
|
446
|
-
}
|
|
447
|
-
if (node.type === AST_NODE_TYPES.ChainExpression) {
|
|
448
|
-
const chunk = getNestedIdentifiers(node.expression);
|
|
449
|
-
identifiers.push(...chunk);
|
|
450
|
-
}
|
|
451
|
-
if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
|
|
452
|
-
const chunk = getNestedIdentifiers(node.expression);
|
|
453
|
-
identifiers.push(...chunk);
|
|
454
|
-
}
|
|
455
|
-
if (node.type === AST_NODE_TYPES.TSAsExpression) {
|
|
456
|
-
const chunk = getNestedIdentifiers(node.expression);
|
|
457
|
-
identifiers.push(...chunk);
|
|
458
|
-
}
|
|
459
|
-
if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
|
|
460
|
-
const chunk = getNestedIdentifiers(node.expression);
|
|
461
|
-
identifiers.push(...chunk);
|
|
462
|
-
}
|
|
463
|
-
if (node.type === AST_NODE_TYPES.ConditionalExpression) {
|
|
464
|
-
identifiers.push(...getNestedIdentifiers(node.test));
|
|
465
|
-
identifiers.push(...getNestedIdentifiers(node.consequent));
|
|
466
|
-
identifiers.push(...getNestedIdentifiers(node.alternate));
|
|
467
|
-
}
|
|
468
|
-
if (node.type === AST_NODE_TYPES.AwaitExpression) identifiers.push(...getNestedIdentifiers(node.argument));
|
|
469
|
-
if (node.type === AST_NODE_TYPES.YieldExpression && node.argument != null) identifiers.push(...getNestedIdentifiers(node.argument));
|
|
470
|
-
if (node.type === AST_NODE_TYPES.UpdateExpression) identifiers.push(...getNestedIdentifiers(node.argument));
|
|
471
|
-
if (node.type === AST_NODE_TYPES.CallExpression || node.type === AST_NODE_TYPES.NewExpression) identifiers.push(...getNestedIdentifiers(node.callee));
|
|
472
|
-
if (node.type === AST_NODE_TYPES.TaggedTemplateExpression) {
|
|
473
|
-
identifiers.push(...getNestedIdentifiers(node.tag));
|
|
474
|
-
identifiers.push(...getNestedIdentifiers(node.quasi));
|
|
475
|
-
}
|
|
476
|
-
if (node.type === AST_NODE_TYPES.ImportExpression) identifiers.push(...getNestedIdentifiers(node.source));
|
|
477
|
-
if (node.type === AST_NODE_TYPES.TSTypeAssertion) identifiers.push(...getNestedIdentifiers(node.expression));
|
|
478
|
-
if (node.type === AST_NODE_TYPES.TSInstantiationExpression) identifiers.push(...getNestedIdentifiers(node.expression));
|
|
479
|
-
return identifiers;
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Gets the nested return statements in the node that are within the same function
|
|
483
|
-
* @param node The AST node
|
|
484
|
-
* @returns The nested return statements in the node
|
|
485
|
-
*/
|
|
486
|
-
function getNestedReturnStatements(node) {
|
|
487
|
-
const statements = [];
|
|
488
|
-
const boundaryNode = isFunction(node) ? node : findParent(node, isFunction);
|
|
489
|
-
simpleTraverse(node, { enter(node) {
|
|
490
|
-
if (node.type !== AST_NODE_TYPES.ReturnStatement) return;
|
|
491
|
-
if (findParent(node, isFunction) !== boundaryNode) return;
|
|
492
|
-
statements.push(node);
|
|
493
|
-
} });
|
|
494
|
-
return statements;
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Get all nested expressions of type T in an expression like node
|
|
498
|
-
* @param type The type of the expression to retrieve within the node
|
|
499
|
-
* @returns A partially applied function bound to a predicate of type AST. The returned function can be called passing a
|
|
500
|
-
* node, and it will return an array of all nested expressions of type AST.
|
|
501
|
-
*/
|
|
502
|
-
function getNestedExpressionsOfType(type) {
|
|
503
|
-
const isNodeOfType = is(type);
|
|
504
|
-
const recurse = (node) => {
|
|
505
|
-
const expressions = [];
|
|
506
|
-
if (isNodeOfType(node)) expressions.push(node);
|
|
507
|
-
if ("arguments" in node) {
|
|
508
|
-
const chunk = node.arguments.flatMap(recurse);
|
|
509
|
-
expressions.push(...chunk);
|
|
510
|
-
}
|
|
511
|
-
if ("expression" in node && node.expression !== true && node.expression !== false) {
|
|
512
|
-
const chunk = recurse(node.expression);
|
|
513
|
-
expressions.push(...chunk);
|
|
514
|
-
}
|
|
515
|
-
if ("left" in node) {
|
|
516
|
-
const chunk = recurse(node.left);
|
|
517
|
-
expressions.push(...chunk);
|
|
518
|
-
}
|
|
519
|
-
if ("right" in node) {
|
|
520
|
-
const chunk = recurse(node.right);
|
|
521
|
-
expressions.push(...chunk);
|
|
522
|
-
}
|
|
523
|
-
if ("test" in node && node.test != null) {
|
|
524
|
-
const chunk = recurse(node.test);
|
|
525
|
-
expressions.push(...chunk);
|
|
526
|
-
}
|
|
527
|
-
if ("consequent" in node) {
|
|
528
|
-
const chunk = Array.isArray(node.consequent) ? node.consequent.flatMap(recurse) : recurse(node.consequent);
|
|
529
|
-
expressions.push(...chunk);
|
|
530
|
-
}
|
|
531
|
-
if ("alternate" in node && node.alternate != null) {
|
|
532
|
-
const chunk = Array.isArray(node.alternate) ? node.alternate.flatMap(recurse) : recurse(node.alternate);
|
|
533
|
-
expressions.push(...chunk);
|
|
534
|
-
}
|
|
535
|
-
if ("elements" in node) {
|
|
536
|
-
const chunk = node.elements.filter((x) => x != null).flatMap(recurse);
|
|
537
|
-
expressions.push(...chunk);
|
|
538
|
-
}
|
|
539
|
-
if ("properties" in node) {
|
|
540
|
-
const chunk = node.properties.flatMap(recurse);
|
|
541
|
-
expressions.push(...chunk);
|
|
542
|
-
}
|
|
543
|
-
if ("expressions" in node) {
|
|
544
|
-
const chunk = node.expressions.flatMap(recurse);
|
|
545
|
-
expressions.push(...chunk);
|
|
546
|
-
}
|
|
547
|
-
if (node.type === AST_NODE_TYPES.Property) {
|
|
548
|
-
const chunk = recurse(node.value);
|
|
549
|
-
expressions.push(...chunk);
|
|
550
|
-
}
|
|
551
|
-
if (node.type === AST_NODE_TYPES.SpreadElement) {
|
|
552
|
-
const chunk = recurse(node.argument);
|
|
553
|
-
expressions.push(...chunk);
|
|
554
|
-
}
|
|
555
|
-
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
556
|
-
expressions.push(...recurse(node.object));
|
|
557
|
-
if (node.computed) expressions.push(...recurse(node.property));
|
|
558
|
-
}
|
|
559
|
-
if (node.type === AST_NODE_TYPES.UnaryExpression) {
|
|
560
|
-
const chunk = recurse(node.argument);
|
|
561
|
-
expressions.push(...chunk);
|
|
562
|
-
}
|
|
563
|
-
if (node.type === AST_NODE_TYPES.AwaitExpression) expressions.push(...recurse(node.argument));
|
|
564
|
-
if (node.type === AST_NODE_TYPES.YieldExpression && node.argument != null) expressions.push(...recurse(node.argument));
|
|
565
|
-
if (node.type === AST_NODE_TYPES.UpdateExpression) expressions.push(...recurse(node.argument));
|
|
566
|
-
if (node.type === AST_NODE_TYPES.CallExpression || node.type === AST_NODE_TYPES.NewExpression) expressions.push(...recurse(node.callee));
|
|
567
|
-
if (node.type === AST_NODE_TYPES.TaggedTemplateExpression) {
|
|
568
|
-
expressions.push(...recurse(node.tag));
|
|
569
|
-
expressions.push(...recurse(node.quasi));
|
|
570
|
-
}
|
|
571
|
-
if (node.type === AST_NODE_TYPES.ImportExpression) expressions.push(...recurse(node.source));
|
|
572
|
-
return expressions;
|
|
573
|
-
};
|
|
574
|
-
return recurse;
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Get all nested new expressions in an expression like node
|
|
578
|
-
* @param node The node to get the nested new expressions from
|
|
579
|
-
* @returns All nested new expressions
|
|
580
|
-
*/
|
|
581
|
-
const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
|
|
582
|
-
/**
|
|
583
|
-
* Get all nested call expressions in a expression like node
|
|
584
|
-
* @param node The node to get the nested call expressions from
|
|
585
|
-
* @returns All nested call expressions
|
|
586
|
-
*/
|
|
587
|
-
const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
|
|
588
|
-
|
|
589
|
-
//#endregion
|
|
590
|
-
//#region src/file-directive.ts
|
|
591
|
-
/**
|
|
592
|
-
* Get all directive expression statements from the top of a program AST node
|
|
593
|
-
* @param node The program AST node
|
|
594
|
-
* @returns The array of directive string literals (ex: "use strict")
|
|
595
|
-
*/
|
|
596
|
-
function getFileDirectives(node) {
|
|
597
|
-
const directives = [];
|
|
598
|
-
for (const stmt of node.body) {
|
|
599
|
-
if (!isDirective(stmt)) continue;
|
|
600
|
-
directives.push(stmt);
|
|
601
|
-
}
|
|
602
|
-
return directives;
|
|
603
|
-
}
|
|
155
|
+
//#region src/file.ts
|
|
604
156
|
/**
|
|
605
157
|
* Check if a directive with the given name exists in the file directives
|
|
606
158
|
* @param node The program AST node
|
|
607
159
|
* @param name The directive name to check (ex: "use strict", "use memo", "use no memo")
|
|
608
160
|
* @returns True if the directive exists, false otherwise
|
|
609
161
|
*/
|
|
610
|
-
function
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
//#endregion
|
|
615
|
-
//#region src/function-directive.ts
|
|
616
|
-
/**
|
|
617
|
-
* Get all directive expression statements from the top of a function AST node
|
|
618
|
-
* @param node The function AST node
|
|
619
|
-
* @returns The array of directive string literals (ex: "use memo", "use no memo")
|
|
620
|
-
*/
|
|
621
|
-
function getFunctionDirectives(node) {
|
|
622
|
-
const directives = [];
|
|
623
|
-
if (node.body.type !== AST_NODE_TYPES.BlockStatement) return directives;
|
|
624
|
-
for (const stmt of node.body.body) {
|
|
625
|
-
if (!isDirective(stmt)) continue;
|
|
626
|
-
directives.push(stmt);
|
|
627
|
-
}
|
|
628
|
-
return directives;
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Check if a directive with the given name exists in the function directives
|
|
632
|
-
* @param node The function AST node
|
|
633
|
-
* @param name The directive name to check (ex: "use memo", "use no memo")
|
|
634
|
-
* @returns True if the directive exists, false otherwise
|
|
635
|
-
*/
|
|
636
|
-
function isDirectiveInFunction(node, name) {
|
|
637
|
-
return getFunctionDirectives(node).some((d) => d.directive === name);
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
//#endregion
|
|
641
|
-
//#region src/function-id.ts
|
|
642
|
-
/**
|
|
643
|
-
* Gets the static name of a function AST node. For function declarations it is
|
|
644
|
-
* easy. For anonymous function expressions it is much harder. If you search for
|
|
645
|
-
* `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
|
|
646
|
-
* where JS gives anonymous function expressions names. We roughly detect the
|
|
647
|
-
* same AST nodes with some exceptions to better fit our use case.
|
|
648
|
-
*/
|
|
649
|
-
function getFunctionId(node) {
|
|
650
|
-
switch (true) {
|
|
651
|
-
case "id" in node && node.id != null: return node.id;
|
|
652
|
-
case node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node: return node.parent.id;
|
|
653
|
-
case node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.right === node && node.parent.operator === "=": return node.parent.left;
|
|
654
|
-
case node.parent.type === AST_NODE_TYPES.Property && node.parent.value === node && !node.parent.computed: return node.parent.key;
|
|
655
|
-
case isMethodOrProperty(node.parent) && node.parent.value === node: return node.parent.key;
|
|
656
|
-
case node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node: return node.parent.left;
|
|
657
|
-
case node.parent.type === AST_NODE_TYPES.ConditionalExpression: return getFunctionId(node.parent);
|
|
658
|
-
case isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
|
|
659
|
-
}
|
|
660
|
-
return null;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
//#endregion
|
|
664
|
-
//#region src/function-init-path.ts
|
|
665
|
-
/**
|
|
666
|
-
* Identifies the initialization path of a function node in the ast.
|
|
667
|
-
* Determine what kind of component declaration pattern the function belongs to.
|
|
668
|
-
*
|
|
669
|
-
* @param node The function node to analyze
|
|
670
|
-
* @returns The function initialization path or null if not identifiable
|
|
671
|
-
*/
|
|
672
|
-
function getFunctionInitPath(node) {
|
|
673
|
-
if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
|
|
674
|
-
let parent = node.parent;
|
|
675
|
-
while (isTypeExpression(parent)) parent = parent.parent;
|
|
676
|
-
switch (true) {
|
|
677
|
-
case parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
678
|
-
parent.parent,
|
|
679
|
-
parent,
|
|
680
|
-
node
|
|
681
|
-
];
|
|
682
|
-
case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
683
|
-
parent.parent.parent,
|
|
684
|
-
parent.parent,
|
|
685
|
-
parent,
|
|
686
|
-
node
|
|
687
|
-
];
|
|
688
|
-
case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
689
|
-
parent.parent.parent.parent,
|
|
690
|
-
parent.parent.parent,
|
|
691
|
-
parent.parent,
|
|
692
|
-
parent,
|
|
693
|
-
node
|
|
694
|
-
];
|
|
695
|
-
case parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
696
|
-
parent.parent.parent.parent,
|
|
697
|
-
parent.parent.parent,
|
|
698
|
-
parent.parent,
|
|
699
|
-
parent,
|
|
700
|
-
node
|
|
701
|
-
];
|
|
702
|
-
case parent.type === AST_NODE_TYPES.MethodDefinition: return [
|
|
703
|
-
parent.parent.parent,
|
|
704
|
-
parent.parent,
|
|
705
|
-
parent,
|
|
706
|
-
node
|
|
707
|
-
];
|
|
708
|
-
case parent.type === AST_NODE_TYPES.PropertyDefinition: return [
|
|
709
|
-
parent.parent.parent,
|
|
710
|
-
parent.parent,
|
|
711
|
-
parent,
|
|
712
|
-
node
|
|
713
|
-
];
|
|
714
|
-
}
|
|
715
|
-
return null;
|
|
716
|
-
}
|
|
717
|
-
/**
|
|
718
|
-
* Check if a specific function call exists in the function initialization path.
|
|
719
|
-
* Useful for detecting HOCs like React.memo, React.forwardRef, etc.
|
|
720
|
-
*
|
|
721
|
-
* @param callName The name of the call to check for (ex: "memo", "forwardRef")
|
|
722
|
-
* @param initPath The function initialization path to search in
|
|
723
|
-
* @returns True if the call exists in the path, false otherwise
|
|
724
|
-
*/
|
|
725
|
-
function hasCallInFunctionInitPath(callName, initPath) {
|
|
726
|
-
return initPath.some((node) => {
|
|
727
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
728
|
-
const { callee } = node;
|
|
729
|
-
if (callee.type === AST_NODE_TYPES.Identifier) return callee.name === callName;
|
|
730
|
-
if (callee.type === AST_NODE_TYPES.MemberExpression && "name" in callee.property) return callee.property.name === callName;
|
|
731
|
-
return false;
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
//#endregion
|
|
736
|
-
//#region src/function-is.ts
|
|
737
|
-
/**
|
|
738
|
-
* Check if a function is empty
|
|
739
|
-
* @param node The function node to check
|
|
740
|
-
* @returns True if the function is empty, false otherwise
|
|
741
|
-
*/
|
|
742
|
-
function isFunctionEmpty(node) {
|
|
743
|
-
return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Check if a function is immediately invoked
|
|
747
|
-
* @param node The function node to check
|
|
748
|
-
* @returns True if the function is immediately invoked, false otherwise
|
|
749
|
-
*/
|
|
750
|
-
function isFunctionImmediatelyInvoked(node) {
|
|
751
|
-
return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
|
|
162
|
+
function isFileHasDirective(node, name) {
|
|
163
|
+
for (const stmt of node.body) if (isDirective(stmt) && stmt.directive === name) return true;
|
|
164
|
+
return false;
|
|
752
165
|
}
|
|
753
166
|
|
|
754
167
|
//#endregion
|
|
@@ -763,19 +176,6 @@ function isIdentifier(node, name) {
|
|
|
763
176
|
return node != null && node.type === AST_NODE_TYPES.Identifier && (name == null || node.name === name);
|
|
764
177
|
}
|
|
765
178
|
|
|
766
|
-
//#endregion
|
|
767
|
-
//#region src/identifier-name.ts
|
|
768
|
-
/**
|
|
769
|
-
* Check if a string is a valid JavaScript identifier name
|
|
770
|
-
* Note: This only checks for ASCII identifiers. Unicode identifiers (e.g., `const 变量 = 1`)
|
|
771
|
-
* are not supported by this simple regex check.
|
|
772
|
-
* @param name The string to check
|
|
773
|
-
* @returns True if the string is a valid ASCII identifier name
|
|
774
|
-
*/
|
|
775
|
-
function isIdentifierName(name) {
|
|
776
|
-
return /^[A-Z$_][\w$]*$/i.test(name);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
179
|
//#endregion
|
|
780
180
|
//#region src/identifier-traverse.ts
|
|
781
181
|
/**
|
|
@@ -793,6 +193,138 @@ function getRootIdentifier(node) {
|
|
|
793
193
|
}
|
|
794
194
|
}
|
|
795
195
|
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/literal-is.ts
|
|
198
|
+
function isLiteral(node, type) {
|
|
199
|
+
if (node.type !== AST_NODE_TYPES.Literal) return false;
|
|
200
|
+
if (type == null) return true;
|
|
201
|
+
switch (type) {
|
|
202
|
+
case "boolean": return typeof node.value === "boolean";
|
|
203
|
+
case "null": return node.value === null;
|
|
204
|
+
case "number": return typeof node.value === "number";
|
|
205
|
+
case "regexp": return "regex" in node;
|
|
206
|
+
case "string": return typeof node.value === "string";
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region ../../.pkgs/eff/dist/index.js
|
|
212
|
+
/**
|
|
213
|
+
* Creates a function that can be used in a data-last (aka `pipe`able) or
|
|
214
|
+
* data-first style.
|
|
215
|
+
*
|
|
216
|
+
* The first parameter to `dual` is either the arity of the uncurried function
|
|
217
|
+
* or a predicate that determines if the function is being used in a data-first
|
|
218
|
+
* or data-last style.
|
|
219
|
+
*
|
|
220
|
+
* Using the arity is the most common use case, but there are some cases where
|
|
221
|
+
* you may want to use a predicate. For example, if you have a function that
|
|
222
|
+
* takes an optional argument, you can use a predicate to determine if the
|
|
223
|
+
* function is being used in a data-first or data-last style.
|
|
224
|
+
*
|
|
225
|
+
* You can pass either the arity of the uncurried function or a predicate
|
|
226
|
+
* which determines if the function is being used in a data-first or
|
|
227
|
+
* data-last style.
|
|
228
|
+
*
|
|
229
|
+
* **Example** (Using arity to determine data-first or data-last style)
|
|
230
|
+
*
|
|
231
|
+
* ```ts
|
|
232
|
+
* import { dual, pipe } from "effect/Function"
|
|
233
|
+
*
|
|
234
|
+
* const sum = dual<
|
|
235
|
+
* (that: number) => (self: number) => number,
|
|
236
|
+
* (self: number, that: number) => number
|
|
237
|
+
* >(2, (self, that) => self + that)
|
|
238
|
+
*
|
|
239
|
+
* console.log(sum(2, 3)) // 5
|
|
240
|
+
* console.log(pipe(2, sum(3))) // 5
|
|
241
|
+
* ```
|
|
242
|
+
*
|
|
243
|
+
* **Example** (Using call signatures to define the overloads)
|
|
244
|
+
*
|
|
245
|
+
* ```ts
|
|
246
|
+
* import { dual, pipe } from "effect/Function"
|
|
247
|
+
*
|
|
248
|
+
* const sum: {
|
|
249
|
+
* (that: number): (self: number) => number
|
|
250
|
+
* (self: number, that: number): number
|
|
251
|
+
* } = dual(2, (self: number, that: number): number => self + that)
|
|
252
|
+
*
|
|
253
|
+
* console.log(sum(2, 3)) // 5
|
|
254
|
+
* console.log(pipe(2, sum(3))) // 5
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* **Example** (Using a predicate to determine data-first or data-last style)
|
|
258
|
+
*
|
|
259
|
+
* ```ts
|
|
260
|
+
* import { dual, pipe } from "effect/Function"
|
|
261
|
+
*
|
|
262
|
+
* const sum = dual<
|
|
263
|
+
* (that: number) => (self: number) => number,
|
|
264
|
+
* (self: number, that: number) => number
|
|
265
|
+
* >(
|
|
266
|
+
* (args) => args.length === 2,
|
|
267
|
+
* (self, that) => self + that
|
|
268
|
+
* )
|
|
269
|
+
*
|
|
270
|
+
* console.log(sum(2, 3)) // 5
|
|
271
|
+
* console.log(pipe(2, sum(3))) // 5
|
|
272
|
+
* ```
|
|
273
|
+
*
|
|
274
|
+
* @param arity - The arity of the uncurried function or a predicate that determines if the function is being used in a data-first or data-last style.
|
|
275
|
+
* @param body - The function to be curried.
|
|
276
|
+
* @since 1.0.0
|
|
277
|
+
*/
|
|
278
|
+
const dual = function(arity, body) {
|
|
279
|
+
if (typeof arity === "function") return function() {
|
|
280
|
+
return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
|
|
281
|
+
};
|
|
282
|
+
switch (arity) {
|
|
283
|
+
case 0:
|
|
284
|
+
case 1: throw new RangeError(`Invalid arity ${arity}`);
|
|
285
|
+
case 2: return function(a, b) {
|
|
286
|
+
if (arguments.length >= 2) return body(a, b);
|
|
287
|
+
return function(self) {
|
|
288
|
+
return body(self, a);
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
case 3: return function(a, b, c) {
|
|
292
|
+
if (arguments.length >= 3) return body(a, b, c);
|
|
293
|
+
return function(self) {
|
|
294
|
+
return body(self, a, b);
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
default: return function() {
|
|
298
|
+
if (arguments.length >= arity) return body.apply(this, arguments);
|
|
299
|
+
const args = arguments;
|
|
300
|
+
return function(self) {
|
|
301
|
+
return body(self, ...args);
|
|
302
|
+
};
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
* Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
|
|
308
|
+
* The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
|
|
309
|
+
*
|
|
310
|
+
* @param self - The first function to apply (or the composed function in data-last style).
|
|
311
|
+
* @param bc - The second function to apply.
|
|
312
|
+
* @returns A composed function that applies both functions in sequence.
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* import * as assert from "node:assert"
|
|
316
|
+
* import { compose } from "effect/Function"
|
|
317
|
+
*
|
|
318
|
+
* const increment = (n: number) => n + 1;
|
|
319
|
+
* const square = (n: number) => n * n;
|
|
320
|
+
*
|
|
321
|
+
* assert.strictEqual(compose(increment, square)(2), 9);
|
|
322
|
+
* ```
|
|
323
|
+
*
|
|
324
|
+
* @since 1.0.0
|
|
325
|
+
*/
|
|
326
|
+
const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
|
|
327
|
+
|
|
796
328
|
//#endregion
|
|
797
329
|
//#region src/node-equality.ts
|
|
798
330
|
/**
|
|
@@ -849,15 +381,6 @@ function getHumanReadableKind(node, delimiter = " ") {
|
|
|
849
381
|
return toLowerCase(delimiterCase(node.type, delimiter));
|
|
850
382
|
}
|
|
851
383
|
|
|
852
|
-
//#endregion
|
|
853
|
-
//#region src/node-line.ts
|
|
854
|
-
function isMultiLine(node) {
|
|
855
|
-
return node.loc.start.line !== node.loc.end.line;
|
|
856
|
-
}
|
|
857
|
-
function isLineBreak(node) {
|
|
858
|
-
return isOneOf([AST_NODE_TYPES.Literal, AST_NODE_TYPES.JSXText])(node) && typeof node.value === "string" && node.value.trim() === "" && isMultiLine(node);
|
|
859
|
-
}
|
|
860
|
-
|
|
861
384
|
//#endregion
|
|
862
385
|
//#region src/node-name.ts
|
|
863
386
|
function getFullyQualifiedName(node, getText) {
|
|
@@ -877,10 +400,6 @@ function getFullyQualifiedName(node, getText) {
|
|
|
877
400
|
//#endregion
|
|
878
401
|
//#region src/node-selectors.ts
|
|
879
402
|
/**
|
|
880
|
-
* Selector for arrow function expressions with implicit return
|
|
881
|
-
*/
|
|
882
|
-
const SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION = "ArrowFunctionExpression[body.type!='BlockStatement']";
|
|
883
|
-
/**
|
|
884
403
|
* Selector for variable declarators with object destructuring
|
|
885
404
|
*/
|
|
886
405
|
const SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR = [
|
|
@@ -899,38 +418,15 @@ const SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION = [
|
|
|
899
418
|
].join("");
|
|
900
419
|
|
|
901
420
|
//#endregion
|
|
902
|
-
//#region src/
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* Check if the given node is a binary expression that compares `process.env.NODE_ENV` with a string literal.
|
|
913
|
-
* @param node The AST node
|
|
914
|
-
* @param operator The operator used in the comparison
|
|
915
|
-
* @param value The string literal value to compare against
|
|
916
|
-
* @returns True if the node is a binary expression that compares `process.env.NODE_ENV` with the specified value, false otherwise
|
|
917
|
-
*/
|
|
918
|
-
function isProcessEnvNodeEnvCompare(node, operator, value) {
|
|
919
|
-
if (node == null) return false;
|
|
920
|
-
if (node.type !== AST_NODE_TYPES.BinaryExpression) return false;
|
|
921
|
-
if (node.operator !== operator) return false;
|
|
922
|
-
if (isProcessEnvNodeEnv(node.left) && isLiteral(node.right, "string")) return node.right.value === value;
|
|
923
|
-
if (isLiteral(node.left, "string") && isProcessEnvNodeEnv(node.right)) return node.left.value === value;
|
|
924
|
-
return false;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
//#endregion
|
|
928
|
-
//#region src/pattern-test-mock.ts
|
|
929
|
-
function isTestMock(node) {
|
|
930
|
-
return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "mock";
|
|
931
|
-
}
|
|
932
|
-
function isTestMockCallback(node) {
|
|
933
|
-
return node != null && isFunction(node) && node.parent.type === AST_NODE_TYPES.CallExpression && isTestMock(node.parent.callee) && node.parent.arguments[1] === node;
|
|
421
|
+
//#region src/node-traverse.ts
|
|
422
|
+
function findParent(node, test) {
|
|
423
|
+
if (node == null) return null;
|
|
424
|
+
let parent = node.parent;
|
|
425
|
+
while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
|
|
426
|
+
if (test(parent)) return parent;
|
|
427
|
+
parent = parent.parent;
|
|
428
|
+
}
|
|
429
|
+
return null;
|
|
934
430
|
}
|
|
935
431
|
|
|
936
432
|
//#endregion
|
|
@@ -971,4 +467,4 @@ function findProperty(properties, name) {
|
|
|
971
467
|
}
|
|
972
468
|
|
|
973
469
|
//#endregion
|
|
974
|
-
export { SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION,
|
|
470
|
+
export { SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, findParent, findProperty, getFullyQualifiedName, getHumanReadableKind, getPropertyName, getRootIdentifier, getUnderlyingExpression, is, isClass, isDirective, isFileHasDirective, isFunction, isIdentifier, isJSX, isJSXElement, isJSXElementLike, isJSXTagNameExpression, isLiteral, isMethodOrProperty, isNodeEqual, isOneOf, isProperty, isThisExpressionLoose, isTypeAssertionExpression, isTypeExpression };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/ast",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.1-beta.3",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "git+https://github.com/Rel1cx/eslint-react.git",
|
|
12
|
-
"directory": "packages
|
|
12
|
+
"directory": "packages/ast"
|
|
13
13
|
},
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"author": "Rel1cx",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"tsdown": "^0.21.7",
|
|
40
|
-
"@local/
|
|
41
|
-
"@local/
|
|
40
|
+
"@local/configs": "0.0.0",
|
|
41
|
+
"@local/eff": "3.0.0-beta.72"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"eslint": "^10.2.0",
|