@eslint-react/core 1.24.0-beta.1 → 1.24.0-beta.18

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,35 +1,13 @@
1
1
  import * as AST8 from '@eslint-react/ast';
2
- import { flip, birecord, dual, _, returnFalse } from '@eslint-react/eff';
3
- import * as JSX4 from '@eslint-react/jsx';
2
+ import { flip, dual, _, returnFalse } from '@eslint-react/eff';
3
+ import * as JSX3 from '@eslint-react/jsx';
4
+ import { unsafeDecodeSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
4
5
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
5
6
  import * as VAR from '@eslint-react/var';
6
- import { unsafeDecodeSettings } from '@eslint-react/shared';
7
+ import birecord from 'birecord';
7
8
 
8
9
  // src/component/component-collector.ts
9
- function getElementNameAndRepresentName(node, context, polymorphicPropName, additionalComponents = []) {
10
- const name = JSX4.getElementName(node);
11
- if (name === name.toLowerCase()) return [name, name];
12
- const component = additionalComponents.findLast((c) => c.name === name || c.re.test(name));
13
- if (component != null) return [name, component.as];
14
- if (polymorphicPropName == null) return [name, name];
15
- const initialScope = context.sourceCode.getScope(node);
16
- const polymorphicProp = JSX4.findPropInAttributes(
17
- polymorphicPropName,
18
- initialScope,
19
- node.attributes
20
- );
21
- if (polymorphicProp == null) return [name, name];
22
- const polymorphicName = VAR.toResolved(JSX4.getPropValue(polymorphicProp, initialScope)).value;
23
- if (typeof polymorphicName === "string") {
24
- return [name, polymorphicName];
25
- }
26
- return [name, name];
27
- }
28
-
29
- // src/utils/get-id.ts
30
- var id = 0n;
31
- var getId = () => (id++).toString();
32
- function isInitializedFromReact(name, initialScope, importSource = "react") {
10
+ function isInitializedFromReact(name, importSource, initialScope) {
33
11
  return name.toLowerCase() === "react" || VAR.isInitializedFromSource(
34
12
  name,
35
13
  importSource,
@@ -47,12 +25,13 @@ function isFromReact(name) {
47
25
  }
48
26
  return node.name === name;
49
27
  }
28
+ const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
50
29
  const initialScope = context.sourceCode.getScope(node);
51
30
  if (node.type === AST_NODE_TYPES.MemberExpression) {
52
- return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, initialScope, settings.importSource);
31
+ return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, importSource, initialScope);
53
32
  }
54
33
  if (node.name === name) {
55
- return isInitializedFromReact(name, initialScope, settings.importSource);
34
+ return isInitializedFromReact(name, importSource, initialScope);
56
35
  }
57
36
  return false;
58
37
  };
@@ -72,14 +51,15 @@ function isFromReactMember(memberName, name) {
72
51
  }
73
52
  return false;
74
53
  }
54
+ const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
75
55
  const initialScope = context.sourceCode.getScope(node);
76
56
  if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) {
77
57
  return false;
78
58
  }
79
59
  if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
80
- return isInitializedFromReact(node.object.name, initialScope, settings.importSource);
60
+ return isInitializedFromReact(node.object.name, importSource, initialScope);
81
61
  }
82
- if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, initialScope, settings.importSource) && node.object.property.type === AST_NODE_TYPES.Identifier) {
62
+ if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, importSource, initialScope) && node.object.property.type === AST_NODE_TYPES.Identifier) {
83
63
  return node.object.property.name === memberName;
84
64
  }
85
65
  return false;
@@ -140,9 +120,9 @@ var isMemoCall = isReactAPICallWithName("memo");
140
120
 
141
121
  // src/element/hierarchy.ts
142
122
  function isInsideCreateElementProps(node, context) {
143
- const call = AST8.findParentNodeGuard(node, isCreateElementCall(context));
123
+ const call = AST8.findParentNode(node, isCreateElementCall(context));
144
124
  if (call == null) return false;
145
- const prop = AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
125
+ const prop = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
146
126
  if (prop == null) return false;
147
127
  return prop === call.arguments[1];
148
128
  }
@@ -162,8 +142,8 @@ function isReactHookName(name) {
162
142
  // src/hook/is.ts
163
143
  function isReactHook(node) {
164
144
  if (node == null) return _;
165
- const id2 = AST8.getFunctionIdentifier(node);
166
- return id2?.name != null && isReactHookName(id2.name);
145
+ const id = AST8.getFunctionIdentifier(node);
146
+ return id?.name != null && isReactHookName(id.name);
167
147
  }
168
148
  function isReactHookCall(node) {
169
149
  if (node == null) return false;
@@ -181,13 +161,14 @@ function isReactHookCall(node) {
181
161
  function isReactHookCallWithName(node, context) {
182
162
  if (node == null) return returnFalse;
183
163
  const settings = unsafeDecodeSettings(context.settings);
164
+ const importSource = settings.importSource ?? "react";
165
+ const initialScope = context.sourceCode.getScope(node);
184
166
  return (name) => {
185
- const initialScope = context.sourceCode.getScope(node);
186
167
  switch (true) {
187
168
  case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
188
- return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
169
+ return !settings.strictImportCheck || isInitializedFromReact(name, importSource, initialScope);
189
170
  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):
190
- return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
171
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
191
172
  default:
192
173
  return false;
193
174
  }
@@ -208,13 +189,14 @@ function isReactHookCallWithNameLoose(node) {
208
189
  }
209
190
  function isReactHookCallWithNameAlias(name, context, alias) {
210
191
  const settings = unsafeDecodeSettings(context);
192
+ const importSource = settings.importSource ?? "react";
211
193
  return (node) => {
212
194
  const initialScope = context.sourceCode.getScope(node);
213
195
  switch (true) {
214
196
  case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
215
- return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
197
+ return !settings.strictImportCheck || isInitializedFromReact(name, importSource, initialScope);
216
198
  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):
217
- return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
199
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
218
200
  default:
219
201
  return alias.some(isReactHookCallWithNameLoose(node));
220
202
  }
@@ -252,20 +234,20 @@ var isUseTransitionCall = flip(isReactHookCallWithName)("useTransition");
252
234
 
253
235
  // src/hook/hierarchy.ts
254
236
  function isInsideReactHook(node) {
255
- return isReactHook(AST8.findParentNodeGuard(node, AST8.isFunction));
237
+ return isReactHook(AST8.findParentNode(node, AST8.isFunction));
256
238
  }
257
239
  function useHookCollector() {
258
240
  const hooks = /* @__PURE__ */ new Map();
259
241
  const fEntries = [];
260
242
  const onFunctionEnter = (node) => {
261
- const id2 = AST8.getFunctionIdentifier(node);
262
- const name = id2?.name;
243
+ const id = AST8.getFunctionIdentifier(node);
244
+ const name = id?.name;
263
245
  if (name != null && isReactHookName(name)) {
264
246
  const key = getId();
265
247
  fEntries.push({ key, node });
266
248
  hooks.set(key, {
267
- _: key,
268
- id: id2,
249
+ id,
250
+ key,
269
251
  kind: "function",
270
252
  name,
271
253
  node,
@@ -304,19 +286,13 @@ function useHookCollector() {
304
286
  if (hook == null) {
305
287
  return;
306
288
  }
307
- hooks.set(hook._, {
308
- ...hook,
309
- hookCalls: [
310
- ...hook.hookCalls,
311
- node
312
- ]
313
- });
289
+ hook.hookCalls.push(node);
314
290
  }
315
291
  };
316
292
  return { ctx, listeners };
317
293
  }
318
294
  var ERComponentHint = {
319
- ...JSX4.JSXValueHint,
295
+ ...JSX3.JSXValueHint,
320
296
  // 1n << 0n - 1n << 63n are reserved for JSXValueHint
321
297
  // Skip function component created by React.memo
322
298
  SkipMemo: 1n << 64n,
@@ -332,6 +308,17 @@ var ERComponentHint = {
332
308
  SkipClassProperty: 1n << 69n
333
309
  };
334
310
  var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefined | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
311
+ var COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
312
+ "AssignmentExpression",
313
+ "[type]",
314
+ "[operator='=']",
315
+ "[left.type='MemberExpression']",
316
+ "[left.property.name='displayName']"
317
+ ].join("");
318
+ function isComponentDisplayNameAssignment(node) {
319
+ if (node == null) return false;
320
+ return node.type === AST_NODE_TYPES.AssignmentExpression && node.operator === "=" && node.left.type === AST_NODE_TYPES.MemberExpression && node.left.property.type === AST_NODE_TYPES.Identifier && node.left.property.name === "displayName";
321
+ }
335
322
 
336
323
  // src/component/component-flag.ts
337
324
  var ERClassComponentFlag = {
@@ -371,14 +358,6 @@ function getFunctionComponentIdentifier(node, context) {
371
358
  }
372
359
  return _;
373
360
  }
374
- var RE_COMPONENT_NAME = /^_?[A-Z]/u;
375
- function getComponentNameFromIdentifier(node) {
376
- if (node == null) return _;
377
- return Array.isArray(node) ? node.map((n) => n.name).join(".") : node.name;
378
- }
379
- function isComponentName(name) {
380
- return RE_COMPONENT_NAME.test(name);
381
- }
382
361
  function isClassComponent(node) {
383
362
  if ("superClass" in node && node.superClass != null) {
384
363
  const re = /^(?:Pure)?Component$/u;
@@ -404,9 +383,30 @@ function isPureComponent(node) {
404
383
  return false;
405
384
  }
406
385
 
407
- // src/component/component-render-method.ts
386
+ // src/component/component-lifecycle.ts
387
+ function isComponentDidMount(node) {
388
+ return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
389
+ }
390
+ function isComponentWillUnmount(node) {
391
+ return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
392
+ }
393
+ function isComponentDidCatch(node) {
394
+ return AST8.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
395
+ }
396
+ function isGetDerivedStateFromError(node) {
397
+ return AST8.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
398
+ }
399
+ function isGetDerivedStateFromProps(node) {
400
+ return AST8.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
401
+ }
402
+ function isFunctionOfComponentDidMount(node) {
403
+ return AST8.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
404
+ }
405
+ function isFunctionOfComponentWillUnmount(node) {
406
+ return AST8.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
407
+ }
408
408
  function isRenderMethodLike(node) {
409
- 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;
409
+ return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
410
410
  }
411
411
  function isFunctionOfRenderMethod(node) {
412
412
  if (!isRenderMethodLike(node.parent)) {
@@ -417,12 +417,18 @@ function isFunctionOfRenderMethod(node) {
417
417
  function isInsideRenderMethod(node) {
418
418
  return AST8.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
419
419
  }
420
-
421
- // src/component/misc.ts
420
+ var RE_COMPONENT_NAME = /^_?[A-Z]/u;
421
+ function getComponentNameFromIdentifier(node) {
422
+ if (node == null) return _;
423
+ return Array.isArray(node) ? node.map((n) => n.name).join(".") : node.name;
424
+ }
425
+ function isComponentName(name) {
426
+ return RE_COMPONENT_NAME.test(name);
427
+ }
422
428
  function hasNoneOrValidComponentName(node, context) {
423
- const id2 = getFunctionComponentIdentifier(node, context);
424
- if (id2 == null) return true;
425
- const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
429
+ const id = getFunctionComponentIdentifier(node, context);
430
+ if (id == null) return true;
431
+ const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
426
432
  return name != null && isComponentName(name);
427
433
  }
428
434
 
@@ -457,15 +463,16 @@ function hasValidHierarchy(node, context, hint) {
457
463
  }
458
464
  function getComponentFlag(initPath) {
459
465
  let flag = ERFunctionComponentFlag.None;
460
- if (initPath != null && AST8.hasCallInFunctionInitPath("memo")(initPath)) {
466
+ if (initPath != null && AST8.hasCallInFunctionInitPath("memo", initPath)) {
461
467
  flag |= ERFunctionComponentFlag.Memo;
462
468
  }
463
- if (initPath != null && AST8.hasCallInFunctionInitPath("forwardRef")(initPath)) {
469
+ if (initPath != null && AST8.hasCallInFunctionInitPath("forwardRef", initPath)) {
464
470
  flag |= ERFunctionComponentFlag.ForwardRef;
465
471
  }
466
472
  return flag;
467
473
  }
468
- function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
474
+ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options = {}) {
475
+ const { collectDisplayName = false, collectHookCalls = false } = options;
469
476
  const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
470
477
  const components = /* @__PURE__ */ new Map();
471
478
  const functionEntries = [];
@@ -481,7 +488,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
481
488
  return functionEntries.pop();
482
489
  }
483
490
  const shouldDrop = AST8.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
484
- return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
491
+ return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3.isJSXValue(r.argument, jsxCtx, hint);
485
492
  });
486
493
  if (shouldDrop) {
487
494
  components.delete(entry.key);
@@ -507,17 +514,17 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
507
514
  return;
508
515
  }
509
516
  const { body } = entry.node;
510
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
517
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
511
518
  if (!isComponent) {
512
519
  return;
513
520
  }
514
521
  const initPath = AST8.getFunctionInitPath(entry.node);
515
- const id2 = getFunctionComponentIdentifier(entry.node, context);
516
- const name = getComponentNameFromIdentifier(id2);
522
+ const id = getFunctionComponentIdentifier(entry.node, context);
523
+ const name = getComponentNameFromIdentifier(id);
517
524
  const key = getId();
518
525
  components.set(key, {
519
- _: key,
520
- id: id2,
526
+ id,
527
+ key,
521
528
  kind: "function",
522
529
  name,
523
530
  node: entry.node,
@@ -528,46 +535,47 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
528
535
  initPath
529
536
  });
530
537
  },
531
- "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"(node) {
532
- const { left, right } = node;
533
- const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
534
- const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
535
- if (component == null) {
536
- return;
537
- }
538
- components.set(component._, {
539
- ...component,
540
- displayName: right
541
- });
542
- },
543
- "CallExpression[type]:exit"(node) {
544
- if (!isReactHookCall(node)) {
545
- return;
538
+ ...collectDisplayName ? {
539
+ [COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR](node) {
540
+ const { left, right } = node;
541
+ if (left.type !== AST_NODE_TYPES.MemberExpression) return;
542
+ const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
543
+ const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
544
+ if (component == null) {
545
+ return;
546
+ }
547
+ component.displayName = right;
546
548
  }
547
- const entry = getCurrentEntry();
548
- if (entry == null) {
549
- return;
549
+ } : {},
550
+ ...collectHookCalls ? {
551
+ "CallExpression[type]:exit"(node) {
552
+ if (!isReactHookCall(node)) {
553
+ return;
554
+ }
555
+ const entry = getCurrentEntry();
556
+ if (entry == null) {
557
+ return;
558
+ }
559
+ entry.hookCalls.push(node);
550
560
  }
551
- functionEntries.pop();
552
- functionEntries.push({ ...entry, hookCalls: [...entry.hookCalls, node] });
553
- },
561
+ } : {},
554
562
  "ReturnStatement[type]"(node) {
555
563
  const entry = getCurrentEntry();
556
564
  if (entry == null) {
557
565
  return;
558
566
  }
559
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
567
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
560
568
  if (!isComponent) {
561
569
  return;
562
570
  }
563
571
  functionEntries.pop();
564
572
  functionEntries.push({ ...entry, isComponent });
565
573
  const initPath = AST8.getFunctionInitPath(entry.node);
566
- const id2 = getFunctionComponentIdentifier(entry.node, context);
567
- const name = getComponentNameFromIdentifier(id2);
574
+ const id = getFunctionComponentIdentifier(entry.node, context);
575
+ const name = getComponentNameFromIdentifier(id);
568
576
  components.set(entry.key, {
569
- _: entry.key,
570
- id: id2,
577
+ id,
578
+ key: entry.key,
571
579
  kind: "function",
572
580
  name,
573
581
  node: entry.node,
@@ -593,16 +601,16 @@ function useComponentCollectorLegacy() {
593
601
  if (!isClassComponent(node)) {
594
602
  return;
595
603
  }
596
- const id2 = AST8.getClassIdentifier(node);
604
+ const id = AST8.getClassIdentifier(node);
597
605
  const key = getId();
598
606
  const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
599
607
  components.set(
600
608
  key,
601
609
  {
602
- _: key,
603
- id: id2,
610
+ id,
611
+ key,
604
612
  kind: "class",
605
- name: id2?.name,
613
+ name: id?.name,
606
614
  node,
607
615
  // TODO: Get displayName of class component
608
616
  displayName: _,
@@ -619,60 +627,22 @@ function useComponentCollectorLegacy() {
619
627
  };
620
628
  return { ctx, listeners };
621
629
  }
622
- function isSetupFunction(node) {
623
- if (node == null) return _;
624
- 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);
625
- }
626
- function isCleanupFunction(node) {
627
- const nearReturn = AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.ReturnStatement));
628
- const nearFunction = AST8.findParentNodeGuard(node, AST8.isFunction);
629
- const nearFunctionOfReturn = AST8.findParentNodeGuard(nearReturn, AST8.isFunction);
630
- return nearFunction === nearFunctionOfReturn && isSetupFunction(nearFunction);
631
- }
632
- function isComponentDidMount(node) {
633
- return AST8.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
634
- }
635
- function isComponentWillUnmount(node) {
636
- return AST8.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
637
- }
638
- function isComponentDidMountFunction(node) {
639
- return AST8.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
640
- }
641
- function isComponentWillUnmountFunction(node) {
642
- return AST8.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
643
- }
644
630
  var ERPhaseRelevance = birecord({
645
631
  mount: "unmount",
646
632
  setup: "cleanup"
647
633
  });
648
634
  var isInversePhase = dual(2, (a, b) => ERPhaseRelevance.get(a) === b);
649
- function isDirectValueOfRenderPropertyLoose(node) {
650
- const matching = (node2) => {
651
- return node2.type === AST_NODE_TYPES.Property && node2.key.type === AST_NODE_TYPES.Identifier && node2.key.name.startsWith("render");
652
- };
653
- return matching(node) || node.parent != null && matching(node.parent);
654
- }
655
- function isDeclaredInRenderPropLoose(node) {
656
- if (isDirectValueOfRenderPropertyLoose(node)) {
657
- return true;
658
- }
659
- const parent = AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
660
- if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
661
- return false;
662
- }
663
- return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
664
- }
665
635
  function isRenderFunctionLoose(node, context) {
666
636
  const { body, parent } = node;
667
637
  if (AST8.getFunctionIdentifier(node)?.name.startsWith("render")) {
668
638
  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");
669
639
  }
670
- return JSX4.isJSXValue(
640
+ return JSX3.isJSXValue(
671
641
  body,
672
642
  {
673
643
  getScope: (node2) => context.sourceCode.getScope(node2)
674
644
  },
675
- JSX4.JSXValueHint.SkipNullLiteral | JSX4.JSXValueHint.SkipUndefined | JSX4.JSXValueHint.StrictLogical | JSX4.JSXValueHint.StrictConditional
645
+ JSX3.JSXValueHint.SkipNullLiteral | JSX3.JSXValueHint.SkipUndefined | JSX3.JSXValueHint.StrictLogical | JSX3.JSXValueHint.StrictConditional
676
646
  );
677
647
  }
678
648
  function isRenderPropLoose(node, context) {
@@ -681,9 +651,35 @@ function isRenderPropLoose(node, context) {
681
651
  }
682
652
  return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST8.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
683
653
  }
654
+ function isDirectValueOfRenderPropertyLoose(node) {
655
+ const matching = (node2) => {
656
+ return node2.type === AST_NODE_TYPES.Property && node2.key.type === AST_NODE_TYPES.Identifier && node2.key.name.startsWith("render");
657
+ };
658
+ return matching(node) || node.parent != null && matching(node.parent);
659
+ }
660
+ function isDeclaredInRenderPropLoose(node) {
661
+ if (isDirectValueOfRenderPropertyLoose(node)) {
662
+ return true;
663
+ }
664
+ const parent = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
665
+ if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
666
+ return false;
667
+ }
668
+ return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
669
+ }
684
670
  function isThisSetState(node) {
685
671
  const { callee } = node;
686
672
  return callee.type === AST_NODE_TYPES.MemberExpression && AST8.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
687
673
  }
674
+ function isFunctionOfUseEffectSetup(node) {
675
+ if (node == null) return _;
676
+ 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);
677
+ }
678
+ function isFunctionOfUseEffectCleanup(node) {
679
+ const nearReturn = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ReturnStatement));
680
+ const nearFunction = AST8.findParentNode(node, AST8.isFunction);
681
+ const nearFunctionOfReturn = AST8.findParentNode(nearReturn, AST8.isFunction);
682
+ return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
683
+ }
688
684
 
689
- export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementNameAndRepresentName, 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 };
685
+ export { COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR, DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDisplayNameAssignment, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, 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.24.0-beta.1",
3
+ "version": "1.24.0-beta.18",
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": {
@@ -33,17 +33,17 @@
33
33
  "./package.json"
34
34
  ],
35
35
  "dependencies": {
36
- "@typescript-eslint/scope-manager": "^8.19.1",
37
- "@typescript-eslint/type-utils": "^8.19.1",
38
- "@typescript-eslint/types": "^8.19.1",
39
- "@typescript-eslint/utils": "^8.19.1",
40
- "ts-pattern": "^5.6.0",
41
- "@eslint-react/ast": "1.24.0-beta.1",
42
- "@eslint-react/eff": "1.24.0-beta.1",
43
- "@eslint-react/jsx": "1.24.0-beta.1",
44
- "@eslint-react/types": "1.24.0-beta.1",
45
- "@eslint-react/shared": "1.24.0-beta.1",
46
- "@eslint-react/var": "1.24.0-beta.1"
36
+ "@typescript-eslint/scope-manager": "^8.20.0",
37
+ "@typescript-eslint/type-utils": "^8.20.0",
38
+ "@typescript-eslint/types": "^8.20.0",
39
+ "@typescript-eslint/utils": "^8.20.0",
40
+ "birecord": "^0.1.1",
41
+ "ts-pattern": "^5.6.1",
42
+ "@eslint-react/ast": "1.24.0-beta.18",
43
+ "@eslint-react/eff": "1.24.0-beta.18",
44
+ "@eslint-react/jsx": "1.24.0-beta.18",
45
+ "@eslint-react/var": "1.24.0-beta.18",
46
+ "@eslint-react/shared": "1.24.0-beta.18"
47
47
  },
48
48
  "devDependencies": {
49
49
  "tsup": "^8.3.5",