@eslint-react/core 1.23.2 → 1.23.3-beta.5

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 CHANGED
@@ -1,4 +1,4 @@
1
- import * as AST9 from '@eslint-react/ast';
1
+ import * as AST8 from '@eslint-react/ast';
2
2
  import { F, isString, O } from '@eslint-react/eff';
3
3
  import * as JSX4 from '@eslint-react/jsx';
4
4
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
@@ -10,10 +10,14 @@ import { birecord } from '@eslint-react/types';
10
10
  // src/component/component-collector.ts
11
11
  function getElementRepresentName(node, context) {
12
12
  const rawElementName = JSX4.getElementName(node);
13
- if (rawElementName === rawElementName.toLowerCase()) return rawElementName;
13
+ if (rawElementName === rawElementName.toLowerCase()) {
14
+ return rawElementName;
15
+ }
14
16
  const { components, polymorphicPropName } = getSettingsFromContext(context);
15
17
  const asElementName = components.get(rawElementName);
16
- if (isString(asElementName)) return asElementName;
18
+ if (isString(asElementName)) {
19
+ return asElementName;
20
+ }
17
21
  return F.pipe(
18
22
  O.fromNullable(polymorphicPropName),
19
23
  O.flatMap(JSX4.findPropInAttributes(node.attributes, context.sourceCode.getScope(node))),
@@ -58,15 +62,21 @@ function isFromReactMember(memberName, name) {
58
62
  return (node, context) => {
59
63
  const settings = unsafeDecodeSettings(context.settings);
60
64
  if (!settings.strictImportCheck) {
61
- if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
62
- if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) return true;
65
+ if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) {
66
+ return false;
67
+ }
68
+ if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
69
+ return true;
70
+ }
63
71
  if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && node.object.property.type === AST_NODE_TYPES.Identifier) {
64
72
  return node.object.property.name === memberName;
65
73
  }
66
74
  return false;
67
75
  }
68
76
  const initialScope = context.sourceCode.getScope(node);
69
- if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
77
+ if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) {
78
+ return false;
79
+ }
70
80
  if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
71
81
  return isInitializedFromReact(node.object.name, initialScope, settings.importSource);
72
82
  }
@@ -78,15 +88,23 @@ function isFromReactMember(memberName, name) {
78
88
  }
79
89
  function isCallFromReact(name) {
80
90
  return F.dual(2, (node, context) => {
81
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
82
- if (!AST9.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) return false;
91
+ if (node.type !== AST_NODE_TYPES.CallExpression) {
92
+ return false;
93
+ }
94
+ if (!AST8.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) {
95
+ return false;
96
+ }
83
97
  return isFromReact(name)(node.callee, context);
84
98
  });
85
99
  }
86
100
  function isCallFromReactMember(pragmaMemberName, name) {
87
101
  return F.dual(2, (node, context) => {
88
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
89
- if (!AST9.is(AST_NODE_TYPES.MemberExpression)(node.callee)) return false;
102
+ if (node.type !== AST_NODE_TYPES.CallExpression) {
103
+ return false;
104
+ }
105
+ if (!AST8.is(AST_NODE_TYPES.MemberExpression)(node.callee)) {
106
+ return false;
107
+ }
90
108
  return isFromReactMember(pragmaMemberName, name)(node.callee, context);
91
109
  });
92
110
  }
@@ -125,8 +143,8 @@ var isMemoCall = isReactAPICallWithName("memo");
125
143
  function isInsideCreateElementProps(node, context) {
126
144
  return F.pipe(
127
145
  O.Do,
128
- O.bind("call", () => AST9.findParentNodeGuard(node, isCreateElementCall(context))),
129
- O.bind("prop", () => AST9.findParentNodeGuard(node, AST9.is(AST_NODE_TYPES.ObjectExpression))),
146
+ O.bind("call", () => AST8.findParentNodeGuard(node, isCreateElementCall(context))),
147
+ O.bind("prop", () => AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.ObjectExpression))),
130
148
  O.bind("arg1", ({ call }) => O.fromNullable(call.arguments[1])),
131
149
  O.exists(({ arg1, prop }) => prop === arg1)
132
150
  );
@@ -134,7 +152,7 @@ function isInsideCreateElementProps(node, context) {
134
152
  function isChildrenOfCreateElement(node, context) {
135
153
  return F.pipe(
136
154
  O.fromNullable(node.parent),
137
- O.filter(AST9.is(AST_NODE_TYPES.CallExpression)),
155
+ O.filter(AST8.is(AST_NODE_TYPES.CallExpression)),
138
156
  O.filter(isCreateElementCall(context)),
139
157
  O.exists(
140
158
  (n) => n.arguments.slice(2).some((arg) => arg === node)
@@ -151,14 +169,18 @@ function isReactHookName(name) {
151
169
  // src/hook/is.ts
152
170
  function isReactHook(node) {
153
171
  return F.pipe(
154
- AST9.getFunctionIdentifier(node),
172
+ AST8.getFunctionIdentifier(node),
155
173
  O.flatMapNullable((id2) => id2.name),
156
174
  O.exists(isReactHookName)
157
175
  );
158
176
  }
159
177
  function isReactHookCall(node) {
160
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
161
- if (node.callee.type === AST_NODE_TYPES.Identifier) return isReactHookName(node.callee.name);
178
+ if (node.type !== AST_NODE_TYPES.CallExpression) {
179
+ return false;
180
+ }
181
+ if (node.callee.type === AST_NODE_TYPES.Identifier) {
182
+ return isReactHookName(node.callee.name);
183
+ }
162
184
  if (node.callee.type === AST_NODE_TYPES.MemberExpression) {
163
185
  return node.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.callee.property.name);
164
186
  }
@@ -205,7 +227,9 @@ function isReactHookCallWithNameAlias(name, context, alias) {
205
227
  };
206
228
  }
207
229
  function isUseEffectCallLoose(node) {
208
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
230
+ if (node.type !== AST_NODE_TYPES.CallExpression) {
231
+ return false;
232
+ }
209
233
  switch (node.callee.type) {
210
234
  case AST_NODE_TYPES.Identifier:
211
235
  return /^use\w*Effect$/u.test(node.callee.name);
@@ -233,13 +257,13 @@ var isUseTransitionCall = F.flip(isReactHookCallWithName)("useTransition");
233
257
 
234
258
  // src/hook/hierarchy.ts
235
259
  function isInsideReactHook(node) {
236
- return O.exists(AST9.findParentNodeGuard(node, AST9.isFunction), isReactHook);
260
+ return O.exists(AST8.findParentNodeGuard(node, AST8.isFunction), isReactHook);
237
261
  }
238
262
  function useHookCollector() {
239
263
  const hooks = /* @__PURE__ */ new Map();
240
264
  const fStack = [];
241
265
  const onFunctionEnter = (node) => {
242
- const id2 = AST9.getFunctionIdentifier(node);
266
+ const id2 = AST8.getFunctionIdentifier(node);
243
267
  const name = O.flatMapNullable(id2, (id3) => id3.name);
244
268
  if (O.isSome(id2) && O.isSome(name) && isReactHookName(name.value)) {
245
269
  const key = getId();
@@ -273,9 +297,13 @@ function useHookCollector() {
273
297
  ":function[type]": onFunctionEnter,
274
298
  ":function[type]:exit": onFunctionExit,
275
299
  "CallExpression[type]"(node) {
276
- if (!isReactHookCall(node)) return;
300
+ if (!isReactHookCall(node)) {
301
+ return;
302
+ }
277
303
  const [fNode, hookId] = fStack.at(-1) ?? [];
278
- if (!fNode || !hookId) return;
304
+ if (!fNode || !hookId) {
305
+ return;
306
+ }
279
307
  F.pipe(
280
308
  O.Do,
281
309
  O.bind("id", () => hookId),
@@ -310,7 +338,7 @@ var ERComponentHint = {
310
338
  // Skip function component defined on class property
311
339
  SkipClassProperty: 1n << 69n
312
340
  };
313
- var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefinedLiteral | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
341
+ var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefined | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
314
342
 
315
343
  // src/component/component-flag.ts
316
344
  var ERClassComponentFlag = {
@@ -331,12 +359,16 @@ var ERFunctionComponentFlag = {
331
359
  // Async: 1n << 4n,
332
360
  };
333
361
  function isComponentWrapperCall(node, context) {
334
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
362
+ if (node.type !== AST_NODE_TYPES.CallExpression) {
363
+ return false;
364
+ }
335
365
  return isMemoCall(node, context) || isForwardRefCall(node, context) || isReactHookCallWithNameLoose(node)("useCallback");
336
366
  }
337
367
  function getFunctionComponentIdentifier(node, context) {
338
- const functionId = AST9.getFunctionIdentifier(node);
339
- if (O.isSome(functionId)) return functionId;
368
+ const functionId = AST8.getFunctionIdentifier(node);
369
+ if (O.isSome(functionId)) {
370
+ return functionId;
371
+ }
340
372
  const { parent } = node;
341
373
  if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(parent, context) && parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.id.type === AST_NODE_TYPES.Identifier) {
342
374
  return O.some(parent.parent.id);
@@ -356,98 +388,42 @@ function isComponentName(name) {
356
388
  return !!name && RE_COMPONENT_NAME.test(name);
357
389
  }
358
390
  function isClassComponent(node) {
359
- if (!("superClass" in node && node.superClass)) return false;
360
- const { superClass } = node;
361
- return match(superClass).with({
362
- type: AST_NODE_TYPES.Identifier,
363
- name: P.string
364
- }, ({ name }) => /^(?:Pure)?Component$/u.test(name)).with({
365
- type: AST_NODE_TYPES.MemberExpression,
366
- property: { name: P.string }
367
- }, ({ property }) => /^(?:Pure)?Component$/u.test(property.name)).otherwise(() => false);
368
- }
369
- function isPureComponent(node) {
370
391
  if ("superClass" in node && node.superClass) {
371
- return match(node.superClass).with({
372
- type: AST_NODE_TYPES.Identifier,
373
- name: P.string
374
- }, ({ name }) => /^PureComponent$/u.test(name)).with({
375
- type: AST_NODE_TYPES.MemberExpression,
376
- property: { name: P.string }
377
- }, ({ property }) => /^PureComponent$/u.test(property.name)).otherwise(() => false);
392
+ const re = /^(?:Pure)?Component$/u;
393
+ switch (true) {
394
+ case node.superClass.type === AST_NODE_TYPES.Identifier:
395
+ return re.test(node.superClass.name);
396
+ case (node.superClass.type === AST_NODE_TYPES.MemberExpression && node.superClass.property.type === AST_NODE_TYPES.Identifier):
397
+ return re.test(node.superClass.property.name);
398
+ }
378
399
  }
379
400
  return false;
380
401
  }
381
- function isComponentDidMount(node) {
382
- return AST9.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
383
- }
384
- function isComponentWillUnmount(node) {
385
- return AST9.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
386
- }
387
- function isComponentDidMountFunction(node) {
388
- return AST9.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
389
- }
390
- function isComponentWillUnmountFunction(node) {
391
- return AST9.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
392
- }
393
- function useComponentCollectorLegacy() {
394
- const components = /* @__PURE__ */ new Map();
395
- const ctx = {
396
- getAllComponents(_) {
397
- return components;
402
+ function isPureComponent(node) {
403
+ if ("superClass" in node && node.superClass) {
404
+ const re = /^PureComponent$/u;
405
+ switch (true) {
406
+ case node.superClass.type === AST_NODE_TYPES.Identifier:
407
+ return re.test(node.superClass.name);
408
+ case (node.superClass.type === AST_NODE_TYPES.MemberExpression && node.superClass.property.type === AST_NODE_TYPES.Identifier):
409
+ return re.test(node.superClass.property.name);
398
410
  }
399
- };
400
- const collect = (node) => {
401
- if (!isClassComponent(node)) return;
402
- const id2 = AST9.getClassIdentifier(node);
403
- const key = getId();
404
- const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
405
- components.set(
406
- key,
407
- {
408
- _: key,
409
- id: id2,
410
- kind: "class",
411
- name: O.flatMapNullable(id2, (n) => n.name),
412
- node,
413
- // TODO: Get displayName of class component
414
- displayName: O.none(),
415
- flag,
416
- hint: 0n,
417
- // TODO: Get methods of class component
418
- methods: []
419
- }
420
- );
421
- };
422
- const listeners = {
423
- "ClassDeclaration[type]": collect,
424
- "ClassExpression[type]": collect
425
- };
426
- return { ctx, listeners };
411
+ }
412
+ return false;
427
413
  }
428
414
 
429
415
  // src/component/component-render-method.ts
430
- var isRenderMethodLike = isMatching({
431
- key: {
432
- type: AST_NODE_TYPES.Identifier,
433
- name: "render"
434
- },
435
- type: P.union(AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition),
436
- parent: {
437
- type: AST_NODE_TYPES.ClassBody,
438
- parent: {
439
- type: AST_NODE_TYPES.ClassDeclaration
440
- }
441
- }
442
- });
416
+ function isRenderMethodLike(node) {
417
+ return (node.type === AST_NODE_TYPES.MethodDefinition || node.type === AST_NODE_TYPES.PropertyDefinition) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
418
+ }
443
419
  function isFunctionOfRenderMethod(node) {
444
- if (!isRenderMethodLike(node.parent)) return false;
420
+ if (!isRenderMethodLike(node.parent)) {
421
+ return false;
422
+ }
445
423
  return isClassComponent(node.parent.parent.parent);
446
424
  }
447
425
  function isInsideRenderMethod(node) {
448
- return O.isSome(AST9.findParentNode(node, (node2) => {
449
- return isRenderMethodLike(node2) && isClassComponent(node2.parent.parent);
450
- }));
426
+ return O.isSome(AST8.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)));
451
427
  }
452
428
  function hasNoneOrValidComponentName(node, context) {
453
429
  const mbIdentifier = getFunctionComponentIdentifier(node, context);
@@ -464,22 +440,22 @@ function hasValidHierarchy(node, context, hint) {
464
440
  if (isChildrenOfCreateElement(node, context) || isFunctionOfRenderMethod(node)) {
465
441
  return false;
466
442
  }
467
- if (hint & ERComponentHint.SkipMapCallback && AST9.isMapCallLoose(node.parent)) {
443
+ if (hint & ERComponentHint.SkipMapCallback && AST8.isMapCallLoose(node.parent)) {
468
444
  return false;
469
445
  }
470
- if (hint & ERComponentHint.SkipObjectMethod && AST9.isFunctionOfObjectMethod(node.parent)) {
446
+ if (hint & ERComponentHint.SkipObjectMethod && AST8.isFunctionOfObjectMethod(node.parent)) {
471
447
  return false;
472
448
  }
473
- if (hint & ERComponentHint.SkipClassMethod && AST9.isFunctionOfClassMethod(node.parent)) {
449
+ if (hint & ERComponentHint.SkipClassMethod && AST8.isFunctionOfClassMethod(node.parent)) {
474
450
  return false;
475
451
  }
476
- if (hint & ERComponentHint.SkipClassProperty && AST9.isFunctionOfClassProperty(node.parent)) {
452
+ if (hint & ERComponentHint.SkipClassProperty && AST8.isFunctionOfClassProperty(node.parent)) {
477
453
  return false;
478
454
  }
479
455
  return !O.exists(
480
- AST9.findParentNode(
456
+ AST8.findParentNode(
481
457
  node,
482
- AST9.isOneOf([
458
+ AST8.isOneOf([
483
459
  AST_NODE_TYPES.JSXExpressionContainer,
484
460
  AST_NODE_TYPES.ArrowFunctionExpression,
485
461
  AST_NODE_TYPES.FunctionExpression,
@@ -487,15 +463,15 @@ function hasValidHierarchy(node, context, hint) {
487
463
  AST_NODE_TYPES.ClassBody
488
464
  ])
489
465
  ),
490
- AST9.is(AST_NODE_TYPES.JSXExpressionContainer)
466
+ AST8.is(AST_NODE_TYPES.JSXExpressionContainer)
491
467
  );
492
468
  }
493
469
  function getComponentFlag(initPath) {
494
470
  let flag = ERFunctionComponentFlag.None;
495
- if (AST9.hasCallInFunctionInitPath("memo")(initPath)) {
471
+ if (AST8.hasCallInFunctionInitPath("memo")(initPath)) {
496
472
  flag |= ERFunctionComponentFlag.Memo;
497
473
  }
498
- if (AST9.hasCallInFunctionInitPath("forwardRef")(initPath)) {
474
+ if (AST8.hasCallInFunctionInitPath("forwardRef")(initPath)) {
499
475
  flag |= ERFunctionComponentFlag.ForwardRef;
500
476
  }
501
477
  return flag;
@@ -510,12 +486,16 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
510
486
  functionEntries.push({ key, node, hookCalls: [], isComponent: false });
511
487
  };
512
488
  const onFunctionExit = () => {
513
- const { key, node, isComponent } = functionEntries.at(-1) ?? {};
514
- if (!key || !node || !isComponent) return functionEntries.pop();
515
- const shouldDrop = AST9.getNestedReturnStatements(node.body).slice().reverse().some((r) => {
516
- return context.sourceCode.getScope(r).block === node && r.argument !== null && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
489
+ const entry = functionEntries.at(-1);
490
+ if (!entry?.isComponent) {
491
+ return functionEntries.pop();
492
+ }
493
+ const shouldDrop = AST8.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
494
+ return context.sourceCode.getScope(r).block === entry.node && r.argument !== null && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
517
495
  });
518
- if (shouldDrop) components.delete(key);
496
+ if (shouldDrop) {
497
+ components.delete(entry.key);
498
+ }
519
499
  return functionEntries.pop();
520
500
  };
521
501
  const ctx = {
@@ -532,12 +512,16 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
532
512
  ":function[type]:exit": onFunctionExit,
533
513
  "ArrowFunctionExpression[type][body.type!='BlockStatement']"() {
534
514
  const mbEntry = getCurrentFunction();
535
- if (O.isNone(mbEntry)) return;
515
+ if (O.isNone(mbEntry)) {
516
+ return;
517
+ }
536
518
  const entry = mbEntry.value;
537
519
  const { body } = entry.node;
538
520
  const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
539
- if (!isComponent) return;
540
- const initPath = AST9.getFunctionInitPath(entry.node);
521
+ if (!isComponent) {
522
+ return;
523
+ }
524
+ const initPath = AST8.getFunctionInitPath(entry.node);
541
525
  const id2 = getFunctionComponentIdentifier(entry.node, context);
542
526
  const name = O.flatMapNullable(id2, getComponentNameFromIdentifier);
543
527
  const key = getId();
@@ -557,32 +541,44 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
557
541
  "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"(node) {
558
542
  const { left, right } = node;
559
543
  const mbComponentName = match(left.object).with({ type: AST_NODE_TYPES.Identifier }, (n) => O.some(n.name)).otherwise(O.none);
560
- if (O.isNone(mbComponentName)) return;
544
+ if (O.isNone(mbComponentName)) {
545
+ return;
546
+ }
561
547
  const componentName = mbComponentName.value;
562
548
  const component = Array.from(components.values()).findLast(({ name }) => O.exists(name, (n) => n === componentName));
563
- if (!component) return;
549
+ if (!component) {
550
+ return;
551
+ }
564
552
  components.set(component._, {
565
553
  ...component,
566
554
  displayName: O.some(right)
567
555
  });
568
556
  },
569
557
  "CallExpression[type]:exit"(node) {
570
- if (!isReactHookCall(node)) return;
558
+ if (!isReactHookCall(node)) {
559
+ return;
560
+ }
571
561
  const mbEntry = getCurrentFunction();
572
- if (O.isNone(mbEntry)) return;
562
+ if (O.isNone(mbEntry)) {
563
+ return;
564
+ }
573
565
  const entry = mbEntry.value;
574
566
  functionEntries.pop();
575
567
  functionEntries.push({ ...entry, hookCalls: [...entry.hookCalls, node] });
576
568
  },
577
569
  "ReturnStatement[type]"(node) {
578
570
  const mbEntry = getCurrentFunction();
579
- if (O.isNone(mbEntry)) return;
571
+ if (O.isNone(mbEntry)) {
572
+ return;
573
+ }
580
574
  const entry = mbEntry.value;
581
575
  const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
582
- if (!isComponent) return;
576
+ if (!isComponent) {
577
+ return;
578
+ }
583
579
  functionEntries.pop();
584
580
  functionEntries.push({ ...entry, isComponent });
585
- const initPath = AST9.getFunctionInitPath(entry.node);
581
+ const initPath = AST8.getFunctionInitPath(entry.node);
586
582
  const id2 = getFunctionComponentIdentifier(entry.node, context);
587
583
  const name = O.flatMapNullable(id2, getComponentNameFromIdentifier);
588
584
  components.set(entry.key, {
@@ -601,17 +597,70 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
601
597
  };
602
598
  return { ctx, listeners };
603
599
  }
600
+ function useComponentCollectorLegacy() {
601
+ const components = /* @__PURE__ */ new Map();
602
+ const ctx = {
603
+ getAllComponents(_) {
604
+ return components;
605
+ }
606
+ };
607
+ const collect = (node) => {
608
+ if (!isClassComponent(node)) {
609
+ return;
610
+ }
611
+ const id2 = AST8.getClassIdentifier(node);
612
+ const key = getId();
613
+ const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
614
+ components.set(
615
+ key,
616
+ {
617
+ _: key,
618
+ id: id2,
619
+ kind: "class",
620
+ name: O.flatMapNullable(id2, (n) => n.name),
621
+ node,
622
+ // TODO: Get displayName of class component
623
+ displayName: O.none(),
624
+ flag,
625
+ hint: 0n,
626
+ // TODO: Get methods of class component
627
+ methods: []
628
+ }
629
+ );
630
+ };
631
+ const listeners = {
632
+ "ClassDeclaration[type]": collect,
633
+ "ClassExpression[type]": collect
634
+ };
635
+ return { ctx, listeners };
636
+ }
604
637
  function isSetupFunction(node) {
605
638
  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);
606
639
  }
607
640
  function isCleanupFunction(node) {
608
- const nearestRet = O.getOrNull(AST9.findParentNodeGuard(node, AST9.is(AST_NODE_TYPES.ReturnStatement)));
609
- if (!nearestRet) return false;
610
- const nearestFunction = O.getOrNull(AST9.findParentNodeGuard(node, AST9.isFunction));
611
- const nearestFunctionOfRet = O.getOrNull(AST9.findParentNodeGuard(nearestRet, AST9.isFunction));
612
- if (!nearestFunction || !nearestFunctionOfRet) return false;
641
+ const nearestRet = O.getOrNull(AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.ReturnStatement)));
642
+ if (!nearestRet) {
643
+ return false;
644
+ }
645
+ const nearestFunction = O.getOrNull(AST8.findParentNodeGuard(node, AST8.isFunction));
646
+ const nearestFunctionOfRet = O.getOrNull(AST8.findParentNodeGuard(nearestRet, AST8.isFunction));
647
+ if (!nearestFunction || !nearestFunctionOfRet) {
648
+ return false;
649
+ }
613
650
  return nearestFunction === nearestFunctionOfRet && isSetupFunction(nearestFunction);
614
651
  }
652
+ function isComponentDidMount(node) {
653
+ return AST8.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
654
+ }
655
+ function isComponentWillUnmount(node) {
656
+ return AST8.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
657
+ }
658
+ function isComponentDidMountFunction(node) {
659
+ return AST8.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
660
+ }
661
+ function isComponentWillUnmountFunction(node) {
662
+ return AST8.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
663
+ }
615
664
  var ERPhaseRelevance = birecord({
616
665
  mount: "unmount",
617
666
  setup: "cleanup"
@@ -632,9 +681,9 @@ function isDeclaredInRenderPropLoose(node) {
632
681
  return true;
633
682
  }
634
683
  return F.pipe(
635
- AST9.findParentNodeGuard(node, AST9.is(AST_NODE_TYPES.JSXExpressionContainer)),
684
+ AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.JSXExpressionContainer)),
636
685
  O.flatMapNullable((c) => c.parent),
637
- O.filter(AST9.is(AST_NODE_TYPES.JSXAttribute)),
686
+ O.filter(AST8.is(AST_NODE_TYPES.JSXAttribute)),
638
687
  O.flatMapNullable((a) => a.name),
639
688
  O.exists(isMatching({
640
689
  type: AST_NODE_TYPES.JSXIdentifier,
@@ -644,7 +693,7 @@ function isDeclaredInRenderPropLoose(node) {
644
693
  }
645
694
  function isRenderFunctionLoose(node, context) {
646
695
  const { body, parent } = node;
647
- if (O.exists(AST9.getFunctionIdentifier(node), (id2) => id2.name.startsWith("render"))) {
696
+ if (O.exists(AST8.getFunctionIdentifier(node), (id2) => id2.name.startsWith("render"))) {
648
697
  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");
649
698
  }
650
699
  return JSX4.isJSXValue(
@@ -652,16 +701,18 @@ function isRenderFunctionLoose(node, context) {
652
701
  {
653
702
  getScope: (node2) => context.sourceCode.getScope(node2)
654
703
  },
655
- JSX4.JSXValueHint.SkipNullLiteral | JSX4.JSXValueHint.SkipUndefinedLiteral | JSX4.JSXValueHint.StrictLogical | JSX4.JSXValueHint.StrictConditional
704
+ JSX4.JSXValueHint.SkipNullLiteral | JSX4.JSXValueHint.SkipUndefined | JSX4.JSXValueHint.StrictLogical | JSX4.JSXValueHint.StrictConditional
656
705
  );
657
706
  }
658
707
  function isRenderPropLoose(node, context) {
659
- if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) return false;
660
- return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST9.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
708
+ if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {
709
+ return false;
710
+ }
711
+ return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST8.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
661
712
  }
662
713
  function isThisSetState(node) {
663
714
  const { callee } = node;
664
- return callee.type === AST_NODE_TYPES.MemberExpression && AST9.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
715
+ return callee.type === AST_NODE_TYPES.MemberExpression && AST8.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
665
716
  }
666
717
 
667
- export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementRepresentName, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
718
+ export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementRepresentName, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isSetupFunction, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "1.23.2",
3
+ "version": "1.23.3-beta.5",
4
4
  "description": "ESLint React's ESLint utility module for static analysis of React core APIs and Patterns.",
5
5
  "homepage": "https://github.com/rEl1cx/eslint-react",
6
6
  "bugs": {
@@ -38,12 +38,12 @@
38
38
  "@typescript-eslint/types": "^8.19.1",
39
39
  "@typescript-eslint/utils": "^8.19.1",
40
40
  "ts-pattern": "^5.6.0",
41
- "@eslint-react/ast": "1.23.2",
42
- "@eslint-react/eff": "1.23.2",
43
- "@eslint-react/shared": "1.23.2",
44
- "@eslint-react/var": "1.23.2",
45
- "@eslint-react/jsx": "1.23.2",
46
- "@eslint-react/types": "1.23.2"
41
+ "@eslint-react/ast": "1.23.3-beta.5",
42
+ "@eslint-react/eff": "1.23.3-beta.5",
43
+ "@eslint-react/jsx": "1.23.3-beta.5",
44
+ "@eslint-react/shared": "1.23.3-beta.5",
45
+ "@eslint-react/var": "1.23.3-beta.5",
46
+ "@eslint-react/types": "1.23.3-beta.5"
47
47
  },
48
48
  "devDependencies": {
49
49
  "tsup": "^8.3.5",