@eslint-react/ast 2.0.0-next.9 → 2.0.1-beta.0

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 +187 -208
  2. package/dist/index.js +591 -551
  3. package/package.json +8 -9
package/dist/index.js CHANGED
@@ -1,595 +1,635 @@
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;
163
+ //#endregion
164
+ //#region src/node-format.ts
165
+ function getLiteralValueType(input) {
166
+ if (input === null) return "null";
167
+ return typeof input;
198
168
  }
199
- function isThisExpression(node) {
200
- return getJSExpression(node).type === AST_NODE_TYPES.ThisExpression;
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));
201
179
  }
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 _;
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
+ }
234
197
  }
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 _;
255
- }
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
- });
270
- }
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
+ if (findParentNode(node$1, isFunction) !== boundaryNode) return;
317
+ statements.push(node$1);
318
+ } });
319
+ return statements;
367
320
  }
321
+ /**
322
+ * Get all nested expressions of type T in an expression like node
323
+ * @param type The type of the expression to retrieve within the node
324
+ * @returns A partially applied function bound to a predicate of type T. The returned function can be called passing a
325
+ * node, and it will return an array of all nested expressions of type T.
326
+ */
368
327
  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
- };
328
+ const isNodeOfType = is(type);
329
+ return function(node) {
330
+ const boundGetNestedExpressionsOfType = getNestedExpressionsOfType(type);
331
+ const expressions = [];
332
+ if (isNodeOfType(node)) expressions.push(node);
333
+ if ("arguments" in node) {
334
+ const chunk = node.arguments.map(getNestedExpressionsOfType(type)).flat(1);
335
+ expressions.push(...chunk);
336
+ }
337
+ if ("expression" in node && node.expression !== true && node.expression !== false) {
338
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
339
+ expressions.push(...chunk);
340
+ }
341
+ if ("left" in node) {
342
+ const chunk = boundGetNestedExpressionsOfType(node.left);
343
+ expressions.push(...chunk);
344
+ }
345
+ if ("right" in node) {
346
+ const chunk = boundGetNestedExpressionsOfType(node.right);
347
+ expressions.push(...chunk);
348
+ }
349
+ if ("test" in node && node.test != null) {
350
+ const chunk = boundGetNestedExpressionsOfType(node.test);
351
+ expressions.push(...chunk);
352
+ }
353
+ if ("consequent" in node) {
354
+ const chunk = Array.isArray(node.consequent) ? node.consequent.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.consequent);
355
+ expressions.push(...chunk);
356
+ }
357
+ if ("alternate" in node && node.alternate != null) {
358
+ const chunk = Array.isArray(node.alternate) ? node.alternate.map(boundGetNestedExpressionsOfType).flat(1) : boundGetNestedExpressionsOfType(node.alternate);
359
+ expressions.push(...chunk);
360
+ }
361
+ if ("elements" in node) {
362
+ const chunk = node.elements.filter((x) => x != null).map(getNestedExpressionsOfType(type)).flat(1);
363
+ expressions.push(...chunk);
364
+ }
365
+ if ("properties" in node) {
366
+ const chunk = node.properties.map(boundGetNestedExpressionsOfType).flat(1);
367
+ expressions.push(...chunk);
368
+ }
369
+ if ("expressions" in node) {
370
+ const chunk = node.expressions.map(boundGetNestedExpressionsOfType).flat(1);
371
+ expressions.push(...chunk);
372
+ }
373
+ if (node.type === AST_NODE_TYPES.Property) {
374
+ const chunk = boundGetNestedExpressionsOfType(node.value);
375
+ expressions.push(...chunk);
376
+ }
377
+ if (node.type === AST_NODE_TYPES.SpreadElement) {
378
+ const chunk = boundGetNestedExpressionsOfType(node.argument);
379
+ expressions.push(...chunk);
380
+ }
381
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
382
+ const chunk = boundGetNestedExpressionsOfType(node.object);
383
+ expressions.push(...chunk);
384
+ }
385
+ if (node.type === AST_NODE_TYPES.UnaryExpression) {
386
+ const chunk = boundGetNestedExpressionsOfType(node.argument);
387
+ expressions.push(...chunk);
388
+ }
389
+ if (node.type === AST_NODE_TYPES.ChainExpression) {
390
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
391
+ expressions.push(...chunk);
392
+ }
393
+ if (node.type === AST_NODE_TYPES.TSNonNullExpression) {
394
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
395
+ expressions.push(...chunk);
396
+ }
397
+ if (node.type === AST_NODE_TYPES.TSAsExpression) {
398
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
399
+ expressions.push(...chunk);
400
+ }
401
+ if (node.type === AST_NODE_TYPES.TSSatisfiesExpression) {
402
+ const chunk = boundGetNestedExpressionsOfType(node.expression);
403
+ expressions.push(...chunk);
404
+ }
405
+ return expressions;
406
+ };
450
407
  }
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;
408
+ /**
409
+ * Get all nested new expressions in an expression like node
410
+ * @param node The node to get the nested new expressions from
411
+ * @returns All nested new expressions
412
+ */
413
+ const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
414
+ /**
415
+ * Get all nested call expressions in a expression like node
416
+ * @param node The node to get the nested call expressions from
417
+ * @returns All nested call expressions
418
+ */
419
+ const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
420
+
421
+ //#endregion
422
+ //#region src/function-id.ts
423
+ /**
424
+ * Gets the static name of a function AST node. For function declarations it is
425
+ * easy. For anonymous function expressions it is much harder. If you search for
426
+ * `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
427
+ * where JS gives anonymous function expressions names. We roughly detect the
428
+ * same AST nodes with some exceptions to better fit our use case.
429
+ */
430
+ function getFunctionId(node) {
431
+ switch (true) {
432
+ case "id" in node && node.id != null: return node.id;
433
+ case node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node && node.parent.id.type === AST_NODE_TYPES.Identifier: return node.parent.id;
434
+ 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;
435
+ 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;
436
+ case isMethodOrProperty(node.parent) && node.parent.value === node && node.parent.key.type === AST_NODE_TYPES.Identifier: return node.parent.key;
437
+ case node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node && node.parent.left.type === AST_NODE_TYPES.Identifier: return node.parent.left;
438
+ case isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
439
+ }
440
+ return unit;
455
441
  }
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);
442
+
443
+ //#endregion
444
+ //#region src/function-init-path.ts
445
+ /**
446
+ * Identifies the initialization path of a function node in the AST.
447
+ * Determines what kind of component declaration pattern the function belongs to.
448
+ *
449
+ * @param node - The function node to analyze
450
+ * @returns The function initialization path or unit if not identifiable
451
+ */
452
+ function getFunctionInitPath(node) {
453
+ if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
454
+ const { parent } = node;
455
+ switch (true) {
456
+ case parent.type === AST_NODE_TYPES.VariableDeclarator: return [
457
+ parent.parent,
458
+ parent,
459
+ node
460
+ ];
461
+ case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
462
+ parent.parent.parent,
463
+ parent.parent,
464
+ parent,
465
+ node
466
+ ];
467
+ case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
468
+ parent.parent.parent.parent,
469
+ parent.parent.parent,
470
+ parent.parent,
471
+ parent,
472
+ node
473
+ ];
474
+ case parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
475
+ parent.parent.parent.parent,
476
+ parent.parent.parent,
477
+ parent.parent,
478
+ parent,
479
+ node
480
+ ];
481
+ case parent.type === AST_NODE_TYPES.MethodDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
482
+ parent.parent.parent,
483
+ parent.parent,
484
+ parent,
485
+ node
486
+ ];
487
+ case parent.type === AST_NODE_TYPES.PropertyDefinition && parent.parent.parent.type === AST_NODE_TYPES.ClassDeclaration: return [
488
+ parent.parent.parent,
489
+ parent.parent,
490
+ parent,
491
+ node
492
+ ];
493
+ }
494
+ return unit;
495
+ }
496
+ /**
497
+ * Checks if a specific function call exists in the function initialization path.
498
+ * Useful for detecting HOCs like React.memo, React.forwardRef, etc.
499
+ *
500
+ * @param callName - The name of the call to check for (e.g., "memo", "forwardRef")
501
+ * @param initPath - The function initialization path to search in
502
+ * @returns True if the call exists in the path, false otherwise
503
+ */
504
+ function hasCallInFunctionInitPath(callName, initPath) {
505
+ return initPath.some((node) => {
506
+ if (node.type !== AST_NODE_TYPES.CallExpression) return false;
507
+ const { callee } = node;
508
+ if (callee.type === AST_NODE_TYPES.Identifier) return callee.name === callName;
509
+ if (callee.type === AST_NODE_TYPES.MemberExpression && "name" in callee.property) return callee.property.name === callName;
510
+ return false;
511
+ });
512
+ }
513
+
514
+ //#endregion
515
+ //#region src/function-is.ts
516
+ function isFunctionEmpty(node) {
517
+ return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
518
+ }
519
+ function isFunctionImmediatelyInvoked(node) {
520
+ return node.type !== AST_NODE_TYPES.FunctionDeclaration && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node;
458
521
  }
522
+
523
+ //#endregion
524
+ //#region src/literal.ts
459
525
  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
- }
526
+ if (node.type !== AST_NODE_TYPES.Literal) return false;
527
+ if (type == null) return true;
528
+ switch (type) {
529
+ case "boolean": return typeof node.value === "boolean";
530
+ case "null": return node.value === null;
531
+ case "number": return typeof node.value === "number";
532
+ case "regexp": return "regex" in node;
533
+ case "string": return typeof node.value === "string";
534
+ }
474
535
  }
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
- });
536
+
537
+ //#endregion
538
+ //#region src/misc.ts
539
+ /**
540
+ * Check if a node is multiline
541
+ * @param node The AST node to check
542
+ * @returns `true` if the node is multiline
543
+ */
544
+ function isMultiLine(node) {
545
+ return node.loc.start.line !== node.loc.end.line;
546
+ }
547
+ /**
548
+ * Check if a node is a line break
549
+ * @param node The AST node to check
550
+ * @returns boolean
551
+ */
552
+ function isLineBreak(node) {
553
+ return isOneOf([AST_NODE_TYPES.Literal, AST_NODE_TYPES.JSXText])(node) && typeof node.value === "string" && node.value.trim() === "" && isMultiLine(node);
554
+ }
555
+
556
+ //#endregion
557
+ //#region src/node-selectors.ts
558
+ const SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION = "ArrowFunctionExpression[body.type!='BlockStatement']";
559
+ const SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR = [
560
+ "VariableDeclarator",
561
+ "[id.type='ObjectPattern']",
562
+ "[init.type='Identifier']"
563
+ ].join("");
564
+ const SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION = [
565
+ "AssignmentExpression",
566
+ "[operator='=']",
567
+ "[left.type='MemberExpression']",
568
+ "[left.property.name='displayName']"
569
+ ].join("");
570
+
571
+ //#endregion
572
+ //#region src/process-env-node-env.ts
573
+ /**
574
+ * Check if the given node is a member expression that accesses `process.env.NODE_ENV`
575
+ * @param node The AST node
576
+ * @returns True if the node is a member expression that accesses `process.env.NODE_ENV`, false otherwise
577
+ */
526
578
  function isProcessEnvNodeEnv(node) {
527
- 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";
579
+ 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";
528
580
  }
581
+ /**
582
+ * Check if the given node is a binary expression that compares `process.env.NODE_ENV` with a string literal.
583
+ * @param node The AST node
584
+ * @param operator The operator used in the comparison
585
+ * @param value The string literal value to compare against
586
+ * @returns True if the node is a binary expression that compares `process.env.NODE_ENV` with the specified value, false otherwise
587
+ */
529
588
  function isProcessEnvNodeEnvCompare(node, operator, value) {
530
- if (node == null) return false;
531
- if (node.type !== AST_NODE_TYPES.BinaryExpression) return false;
532
- if (node.operator !== operator) return false;
533
- if (isProcessEnvNodeEnv(node.left) && isLiteral(node.right, "string")) {
534
- return node.right.value === value;
535
- }
536
- if (isLiteral(node.left, "string") && isProcessEnvNodeEnv(node.right)) {
537
- return node.left.value === value;
538
- }
539
- return false;
540
- }
541
- function getPropertyName(node) {
542
- if (isTypeExpression(node)) {
543
- return getPropertyName(getJSExpression(node));
544
- }
545
- if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) {
546
- return node.name;
547
- }
548
- if (node.type === AST_NODE_TYPES.Literal) {
549
- return String(node.value);
550
- }
551
- if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) {
552
- return node.quasis[0]?.value.raw;
553
- }
554
- return _;
589
+ if (node == null) return false;
590
+ if (node.type !== AST_NODE_TYPES.BinaryExpression) return false;
591
+ if (node.operator !== operator) return false;
592
+ if (isProcessEnvNodeEnv(node.left) && isLiteral(node.right, "string")) return node.right.value === value;
593
+ if (isLiteral(node.left, "string") && isProcessEnvNodeEnv(node.right)) return node.left.value === value;
594
+ return false;
555
595
  }
596
+
597
+ //#endregion
598
+ //#region src/promise-then.ts
556
599
  function isThenCall(node) {
557
- return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
600
+ return node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "then";
558
601
  }
559
- function getLiteralValueType(input) {
560
- if (input === null) return "null";
561
- return typeof input;
602
+
603
+ //#endregion
604
+ //#region src/property-name.ts
605
+ function getPropertyName(node) {
606
+ if (isTypeExpression(node)) return getPropertyName(getUnderlyingExpression(node));
607
+ if (node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier) return node.name;
608
+ if (node.type === AST_NODE_TYPES.Literal) return String(node.value);
609
+ if (node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) return node.quasis[0]?.value.raw;
610
+ return unit;
562
611
  }
563
- function toDelimiterCaseType(node, delimiter = " ") {
564
- if (node.type === AST_NODE_TYPES.Literal) {
565
- if ("regex" in node) {
566
- return "RegExp literal";
567
- }
568
- return `${getLiteralValueType(node.value)} literal`;
569
- }
570
- if (isJSX(node)) {
571
- return `JSX ${toLowerCase(delimiterCase(replace(node.type, "JSX", ""), delimiter))}`;
572
- }
573
- return toLowerCase(delimiterCase(node.type, delimiter));
612
+
613
+ //#endregion
614
+ //#region src/vitest-mock.ts
615
+ /**
616
+ * Checks if the given node is a `vi.mock`.
617
+ * @param node The node to check
618
+ * @returns `true` if the node is a `vi.mock`, otherwise `false`.
619
+ * @internal
620
+ */
621
+ function isViMock(node) {
622
+ return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier && node.object.name === "vi" && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "mock";
574
623
  }
575
- function toString(node, getText) {
576
- switch (node.type) {
577
- case AST_NODE_TYPES.Identifier:
578
- case AST_NODE_TYPES.JSXIdentifier:
579
- case AST_NODE_TYPES.PrivateIdentifier:
580
- return node.name;
581
- case AST_NODE_TYPES.MemberExpression:
582
- case AST_NODE_TYPES.JSXMemberExpression:
583
- return `${toString(node.object, getText)}.${toString(node.property, getText)}`;
584
- case AST_NODE_TYPES.JSXNamespacedName:
585
- return `${node.namespace.name}:${node.name.name}`;
586
- case AST_NODE_TYPES.JSXText:
587
- return node.value;
588
- case AST_NODE_TYPES.Literal:
589
- return node.raw;
590
- default:
591
- return getText(node);
592
- }
624
+ /**
625
+ * Checks if the given node is a `vi.mock` callback.
626
+ * @param node The node to check
627
+ * @returns `true` if the node is a `vi.mock` callback, otherwise `false`.
628
+ * @internal
629
+ */
630
+ function isViMockCallback(node) {
631
+ return node != null && isFunction(node) && node.parent.type === AST_NODE_TYPES.CallExpression && isViMock(node.parent.callee) && node.parent.arguments[1] === node;
593
632
  }
594
633
 
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, toDelimiterCaseType, toString };
634
+ //#endregion
635
+ export { SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_IMPLICIT_RETURN_ARROW_FUNCTION_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, 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, isProcessEnvNodeEnv, isProcessEnvNodeEnvCompare, isProperty, isThenCall, isThisExpression, isTypeAssertionExpression, isTypeExpression, isViMock, isViMockCallback, toDelimiterFormat, toStringFormat };