@eslint-react/ast 2.0.0-next.58 → 2.0.0-next.61

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 +137 -209
  2. package/dist/index.js +531 -554
  3. package/package.json +8 -9
package/dist/index.js CHANGED
@@ -1,595 +1,572 @@
1
- import { AST_NODE_TYPES } from '@typescript-eslint/types';
2
- import { or, dual, unit } 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 unit;
46
+ if (node.id != null) return node.id;
47
+ if (node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES.Identifier) return node.parent.id;
48
+ return unit;
47
49
  }
48
- 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 unit;
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 unit;
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
+ * @internal
182
+ */
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);
194
+ }
270
195
  }
271
- function isEmptyFunction(node) {
272
- return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
196
+
197
+ //#endregion
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;
273
209
  }
274
- function isImmediatelyInvokedFunction(node) {
275
- return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
210
+
211
+ //#endregion
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;
276
222
  }
223
+
224
+ //#endregion
225
+ //#region src/traverse-up.ts
277
226
  function findParentNode(node, test) {
278
- if (node == null) return unit;
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 unit;
227
+ if (node == null) return unit;
228
+ let parent = node.parent;
229
+ while (parent != null && parent.type !== AST_NODE_TYPES.Program) {
230
+ if (test(parent)) return parent;
231
+ parent = parent.parent;
232
+ }
233
+ return unit;
287
234
  }
235
+
236
+ //#endregion
237
+ //#region src/expression-nested.ts
238
+ /**
239
+ * Get all nested identifiers in a expression like node
240
+ * @param node The node to get the nested identifiers from
241
+ * @returns All nested identifiers
242
+ */
288
243
  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;
244
+ const identifiers = [];
245
+ if (node.type === AST_NODE_TYPES.Identifier) identifiers.push(node);
246
+ if ("arguments" in node) {
247
+ const chunk = node.arguments.map(getNestedIdentifiers).flat(1);
248
+ identifiers.push(...chunk);
249
+ }
250
+ if ("elements" in node) {
251
+ const chunk = node.elements.filter((x) => x != null).map(getNestedIdentifiers).flat(1);
252
+ identifiers.push(...chunk);
253
+ }
254
+ if ("properties" in node) {
255
+ const chunk = node.properties.map(getNestedIdentifiers).flat(1);
256
+ identifiers.push(...chunk);
257
+ }
258
+ if ("expressions" in node) {
259
+ const chunk = node.expressions.map(getNestedIdentifiers).flat(1);
260
+ identifiers.push(...chunk);
261
+ }
262
+ if ("left" in node) {
263
+ const chunk = getNestedIdentifiers(node.left);
264
+ identifiers.push(...chunk);
265
+ }
266
+ if ("right" in node) {
267
+ const chunk = getNestedIdentifiers(node.right);
268
+ identifiers.push(...chunk);
269
+ }
270
+ if (node.type === AST_NODE_TYPES.Property) {
271
+ const chunk = getNestedIdentifiers(node.value);
272
+ identifiers.push(...chunk);
273
+ }
274
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
275
+ const chunk = getNestedIdentifiers(node.argument);
276
+ identifiers.push(...chunk);
277
+ }
278
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
279
+ const chunk = getNestedIdentifiers(node.object);
280
+ identifiers.push(...chunk);
281
+ }
282
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
283
+ const chunk = getNestedIdentifiers(node.argument);
284
+ identifiers.push(...chunk);
285
+ }
286
+ if (node.type === AST_NODE_TYPES.ChainExpression) {
287
+ const chunk = getNestedIdentifiers(node.expression);
288
+ identifiers.push(...chunk);
289
+ }
290
+ if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
291
+ const chunk = getNestedIdentifiers(node.expression);
292
+ identifiers.push(...chunk);
293
+ }
294
+ if (node.type === AST_NODE_TYPES.TSAsExpression) {
295
+ const chunk = getNestedIdentifiers(node.expression);
296
+ identifiers.push(...chunk);
297
+ }
298
+ if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
299
+ const chunk = getNestedIdentifiers(node.expression);
300
+ identifiers.push(...chunk);
301
+ }
302
+ return identifiers;
350
303
  }
304
+ /**
305
+ * Gets the nested return statements in the node that are within the same function
306
+ * @param node The AST node
307
+ * @returns The nested return statements in the node
308
+ */
351
309
  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;
310
+ const statements = [];
311
+ const boundaryNode = isFunction(node) ? node : findParentNode(node, isFunction);
312
+ simpleTraverse(node, { enter(node$1) {
313
+ if (node$1.type !== AST_NODE_TYPES.ReturnStatement) return;
314
+ const parentFunction = findParentNode(node$1, isFunction);
315
+ if (parentFunction !== boundaryNode) return;
316
+ statements.push(node$1);
317
+ } });
318
+ return statements;
367
319
  }
320
+ /**
321
+ * Get all nested expressions of type T in an expression like node
322
+ * @param type The type of the expression to retrieve within the node
323
+ * @returns A partially applied function bound to a predicate of type T. The returned function can be called passing a
324
+ * node, and it will return an array of all nested expressions of type T.
325
+ */
368
326
  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;
327
+ const isNodeOfType = is(type);
328
+ return function(node) {
329
+ const boundGetNestedExpressionsOfType = getNestedExpressionsOfType(type);
330
+ const expressions = [];
331
+ if (isNodeOfType(node)) expressions.push(node);
332
+ if ("arguments" in node) {
333
+ const chunk = node.arguments.map(getNestedExpressionsOfType(type)).flat(1);
334
+ expressions.push(...chunk);
335
+ }
336
+ if ("expression" in node && node.expression !== true && node.expression !== false) {
337
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
338
+ expressions.push(...chunk);
339
+ }
340
+ if ("left" in node) {
341
+ const chunk = boundGetNestedExpressionsOfType(node.left);
342
+ expressions.push(...chunk);
343
+ }
344
+ if ("right" in node) {
345
+ const chunk = boundGetNestedExpressionsOfType(node.right);
346
+ expressions.push(...chunk);
347
+ }
348
+ if ("test" in node && node.test != null) {
349
+ const chunk = boundGetNestedExpressionsOfType(node.test);
350
+ expressions.push(...chunk);
351
+ }
352
+ if ("consequent" in node) {
353
+ const chunk = Array.isArray(node.consequent) ? node.consequent.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.consequent);
354
+ expressions.push(...chunk);
355
+ }
356
+ if ("alternate" in node && node.alternate != null) {
357
+ const chunk = Array.isArray(node.alternate) ? node.alternate.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.alternate);
358
+ expressions.push(...chunk);
359
+ }
360
+ if ("elements" in node) {
361
+ const chunk = node.elements.filter((x) => x != null).map(getNestedExpressionsOfType(type)).flat(1);
362
+ expressions.push(...chunk);
363
+ }
364
+ if ("properties" in node) {
365
+ const chunk = node.properties.map(boundGetNestedExpressionsOfType).flat(1);
366
+ expressions.push(...chunk);
367
+ }
368
+ if ("expressions" in node) {
369
+ const chunk = node.expressions.map(boundGetNestedExpressionsOfType).flat(1);
370
+ expressions.push(...chunk);
371
+ }
372
+ if (node.type === AST_NODE_TYPES.Property) {
373
+ const chunk = boundGetNestedExpressionsOfType(node.value);
374
+ expressions.push(...chunk);
375
+ }
376
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
377
+ const chunk = boundGetNestedExpressionsOfType(node.argument);
378
+ expressions.push(...chunk);
379
+ }
380
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
381
+ const chunk = boundGetNestedExpressionsOfType(node.object);
382
+ expressions.push(...chunk);
383
+ }
384
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
385
+ const chunk = boundGetNestedExpressionsOfType(node.argument);
386
+ expressions.push(...chunk);
387
+ }
388
+ if (node.type === AST_NODE_TYPES.ChainExpression) {
389
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
390
+ expressions.push(...chunk);
391
+ }
392
+ if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
393
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
394
+ expressions.push(...chunk);
395
+ }
396
+ if (node.type === AST_NODE_TYPES.TSAsExpression) {
397
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
398
+ expressions.push(...chunk);
399
+ }
400
+ if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
401
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
402
+ expressions.push(...chunk);
403
+ }
404
+ return expressions;
405
+ };
455
406
  }
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);
407
+ /**
408
+ * Get all nested new expressions in an expression like node
409
+ * @param node The node to get the nested new expressions from
410
+ * @returns All nested new expressions
411
+ */
412
+ const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
413
+ /**
414
+ * Get all nested call expressions in a expression like node
415
+ * @param node The node to get the nested call expressions from
416
+ * @returns All nested call expressions
417
+ */
418
+ const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
419
+
420
+ //#endregion
421
+ //#region src/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;
458
440
  }
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
- }
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;
474
494
  }
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;
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
+ });
529
511
  }
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));
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;
541
517
  }
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
- }
518
+ function isFunctionImmediatelyInvoked(node) {
519
+ return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
560
520
  }
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";
521
+
522
+ //#endregion
523
+ //#region src/literal.ts
524
+ function isLiteral(node, type) {
525
+ if (node.type !== AST_NODE_TYPES.Literal) return false;
526
+ if (type == null) return true;
527
+ switch (type) {
528
+ case "boolean": return typeof node.value === "boolean";
529
+ case "null": return node.value === null;
530
+ case "number": return typeof node.value === "number";
531
+ case "regexp": return "regex" in node;
532
+ case "string": return typeof node.value === "string";
533
+ }
563
534
  }
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;
535
+
536
+ //#endregion
537
+ //#region src/misc.ts
538
+ /**
539
+ * Check if a node is multiline
540
+ * @param node The AST node to check
541
+ * @returns `true` if the node is multiline
542
+ */
543
+ function isMultiLine(node) {
544
+ return node.loc.start.line !== node.loc.end.line;
575
545
  }
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 unit;
546
+ /**
547
+ * Check if a node is a line break
548
+ * @param node The AST node to check
549
+ * @returns boolean
550
+ */
551
+ function isLineBreak(node) {
552
+ return isOneOf([AST_NODE_TYPES.Literal, AST_NODE_TYPES.JSXText])(node) && typeof node.value === "string" && node.value.trim() === "" && isMultiLine(node);
590
553
  }
554
+
555
+ //#endregion
556
+ //#region src/promise-then.ts
591
557
  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";
558
+ return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
559
+ }
560
+
561
+ //#endregion
562
+ //#region src/property-name.ts
563
+ function getPropertyName(node) {
564
+ if (isTypeExpression(node)) return getPropertyName(getUnderlyingExpression(node));
565
+ if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
566
+ if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
567
+ if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.raw;
568
+ return unit;
593
569
  }
594
570
 
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 };
571
+ //#endregion
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 };