@eslint-react/ast 2.0.0-next.152 → 2.0.0-next.154
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 +120 -131
- package/dist/index.js +220 -191
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,14 +2,57 @@ import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
|
|
|
2
2
|
import { unit } from "@eslint-react/eff";
|
|
3
3
|
import { TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
|
|
4
4
|
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/array-index.d.ts
|
|
6
|
+
declare function getArrayMethodCallbackIndexParamPosition(methodName: string): number;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/array-method.d.ts
|
|
6
9
|
declare function isArrayFromCall(node: TSESTree.Node, loose?: boolean): node is TSESTree.CallExpression;
|
|
7
10
|
declare function isArrayMapCall(node: TSESTree.Node, loose?: boolean): node is TSESTree.CallExpression;
|
|
8
11
|
//#endregion
|
|
9
|
-
//#region src/
|
|
10
|
-
|
|
12
|
+
//#region src/node-equal.d.ts
|
|
13
|
+
/**
|
|
14
|
+
* Determines whether node equals to another node
|
|
15
|
+
* @param a node to compare
|
|
16
|
+
* @param b node to compare
|
|
17
|
+
* @returns `true` if node equal
|
|
18
|
+
* @see https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/util/isNodeEqual.ts
|
|
19
|
+
*/
|
|
20
|
+
declare const isNodeEqual: {
|
|
21
|
+
(a: TSESTree.Node): (b: TSESTree.Node) => boolean;
|
|
22
|
+
(a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/node-format.d.ts
|
|
26
|
+
/**
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
declare function toDelimiterFormat(node: TSESTree.Node, delimiter?: string): "RegExp literal" | Lowercase<string> | `JSX ${Lowercase<string>}`;
|
|
30
|
+
/**
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
declare function toStringFormat(node: TSESTree.Node, getText: (node: TSESTree.Node) => string): string;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/node-is.d.ts
|
|
36
|
+
declare const is: <NodeType extends TSESTree.AST_NODE_TYPES>(nodeType: NodeType) => (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, {
|
|
37
|
+
type: NodeType;
|
|
38
|
+
}>;
|
|
39
|
+
declare const isOneOf: <NodeTypes extends readonly TSESTree.AST_NODE_TYPES[]>(nodeTypes: NodeTypes) => (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, {
|
|
40
|
+
type: NodeTypes[number];
|
|
41
|
+
}>;
|
|
42
|
+
declare const isFunction: (node: TSESTree.Node | null | undefined) => node is TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.FunctionExpression;
|
|
43
|
+
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;
|
|
44
|
+
declare const isClass: (node: TSESTree.Node | null | undefined) => node is TSESTree.ClassDeclarationWithName | TSESTree.ClassDeclarationWithOptionalName | TSESTree.ClassExpression;
|
|
45
|
+
declare const isMethodOrProperty: (node: TSESTree.Node | null | undefined) => node is TSESTree.MethodDefinitionComputedName | TSESTree.MethodDefinitionNonComputedName | TSESTree.PropertyDefinitionComputedName | TSESTree.PropertyDefinitionNonComputedName;
|
|
46
|
+
declare const isProperty: (node: TSESTree.Node | null | undefined) => node is TSESTree.PropertyDefinitionComputedName | TSESTree.PropertyDefinitionNonComputedName | TSESTree.TSIndexSignature | TSESTree.TSParameterProperty | TSESTree.TSPropertySignatureComputedName | TSESTree.TSPropertySignatureNonComputedName;
|
|
47
|
+
declare const isJSXElement: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXElement;
|
|
48
|
+
declare const isJSXFragment: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXFragment;
|
|
49
|
+
declare const isJSXTagNameExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXIdentifier | TSESTree.JSXMemberExpression | TSESTree.JSXNamespacedName;
|
|
50
|
+
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;
|
|
51
|
+
declare const isLoop: (node: TSESTree.Node | null | undefined) => node is TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.WhileStatement;
|
|
52
|
+
declare const isTypeExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
53
|
+
declare const isTypeAssertionExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
11
54
|
//#endregion
|
|
12
|
-
//#region src/
|
|
55
|
+
//#region src/node-types.d.ts
|
|
13
56
|
type TSESTreeFunction = TSESTree$1.ArrowFunctionExpression | TSESTree$1.FunctionDeclaration | TSESTree$1.FunctionExpression;
|
|
14
57
|
type TSESTreeFunctionType = TSESTree$1.TSCallSignatureDeclaration | TSESTree$1.TSConstructSignatureDeclaration | TSESTree$1.TSDeclareFunction | TSESTree$1.TSEmptyBodyFunctionExpression | TSESTree$1.TSFunctionType | TSESTree$1.TSMethodSignature | TSESTreeFunction;
|
|
15
58
|
type TSESTreeClass = TSESTree$1.ClassDeclaration | TSESTree$1.ClassExpression;
|
|
@@ -23,95 +66,30 @@ type TSESTreeTypeDeclaration = TSESTree$1.TSInterfaceDeclaration | TSESTree$1.TS
|
|
|
23
66
|
type TSESTreeTypeExpression = TSESTree$1.TSAsExpression | TSESTree$1.TSNonNullExpression | TSESTree$1.TSSatisfiesExpression | TSESTree$1.TSTypeAssertion | TSESTree$1.TSInstantiationExpression;
|
|
24
67
|
type TSESTreeTypeAssertionExpression = TSESTree$1.TSAsExpression | TSESTree$1.TSNonNullExpression | TSESTree$1.TSSatisfiesExpression | TSESTree$1.TSTypeAssertion;
|
|
25
68
|
//#endregion
|
|
26
|
-
//#region src/
|
|
69
|
+
//#region src/class-id.d.ts
|
|
27
70
|
declare function getClassId(node: TSESTreeClass): TSESTree.Identifier | unit;
|
|
28
71
|
//#endregion
|
|
29
|
-
//#region src/
|
|
72
|
+
//#region src/expression-base.d.ts
|
|
30
73
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
declare function isThisExpression(node: TSESTree.Expression): boolean;
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/ast-function-id.d.ts
|
|
39
|
-
/**
|
|
40
|
-
* Gets the static name of a function AST node. For function declarations it is
|
|
41
|
-
* easy. For anonymous function expressions it is much harder. If you search for
|
|
42
|
-
* `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
|
|
43
|
-
* where JS gives anonymous function expressions names. We roughly detect the
|
|
44
|
-
* same AST nodes with some exceptions to better fit our use case.
|
|
74
|
+
* Unwraps any type expressions to get the underlying JavaScript expression node.
|
|
75
|
+
* Recursively processes nodes until a non-type expression is found.
|
|
76
|
+
*
|
|
77
|
+
* @param node - The AST node to unwrap
|
|
78
|
+
* @returns The underlying JavaScript expression node
|
|
45
79
|
*/
|
|
46
|
-
declare function
|
|
80
|
+
declare function getUnderlyingExpression(node: TSESTree.Node): Exclude<TSESTree.Node, TSESTreeTypeExpression>;
|
|
47
81
|
//#endregion
|
|
48
|
-
//#region src/
|
|
49
|
-
type FunctionInitPath =
|
|
82
|
+
//#region src/expression-is.d.ts
|
|
50
83
|
/**
|
|
51
|
-
*
|
|
84
|
+
* Checks if the given expression is a 'this' expression.
|
|
85
|
+
* Unwraps any type expressions before checking.
|
|
86
|
+
*
|
|
87
|
+
* @param node - The expression node to check
|
|
88
|
+
* @returns true if the expression is a ThisExpression, false otherwise
|
|
52
89
|
*/
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* const Comp = () => <div />;
|
|
56
|
-
* const Comp = function () { return <div />; };
|
|
57
|
-
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTreeFunction]
|
|
58
|
-
/**
|
|
59
|
-
* const Comp = React.memo(() => <div />);
|
|
60
|
-
* const Comp = React.forwardRef(() => <div />);
|
|
61
|
-
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTreeFunction]
|
|
62
|
-
/**
|
|
63
|
-
* const Comp = React.memo(React.forwardRef(() => <div />));
|
|
64
|
-
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTree.CallExpression, TSESTreeFunction]
|
|
65
|
-
/**
|
|
66
|
-
* const Comps = {
|
|
67
|
-
* TopNav() { return <div />; },
|
|
68
|
-
* SidPanel: () => <div />,
|
|
69
|
-
* }
|
|
70
|
-
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTreeFunction]
|
|
71
|
-
/**
|
|
72
|
-
* const Comps = {
|
|
73
|
-
* TopNav: React.memo(() => <div />),
|
|
74
|
-
* SidPanel: React.forwardRef(() => <div />),
|
|
75
|
-
* }
|
|
76
|
-
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTreeFunction]
|
|
77
|
-
/**
|
|
78
|
-
* const Comps = {
|
|
79
|
-
* TopNav: React.memo(React.forwardRef(() => <div />)),
|
|
80
|
-
* SidPanel: React.forwardRef(React.memo(() => <div />)),
|
|
81
|
-
* }
|
|
82
|
-
*/ | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTree.CallExpression, TSESTreeFunction]
|
|
83
|
-
/**
|
|
84
|
-
* class Comp {
|
|
85
|
-
* TopNav() { return <div />; }
|
|
86
|
-
* }
|
|
87
|
-
*/ | readonly [TSESTree.ClassDeclaration, TSESTree.ClassBody, TSESTree.MethodDefinition, TSESTreeFunction]
|
|
88
|
-
/**
|
|
89
|
-
* class Comp {
|
|
90
|
-
* TopNav = () => <div />;
|
|
91
|
-
* }
|
|
92
|
-
*/ | readonly [TSESTree.ClassDeclaration, TSESTree.ClassBody, TSESTree.PropertyDefinition, TSESTreeFunction];
|
|
93
|
-
declare function getFunctionInitPath(node: TSESTreeFunction): unit | FunctionInitPath;
|
|
94
|
-
declare function hasCallInFunctionInitPath(callName: string, initPath: FunctionInitPath): boolean;
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region src/ast-function-is.d.ts
|
|
97
|
-
declare function isEmptyFunction(node: TSESTreeFunction): boolean;
|
|
98
|
-
declare function isImmediatelyInvokedFunction(node: TSESTreeFunction): boolean;
|
|
90
|
+
declare function isThisExpression(node: TSESTree.Expression): boolean;
|
|
99
91
|
//#endregion
|
|
100
|
-
//#region src/
|
|
101
|
-
/**
|
|
102
|
-
* Find the parent node that satisfies the test function
|
|
103
|
-
* @param node The AST node
|
|
104
|
-
* @param test The test function
|
|
105
|
-
* @returns The parent node that satisfies the test function or `_` if not found
|
|
106
|
-
*/
|
|
107
|
-
declare function findParentNode<A extends TSESTree.Node>(node: TSESTree.Node | unit, test: (n: TSESTree.Node) => n is A): A | unit;
|
|
108
|
-
/**
|
|
109
|
-
* Find the parent node that satisfies the test function or `_` if not found
|
|
110
|
-
* @param node The AST node
|
|
111
|
-
* @param test The test function
|
|
112
|
-
* @returns The parent node that satisfies the test function
|
|
113
|
-
*/
|
|
114
|
-
declare function findParentNode(node: TSESTree.Node | unit, test: (node: TSESTree.Node) => boolean): TSESTree.Node | unit;
|
|
92
|
+
//#region src/expression-nested.d.ts
|
|
115
93
|
/**
|
|
116
94
|
* Get all nested identifiers in a expression like node
|
|
117
95
|
* @param node The node to get the nested identifiers from
|
|
@@ -146,7 +124,45 @@ declare const getNestedNewExpressions: (node: TSESTree.Node) => TSESTree.NewExpr
|
|
|
146
124
|
*/
|
|
147
125
|
declare const getNestedCallExpressions: (node: TSESTree.Node) => TSESTree.CallExpression[];
|
|
148
126
|
//#endregion
|
|
149
|
-
//#region src/
|
|
127
|
+
//#region src/function-id.d.ts
|
|
128
|
+
/**
|
|
129
|
+
* Gets the static name of a function AST node. For function declarations it is
|
|
130
|
+
* easy. For anonymous function expressions it is much harder. If you search for
|
|
131
|
+
* `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
|
|
132
|
+
* where JS gives anonymous function expressions names. We roughly detect the
|
|
133
|
+
* same AST nodes with some exceptions to better fit our use case.
|
|
134
|
+
*/
|
|
135
|
+
declare function getFunctionId(node: TSESTree.Expression | TSESTreeFunction): TSESTree.Identifier | unit;
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region src/function-init-path.d.ts
|
|
138
|
+
/**
|
|
139
|
+
* Represents various AST paths for React component function declarations.
|
|
140
|
+
* Each tuple type represents a specific component definition pattern.
|
|
141
|
+
*/
|
|
142
|
+
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.ClassBody, TSESTree.MethodDefinition, TSESTreeFunction] | readonly [TSESTree.ClassDeclaration, TSESTree.ClassBody, TSESTree.PropertyDefinition, TSESTreeFunction];
|
|
143
|
+
/**
|
|
144
|
+
* Identifies the initialization path of a function node in the AST.
|
|
145
|
+
* Determines what kind of component declaration pattern the function belongs to.
|
|
146
|
+
*
|
|
147
|
+
* @param node - The function node to analyze
|
|
148
|
+
* @returns The function initialization path or unit if not identifiable
|
|
149
|
+
*/
|
|
150
|
+
declare function getFunctionInitPath(node: TSESTreeFunction): unit | FunctionInitPath;
|
|
151
|
+
/**
|
|
152
|
+
* Checks if a specific function call exists in the function initialization path.
|
|
153
|
+
* Useful for detecting HOCs like React.memo, React.forwardRef, etc.
|
|
154
|
+
*
|
|
155
|
+
* @param callName - The name of the call to check for (e.g., "memo", "forwardRef")
|
|
156
|
+
* @param initPath - The function initialization path to search in
|
|
157
|
+
* @returns True if the call exists in the path, false otherwise
|
|
158
|
+
*/
|
|
159
|
+
declare function hasCallInFunctionInitPath(callName: string, initPath: FunctionInitPath): boolean;
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/function-is.d.ts
|
|
162
|
+
declare function isFunctionEmpty(node: TSESTreeFunction): boolean;
|
|
163
|
+
declare function isFunctionImmediatelyInvoked(node: TSESTreeFunction): boolean;
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/line.d.ts
|
|
150
166
|
/**
|
|
151
167
|
* Check if a node is multiline
|
|
152
168
|
* @param node The AST node to check
|
|
@@ -160,7 +176,7 @@ declare function isMultiLine(node: TSESTree.Node): boolean;
|
|
|
160
176
|
*/
|
|
161
177
|
declare function isLineBreak(node: TSESTree.Node): boolean;
|
|
162
178
|
//#endregion
|
|
163
|
-
//#region src/
|
|
179
|
+
//#region src/literal.d.ts
|
|
164
180
|
declare function isLiteral(node: TSESTree.Node): node is TSESTree.Literal;
|
|
165
181
|
declare function isLiteral(node: TSESTree.Node, type: "boolean"): node is TSESTree.BooleanLiteral;
|
|
166
182
|
declare function isLiteral(node: TSESTree.Node, type: "null"): node is TSESTree.NullLiteral;
|
|
@@ -168,53 +184,26 @@ declare function isLiteral(node: TSESTree.Node, type: "number"): node is TSESTre
|
|
|
168
184
|
declare function isLiteral(node: TSESTree.Node, type: "regexp"): node is TSESTree.RegExpLiteral;
|
|
169
185
|
declare function isLiteral(node: TSESTree.Node, type: "string"): node is TSESTree.StringLiteral;
|
|
170
186
|
//#endregion
|
|
171
|
-
//#region src/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
* @returns `true` if node equal
|
|
177
|
-
* @see https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/util/isNodeEqual.ts
|
|
178
|
-
*/
|
|
179
|
-
declare const isNodeEqual: {
|
|
180
|
-
(a: TSESTree.Node): (b: TSESTree.Node) => boolean;
|
|
181
|
-
(a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
182
|
-
};
|
|
187
|
+
//#region src/promise-then.d.ts
|
|
188
|
+
declare function isThenCall(node: TSESTree.CallExpression): boolean;
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/property-name.d.ts
|
|
191
|
+
declare function getPropertyName(node: TSESTree.Node): string | unit;
|
|
183
192
|
//#endregion
|
|
184
|
-
//#region src/
|
|
193
|
+
//#region src/traverse-up.d.ts
|
|
185
194
|
/**
|
|
186
|
-
*
|
|
195
|
+
* Find the parent node that satisfies the test function
|
|
196
|
+
* @param node The AST node
|
|
197
|
+
* @param test The test function
|
|
198
|
+
* @returns The parent node that satisfies the test function or `_` if not found
|
|
187
199
|
*/
|
|
188
|
-
declare function
|
|
200
|
+
declare function findParentNode<A extends TSESTree.Node>(node: TSESTree.Node | unit, test: (n: TSESTree.Node) => n is A): A | unit;
|
|
189
201
|
/**
|
|
190
|
-
*
|
|
202
|
+
* Find the parent node that satisfies the test function or `_` if not found
|
|
203
|
+
* @param node The AST node
|
|
204
|
+
* @param test The test function
|
|
205
|
+
* @returns The parent node that satisfies the test function
|
|
191
206
|
*/
|
|
192
|
-
declare function
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/ast-node-is.d.ts
|
|
195
|
-
declare const is: <NodeType extends TSESTree.AST_NODE_TYPES>(nodeType: NodeType) => (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, {
|
|
196
|
-
type: NodeType;
|
|
197
|
-
}>;
|
|
198
|
-
declare const isOneOf: <NodeTypes extends readonly TSESTree.AST_NODE_TYPES[]>(nodeTypes: NodeTypes) => (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, {
|
|
199
|
-
type: NodeTypes[number];
|
|
200
|
-
}>;
|
|
201
|
-
declare const isFunction: (node: TSESTree.Node | null | undefined) => node is TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression;
|
|
202
|
-
declare const isFunctionType: (node: TSESTree.Node | null | undefined) => node is TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructSignatureDeclaration | TSESTree.TSDeclareFunctionNoDeclare | TSESTree.TSDeclareFunctionWithDeclare | TSESTree.TSEmptyBodyFunctionExpression | TSESTree.TSFunctionType | TSESTree.TSMethodSignatureComputedName | TSESTree.TSMethodSignatureNonComputedName;
|
|
203
|
-
declare const isClass: (node: TSESTree.Node | null | undefined) => node is TSESTree.ClassDeclarationWithName | TSESTree.ClassDeclarationWithOptionalName | TSESTree.ClassExpression;
|
|
204
|
-
declare const isMethodOrProperty: (node: TSESTree.Node | null | undefined) => node is TSESTree.MethodDefinitionComputedName | TSESTree.MethodDefinitionNonComputedName | TSESTree.PropertyDefinitionComputedName | TSESTree.PropertyDefinitionNonComputedName;
|
|
205
|
-
declare const isProperty: (node: TSESTree.Node | null | undefined) => node is TSESTree.PropertyDefinitionComputedName | TSESTree.PropertyDefinitionNonComputedName | TSESTree.TSIndexSignature | TSESTree.TSParameterProperty | TSESTree.TSPropertySignatureComputedName | TSESTree.TSPropertySignatureNonComputedName;
|
|
206
|
-
declare const isJSXElement: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXElement;
|
|
207
|
-
declare const isJSXFragment: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXFragment;
|
|
208
|
-
declare const isJSXTagNameExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXIdentifier | TSESTree.JSXMemberExpression | TSESTree.JSXNamespacedName;
|
|
209
|
-
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;
|
|
210
|
-
declare const isLoop: (node: TSESTree.Node | null | undefined) => node is TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.WhileStatement;
|
|
211
|
-
declare const isTypeExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
212
|
-
declare const isTypeAssertionExpression: (node: TSESTree.Node | null | undefined) => node is TSESTree.TSAsExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion;
|
|
213
|
-
//#endregion
|
|
214
|
-
//#region src/ast-property-name.d.ts
|
|
215
|
-
declare function getPropertyName(node: TSESTree.Node): string | unit;
|
|
216
|
-
//#endregion
|
|
217
|
-
//#region src/ast-then.d.ts
|
|
218
|
-
declare function isThenCall(node: TSESTree.CallExpression): boolean;
|
|
207
|
+
declare function findParentNode(node: TSESTree.Node | unit, test: (node: TSESTree.Node) => boolean): TSESTree.Node | unit;
|
|
219
208
|
//#endregion
|
|
220
|
-
export { FunctionInitPath, TSESTreeArrayTupleType, TSESTreeClass, TSESTreeDestructuringPattern, TSESTreeFunction, TSESTreeFunctionType, TSESTreeJSX, TSESTreeLoop, TSESTreeMethodOrProperty, TSESTreeProperty, TSESTreeTypeAssertionExpression, TSESTreeTypeDeclaration, TSESTreeTypeExpression, findParentNode, getArrayMethodCallbackIndexParamPosition, getClassId, getFunctionId, getFunctionInitPath,
|
|
209
|
+
export { FunctionInitPath, TSESTreeArrayTupleType, TSESTreeClass, TSESTreeDestructuringPattern, TSESTreeFunction, TSESTreeFunctionType, TSESTreeJSX, TSESTreeLoop, TSESTreeMethodOrProperty, TSESTreeProperty, TSESTreeTypeAssertionExpression, TSESTreeTypeDeclaration, TSESTreeTypeExpression, findParentNode, getArrayMethodCallbackIndexParamPosition, getClassId, getFunctionId, getFunctionInitPath, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, getUnderlyingExpression, hasCallInFunctionInitPath, is, isArrayFromCall, isArrayMapCall, isClass, isFunction, isFunctionEmpty, isFunctionImmediatelyInvoked, isFunctionType, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProperty, isThenCall, isThisExpression, isTypeAssertionExpression, isTypeExpression, toDelimiterFormat, toStringFormat };
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
2
2
|
import { dual, unit } from "@eslint-react/eff";
|
|
3
|
+
import { delimiterCase, replace, toLowerCase } from "string-ts";
|
|
3
4
|
import { ASTUtils } from "@typescript-eslint/utils";
|
|
4
5
|
import { simpleTraverse } from "@typescript-eslint/typescript-estree";
|
|
5
|
-
import { delimiterCase, replace, toLowerCase } from "string-ts";
|
|
6
6
|
|
|
7
|
-
//#region src/
|
|
8
|
-
function isArrayFromCall(node, loose = true) {
|
|
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
|
-
}
|
|
15
|
-
function isArrayMapCall(node, loose = true) {
|
|
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
|
-
}
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
//#region src/ast-array-method-callback.ts
|
|
7
|
+
//#region src/array-index.ts
|
|
25
8
|
const indexParamPosition = new Map([
|
|
26
9
|
["every", 1],
|
|
27
10
|
["filter", 1],
|
|
@@ -41,7 +24,24 @@ function getArrayMethodCallbackIndexParamPosition(methodName) {
|
|
|
41
24
|
}
|
|
42
25
|
|
|
43
26
|
//#endregion
|
|
44
|
-
//#region src/
|
|
27
|
+
//#region src/array-method.ts
|
|
28
|
+
function isArrayFromCall(node, loose = true) {
|
|
29
|
+
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
30
|
+
if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
31
|
+
if (node.callee.property.type !== AST_NODE_TYPES.Identifier) return false;
|
|
32
|
+
const name = node.callee.property.name;
|
|
33
|
+
return name === "from" || loose && name.startsWith("from");
|
|
34
|
+
}
|
|
35
|
+
function isArrayMapCall(node, loose = true) {
|
|
36
|
+
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
37
|
+
if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
38
|
+
if (node.callee.property.type !== AST_NODE_TYPES.Identifier) return false;
|
|
39
|
+
const name = node.callee.property.name;
|
|
40
|
+
return name === "map" || loose && name.endsWith("Map");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/class-id.ts
|
|
45
45
|
function getClassId(node) {
|
|
46
46
|
if (node.id != null) return node.id;
|
|
47
47
|
if (node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES.Identifier) return node.parent.id;
|
|
@@ -49,7 +49,46 @@ function getClassId(node) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
//#endregion
|
|
52
|
-
//#region src/
|
|
52
|
+
//#region src/node-equal.ts
|
|
53
|
+
/**
|
|
54
|
+
* Determines whether node equals to another node
|
|
55
|
+
* @param a node to compare
|
|
56
|
+
* @param b node to compare
|
|
57
|
+
* @returns `true` if node equal
|
|
58
|
+
* @see https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/util/isNodeEqual.ts
|
|
59
|
+
*/
|
|
60
|
+
const isNodeEqual = dual(2, (a, b) => {
|
|
61
|
+
switch (true) {
|
|
62
|
+
case a === b: return true;
|
|
63
|
+
case a.type !== b.type: return false;
|
|
64
|
+
case a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal: return a.value === b.value;
|
|
65
|
+
case a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement: return a.value.raw === b.value.raw;
|
|
66
|
+
case a.type === AST_NODE_TYPES.TemplateLiteral && b.type === AST_NODE_TYPES.TemplateLiteral: {
|
|
67
|
+
if (a.quasis.length !== b.quasis.length || a.expressions.length !== b.expressions.length) return false;
|
|
68
|
+
let i = a.quasis.length;
|
|
69
|
+
while (i--) if (a.quasis[i]?.value.raw !== b.quasis[i]?.value.raw) return false;
|
|
70
|
+
i = a.expressions.length;
|
|
71
|
+
while (i--) {
|
|
72
|
+
const exprA = a.expressions[i];
|
|
73
|
+
const exprB = b.expressions[i];
|
|
74
|
+
if (!isNodeEqual(exprA, exprB)) return false;
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
case a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier: return a.name === b.name;
|
|
79
|
+
case a.type === AST_NODE_TYPES.PrivateIdentifier && b.type === AST_NODE_TYPES.PrivateIdentifier: return a.name === b.name;
|
|
80
|
+
case a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression: return isNodeEqual(a.property, b.property) && isNodeEqual(a.object, b.object);
|
|
81
|
+
case a.type === AST_NODE_TYPES.JSXAttribute && b.type === AST_NODE_TYPES.JSXAttribute:
|
|
82
|
+
if (a.name.name !== b.name.name) return false;
|
|
83
|
+
if (a.value == null || b.value == null) return a.value === b.value;
|
|
84
|
+
return isNodeEqual(a.value, b.value);
|
|
85
|
+
case a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression: return true;
|
|
86
|
+
default: return false;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/node-is.ts
|
|
53
92
|
const is = ASTUtils.isNodeOfType;
|
|
54
93
|
const isOneOf = ASTUtils.isNodeOfTypes;
|
|
55
94
|
const isFunction = isOneOf([
|
|
@@ -122,110 +161,68 @@ const isTypeAssertionExpression = isOneOf([
|
|
|
122
161
|
]);
|
|
123
162
|
|
|
124
163
|
//#endregion
|
|
125
|
-
//#region src/
|
|
164
|
+
//#region src/node-format.ts
|
|
165
|
+
function getLiteralValueType(input) {
|
|
166
|
+
if (input === null) return "null";
|
|
167
|
+
return typeof input;
|
|
168
|
+
}
|
|
126
169
|
/**
|
|
127
|
-
*
|
|
128
|
-
* @param node - The node to get the expression from
|
|
129
|
-
* @returns The inner expression
|
|
170
|
+
* @internal
|
|
130
171
|
*/
|
|
131
|
-
function
|
|
132
|
-
if (
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return
|
|
172
|
+
function toDelimiterFormat(node, delimiter = " ") {
|
|
173
|
+
if (node.type === AST_NODE_TYPES.Literal) {
|
|
174
|
+
if ("regex" in node) return "RegExp literal";
|
|
175
|
+
return `${getLiteralValueType(node.value)} literal`;
|
|
176
|
+
}
|
|
177
|
+
if (isJSX(node)) return `JSX ${toLowerCase(delimiterCase(replace(node.type, "JSX", ""), delimiter))}`;
|
|
178
|
+
return toLowerCase(delimiterCase(node.type, delimiter));
|
|
137
179
|
}
|
|
138
|
-
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region src/ast-function-id.ts
|
|
141
180
|
/**
|
|
142
|
-
*
|
|
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.
|
|
181
|
+
* @internal
|
|
147
182
|
*/
|
|
148
|
-
function
|
|
149
|
-
switch (
|
|
150
|
-
case
|
|
151
|
-
case
|
|
152
|
-
case
|
|
153
|
-
case
|
|
154
|
-
case
|
|
155
|
-
case
|
|
156
|
-
case
|
|
183
|
+
function toStringFormat(node, getText) {
|
|
184
|
+
switch (node.type) {
|
|
185
|
+
case AST_NODE_TYPES.Identifier:
|
|
186
|
+
case AST_NODE_TYPES.JSXIdentifier:
|
|
187
|
+
case AST_NODE_TYPES.PrivateIdentifier: return node.name;
|
|
188
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
189
|
+
case AST_NODE_TYPES.JSXMemberExpression: return `${toStringFormat(node.object, getText)}.${toStringFormat(node.property, getText)}`;
|
|
190
|
+
case AST_NODE_TYPES.JSXNamespacedName: return `${node.namespace.name}:${node.name.name}`;
|
|
191
|
+
case AST_NODE_TYPES.JSXText: return node.value;
|
|
192
|
+
case AST_NODE_TYPES.Literal: return node.raw;
|
|
193
|
+
default: return getText(node);
|
|
157
194
|
}
|
|
158
|
-
return unit;
|
|
159
195
|
}
|
|
160
196
|
|
|
161
197
|
//#endregion
|
|
162
|
-
//#region src/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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;
|
|
206
|
-
}
|
|
207
|
-
function hasCallInFunctionInitPath(callName, initPath) {
|
|
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
|
-
});
|
|
198
|
+
//#region src/expression-base.ts
|
|
199
|
+
/**
|
|
200
|
+
* Unwraps any type expressions to get the underlying JavaScript expression node.
|
|
201
|
+
* Recursively processes nodes until a non-type expression is found.
|
|
202
|
+
*
|
|
203
|
+
* @param node - The AST node to unwrap
|
|
204
|
+
* @returns The underlying JavaScript expression node
|
|
205
|
+
*/
|
|
206
|
+
function getUnderlyingExpression(node) {
|
|
207
|
+
if (isTypeExpression(node)) return getUnderlyingExpression(node.expression);
|
|
208
|
+
return node;
|
|
216
209
|
}
|
|
217
210
|
|
|
218
211
|
//#endregion
|
|
219
|
-
//#region src/
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
212
|
+
//#region src/expression-is.ts
|
|
213
|
+
/**
|
|
214
|
+
* Checks if the given expression is a 'this' expression.
|
|
215
|
+
* Unwraps any type expressions before checking.
|
|
216
|
+
*
|
|
217
|
+
* @param node - The expression node to check
|
|
218
|
+
* @returns true if the expression is a ThisExpression, false otherwise
|
|
219
|
+
*/
|
|
220
|
+
function isThisExpression(node) {
|
|
221
|
+
return getUnderlyingExpression(node).type === AST_NODE_TYPES.ThisExpression;
|
|
225
222
|
}
|
|
226
223
|
|
|
227
224
|
//#endregion
|
|
228
|
-
//#region src/
|
|
225
|
+
//#region src/traverse-up.ts
|
|
229
226
|
function findParentNode(node, test) {
|
|
230
227
|
if (node == null) return unit;
|
|
231
228
|
let parent = node.parent;
|
|
@@ -235,6 +232,9 @@ function findParentNode(node, test) {
|
|
|
235
232
|
}
|
|
236
233
|
return unit;
|
|
237
234
|
}
|
|
235
|
+
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/expression-nested.ts
|
|
238
238
|
/**
|
|
239
239
|
* Get all nested identifiers in a expression like node
|
|
240
240
|
* @param node The node to get the nested identifiers from
|
|
@@ -418,7 +418,109 @@ const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExp
|
|
|
418
418
|
const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
|
|
419
419
|
|
|
420
420
|
//#endregion
|
|
421
|
-
//#region src/
|
|
421
|
+
//#region src/function-id.ts
|
|
422
|
+
/**
|
|
423
|
+
* Gets the static name of a function AST node. For function declarations it is
|
|
424
|
+
* easy. For anonymous function expressions it is much harder. If you search for
|
|
425
|
+
* `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
|
|
426
|
+
* where JS gives anonymous function expressions names. We roughly detect the
|
|
427
|
+
* same AST nodes with some exceptions to better fit our use case.
|
|
428
|
+
*/
|
|
429
|
+
function getFunctionId(node) {
|
|
430
|
+
switch (true) {
|
|
431
|
+
case "id" in node && node.id != null: return node.id;
|
|
432
|
+
case node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node && node.parent.id.type === AST_NODE_TYPES.Identifier: return node.parent.id;
|
|
433
|
+
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;
|
|
434
|
+
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;
|
|
435
|
+
case isMethodOrProperty(node.parent) && node.parent.value === node && node.parent.key.type === AST_NODE_TYPES.Identifier: return node.parent.key;
|
|
436
|
+
case node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node && node.parent.left.type === AST_NODE_TYPES.Identifier: return node.parent.left;
|
|
437
|
+
case isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
|
|
438
|
+
}
|
|
439
|
+
return unit;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/function-init-path.ts
|
|
444
|
+
/**
|
|
445
|
+
* Identifies the initialization path of a function node in the AST.
|
|
446
|
+
* Determines what kind of component declaration pattern the function belongs to.
|
|
447
|
+
*
|
|
448
|
+
* @param node - The function node to analyze
|
|
449
|
+
* @returns The function initialization path or unit if not identifiable
|
|
450
|
+
*/
|
|
451
|
+
function getFunctionInitPath(node) {
|
|
452
|
+
if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
|
|
453
|
+
const { parent } = node;
|
|
454
|
+
switch (true) {
|
|
455
|
+
case parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
456
|
+
parent.parent,
|
|
457
|
+
parent,
|
|
458
|
+
node
|
|
459
|
+
];
|
|
460
|
+
case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
461
|
+
parent.parent.parent,
|
|
462
|
+
parent.parent,
|
|
463
|
+
parent,
|
|
464
|
+
node
|
|
465
|
+
];
|
|
466
|
+
case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
467
|
+
parent.parent.parent.parent,
|
|
468
|
+
parent.parent.parent,
|
|
469
|
+
parent.parent,
|
|
470
|
+
parent,
|
|
471
|
+
node
|
|
472
|
+
];
|
|
473
|
+
case parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
|
|
474
|
+
parent.parent.parent.parent,
|
|
475
|
+
parent.parent.parent,
|
|
476
|
+
parent.parent,
|
|
477
|
+
parent,
|
|
478
|
+
node
|
|
479
|
+
];
|
|
480
|
+
case parent.type === AST_NODE_TYPES.MethodDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
|
|
481
|
+
parent.parent.parent,
|
|
482
|
+
parent.parent,
|
|
483
|
+
parent,
|
|
484
|
+
node
|
|
485
|
+
];
|
|
486
|
+
case parent.type === AST_NODE_TYPES.PropertyDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
|
|
487
|
+
parent.parent.parent,
|
|
488
|
+
parent.parent,
|
|
489
|
+
parent,
|
|
490
|
+
node
|
|
491
|
+
];
|
|
492
|
+
}
|
|
493
|
+
return unit;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Checks if a specific function call exists in the function initialization path.
|
|
497
|
+
* Useful for detecting HOCs like React.memo, React.forwardRef, etc.
|
|
498
|
+
*
|
|
499
|
+
* @param callName - The name of the call to check for (e.g., "memo", "forwardRef")
|
|
500
|
+
* @param initPath - The function initialization path to search in
|
|
501
|
+
* @returns True if the call exists in the path, false otherwise
|
|
502
|
+
*/
|
|
503
|
+
function hasCallInFunctionInitPath(callName, initPath) {
|
|
504
|
+
return initPath.some((node) => {
|
|
505
|
+
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
506
|
+
const { callee } = node;
|
|
507
|
+
if (callee.type === AST_NODE_TYPES.Identifier) return callee.name === callName;
|
|
508
|
+
if (callee.type === AST_NODE_TYPES.MemberExpression && "name" in callee.property) return callee.property.name === callName;
|
|
509
|
+
return false;
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/function-is.ts
|
|
515
|
+
function isFunctionEmpty(node) {
|
|
516
|
+
return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
|
|
517
|
+
}
|
|
518
|
+
function isFunctionImmediatelyInvoked(node) {
|
|
519
|
+
return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
//#endregion
|
|
523
|
+
//#region src/line.ts
|
|
422
524
|
/**
|
|
423
525
|
* Check if a node is multiline
|
|
424
526
|
* @param node The AST node to check
|
|
@@ -437,7 +539,7 @@ function isLineBreak(node) {
|
|
|
437
539
|
}
|
|
438
540
|
|
|
439
541
|
//#endregion
|
|
440
|
-
//#region src/
|
|
542
|
+
//#region src/literal.ts
|
|
441
543
|
function isLiteral(node, type) {
|
|
442
544
|
if (node.type !== AST_NODE_TYPES.Literal) return false;
|
|
443
545
|
if (type == null) return true;
|
|
@@ -451,82 +553,15 @@ function isLiteral(node, type) {
|
|
|
451
553
|
}
|
|
452
554
|
|
|
453
555
|
//#endregion
|
|
454
|
-
//#region src/
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
}
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
//#endregion
|
|
493
|
-
//#region src/ast-node-format.ts
|
|
494
|
-
function getLiteralValueType(input) {
|
|
495
|
-
if (input === null) return "null";
|
|
496
|
-
return typeof input;
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* @internal
|
|
500
|
-
*/
|
|
501
|
-
function toDelimiterFormat(node, 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));
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* @internal
|
|
511
|
-
*/
|
|
512
|
-
function toStringFormat(node, getText) {
|
|
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
|
-
}
|
|
556
|
+
//#region src/promise-then.ts
|
|
557
|
+
function isThenCall(node) {
|
|
558
|
+
return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
|
|
524
559
|
}
|
|
525
560
|
|
|
526
561
|
//#endregion
|
|
527
|
-
//#region src/
|
|
562
|
+
//#region src/property-name.ts
|
|
528
563
|
function getPropertyName(node) {
|
|
529
|
-
if (isTypeExpression(node)) return getPropertyName(
|
|
564
|
+
if (isTypeExpression(node)) return getPropertyName(getUnderlyingExpression(node));
|
|
530
565
|
if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
|
|
531
566
|
if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
|
|
532
567
|
if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.raw;
|
|
@@ -534,10 +569,4 @@ function getPropertyName(node) {
|
|
|
534
569
|
}
|
|
535
570
|
|
|
536
571
|
//#endregion
|
|
537
|
-
|
|
538
|
-
function isThenCall(node) {
|
|
539
|
-
return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
|
|
540
|
-
}
|
|
541
|
-
|
|
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 };
|
|
572
|
+
export { findParentNode, getArrayMethodCallbackIndexParamPosition, getClassId, getFunctionId, getFunctionInitPath, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, getUnderlyingExpression, hasCallInFunctionInitPath, is, isArrayFromCall, isArrayMapCall, isClass, isFunction, isFunctionEmpty, isFunctionImmediatelyInvoked, isFunctionType, 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-next.
|
|
3
|
+
"version": "2.0.0-next.154",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
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-next.
|
|
35
|
+
"@eslint-react/eff": "2.0.0-next.154"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"tsdown": "^0.14.2",
|