@eslint-react/ast 2.0.0-next.16 → 2.0.0-next.162

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +142 -212
  2. package/dist/index.js +533 -554
  3. package/package.json +8 -9
package/dist/index.js CHANGED
@@ -1,595 +1,574 @@
1
- import { AST_NODE_TYPES } from '@typescript-eslint/types';
2
- import { or, dual, _ } from '@eslint-react/eff';
3
- import { ASTUtils } from '@typescript-eslint/utils';
4
- import { simpleTraverse } from '@typescript-eslint/typescript-estree';
5
- import { toLowerCase, delimiterCase, replace } from 'string-ts';
1
+ import { AST_NODE_TYPES } from "@typescript-eslint/types";
2
+ import { dual, unit } from "@eslint-react/eff";
3
+ import { delimiterCase, replace, toLowerCase } from "string-ts";
4
+ import { ASTUtils } from "@typescript-eslint/utils";
5
+ import { simpleTraverse } from "@typescript-eslint/typescript-estree";
6
6
 
7
- // src/ast-array-method.ts
7
+ //#region src/array-index.ts
8
+ const indexParamPosition = new Map([
9
+ ["every", 1],
10
+ ["filter", 1],
11
+ ["find", 1],
12
+ ["findIndex", 1],
13
+ ["findLast", 1],
14
+ ["findLastIndex", 1],
15
+ ["flatMap", 1],
16
+ ["forEach", 1],
17
+ ["map", 1],
18
+ ["reduce", 2],
19
+ ["reduceRight", 2],
20
+ ["some", 1]
21
+ ]);
22
+ function getArrayMethodCallbackIndexParamPosition(methodName) {
23
+ return indexParamPosition.get(methodName) ?? -1;
24
+ }
25
+
26
+ //#endregion
27
+ //#region src/array-method.ts
8
28
  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");
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");
14
34
  }
15
35
  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");
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");
21
41
  }
22
42
 
23
- // src/ast-array-method-callback.ts
24
- var indexParamPosition = /* @__PURE__ */ new Map([
25
- ["every", 1],
26
- ["filter", 1],
27
- ["find", 1],
28
- ["findIndex", 1],
29
- ["findLast", 1],
30
- ["findLastIndex", 1],
31
- ["flatMap", 1],
32
- ["forEach", 1],
33
- ["map", 1],
34
- ["reduce", 2],
35
- ["reduceRight", 2],
36
- ["some", 1]
37
- ]);
38
- function getArrayMethodCallbackIndexParamPosition(methodName) {
39
- return indexParamPosition.get(methodName) ?? -1;
40
- }
43
+ //#endregion
44
+ //#region src/class-id.ts
41
45
  function getClassId(node) {
42
- if (node.id != null) return node.id;
43
- if (node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES.Identifier) {
44
- return node.parent.id;
45
- }
46
- return _;
46
+ if (node.id != null) return node.id;
47
+ if (node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES.Identifier) return node.parent.id;
48
+ return unit;
47
49
  }
48
- var is = ASTUtils.isNodeOfType;
49
- var isOneOf = ASTUtils.isNodeOfTypes;
50
- var isFunction = isOneOf([
51
- AST_NODE_TYPES.ArrowFunctionExpression,
52
- AST_NODE_TYPES.FunctionDeclaration,
53
- AST_NODE_TYPES.FunctionExpression
54
- ]);
55
- var isFunctionType = isOneOf([
56
- AST_NODE_TYPES.ArrowFunctionExpression,
57
- AST_NODE_TYPES.FunctionDeclaration,
58
- AST_NODE_TYPES.FunctionExpression,
59
- AST_NODE_TYPES.TSCallSignatureDeclaration,
60
- AST_NODE_TYPES.TSConstructSignatureDeclaration,
61
- AST_NODE_TYPES.TSDeclareFunction,
62
- AST_NODE_TYPES.TSEmptyBodyFunctionExpression,
63
- AST_NODE_TYPES.TSFunctionType,
64
- AST_NODE_TYPES.TSMethodSignature
65
- ]);
66
- var isClass = isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression]);
67
- var isMethodOrProperty = isOneOf([
68
- AST_NODE_TYPES.PropertyDefinition,
69
- AST_NODE_TYPES.MethodDefinition
70
- ]);
71
- var isLoop = isOneOf([
72
- AST_NODE_TYPES.DoWhileStatement,
73
- AST_NODE_TYPES.ForInStatement,
74
- AST_NODE_TYPES.ForOfStatement,
75
- AST_NODE_TYPES.ForStatement,
76
- AST_NODE_TYPES.WhileStatement
77
- ]);
78
- var isControlFlow = or(
79
- isLoop,
80
- isOneOf([
81
- AST_NODE_TYPES.IfStatement,
82
- AST_NODE_TYPES.SwitchStatement
83
- ])
84
- );
85
- var isConditional = or(
86
- isControlFlow,
87
- isOneOf([
88
- AST_NODE_TYPES.LogicalExpression,
89
- AST_NODE_TYPES.ConditionalExpression
90
- ])
91
- );
92
- var isArrayTupleType = isOneOf([AST_NODE_TYPES.TSArrayType, AST_NODE_TYPES.TSTupleType]);
93
- var isProperty = isOneOf([
94
- AST_NODE_TYPES.PropertyDefinition,
95
- AST_NODE_TYPES.TSIndexSignature,
96
- AST_NODE_TYPES.TSParameterProperty,
97
- AST_NODE_TYPES.TSPropertySignature
98
- ]);
99
- var isJSXElement = is(AST_NODE_TYPES.JSXElement);
100
- var isJSXFragment = is(AST_NODE_TYPES.JSXFragment);
101
- var isJSXTagNameExpression = isOneOf([
102
- AST_NODE_TYPES.JSXIdentifier,
103
- AST_NODE_TYPES.JSXMemberExpression,
104
- AST_NODE_TYPES.JSXNamespacedName
50
+
51
+ //#endregion
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
92
+ const is = ASTUtils.isNodeOfType;
93
+ const isOneOf = ASTUtils.isNodeOfTypes;
94
+ const isFunction = isOneOf([
95
+ AST_NODE_TYPES.ArrowFunctionExpression,
96
+ AST_NODE_TYPES.FunctionDeclaration,
97
+ AST_NODE_TYPES.FunctionExpression
105
98
  ]);
106
- var isJSX = isOneOf([
107
- AST_NODE_TYPES.JSXAttribute,
108
- AST_NODE_TYPES.JSXClosingElement,
109
- AST_NODE_TYPES.JSXClosingFragment,
110
- AST_NODE_TYPES.JSXElement,
111
- AST_NODE_TYPES.JSXEmptyExpression,
112
- AST_NODE_TYPES.JSXExpressionContainer,
113
- AST_NODE_TYPES.JSXFragment,
114
- AST_NODE_TYPES.JSXIdentifier,
115
- AST_NODE_TYPES.JSXMemberExpression,
116
- AST_NODE_TYPES.JSXNamespacedName,
117
- AST_NODE_TYPES.JSXOpeningElement,
118
- AST_NODE_TYPES.JSXOpeningFragment,
119
- AST_NODE_TYPES.JSXSpreadAttribute,
120
- AST_NODE_TYPES.JSXSpreadChild,
121
- AST_NODE_TYPES.JSXText
99
+ const isFunctionType = isOneOf([
100
+ AST_NODE_TYPES.ArrowFunctionExpression,
101
+ AST_NODE_TYPES.FunctionDeclaration,
102
+ AST_NODE_TYPES.FunctionExpression,
103
+ AST_NODE_TYPES.TSCallSignatureDeclaration,
104
+ AST_NODE_TYPES.TSConstructSignatureDeclaration,
105
+ AST_NODE_TYPES.TSDeclareFunction,
106
+ AST_NODE_TYPES.TSEmptyBodyFunctionExpression,
107
+ AST_NODE_TYPES.TSFunctionType,
108
+ AST_NODE_TYPES.TSMethodSignature
122
109
  ]);
123
- var isDestructuringPattern = isOneOf([
124
- AST_NODE_TYPES.ArrayPattern,
125
- AST_NODE_TYPES.AssignmentPattern,
126
- AST_NODE_TYPES.ObjectPattern,
127
- AST_NODE_TYPES.RestElement
110
+ const isClass = isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression]);
111
+ const isMethodOrProperty = isOneOf([AST_NODE_TYPES.PropertyDefinition, AST_NODE_TYPES.MethodDefinition]);
112
+ const isProperty = isOneOf([
113
+ AST_NODE_TYPES.PropertyDefinition,
114
+ AST_NODE_TYPES.TSIndexSignature,
115
+ AST_NODE_TYPES.TSParameterProperty,
116
+ AST_NODE_TYPES.TSPropertySignature
128
117
  ]);
129
- var isTypeDeclaration = isOneOf([
130
- AST_NODE_TYPES.TSInterfaceDeclaration,
131
- AST_NODE_TYPES.TSTypeAliasDeclaration
118
+ const isJSXElement = is(AST_NODE_TYPES.JSXElement);
119
+ const isJSXFragment = is(AST_NODE_TYPES.JSXFragment);
120
+ const isJSXTagNameExpression = isOneOf([
121
+ AST_NODE_TYPES.JSXIdentifier,
122
+ AST_NODE_TYPES.JSXMemberExpression,
123
+ AST_NODE_TYPES.JSXNamespacedName
132
124
  ]);
133
- var isLeftHandSideExpression = isOneOf([
134
- AST_NODE_TYPES.ArrayExpression,
135
- AST_NODE_TYPES.ArrayPattern,
136
- AST_NODE_TYPES.ArrowFunctionExpression,
137
- AST_NODE_TYPES.CallExpression,
138
- AST_NODE_TYPES.ClassExpression,
139
- AST_NODE_TYPES.FunctionExpression,
140
- AST_NODE_TYPES.Identifier,
141
- AST_NODE_TYPES.JSXElement,
142
- AST_NODE_TYPES.JSXFragment,
143
- AST_NODE_TYPES.Literal,
144
- AST_NODE_TYPES.TemplateLiteral,
145
- AST_NODE_TYPES.MemberExpression,
146
- AST_NODE_TYPES.MetaProperty,
147
- AST_NODE_TYPES.ObjectExpression,
148
- AST_NODE_TYPES.ObjectPattern,
149
- AST_NODE_TYPES.SequenceExpression,
150
- AST_NODE_TYPES.Super,
151
- AST_NODE_TYPES.TaggedTemplateExpression,
152
- AST_NODE_TYPES.ThisExpression
125
+ const isJSX = isOneOf([
126
+ AST_NODE_TYPES.JSXAttribute,
127
+ AST_NODE_TYPES.JSXClosingElement,
128
+ AST_NODE_TYPES.JSXClosingFragment,
129
+ AST_NODE_TYPES.JSXElement,
130
+ AST_NODE_TYPES.JSXEmptyExpression,
131
+ AST_NODE_TYPES.JSXExpressionContainer,
132
+ AST_NODE_TYPES.JSXFragment,
133
+ AST_NODE_TYPES.JSXIdentifier,
134
+ AST_NODE_TYPES.JSXMemberExpression,
135
+ AST_NODE_TYPES.JSXNamespacedName,
136
+ AST_NODE_TYPES.JSXOpeningElement,
137
+ AST_NODE_TYPES.JSXOpeningFragment,
138
+ AST_NODE_TYPES.JSXSpreadAttribute,
139
+ AST_NODE_TYPES.JSXSpreadChild,
140
+ AST_NODE_TYPES.JSXText
153
141
  ]);
154
- var isLeftHandSideExpressionType = isOneOf([
155
- AST_NODE_TYPES.ArrayExpression,
156
- AST_NODE_TYPES.ArrayPattern,
157
- AST_NODE_TYPES.ArrowFunctionExpression,
158
- AST_NODE_TYPES.CallExpression,
159
- AST_NODE_TYPES.ClassExpression,
160
- AST_NODE_TYPES.FunctionExpression,
161
- AST_NODE_TYPES.Identifier,
162
- AST_NODE_TYPES.JSXElement,
163
- AST_NODE_TYPES.JSXFragment,
164
- AST_NODE_TYPES.Literal,
165
- AST_NODE_TYPES.TemplateLiteral,
166
- AST_NODE_TYPES.MemberExpression,
167
- AST_NODE_TYPES.MetaProperty,
168
- AST_NODE_TYPES.ObjectExpression,
169
- AST_NODE_TYPES.ObjectPattern,
170
- AST_NODE_TYPES.SequenceExpression,
171
- AST_NODE_TYPES.Super,
172
- AST_NODE_TYPES.TaggedTemplateExpression,
173
- AST_NODE_TYPES.ThisExpression,
174
- AST_NODE_TYPES.TSAsExpression,
175
- AST_NODE_TYPES.TSNonNullExpression,
176
- AST_NODE_TYPES.TSTypeAssertion
142
+ const isLoop = isOneOf([
143
+ AST_NODE_TYPES.DoWhileStatement,
144
+ AST_NODE_TYPES.ForInStatement,
145
+ AST_NODE_TYPES.ForOfStatement,
146
+ AST_NODE_TYPES.ForStatement,
147
+ AST_NODE_TYPES.WhileStatement
177
148
  ]);
178
- var isTypeExpression = isOneOf([
179
- AST_NODE_TYPES.TSAsExpression,
180
- AST_NODE_TYPES.TSTypeAssertion,
181
- AST_NODE_TYPES.TSNonNullExpression,
182
- AST_NODE_TYPES.TSSatisfiesExpression,
183
- AST_NODE_TYPES.TSInstantiationExpression
149
+ const isTypeExpression = isOneOf([
150
+ AST_NODE_TYPES.TSAsExpression,
151
+ AST_NODE_TYPES.TSTypeAssertion,
152
+ AST_NODE_TYPES.TSNonNullExpression,
153
+ AST_NODE_TYPES.TSSatisfiesExpression,
154
+ AST_NODE_TYPES.TSInstantiationExpression
184
155
  ]);
185
- var isTypeAssertionExpression = isOneOf([
186
- AST_NODE_TYPES.TSAsExpression,
187
- AST_NODE_TYPES.TSTypeAssertion,
188
- AST_NODE_TYPES.TSNonNullExpression,
189
- AST_NODE_TYPES.TSSatisfiesExpression
156
+ const isTypeAssertionExpression = isOneOf([
157
+ AST_NODE_TYPES.TSAsExpression,
158
+ AST_NODE_TYPES.TSTypeAssertion,
159
+ AST_NODE_TYPES.TSNonNullExpression,
160
+ AST_NODE_TYPES.TSSatisfiesExpression
190
161
  ]);
191
162
 
192
- // src/ast-expression.ts
193
- function getJSExpression(node) {
194
- if (isTypeExpression(node)) {
195
- return getJSExpression(node.expression);
196
- }
197
- return node;
198
- }
199
- function isThisExpression(node) {
200
- return getJSExpression(node).type === AST_NODE_TYPES.ThisExpression;
201
- }
202
- function getFunctionId(node) {
203
- switch (true) {
204
- // function MaybeComponent() {}
205
- case ("id" in node && node.id != null):
206
- return node.id;
207
- // const whatever = function MaybeComponent() {};
208
- case (node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node && node.parent.id.type === AST_NODE_TYPES.Identifier):
209
- return node.parent.id;
210
- // MaybeComponent = () => {};
211
- case (node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.right === node && node.parent.operator === "=" && node.parent.left.type === AST_NODE_TYPES.Identifier):
212
- return node.parent.left;
213
- // {MaybeComponent: () => {}}
214
- // {MaybeComponent() {}}
215
- case (node.parent.type === AST_NODE_TYPES.Property && node.parent.value === node && !node.parent.computed && node.parent.key.type === AST_NODE_TYPES.Identifier):
216
- return node.parent.key;
217
- // class {MaybeComponent = () => {}}
218
- // class {MaybeComponent() {}}
219
- case (isMethodOrProperty(node.parent) && node.parent.value === node && node.parent.key.type === AST_NODE_TYPES.Identifier):
220
- return node.parent.key;
221
- // Follow spec convention for `IsAnonymousFunctionDefinition()` usage.
222
- //
223
- // const {MaybeComponent = () => {}} = {};
224
- // ({MaybeComponent = () => {}} = {});
225
- case (node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node && node.parent.left.type === AST_NODE_TYPES.Identifier):
226
- return node.parent.left;
227
- // const MaybeComponent = (() => {})!;
228
- // const MaybeComponent = (() => {}) as FunctionComponent;
229
- // const MaybeComponent = (() => {}) satisfies FunctionComponent;
230
- case isTypeAssertionExpression(node.parent):
231
- return getFunctionId(node.parent);
232
- }
233
- return _;
163
+ //#endregion
164
+ //#region src/node-format.ts
165
+ function getLiteralValueType(input) {
166
+ if (input === null) return "null";
167
+ return typeof input;
234
168
  }
235
- function getFunctionInitPath(node) {
236
- if (node.type === AST_NODE_TYPES.FunctionDeclaration) {
237
- return [node];
238
- }
239
- const { parent } = node;
240
- switch (true) {
241
- case parent.type === AST_NODE_TYPES.VariableDeclarator:
242
- return [parent.parent, parent, node];
243
- case (parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator):
244
- return [parent.parent.parent, parent.parent, parent, node];
245
- case (parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator):
246
- return [parent.parent.parent.parent, parent.parent.parent, parent.parent, parent, node];
247
- case (parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator):
248
- return [parent.parent.parent.parent, parent.parent.parent, parent.parent, parent, node];
249
- case (parent.type === AST_NODE_TYPES.MethodDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration):
250
- return [parent.parent.parent, parent.parent, parent, node];
251
- case (parent.type === AST_NODE_TYPES.PropertyDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration):
252
- return [parent.parent.parent, parent.parent, parent, node];
253
- }
254
- return _;
169
+ /**
170
+ * @internal
171
+ */
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));
255
179
  }
256
- function hasCallInFunctionInitPath(callName, initPath) {
257
- return initPath.some((n) => {
258
- if (n.type !== AST_NODE_TYPES.CallExpression) {
259
- return false;
260
- }
261
- switch (n.callee.type) {
262
- case AST_NODE_TYPES.Identifier:
263
- return n.callee.name === callName;
264
- case AST_NODE_TYPES.MemberExpression:
265
- return "name" in n.callee.property && n.callee.property.name === callName;
266
- default:
267
- return false;
268
- }
269
- });
180
+ /**
181
+ * Incomplete but sufficient stringification of AST nodes for common use cases
182
+ *
183
+ * @internal
184
+ */
185
+ function toStringFormat(node, getText) {
186
+ switch (node.type) {
187
+ case AST_NODE_TYPES.Identifier:
188
+ case AST_NODE_TYPES.JSXIdentifier:
189
+ case AST_NODE_TYPES.PrivateIdentifier: return node.name;
190
+ case AST_NODE_TYPES.MemberExpression:
191
+ case AST_NODE_TYPES.JSXMemberExpression: return `${toStringFormat(node.object, getText)}.${toStringFormat(node.property, getText)}`;
192
+ case AST_NODE_TYPES.JSXNamespacedName: return `${node.namespace.name}:${node.name.name}`;
193
+ case AST_NODE_TYPES.JSXText: return node.value;
194
+ case AST_NODE_TYPES.Literal: return node.raw;
195
+ default: return getText(node);
196
+ }
270
197
  }
271
- function isEmptyFunction(node) {
272
- return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
198
+
199
+ //#endregion
200
+ //#region src/expression-base.ts
201
+ /**
202
+ * Unwraps any type expressions to get the underlying JavaScript expression node.
203
+ * Recursively processes nodes until a non-type expression is found.
204
+ *
205
+ * @param node - The AST node to unwrap
206
+ * @returns The underlying JavaScript expression node
207
+ */
208
+ function getUnderlyingExpression(node) {
209
+ if (isTypeExpression(node)) return getUnderlyingExpression(node.expression);
210
+ return node;
273
211
  }
274
- function isImmediatelyInvokedFunction(node) {
275
- return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
212
+
213
+ //#endregion
214
+ //#region src/expression-is.ts
215
+ /**
216
+ * Checks if the given expression is a 'this' expression.
217
+ * Unwraps any type expressions before checking.
218
+ *
219
+ * @param node - The expression node to check
220
+ * @returns true if the expression is a ThisExpression, false otherwise
221
+ */
222
+ function isThisExpression(node) {
223
+ return getUnderlyingExpression(node).type === AST_NODE_TYPES.ThisExpression;
276
224
  }
225
+
226
+ //#endregion
227
+ //#region src/traverse-up.ts
277
228
  function findParentNode(node, test) {
278
- if (node == null) return _;
279
- let parent = node.parent;
280
- while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
281
- if (test(parent)) {
282
- return parent;
283
- }
284
- parent = parent.parent;
285
- }
286
- return _;
229
+ if (node == null) return unit;
230
+ let parent = node.parent;
231
+ while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
232
+ if (test(parent)) return parent;
233
+ parent = parent.parent;
234
+ }
235
+ return unit;
287
236
  }
237
+
238
+ //#endregion
239
+ //#region src/expression-nested.ts
240
+ /**
241
+ * Get all nested identifiers in a expression like node
242
+ * @param node The node to get the nested identifiers from
243
+ * @returns All nested identifiers
244
+ */
288
245
  function getNestedIdentifiers(node) {
289
- const identifiers = [];
290
- if (node.type === AST_NODE_TYPES.Identifier) {
291
- identifiers.push(node);
292
- }
293
- if ("arguments" in node) {
294
- const chunk = node.arguments.map(getNestedIdentifiers).flat(1);
295
- identifiers.push(...chunk);
296
- }
297
- if ("elements" in node) {
298
- const chunk = node.elements.filter((x) => x != null).map(getNestedIdentifiers).flat(1);
299
- identifiers.push(...chunk);
300
- }
301
- if ("properties" in node) {
302
- const chunk = node.properties.map(getNestedIdentifiers).flat(1);
303
- identifiers.push(...chunk);
304
- }
305
- if ("expressions" in node) {
306
- const chunk = node.expressions.map(getNestedIdentifiers).flat(1);
307
- identifiers.push(...chunk);
308
- }
309
- if ("left" in node) {
310
- const chunk = getNestedIdentifiers(node.left);
311
- identifiers.push(...chunk);
312
- }
313
- if ("right" in node) {
314
- const chunk = getNestedIdentifiers(node.right);
315
- identifiers.push(...chunk);
316
- }
317
- if (node.type === AST_NODE_TYPES.Property) {
318
- const chunk = getNestedIdentifiers(node.value);
319
- identifiers.push(...chunk);
320
- }
321
- if (node.type === AST_NODE_TYPES.SpreadElement) {
322
- const chunk = getNestedIdentifiers(node.argument);
323
- identifiers.push(...chunk);
324
- }
325
- if (node.type === AST_NODE_TYPES.MemberExpression) {
326
- const chunk = getNestedIdentifiers(node.object);
327
- identifiers.push(...chunk);
328
- }
329
- if (node.type === AST_NODE_TYPES.UnaryExpression) {
330
- const chunk = getNestedIdentifiers(node.argument);
331
- identifiers.push(...chunk);
332
- }
333
- if (node.type === AST_NODE_TYPES.ChainExpression) {
334
- const chunk = getNestedIdentifiers(node.expression);
335
- identifiers.push(...chunk);
336
- }
337
- if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
338
- const chunk = getNestedIdentifiers(node.expression);
339
- identifiers.push(...chunk);
340
- }
341
- if (node.type === AST_NODE_TYPES.TSAsExpression) {
342
- const chunk = getNestedIdentifiers(node.expression);
343
- identifiers.push(...chunk);
344
- }
345
- if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
346
- const chunk = getNestedIdentifiers(node.expression);
347
- identifiers.push(...chunk);
348
- }
349
- return identifiers;
246
+ const identifiers = [];
247
+ if (node.type === AST_NODE_TYPES.Identifier) identifiers.push(node);
248
+ if ("arguments" in node) {
249
+ const chunk = node.arguments.map(getNestedIdentifiers).flat(1);
250
+ identifiers.push(...chunk);
251
+ }
252
+ if ("elements" in node) {
253
+ const chunk = node.elements.filter((x) => x != null).map(getNestedIdentifiers).flat(1);
254
+ identifiers.push(...chunk);
255
+ }
256
+ if ("properties" in node) {
257
+ const chunk = node.properties.map(getNestedIdentifiers).flat(1);
258
+ identifiers.push(...chunk);
259
+ }
260
+ if ("expressions" in node) {
261
+ const chunk = node.expressions.map(getNestedIdentifiers).flat(1);
262
+ identifiers.push(...chunk);
263
+ }
264
+ if ("left" in node) {
265
+ const chunk = getNestedIdentifiers(node.left);
266
+ identifiers.push(...chunk);
267
+ }
268
+ if ("right" in node) {
269
+ const chunk = getNestedIdentifiers(node.right);
270
+ identifiers.push(...chunk);
271
+ }
272
+ if (node.type === AST_NODE_TYPES.Property) {
273
+ const chunk = getNestedIdentifiers(node.value);
274
+ identifiers.push(...chunk);
275
+ }
276
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
277
+ const chunk = getNestedIdentifiers(node.argument);
278
+ identifiers.push(...chunk);
279
+ }
280
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
281
+ const chunk = getNestedIdentifiers(node.object);
282
+ identifiers.push(...chunk);
283
+ }
284
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
285
+ const chunk = getNestedIdentifiers(node.argument);
286
+ identifiers.push(...chunk);
287
+ }
288
+ if (node.type === AST_NODE_TYPES.ChainExpression) {
289
+ const chunk = getNestedIdentifiers(node.expression);
290
+ identifiers.push(...chunk);
291
+ }
292
+ if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
293
+ const chunk = getNestedIdentifiers(node.expression);
294
+ identifiers.push(...chunk);
295
+ }
296
+ if (node.type === AST_NODE_TYPES.TSAsExpression) {
297
+ const chunk = getNestedIdentifiers(node.expression);
298
+ identifiers.push(...chunk);
299
+ }
300
+ if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
301
+ const chunk = getNestedIdentifiers(node.expression);
302
+ identifiers.push(...chunk);
303
+ }
304
+ return identifiers;
350
305
  }
306
+ /**
307
+ * Gets the nested return statements in the node that are within the same function
308
+ * @param node The AST node
309
+ * @returns The nested return statements in the node
310
+ */
351
311
  function getNestedReturnStatements(node) {
352
- const statements = [];
353
- const boundaryNode = isFunction(node) ? node : findParentNode(node, isFunction);
354
- simpleTraverse(node, {
355
- enter(node2) {
356
- if (node2.type !== AST_NODE_TYPES.ReturnStatement) {
357
- return;
358
- }
359
- const parentFunction = findParentNode(node2, isFunction);
360
- if (parentFunction !== boundaryNode) {
361
- return;
362
- }
363
- statements.push(node2);
364
- }
365
- });
366
- return statements;
312
+ const statements = [];
313
+ const boundaryNode = isFunction(node) ? node : findParentNode(node, isFunction);
314
+ simpleTraverse(node, { enter(node$1) {
315
+ if (node$1.type !== AST_NODE_TYPES.ReturnStatement) return;
316
+ const parentFunction = findParentNode(node$1, isFunction);
317
+ if (parentFunction !== boundaryNode) return;
318
+ statements.push(node$1);
319
+ } });
320
+ return statements;
367
321
  }
322
+ /**
323
+ * Get all nested expressions of type T in an expression like node
324
+ * @param type The type of the expression to retrieve within the node
325
+ * @returns A partially applied function bound to a predicate of type T. The returned function can be called passing a
326
+ * node, and it will return an array of all nested expressions of type T.
327
+ */
368
328
  function getNestedExpressionsOfType(type) {
369
- const isNodeOfType = is(type);
370
- return function(node) {
371
- const boundGetNestedExpressionsOfType = getNestedExpressionsOfType(type);
372
- const expressions = [];
373
- if (isNodeOfType(node)) {
374
- expressions.push(node);
375
- }
376
- if ("arguments" in node) {
377
- const chunk = node.arguments.map(getNestedExpressionsOfType(type)).flat(1);
378
- expressions.push(...chunk);
379
- }
380
- if ("expression" in node && node.expression !== true && node.expression !== false) {
381
- const chunk = boundGetNestedExpressionsOfType(node.expression);
382
- expressions.push(...chunk);
383
- }
384
- if ("left" in node) {
385
- const chunk = boundGetNestedExpressionsOfType(node.left);
386
- expressions.push(...chunk);
387
- }
388
- if ("right" in node) {
389
- const chunk = boundGetNestedExpressionsOfType(node.right);
390
- expressions.push(...chunk);
391
- }
392
- if ("test" in node && node.test != null) {
393
- const chunk = boundGetNestedExpressionsOfType(node.test);
394
- expressions.push(...chunk);
395
- }
396
- if ("consequent" in node) {
397
- const chunk = Array.isArray(node.consequent) ? node.consequent.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.consequent);
398
- expressions.push(...chunk);
399
- }
400
- if ("alternate" in node && node.alternate != null) {
401
- const chunk = Array.isArray(node.alternate) ? node.alternate.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.alternate);
402
- expressions.push(...chunk);
403
- }
404
- if ("elements" in node) {
405
- const chunk = node.elements.filter((x) => x != null).map(getNestedExpressionsOfType(type)).flat(1);
406
- expressions.push(...chunk);
407
- }
408
- if ("properties" in node) {
409
- const chunk = node.properties.map(boundGetNestedExpressionsOfType).flat(1);
410
- expressions.push(...chunk);
411
- }
412
- if ("expressions" in node) {
413
- const chunk = node.expressions.map(boundGetNestedExpressionsOfType).flat(1);
414
- expressions.push(...chunk);
415
- }
416
- if (node.type === AST_NODE_TYPES.Property) {
417
- const chunk = boundGetNestedExpressionsOfType(node.value);
418
- expressions.push(...chunk);
419
- }
420
- if (node.type === AST_NODE_TYPES.SpreadElement) {
421
- const chunk = boundGetNestedExpressionsOfType(node.argument);
422
- expressions.push(...chunk);
423
- }
424
- if (node.type === AST_NODE_TYPES.MemberExpression) {
425
- const chunk = boundGetNestedExpressionsOfType(node.object);
426
- expressions.push(...chunk);
427
- }
428
- if (node.type === AST_NODE_TYPES.UnaryExpression) {
429
- const chunk = boundGetNestedExpressionsOfType(node.argument);
430
- expressions.push(...chunk);
431
- }
432
- if (node.type === AST_NODE_TYPES.ChainExpression) {
433
- const chunk = boundGetNestedExpressionsOfType(node.expression);
434
- expressions.push(...chunk);
435
- }
436
- if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
437
- const chunk = boundGetNestedExpressionsOfType(node.expression);
438
- expressions.push(...chunk);
439
- }
440
- if (node.type === AST_NODE_TYPES.TSAsExpression) {
441
- const chunk = boundGetNestedExpressionsOfType(node.expression);
442
- expressions.push(...chunk);
443
- }
444
- if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
445
- const chunk = boundGetNestedExpressionsOfType(node.expression);
446
- expressions.push(...chunk);
447
- }
448
- return expressions;
449
- };
450
- }
451
- var getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
452
- var getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
453
- function isMultiLine(node) {
454
- return node.loc.start.line !== node.loc.end.line;
329
+ const isNodeOfType = is(type);
330
+ return function(node) {
331
+ const boundGetNestedExpressionsOfType = getNestedExpressionsOfType(type);
332
+ const expressions = [];
333
+ if (isNodeOfType(node)) expressions.push(node);
334
+ if ("arguments" in node) {
335
+ const chunk = node.arguments.map(getNestedExpressionsOfType(type)).flat(1);
336
+ expressions.push(...chunk);
337
+ }
338
+ if ("expression" in node && node.expression !== true && node.expression !== false) {
339
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
340
+ expressions.push(...chunk);
341
+ }
342
+ if ("left" in node) {
343
+ const chunk = boundGetNestedExpressionsOfType(node.left);
344
+ expressions.push(...chunk);
345
+ }
346
+ if ("right" in node) {
347
+ const chunk = boundGetNestedExpressionsOfType(node.right);
348
+ expressions.push(...chunk);
349
+ }
350
+ if ("test" in node && node.test != null) {
351
+ const chunk = boundGetNestedExpressionsOfType(node.test);
352
+ expressions.push(...chunk);
353
+ }
354
+ if ("consequent" in node) {
355
+ const chunk = Array.isArray(node.consequent) ? node.consequent.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.consequent);
356
+ expressions.push(...chunk);
357
+ }
358
+ if ("alternate" in node && node.alternate != null) {
359
+ const chunk = Array.isArray(node.alternate) ? node.alternate.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.alternate);
360
+ expressions.push(...chunk);
361
+ }
362
+ if ("elements" in node) {
363
+ const chunk = node.elements.filter((x) => x != null).map(getNestedExpressionsOfType(type)).flat(1);
364
+ expressions.push(...chunk);
365
+ }
366
+ if ("properties" in node) {
367
+ const chunk = node.properties.map(boundGetNestedExpressionsOfType).flat(1);
368
+ expressions.push(...chunk);
369
+ }
370
+ if ("expressions" in node) {
371
+ const chunk = node.expressions.map(boundGetNestedExpressionsOfType).flat(1);
372
+ expressions.push(...chunk);
373
+ }
374
+ if (node.type === AST_NODE_TYPES.Property) {
375
+ const chunk = boundGetNestedExpressionsOfType(node.value);
376
+ expressions.push(...chunk);
377
+ }
378
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
379
+ const chunk = boundGetNestedExpressionsOfType(node.argument);
380
+ expressions.push(...chunk);
381
+ }
382
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
383
+ const chunk = boundGetNestedExpressionsOfType(node.object);
384
+ expressions.push(...chunk);
385
+ }
386
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
387
+ const chunk = boundGetNestedExpressionsOfType(node.argument);
388
+ expressions.push(...chunk);
389
+ }
390
+ if (node.type === AST_NODE_TYPES.ChainExpression) {
391
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
392
+ expressions.push(...chunk);
393
+ }
394
+ if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
395
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
396
+ expressions.push(...chunk);
397
+ }
398
+ if (node.type === AST_NODE_TYPES.TSAsExpression) {
399
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
400
+ expressions.push(...chunk);
401
+ }
402
+ if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
403
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
404
+ expressions.push(...chunk);
405
+ }
406
+ return expressions;
407
+ };
455
408
  }
456
- function isLineBreak(node) {
457
- return isOneOf([AST_NODE_TYPES.Literal, AST_NODE_TYPES.JSXText])(node) && typeof node.value === "string" && node.value.trim() === "" && isMultiLine(node);
409
+ /**
410
+ * Get all nested new expressions in an expression like node
411
+ * @param node The node to get the nested new expressions from
412
+ * @returns All nested new expressions
413
+ */
414
+ const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
415
+ /**
416
+ * Get all nested call expressions in a expression like node
417
+ * @param node The node to get the nested call expressions from
418
+ * @returns All nested call expressions
419
+ */
420
+ const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
421
+
422
+ //#endregion
423
+ //#region src/function-id.ts
424
+ /**
425
+ * Gets the static name of a function AST node. For function declarations it is
426
+ * easy. For anonymous function expressions it is much harder. If you search for
427
+ * `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
428
+ * where JS gives anonymous function expressions names. We roughly detect the
429
+ * same AST nodes with some exceptions to better fit our use case.
430
+ */
431
+ function getFunctionId(node) {
432
+ switch (true) {
433
+ case "id" in node && node.id != null: return node.id;
434
+ case node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node && node.parent.id.type === AST_NODE_TYPES.Identifier: return node.parent.id;
435
+ 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;
436
+ 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;
437
+ case isMethodOrProperty(node.parent) && node.parent.value === node && node.parent.key.type === AST_NODE_TYPES.Identifier: return node.parent.key;
438
+ case node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node && node.parent.left.type === AST_NODE_TYPES.Identifier: return node.parent.left;
439
+ case isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
440
+ }
441
+ return unit;
458
442
  }
459
- function isLiteral(node, type) {
460
- if (node.type !== AST_NODE_TYPES.Literal) return false;
461
- if (type == null) return true;
462
- switch (type) {
463
- case "boolean":
464
- return typeof node.value === "boolean";
465
- case "null":
466
- return node.value === null;
467
- case "number":
468
- return typeof node.value === "number";
469
- case "regexp":
470
- return "regex" in node;
471
- case "string":
472
- return typeof node.value === "string";
473
- }
443
+
444
+ //#endregion
445
+ //#region src/function-init-path.ts
446
+ /**
447
+ * Identifies the initialization path of a function node in the AST.
448
+ * Determines what kind of component declaration pattern the function belongs to.
449
+ *
450
+ * @param node - The function node to analyze
451
+ * @returns The function initialization path or unit if not identifiable
452
+ */
453
+ function getFunctionInitPath(node) {
454
+ if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
455
+ const { parent } = node;
456
+ switch (true) {
457
+ case parent.type === AST_NODE_TYPES.VariableDeclarator: return [
458
+ parent.parent,
459
+ parent,
460
+ node
461
+ ];
462
+ case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
463
+ parent.parent.parent,
464
+ parent.parent,
465
+ parent,
466
+ node
467
+ ];
468
+ case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
469
+ parent.parent.parent.parent,
470
+ parent.parent.parent,
471
+ parent.parent,
472
+ parent,
473
+ node
474
+ ];
475
+ case parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
476
+ parent.parent.parent.parent,
477
+ parent.parent.parent,
478
+ parent.parent,
479
+ parent,
480
+ node
481
+ ];
482
+ case parent.type === AST_NODE_TYPES.MethodDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
483
+ parent.parent.parent,
484
+ parent.parent,
485
+ parent,
486
+ node
487
+ ];
488
+ case parent.type === AST_NODE_TYPES.PropertyDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
489
+ parent.parent.parent,
490
+ parent.parent,
491
+ parent,
492
+ node
493
+ ];
494
+ }
495
+ return unit;
474
496
  }
475
- var isNodeEqual = dual(2, (a, b) => {
476
- switch (true) {
477
- case a === b:
478
- return true;
479
- case a.type !== b.type:
480
- return false;
481
- case (a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal):
482
- return a.value === b.value;
483
- case (a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement):
484
- return a.value.raw === b.value.raw;
485
- case (a.type === AST_NODE_TYPES.TemplateLiteral && b.type === AST_NODE_TYPES.TemplateLiteral): {
486
- if (a.quasis.length !== b.quasis.length || a.expressions.length !== b.expressions.length) {
487
- return false;
488
- }
489
- let i = a.quasis.length;
490
- while (i--) {
491
- if (a.quasis[i]?.value.raw !== b.quasis[i]?.value.raw) {
492
- return false;
493
- }
494
- }
495
- i = a.expressions.length;
496
- while (i--) {
497
- const exprA = a.expressions[i];
498
- const exprB = b.expressions[i];
499
- if (!isNodeEqual(exprA, exprB)) {
500
- return false;
501
- }
502
- }
503
- return true;
504
- }
505
- case (a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier):
506
- return a.name === b.name;
507
- case (a.type === AST_NODE_TYPES.PrivateIdentifier && b.type === AST_NODE_TYPES.PrivateIdentifier):
508
- return a.name === b.name;
509
- case (a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression):
510
- return isNodeEqual(a.property, b.property) && isNodeEqual(a.object, b.object);
511
- case (a.type === AST_NODE_TYPES.JSXAttribute && b.type === AST_NODE_TYPES.JSXAttribute): {
512
- if (a.name.name !== b.name.name) {
513
- return false;
514
- }
515
- if (a.value == null || b.value == null) {
516
- return a.value === b.value;
517
- }
518
- return isNodeEqual(a.value, b.value);
519
- }
520
- case (a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression):
521
- return true;
522
- default:
523
- return false;
524
- }
525
- });
526
- function getLiteralValueType(input) {
527
- if (input === null) return "null";
528
- return typeof input;
497
+ /**
498
+ * Checks if a specific function call exists in the function initialization path.
499
+ * Useful for detecting HOCs like React.memo, React.forwardRef, etc.
500
+ *
501
+ * @param callName - The name of the call to check for (e.g., "memo", "forwardRef")
502
+ * @param initPath - The function initialization path to search in
503
+ * @returns True if the call exists in the path, false otherwise
504
+ */
505
+ function hasCallInFunctionInitPath(callName, initPath) {
506
+ return initPath.some((node) => {
507
+ if (node.type !== AST_NODE_TYPES.CallExpression) return false;
508
+ const { callee } = node;
509
+ if (callee.type === AST_NODE_TYPES.Identifier) return callee.name === callName;
510
+ if (callee.type === AST_NODE_TYPES.MemberExpression && "name" in callee.property) return callee.property.name === callName;
511
+ return false;
512
+ });
529
513
  }
530
- function toDelimiterFormat(node, delimiter = " ") {
531
- if (node.type === AST_NODE_TYPES.Literal) {
532
- if ("regex" in node) {
533
- return "RegExp literal";
534
- }
535
- return `${getLiteralValueType(node.value)} literal`;
536
- }
537
- if (isJSX(node)) {
538
- return `JSX ${toLowerCase(delimiterCase(replace(node.type, "JSX", ""), delimiter))}`;
539
- }
540
- return toLowerCase(delimiterCase(node.type, delimiter));
514
+
515
+ //#endregion
516
+ //#region src/function-is.ts
517
+ function isFunctionEmpty(node) {
518
+ return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
541
519
  }
542
- function toStringFormat(node, getText) {
543
- switch (node.type) {
544
- case AST_NODE_TYPES.Identifier:
545
- case AST_NODE_TYPES.JSXIdentifier:
546
- case AST_NODE_TYPES.PrivateIdentifier:
547
- return node.name;
548
- case AST_NODE_TYPES.MemberExpression:
549
- case AST_NODE_TYPES.JSXMemberExpression:
550
- return `${toStringFormat(node.object, getText)}.${toStringFormat(node.property, getText)}`;
551
- case AST_NODE_TYPES.JSXNamespacedName:
552
- return `${node.namespace.name}:${node.name.name}`;
553
- case AST_NODE_TYPES.JSXText:
554
- return node.value;
555
- case AST_NODE_TYPES.Literal:
556
- return node.raw;
557
- default:
558
- return getText(node);
559
- }
520
+ function isFunctionImmediatelyInvoked(node) {
521
+ return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
560
522
  }
561
- function isProcessEnvNodeEnv(node) {
562
- return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && node.object.object.name === "process" && node.object.property.type === AST_NODE_TYPES.Identifier && node.object.property.name === "env" && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "NODE_ENV";
523
+
524
+ //#endregion
525
+ //#region src/literal.ts
526
+ function isLiteral(node, type) {
527
+ if (node.type !== AST_NODE_TYPES.Literal) return false;
528
+ if (type == null) return true;
529
+ switch (type) {
530
+ case "boolean": return typeof node.value === "boolean";
531
+ case "null": return node.value === null;
532
+ case "number": return typeof node.value === "number";
533
+ case "regexp": return "regex" in node;
534
+ case "string": return typeof node.value === "string";
535
+ }
563
536
  }
564
- function isProcessEnvNodeEnvCompare(node, operator, value) {
565
- if (node == null) return false;
566
- if (node.type !== AST_NODE_TYPES.BinaryExpression) return false;
567
- if (node.operator !== operator) return false;
568
- if (isProcessEnvNodeEnv(node.left) && isLiteral(node.right, "string")) {
569
- return node.right.value === value;
570
- }
571
- if (isLiteral(node.left, "string") && isProcessEnvNodeEnv(node.right)) {
572
- return node.left.value === value;
573
- }
574
- return false;
537
+
538
+ //#endregion
539
+ //#region src/misc.ts
540
+ /**
541
+ * Check if a node is multiline
542
+ * @param node The AST node to check
543
+ * @returns `true` if the node is multiline
544
+ */
545
+ function isMultiLine(node) {
546
+ return node.loc.start.line !== node.loc.end.line;
575
547
  }
576
- function getPropertyName(node) {
577
- if (isTypeExpression(node)) {
578
- return getPropertyName(getJSExpression(node));
579
- }
580
- if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {
581
- return node.name;
582
- }
583
- if (node.type === AST_NODE_TYPES.Literal) {
584
- return String(node.value);
585
- }
586
- if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) {
587
- return node.quasis[0]?.value.raw;
588
- }
589
- return _;
548
+ /**
549
+ * Check if a node is a line break
550
+ * @param node The AST node to check
551
+ * @returns boolean
552
+ */
553
+ function isLineBreak(node) {
554
+ return isOneOf([AST_NODE_TYPES.Literal, AST_NODE_TYPES.JSXText])(node) && typeof node.value === "string" && node.value.trim() === "" && isMultiLine(node);
590
555
  }
556
+
557
+ //#endregion
558
+ //#region src/promise-then.ts
591
559
  function isThenCall(node) {
592
- return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
560
+ return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
561
+ }
562
+
563
+ //#endregion
564
+ //#region src/property-name.ts
565
+ function getPropertyName(node) {
566
+ if (isTypeExpression(node)) return getPropertyName(getUnderlyingExpression(node));
567
+ if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
568
+ if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
569
+ if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.raw;
570
+ return unit;
593
571
  }
594
572
 
595
- export { findParentNode, getArrayMethodCallbackIndexParamPosition, getClassId, getFunctionId, getFunctionInitPath, getJSExpression, getNestedCallExpressions, getNestedExpressionsOfType, getNestedIdentifiers, getNestedNewExpressions, getNestedReturnStatements, getPropertyName, hasCallInFunctionInitPath, is, isArrayFromCall, isArrayMapCall, isArrayTupleType, isClass, isConditional, isControlFlow, isDestructuringPattern, isEmptyFunction, isFunction, isFunctionType, isImmediatelyInvokedFunction, isJSX, isJSXElement, isJSXFragment, isJSXTagNameExpression, isLeftHandSideExpression, isLeftHandSideExpressionType, isLineBreak, isLiteral, isLoop, isMethodOrProperty, isMultiLine, isNodeEqual, isOneOf, isProcessEnvNodeEnv, isProcessEnvNodeEnvCompare, isProperty, isThenCall, isThisExpression, isTypeAssertionExpression, isTypeDeclaration, isTypeExpression, toDelimiterFormat, toStringFormat };
573
+ //#endregion
574
+ 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 };