@eslint-react/core 1.52.3-next.9 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs DELETED
@@ -1,955 +0,0 @@
1
- import * as AST9 from '@eslint-react/ast';
2
- import { flip, dual, constFalse, identity, constTrue, unit } from '@eslint-react/eff';
3
- import { RegExp, Selector } from '@eslint-react/kit';
4
- import { coerceSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
5
- import { AST_NODE_TYPES } from '@typescript-eslint/types';
6
- import * as VAR3 from '@eslint-react/var';
7
- import { isMatching, P, match } from 'ts-pattern';
8
- import birecord from 'birecord';
9
-
10
- // src/component/component-collector.ts
11
- function getInstanceId(node, prev) {
12
- switch (true) {
13
- case (node.type === AST_NODE_TYPES.VariableDeclarator && node.init === prev):
14
- return node.id;
15
- case (node.type === AST_NODE_TYPES.AssignmentExpression && node.right === prev):
16
- return node.left;
17
- case (node.type === AST_NODE_TYPES.PropertyDefinition && node.value === prev):
18
- return node.key;
19
- case (node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node):
20
- return unit;
21
- default:
22
- return getInstanceId(node.parent, node);
23
- }
24
- }
25
- function getRequireExpressionArguments(node) {
26
- return match(node).with({ type: AST_NODE_TYPES.CallExpression, arguments: P.select(), callee: { type: AST_NODE_TYPES.Identifier, name: "require" } }, identity).with({ type: AST_NODE_TYPES.MemberExpression, object: P.select() }, getRequireExpressionArguments).otherwise(() => null);
27
- }
28
- function isInitializedFromReact(name, importSource, initialScope) {
29
- if (name.toLowerCase() === "react") return true;
30
- const latestDef = VAR3.findVariable(name, initialScope)?.defs.at(-1);
31
- if (latestDef == null) return false;
32
- const { node, parent } = latestDef;
33
- if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
34
- const { init } = node;
35
- if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) {
36
- return isInitializedFromReact(init.object.name, importSource, initialScope);
37
- }
38
- if (init.type === AST_NODE_TYPES.Identifier) {
39
- return isInitializedFromReact(init.name, importSource, initialScope);
40
- }
41
- const args = getRequireExpressionArguments(init);
42
- const arg0 = args?.[0];
43
- if (arg0 == null || !AST9.isLiteral(arg0, "string")) {
44
- return false;
45
- }
46
- return arg0.value === importSource || arg0.value.startsWith(`${importSource}/`);
47
- }
48
- return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === importSource;
49
- }
50
- function isInstanceIdEqual(context, a, b) {
51
- return AST9.isNodeEqual(a, b) || VAR3.isNodeValueEqual(a, b, [
52
- context.sourceCode.getScope(a),
53
- context.sourceCode.getScope(b)
54
- ]);
55
- }
56
- function isReactAPI(api) {
57
- const func = (context, node) => {
58
- if (node == null) return false;
59
- const getText = (n) => context.sourceCode.getText(n);
60
- const name = AST9.toString(node, getText);
61
- if (name === api) return true;
62
- if (name.substring(name.indexOf(".") + 1) === api) return true;
63
- return false;
64
- };
65
- return dual(2, func);
66
- }
67
- function isReactAPICall(api) {
68
- const func = (context, node) => {
69
- if (node == null) return false;
70
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
71
- return isReactAPI(api)(context, node.callee);
72
- };
73
- return dual(2, func);
74
- }
75
- var isCaptureOwnerStack = isReactAPI("captureOwnerStack");
76
- var isChildrenCount = isReactAPI("Children.count");
77
- var isChildrenForEach = isReactAPI("Children.forEach");
78
- var isChildrenMap = isReactAPI("Children.map");
79
- var isChildrenOnly = isReactAPI("Children.only");
80
- var isChildrenToArray = isReactAPI("Children.toArray");
81
- var isCloneElement = isReactAPI("cloneElement");
82
- var isCreateContext = isReactAPI("createContext");
83
- var isCreateElement = isReactAPI("createElement");
84
- var isCreateRef = isReactAPI("createRef");
85
- var isForwardRef = isReactAPI("forwardRef");
86
- var isMemo = isReactAPI("memo");
87
- var isLazy = isReactAPI("lazy");
88
- var isCaptureOwnerStackCall = isReactAPICall("captureOwnerStack");
89
- var isChildrenCountCall = isReactAPICall("Children.count");
90
- var isChildrenForEachCall = isReactAPICall("Children.forEach");
91
- var isChildrenMapCall = isReactAPICall("Children.map");
92
- var isChildrenOnlyCall = isReactAPICall("Children.only");
93
- var isChildrenToArrayCall = isReactAPICall("Children.toArray");
94
- var isCloneElementCall = isReactAPICall("cloneElement");
95
- var isCreateContextCall = isReactAPICall("createContext");
96
- var isCreateElementCall = isReactAPICall("createElement");
97
- var isCreateRefCall = isReactAPICall("createRef");
98
- var isForwardRefCall = isReactAPICall("forwardRef");
99
- var isMemoCall = isReactAPICall("memo");
100
- var isLazyCall = isReactAPICall("lazy");
101
-
102
- // src/hook/hook-name.ts
103
- function isReactHookName(name) {
104
- return name === "use" || /^use[A-Z0-9]/.test(name);
105
- }
106
-
107
- // src/hook/hook-is.ts
108
- function isReactHook(node) {
109
- if (node == null) return false;
110
- const id = AST9.getFunctionId(node);
111
- return id?.name != null && isReactHookName(id.name);
112
- }
113
- function isReactHookCall(node) {
114
- if (node == null) return false;
115
- if (node.type !== AST_NODE_TYPES.CallExpression) {
116
- return false;
117
- }
118
- if (node.callee.type === AST_NODE_TYPES.Identifier) {
119
- return isReactHookName(node.callee.name);
120
- }
121
- if (node.callee.type === AST_NODE_TYPES.MemberExpression) {
122
- return node.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.callee.property.name);
123
- }
124
- return false;
125
- }
126
- function isReactHookCallWithName(context, node) {
127
- if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
128
- const {
129
- importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource,
130
- skipImportCheck = true
131
- } = coerceSettings(context.settings);
132
- const initialScope = context.sourceCode.getScope(node);
133
- return (name) => {
134
- switch (true) {
135
- case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
136
- return skipImportCheck || isInitializedFromReact(name, importSource, initialScope);
137
- case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
138
- return skipImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
139
- default:
140
- return false;
141
- }
142
- };
143
- }
144
- function isReactHookCallWithNameLoose(node) {
145
- if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
146
- return (name) => {
147
- switch (node.callee.type) {
148
- case AST_NODE_TYPES.Identifier:
149
- return node.callee.name === name;
150
- case AST_NODE_TYPES.MemberExpression:
151
- return node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name;
152
- default:
153
- return false;
154
- }
155
- };
156
- }
157
- function isReactHookCallWithNameAlias(context, name, alias = []) {
158
- const {
159
- importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource,
160
- skipImportCheck = true
161
- } = coerceSettings(context.settings);
162
- return (node) => {
163
- const initialScope = context.sourceCode.getScope(node);
164
- switch (true) {
165
- case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
166
- return skipImportCheck || isInitializedFromReact(name, importSource, initialScope);
167
- case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
168
- return skipImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
169
- default:
170
- return alias.some(isReactHookCallWithNameLoose(node));
171
- }
172
- };
173
- }
174
- function isUseEffectCallLoose(node) {
175
- if (node == null) return false;
176
- if (node.type !== AST_NODE_TYPES.CallExpression) {
177
- return false;
178
- }
179
- switch (node.callee.type) {
180
- case AST_NODE_TYPES.Identifier:
181
- return /^use\w*Effect$/u.test(node.callee.name);
182
- case AST_NODE_TYPES.MemberExpression:
183
- return node.callee.property.type === AST_NODE_TYPES.Identifier && /^use\w*Effect$/u.test(node.callee.property.name);
184
- default:
185
- return false;
186
- }
187
- }
188
- var isUseCall = flip(isReactHookCallWithName)("use");
189
- var isUseActionStateCall = flip(isReactHookCallWithName)("useActionState");
190
- var isUseCallbackCall = flip(isReactHookCallWithName)("useCallback");
191
- var isUseContextCall = flip(isReactHookCallWithName)("useContext");
192
- var isUseDebugValueCall = flip(isReactHookCallWithName)("useDebugValue");
193
- var isUseDeferredValueCall = flip(isReactHookCallWithName)("useDeferredValue");
194
- var isUseEffectCall = flip(isReactHookCallWithName)("useEffect");
195
- var isUseFormStatusCall = flip(isReactHookCallWithName)("useFormStatus");
196
- var isUseIdCall = flip(isReactHookCallWithName)("useId");
197
- var isUseImperativeHandleCall = flip(isReactHookCallWithName)("useImperativeHandle");
198
- var isUseInsertionEffectCall = flip(isReactHookCallWithName)("useInsertionEffect");
199
- var isUseLayoutEffectCall = flip(isReactHookCallWithName)("useLayoutEffect");
200
- var isUseMemoCall = flip(isReactHookCallWithName)("useMemo");
201
- var isUseOptimisticCall = flip(isReactHookCallWithName)("useOptimistic");
202
- var isUseReducerCall = flip(isReactHookCallWithName)("useReducer");
203
- var isUseRefCall = flip(isReactHookCallWithName)("useRef");
204
- var isUseStateCall = flip(isReactHookCallWithName)("useState");
205
- var isUseSyncExternalStoreCall = flip(isReactHookCallWithName)("useSyncExternalStore");
206
- var isUseTransitionCall = flip(isReactHookCallWithName)("useTransition");
207
-
208
- // src/hook/hook-collector.ts
209
- function useHookCollector() {
210
- const hooks = /* @__PURE__ */ new Map();
211
- const functionEntries = [];
212
- const onFunctionEnter = (node) => {
213
- const id = AST9.getFunctionId(node);
214
- const key = getId();
215
- const name = id?.name;
216
- if (name != null && isReactHookName(name)) {
217
- functionEntries.push({ key, node, isHook: true });
218
- hooks.set(key, {
219
- id,
220
- key,
221
- kind: "function",
222
- name,
223
- node,
224
- flag: 0n,
225
- hint: 0n,
226
- hookCalls: []
227
- });
228
- return;
229
- }
230
- functionEntries.push({ key, node, isHook: false });
231
- };
232
- const onFunctionExit = () => {
233
- functionEntries.pop();
234
- };
235
- const ctx = {
236
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
237
- getAllHooks(node) {
238
- return hooks;
239
- }
240
- };
241
- const listeners = {
242
- ":function[type]": onFunctionEnter,
243
- ":function[type]:exit": onFunctionExit,
244
- "CallExpression[type]"(node) {
245
- if (!isReactHookCall(node)) {
246
- return;
247
- }
248
- const fEntry = functionEntries.at(-1);
249
- if (fEntry?.key == null) {
250
- return;
251
- }
252
- const hook = hooks.get(fEntry.key);
253
- if (hook == null) {
254
- return;
255
- }
256
- hook.hookCalls.push(node);
257
- }
258
- };
259
- return { ctx, listeners };
260
- }
261
- function isFunctionOfUseEffectSetup(node) {
262
- if (node == null) return false;
263
- return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && node.parent.callee.type === AST_NODE_TYPES.Identifier && node.parent.arguments.at(0) === node && isUseEffectCallLoose(node.parent);
264
- }
265
- function isFunctionOfUseEffectCleanup(node) {
266
- if (node == null) return false;
267
- const pReturn = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.ReturnStatement));
268
- const pFunction = AST9.findParentNode(node, AST9.isFunction);
269
- const pFunctionOfReturn = AST9.findParentNode(pReturn, AST9.isFunction);
270
- if (pFunction !== pFunctionOfReturn) return false;
271
- return isFunctionOfUseEffectSetup(pFunction);
272
- }
273
- function stringifyJsx(node) {
274
- switch (node.type) {
275
- case AST_NODE_TYPES.JSXIdentifier:
276
- return node.name;
277
- case AST_NODE_TYPES.JSXNamespacedName:
278
- return `${node.namespace.name}:${node.name.name}`;
279
- case AST_NODE_TYPES.JSXMemberExpression:
280
- return `${stringifyJsx(node.object)}.${stringifyJsx(node.property)}`;
281
- case AST_NODE_TYPES.JSXText:
282
- return node.value;
283
- case AST_NODE_TYPES.JSXOpeningElement:
284
- return `<${stringifyJsx(node.name)}>`;
285
- case AST_NODE_TYPES.JSXClosingElement:
286
- return `</${stringifyJsx(node.name)}>`;
287
- case AST_NODE_TYPES.JSXOpeningFragment:
288
- return "<>";
289
- case AST_NODE_TYPES.JSXClosingFragment:
290
- return "</>";
291
- }
292
- }
293
-
294
- // src/jsx/jsx-attribute-name.ts
295
- function getAttributeName(context, node) {
296
- return stringifyJsx(node.name);
297
- }
298
-
299
- // src/jsx/jsx-attribute.ts
300
- function getAttribute(context, name, attributes, initialScope) {
301
- return attributes.findLast((attr) => {
302
- if (attr.type === AST_NODE_TYPES.JSXAttribute) {
303
- return getAttributeName(context, attr) === name;
304
- }
305
- if (initialScope == null) return false;
306
- switch (attr.argument.type) {
307
- case AST_NODE_TYPES.Identifier: {
308
- const variable = VAR3.findVariable(attr.argument.name, initialScope);
309
- const variableNode = VAR3.getVariableInitNode(variable, 0);
310
- if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) {
311
- return VAR3.findPropertyInProperties(name, variableNode.properties, initialScope) != null;
312
- }
313
- return false;
314
- }
315
- case AST_NODE_TYPES.ObjectExpression:
316
- return VAR3.findPropertyInProperties(name, attr.argument.properties, initialScope) != null;
317
- }
318
- return false;
319
- });
320
- }
321
- function getAttributeValue(context, node, name) {
322
- const initialScope = context.sourceCode.getScope(node);
323
- switch (node.type) {
324
- case AST_NODE_TYPES.JSXAttribute:
325
- if (node.value?.type === AST_NODE_TYPES.Literal) {
326
- return {
327
- kind: "some",
328
- node: node.value,
329
- initialScope,
330
- value: node.value.value
331
- };
332
- }
333
- if (node.value?.type === AST_NODE_TYPES.JSXExpressionContainer) {
334
- return VAR3.toStaticValue({
335
- kind: "lazy",
336
- node: node.value.expression,
337
- initialScope
338
- });
339
- }
340
- return { kind: "none", node, initialScope };
341
- case AST_NODE_TYPES.JSXSpreadAttribute: {
342
- const staticValue = VAR3.toStaticValue({
343
- kind: "lazy",
344
- node: node.argument,
345
- initialScope
346
- });
347
- if (staticValue.kind === "none") {
348
- return staticValue;
349
- }
350
- return match(staticValue.value).with({ [name]: P.select(P.any) }, (value) => ({
351
- kind: "some",
352
- node: node.argument,
353
- initialScope,
354
- value
355
- })).otherwise(() => ({ kind: "none", node, initialScope }));
356
- }
357
- default:
358
- return { kind: "none", node, initialScope };
359
- }
360
- }
361
-
362
- // src/jsx/jsx-detection-hint.ts
363
- var JSXDetectionHint = {
364
- None: 0n,
365
- SkipUndefined: 1n << 0n,
366
- SkipNullLiteral: 1n << 1n,
367
- SkipBooleanLiteral: 1n << 2n,
368
- SkipStringLiteral: 1n << 3n,
369
- SkipNumberLiteral: 1n << 4n,
370
- SkipBigIntLiteral: 1n << 5n,
371
- SkipEmptyArray: 1n << 6n,
372
- SkipCreateElement: 1n << 7n,
373
- StrictArray: 1n << 8n,
374
- StrictLogical: 1n << 9n,
375
- StrictConditional: 1n << 10n
376
- };
377
- var DEFAULT_JSX_DETECTION_HINT = 0n | JSXDetectionHint.SkipUndefined | JSXDetectionHint.SkipBooleanLiteral;
378
-
379
- // src/jsx/jsx-detection.ts
380
- function isJsxText(node) {
381
- if (node == null) return false;
382
- return node.type === AST_NODE_TYPES.JSXText || node.type === AST_NODE_TYPES.Literal;
383
- }
384
- function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
385
- if (node == null) return false;
386
- if (AST9.isJSX(node)) return true;
387
- switch (node.type) {
388
- case AST_NODE_TYPES.Literal: {
389
- switch (typeof node.value) {
390
- case "boolean":
391
- return !(hint & JSXDetectionHint.SkipBooleanLiteral);
392
- case "string":
393
- return !(hint & JSXDetectionHint.SkipStringLiteral);
394
- case "number":
395
- return !(hint & JSXDetectionHint.SkipNumberLiteral);
396
- case "bigint":
397
- return !(hint & JSXDetectionHint.SkipBigIntLiteral);
398
- }
399
- if (node.value == null) {
400
- return !(hint & JSXDetectionHint.SkipNullLiteral);
401
- }
402
- return false;
403
- }
404
- case AST_NODE_TYPES.TemplateLiteral: {
405
- return !(hint & JSXDetectionHint.SkipStringLiteral);
406
- }
407
- case AST_NODE_TYPES.ArrayExpression: {
408
- if (node.elements.length === 0) {
409
- return !(hint & JSXDetectionHint.SkipEmptyArray);
410
- }
411
- if (hint & JSXDetectionHint.StrictArray) {
412
- return node.elements.every((n) => isJsxLike(code, n, hint));
413
- }
414
- return node.elements.some((n) => isJsxLike(code, n, hint));
415
- }
416
- case AST_NODE_TYPES.LogicalExpression: {
417
- if (hint & JSXDetectionHint.StrictLogical) {
418
- return isJsxLike(code, node.left, hint) && isJsxLike(code, node.right, hint);
419
- }
420
- return isJsxLike(code, node.left, hint) || isJsxLike(code, node.right, hint);
421
- }
422
- case AST_NODE_TYPES.ConditionalExpression: {
423
- let leftHasJSX2 = function(node2) {
424
- if (Array.isArray(node2.consequent)) {
425
- if (node2.consequent.length === 0) {
426
- return !(hint & JSXDetectionHint.SkipEmptyArray);
427
- }
428
- if (hint & JSXDetectionHint.StrictArray) {
429
- return node2.consequent.every((n) => isJsxLike(code, n, hint));
430
- }
431
- return node2.consequent.some((n) => isJsxLike(code, n, hint));
432
- }
433
- return isJsxLike(code, node2.consequent, hint);
434
- }, rightHasJSX2 = function(node2) {
435
- return isJsxLike(code, node2.alternate, hint);
436
- };
437
- if (hint & JSXDetectionHint.StrictConditional) {
438
- return leftHasJSX2(node) && rightHasJSX2(node);
439
- }
440
- return leftHasJSX2(node) || rightHasJSX2(node);
441
- }
442
- case AST_NODE_TYPES.SequenceExpression: {
443
- const exp = node.expressions.at(-1);
444
- return isJsxLike(code, exp, hint);
445
- }
446
- case AST_NODE_TYPES.CallExpression: {
447
- if (hint & JSXDetectionHint.SkipCreateElement) {
448
- return false;
449
- }
450
- switch (node.callee.type) {
451
- case AST_NODE_TYPES.Identifier:
452
- return node.callee.name === "createElement";
453
- case AST_NODE_TYPES.MemberExpression:
454
- return node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "createElement";
455
- }
456
- return false;
457
- }
458
- case AST_NODE_TYPES.Identifier: {
459
- const { name } = node;
460
- if (name === "undefined") {
461
- return !(hint & JSXDetectionHint.SkipUndefined);
462
- }
463
- if (AST9.isJSXTagNameExpression(node)) {
464
- return true;
465
- }
466
- const variable = VAR3.findVariable(name, code.getScope(node));
467
- const variableNode = variable && VAR3.getVariableInitNode(variable, 0);
468
- return !!variableNode && isJsxLike(code, variableNode, hint);
469
- }
470
- }
471
- return false;
472
- }
473
- function getElementType(context, node) {
474
- if (node.type === AST_NODE_TYPES.JSXFragment) {
475
- return "";
476
- }
477
- return stringifyJsx(node.openingElement.name);
478
- }
479
-
480
- // src/jsx/jsx-has.ts
481
- function hasAttribute(context, name, attributes, initialScope) {
482
- return getAttribute(context, name, attributes, initialScope) != null;
483
- }
484
- function hasAnyAttribute(context, names, attributes, initialScope) {
485
- return names.some((n) => hasAttribute(context, n, attributes, initialScope));
486
- }
487
- function hasEveryAttribute(context, names, attributes, initialScope) {
488
- return names.every((n) => hasAttribute(context, n, attributes, initialScope));
489
- }
490
- function findParentAttribute(node, test = constTrue) {
491
- const guard = (node2) => {
492
- return node2.type === AST_NODE_TYPES.JSXAttribute && test(node2);
493
- };
494
- return AST9.findParentNode(node, guard);
495
- }
496
- function isHostElement(context, node) {
497
- return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
498
- }
499
- function isKeyedElement(context, node, initialScope) {
500
- return node.type === AST_NODE_TYPES.JSXElement && hasAttribute(context, "key", node.openingElement.attributes, initialScope);
501
- }
502
- function isFragmentElement(context, node, allowJSXFragment = false) {
503
- if (node == null) return false;
504
- if (node.type !== AST_NODE_TYPES.JSXElement && node.type !== AST_NODE_TYPES.JSXFragment) return false;
505
- if (node.type === AST_NODE_TYPES.JSXFragment) return allowJSXFragment;
506
- return getElementType(context, node).split(".").at(-1) === "Fragment";
507
- }
508
-
509
- // src/component/component-detection-hint.ts
510
- var ComponentDetectionHint = {
511
- /**
512
- * 1n << 0n - 1n << 63n are reserved for JSXDetectionHint
513
- */
514
- ...JSXDetectionHint,
515
- /**
516
- * Skip function component created by React.memo
517
- */
518
- SkipMemo: 1n << 64n,
519
- /**
520
- * Skip function component created by React.forwardRef
521
- */
522
- SkipForwardRef: 1n << 65n,
523
- /**
524
- * Skip function component defined as array map argument
525
- */
526
- SkipArrayMapArgument: 1n << 66n,
527
- /**
528
- * Skip function component defined on object method
529
- */
530
- SkipObjectMethod: 1n << 67n,
531
- /**
532
- * Skip function component defined on class method
533
- */
534
- SkipClassMethod: 1n << 68n,
535
- /**
536
- * Skip function component defined on class property
537
- */
538
- SkipClassProperty: 1n << 69n
539
- };
540
- var DEFAULT_COMPONENT_DETECTION_HINT = 0n | ComponentDetectionHint.SkipBooleanLiteral | ComponentDetectionHint.SkipEmptyArray | ComponentDetectionHint.SkipArrayMapArgument | ComponentDetectionHint.SkipNumberLiteral | ComponentDetectionHint.SkipStringLiteral | ComponentDetectionHint.SkipUndefined | ComponentDetectionHint.StrictArray | ComponentDetectionHint.StrictConditional | ComponentDetectionHint.StrictLogical;
541
- function isClassComponent(node) {
542
- if ("superClass" in node && node.superClass != null) {
543
- const re = /^(?:Pure)?Component$/u;
544
- switch (true) {
545
- case node.superClass.type === AST_NODE_TYPES.Identifier:
546
- return re.test(node.superClass.name);
547
- case (node.superClass.type === AST_NODE_TYPES.MemberExpression && node.superClass.property.type === AST_NODE_TYPES.Identifier):
548
- return re.test(node.superClass.property.name);
549
- }
550
- }
551
- return false;
552
- }
553
- function isPureComponent(node) {
554
- if ("superClass" in node && node.superClass != null) {
555
- const re = /^PureComponent$/u;
556
- switch (true) {
557
- case node.superClass.type === AST_NODE_TYPES.Identifier:
558
- return re.test(node.superClass.name);
559
- case (node.superClass.type === AST_NODE_TYPES.MemberExpression && node.superClass.property.type === AST_NODE_TYPES.Identifier):
560
- return re.test(node.superClass.property.name);
561
- }
562
- }
563
- return false;
564
- }
565
- function isComponentDidCatch(node) {
566
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
567
- }
568
- function isComponentDidMount(node) {
569
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
570
- }
571
- function isComponentDidUpdate(node) {
572
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidUpdate";
573
- }
574
- function isComponentWillMount(node) {
575
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillMount";
576
- }
577
- function isComponentWillReceiveProps(node) {
578
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillReceiveProps";
579
- }
580
- function isComponentWillUnmount(node) {
581
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
582
- }
583
- function isComponentWillUpdate(node) {
584
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUpdate";
585
- }
586
- function isGetChildContext(node) {
587
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getChildContext";
588
- }
589
- function isGetDefaultProps(node) {
590
- return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDefaultProps";
591
- }
592
- function isGetInitialState(node) {
593
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getInitialState";
594
- }
595
- function isGetSnapshotBeforeUpdate(node) {
596
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getSnapshotBeforeUpdate";
597
- }
598
- function isShouldComponentUpdate(node) {
599
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "shouldComponentUpdate";
600
- }
601
- function isUnsafeComponentWillMount(node) {
602
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillMount";
603
- }
604
- function isUnsafeComponentWillReceiveProps(node) {
605
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillReceiveProps";
606
- }
607
- function isUnsafeComponentWillUpdate(node) {
608
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillUpdate";
609
- }
610
- function isGetDerivedStateFromProps(node) {
611
- return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
612
- }
613
- function isGetDerivedStateFromError(node) {
614
- return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
615
- }
616
- function isRenderLike(node) {
617
- return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
618
- }
619
- function isFunctionOfRender(node) {
620
- if (!isRenderLike(node.parent)) {
621
- return false;
622
- }
623
- return isClassComponent(node.parent.parent.parent);
624
- }
625
- function isRenderMethodLike(node) {
626
- return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render") && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
627
- }
628
-
629
- // src/component/component-hierarchy.ts
630
- function isChildrenOfCreateElement(context, node) {
631
- const parent = node.parent;
632
- if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
633
- if (!isCreateElementCall(context, parent)) return false;
634
- return parent.arguments.slice(2).some((arg) => arg === node);
635
- }
636
- function isInsideRenderMethod(node) {
637
- return AST9.findParentNode(node, (n) => isRenderLike(n) && isClassComponent(n.parent.parent)) != null;
638
- }
639
- function isFunctionOfComponentDidMount(node) {
640
- return AST9.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
641
- }
642
- function isFunctionOfComponentWillUnmount(node) {
643
- return AST9.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
644
- }
645
- function isFunctionOfRenderMethod(node) {
646
- if (!isRenderMethodLike(node.parent)) {
647
- return false;
648
- }
649
- return isClassComponent(node.parent.parent.parent);
650
- }
651
-
652
- // src/component/component-definition.ts
653
- var isFunctionOfClassMethod = isMatching({
654
- type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
655
- parent: AST_NODE_TYPES.MethodDefinition
656
- });
657
- var isFunctionOfClassProperty = isMatching({
658
- type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
659
- parent: AST_NODE_TYPES.Property
660
- });
661
- var isFunctionOfObjectMethod = isMatching({
662
- type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
663
- parent: {
664
- type: AST_NODE_TYPES.Property,
665
- parent: {
666
- type: AST_NODE_TYPES.ObjectExpression
667
- }
668
- }
669
- });
670
- function isValidComponentDefinition(context, node, hint) {
671
- if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) {
672
- return false;
673
- }
674
- if (hint & ComponentDetectionHint.SkipObjectMethod && isFunctionOfObjectMethod(node.parent)) {
675
- return false;
676
- }
677
- if (hint & ComponentDetectionHint.SkipClassMethod && isFunctionOfClassMethod(node.parent)) {
678
- return false;
679
- }
680
- if (hint & ComponentDetectionHint.SkipClassProperty && isFunctionOfClassProperty(node.parent)) {
681
- return false;
682
- }
683
- if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST9.isArrayMapCall(node.parent)) {
684
- return false;
685
- }
686
- const significantParent = AST9.findParentNode(
687
- node,
688
- AST9.isOneOf([
689
- AST_NODE_TYPES.JSXExpressionContainer,
690
- AST_NODE_TYPES.ArrowFunctionExpression,
691
- AST_NODE_TYPES.FunctionExpression,
692
- AST_NODE_TYPES.Property,
693
- AST_NODE_TYPES.ClassBody
694
- ])
695
- );
696
- return significantParent == null || significantParent.type !== AST_NODE_TYPES.JSXExpressionContainer;
697
- }
698
- function isComponentWrapperCall(context, node) {
699
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
700
- return isMemoCall(context, node) || isForwardRefCall(context, node);
701
- }
702
- function isComponentWrapperCallLoose(context, node) {
703
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
704
- return isComponentWrapperCall(context, node) || isUseCallbackCall(context, node);
705
- }
706
-
707
- // src/component/component-id.ts
708
- function getFunctionComponentId(context, node) {
709
- const functionId = AST9.getFunctionId(node);
710
- if (functionId != null) {
711
- return functionId;
712
- }
713
- const { parent } = node;
714
- if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent) && parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.id.type === AST_NODE_TYPES.Identifier) {
715
- return parent.parent.id;
716
- }
717
- if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
718
- return parent.parent.parent.id;
719
- }
720
- return unit;
721
- }
722
-
723
- // src/component/component-flag.ts
724
- var ComponentFlag = {
725
- None: 0n,
726
- PureComponent: 1n << 0n,
727
- CreateElement: 1n << 1n,
728
- Memo: 1n << 2n,
729
- ForwardRef: 1n << 3n,
730
- Async: 1n << 4n
731
- };
732
-
733
- // src/component/component-init-path.ts
734
- function getComponentFlagFromInitPath(initPath) {
735
- let flag = ComponentFlag.None;
736
- if (initPath != null && AST9.hasCallInFunctionInitPath("memo", initPath)) {
737
- flag |= ComponentFlag.Memo;
738
- }
739
- if (initPath != null && AST9.hasCallInFunctionInitPath("forwardRef", initPath)) {
740
- flag |= ComponentFlag.ForwardRef;
741
- }
742
- return flag;
743
- }
744
- function isComponentName(name) {
745
- return RegExp.COMPONENT_NAME.test(name);
746
- }
747
- function isComponentNameLoose(name) {
748
- return RegExp.COMPONENT_NAME_LOOSE.test(name);
749
- }
750
- function getComponentNameFromId(id) {
751
- if (id == null) return unit;
752
- return Array.isArray(id) ? id.map((n) => n.name).join(".") : id.name;
753
- }
754
- function hasNoneOrLooseComponentName(context, fn) {
755
- const id = getFunctionComponentId(context, fn);
756
- if (id == null) return true;
757
- const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
758
- return name != null && isComponentNameLoose(name);
759
- }
760
-
761
- // src/component/component-collector.ts
762
- function useComponentCollector(context, options = {}) {
763
- const {
764
- collectDisplayName = false,
765
- collectHookCalls = false,
766
- hint = DEFAULT_COMPONENT_DETECTION_HINT
767
- } = options;
768
- const components = /* @__PURE__ */ new Map();
769
- const functionEntries = [];
770
- const getCurrentEntry = () => functionEntries.at(-1);
771
- const onFunctionEnter = (node) => {
772
- const key = getId();
773
- functionEntries.push({ key, node, hookCalls: [], isComponent: false });
774
- };
775
- const onFunctionExit = () => {
776
- const entry = functionEntries.at(-1);
777
- if (entry == null) return;
778
- if (!entry.isComponent) return functionEntries.pop();
779
- const rets = AST9.getNestedReturnStatements(entry.node.body);
780
- for (let i = rets.length - 1; i >= 0; i--) {
781
- const ret = rets[i];
782
- if (ret == null) continue;
783
- const shouldDrop = context.sourceCode.getScope(ret).block === entry.node && ret.argument != null && !isJsxLike(context.sourceCode, ret.argument, hint);
784
- if (shouldDrop) {
785
- components.delete(entry.key);
786
- break;
787
- }
788
- }
789
- return functionEntries.pop();
790
- };
791
- const ctx = {
792
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
793
- getAllComponents(node) {
794
- return components;
795
- },
796
- getCurrentEntries() {
797
- return [...functionEntries];
798
- },
799
- getCurrentEntry
800
- };
801
- const listeners = {
802
- ":function[type]": onFunctionEnter,
803
- ":function[type]:exit": onFunctionExit,
804
- "ArrowFunctionExpression[body.type!='BlockStatement']"() {
805
- const entry = getCurrentEntry();
806
- if (entry == null) return;
807
- const { body } = entry.node;
808
- const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, body, hint) && isValidComponentDefinition(context, entry.node, hint);
809
- if (!isComponent) return;
810
- const initPath = AST9.getFunctionInitPath(entry.node);
811
- const id = getFunctionComponentId(context, entry.node);
812
- const name = getComponentNameFromId(id);
813
- const key = getId();
814
- components.set(key, {
815
- id,
816
- key,
817
- kind: "function",
818
- name,
819
- node: entry.node,
820
- displayName: unit,
821
- flag: getComponentFlagFromInitPath(initPath),
822
- hint,
823
- hookCalls: entry.hookCalls,
824
- initPath
825
- });
826
- },
827
- ...collectDisplayName ? {
828
- [Selector.DISPLAY_NAME_ASSIGNMENT_EXPRESSION](node) {
829
- const { left, right } = node;
830
- if (left.type !== AST_NODE_TYPES.MemberExpression) return;
831
- const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : unit;
832
- const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
833
- if (component == null) return;
834
- component.displayName = right;
835
- }
836
- } : {},
837
- ...collectHookCalls ? {
838
- "CallExpression[type]:exit"(node) {
839
- if (!isReactHookCall(node)) return;
840
- const entry = getCurrentEntry();
841
- if (entry == null) return;
842
- entry.hookCalls.push(node);
843
- }
844
- } : {},
845
- "ReturnStatement[type]"(node) {
846
- const entry = getCurrentEntry();
847
- if (entry == null) return;
848
- const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, node.argument, hint) && isValidComponentDefinition(context, entry.node, hint);
849
- if (!isComponent) return;
850
- entry.isComponent = true;
851
- const initPath = AST9.getFunctionInitPath(entry.node);
852
- const id = getFunctionComponentId(context, entry.node);
853
- const name = getComponentNameFromId(id);
854
- components.set(entry.key, {
855
- id,
856
- key: entry.key,
857
- kind: "function",
858
- name,
859
- node: entry.node,
860
- displayName: unit,
861
- flag: getComponentFlagFromInitPath(initPath),
862
- hint,
863
- hookCalls: entry.hookCalls,
864
- initPath
865
- });
866
- }
867
- };
868
- return { ctx, listeners };
869
- }
870
- function useComponentCollectorLegacy() {
871
- const components = /* @__PURE__ */ new Map();
872
- const ctx = {
873
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
874
- getAllComponents(node) {
875
- return components;
876
- }
877
- };
878
- const collect = (node) => {
879
- if (!isClassComponent(node)) {
880
- return;
881
- }
882
- const id = AST9.getClassId(node);
883
- const key = getId();
884
- const flag = isPureComponent(node) ? ComponentFlag.PureComponent : ComponentFlag.None;
885
- components.set(
886
- key,
887
- {
888
- id,
889
- key,
890
- kind: "class",
891
- name: id?.name,
892
- node,
893
- // TODO: Get displayName of class component
894
- displayName: unit,
895
- flag,
896
- hint: 0n,
897
- // TODO: Get methods of class component
898
- methods: []
899
- }
900
- );
901
- };
902
- const listeners = {
903
- "ClassDeclaration[type]": collect,
904
- "ClassExpression[type]": collect
905
- };
906
- return { ctx, listeners };
907
- }
908
- var ComponentPhaseRelevance = birecord({
909
- mount: "unmount",
910
- setup: "cleanup"
911
- });
912
- var isInversePhase = dual(2, (a, b) => ComponentPhaseRelevance.get(a) === b);
913
- function isRenderFunctionLoose(context, node) {
914
- const { body, parent } = node;
915
- if (AST9.getFunctionId(node)?.name.startsWith("render")) {
916
- return parent.type === AST_NODE_TYPES.JSXExpressionContainer && parent.parent.type === AST_NODE_TYPES.JSXAttribute && parent.parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.parent.name.name.startsWith("render");
917
- }
918
- return isJsxLike(
919
- context.sourceCode,
920
- body,
921
- JSXDetectionHint.SkipNullLiteral | JSXDetectionHint.SkipUndefined | JSXDetectionHint.StrictLogical | JSXDetectionHint.StrictConditional
922
- );
923
- }
924
- function isRenderPropLoose(context, node) {
925
- if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {
926
- return false;
927
- }
928
- return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST9.isFunction(node.value.expression) && isRenderFunctionLoose(context, node.value.expression);
929
- }
930
- function isDirectValueOfRenderPropertyLoose(node) {
931
- const matching = (node2) => {
932
- return node2.type === AST_NODE_TYPES.Property && node2.key.type === AST_NODE_TYPES.Identifier && node2.key.name.startsWith("render");
933
- };
934
- return matching(node) || node.parent != null && matching(node.parent);
935
- }
936
- function isDeclaredInRenderPropLoose(node) {
937
- if (isDirectValueOfRenderPropertyLoose(node)) {
938
- return true;
939
- }
940
- const parent = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
941
- if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
942
- return false;
943
- }
944
- return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
945
- }
946
- function isThisSetState(node) {
947
- const { callee } = node;
948
- return callee.type === AST_NODE_TYPES.MemberExpression && AST9.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
949
- }
950
- function isAssignmentToThisState(node) {
951
- const { left } = node;
952
- return left.type === AST_NODE_TYPES.MemberExpression && AST9.isThisExpression(left.object) && AST9.getPropertyName(left.property) === "state";
953
- }
954
-
955
- export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRender, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInsideRenderMethod, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isKeyedElement, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderLike, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, isValidComponentDefinition, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };