@eslint-react/core 2.0.0-next.0 → 2.0.0-next.2

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