@eslint-react/core 1.24.0-beta.0 → 1.24.0-beta.16

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 !== _) 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 === _) 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,15 +120,15 @@ 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));
144
- if (!call) return false;
145
- const prop = AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
146
- if (!prop) return false;
123
+ const call = AST8.findParentNode(node, isCreateElementCall(context));
124
+ if (call == null) return false;
125
+ const prop = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
126
+ if (prop == null) return false;
147
127
  return prop === call.arguments[1];
148
128
  }
149
129
  function isChildrenOfCreateElement(node, context) {
150
130
  const parent = node.parent;
151
- if (!parent || parent.type !== AST_NODE_TYPES.CallExpression) return false;
131
+ if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
152
132
  if (!isCreateElementCall(parent, context)) return false;
153
133
  return parent.arguments.slice(2).some((arg) => arg === node);
154
134
  }
@@ -161,12 +141,12 @@ function isReactHookName(name) {
161
141
 
162
142
  // src/hook/is.ts
163
143
  function isReactHook(node) {
164
- if (node === _) return _;
165
- const id2 = AST8.getFunctionIdentifier(node);
166
- return id2?.name !== _ && isReactHookName(id2.name);
144
+ if (node == null) return _;
145
+ const id = AST8.getFunctionIdentifier(node);
146
+ return id?.name != null && isReactHookName(id.name);
167
147
  }
168
148
  function isReactHookCall(node) {
169
- if (node === _) return false;
149
+ if (node == null) return false;
170
150
  if (node.type !== AST_NODE_TYPES.CallExpression) {
171
151
  return false;
172
152
  }
@@ -179,22 +159,23 @@ function isReactHookCall(node) {
179
159
  return false;
180
160
  }
181
161
  function isReactHookCallWithName(node, context) {
182
- if (node === _) return returnFalse;
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
  }
194
175
  };
195
176
  }
196
177
  function isReactHookCallWithNameLoose(node) {
197
- if (node === _) return returnFalse;
178
+ if (node == null) return returnFalse;
198
179
  return (name) => {
199
180
  switch (node.callee.type) {
200
181
  case AST_NODE_TYPES.Identifier:
@@ -208,20 +189,21 @@ 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
  }
221
203
  };
222
204
  }
223
205
  function isUseEffectCallLoose(node) {
224
- if (node === _) return false;
206
+ if (node == null) return false;
225
207
  if (node.type !== AST_NODE_TYPES.CallExpression) {
226
208
  return false;
227
209
  }
@@ -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;
263
- if (name !== _ && isReactHookName(name)) {
243
+ const id = AST8.getFunctionIdentifier(node);
244
+ const name = id?.name;
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,
@@ -297,26 +279,20 @@ function useHookCollector() {
297
279
  return;
298
280
  }
299
281
  const fEntry = fEntries.at(-1);
300
- if (fEntry?.key === _) {
282
+ if (fEntry?.key == null) {
301
283
  return;
302
284
  }
303
285
  const hook = hooks.get(fEntry.key);
304
- if (hook === _) {
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 = {
@@ -359,7 +346,7 @@ function isComponentWrapperCall(node, context) {
359
346
  }
360
347
  function getFunctionComponentIdentifier(node, context) {
361
348
  const functionId = AST8.getFunctionIdentifier(node);
362
- if (functionId) {
349
+ if (functionId != null) {
363
350
  return functionId;
364
351
  }
365
352
  const { parent } = node;
@@ -371,17 +358,8 @@ function getFunctionComponentIdentifier(node, context) {
371
358
  }
372
359
  return _;
373
360
  }
374
-
375
- // src/component/component-name.ts
376
- var RE_COMPONENT_NAME = /^_?[A-Z]/u;
377
- function getComponentNameFromIdentifier(node) {
378
- return Array.isArray(node) ? node.map((n) => n.name).join(".") : node.name;
379
- }
380
- function isComponentName(name) {
381
- return RE_COMPONENT_NAME.test(name);
382
- }
383
361
  function isClassComponent(node) {
384
- if ("superClass" in node && node.superClass) {
362
+ if ("superClass" in node && node.superClass != null) {
385
363
  const re = /^(?:Pure)?Component$/u;
386
364
  switch (true) {
387
365
  case node.superClass.type === AST_NODE_TYPES.Identifier:
@@ -393,7 +371,7 @@ function isClassComponent(node) {
393
371
  return false;
394
372
  }
395
373
  function isPureComponent(node) {
396
- if ("superClass" in node && node.superClass) {
374
+ if ("superClass" in node && node.superClass != null) {
397
375
  const re = /^PureComponent$/u;
398
376
  switch (true) {
399
377
  case node.superClass.type === AST_NODE_TYPES.Identifier:
@@ -405,9 +383,30 @@ function isPureComponent(node) {
405
383
  return false;
406
384
  }
407
385
 
408
- // 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
+ }
409
408
  function isRenderMethodLike(node) {
410
- 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;
411
410
  }
412
411
  function isFunctionOfRenderMethod(node) {
413
412
  if (!isRenderMethodLike(node.parent)) {
@@ -416,14 +415,20 @@ function isFunctionOfRenderMethod(node) {
416
415
  return isClassComponent(node.parent.parent.parent);
417
416
  }
418
417
  function isInsideRenderMethod(node) {
419
- return !!AST8.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent));
418
+ return AST8.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
419
+ }
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);
420
427
  }
421
-
422
- // src/component/misc.ts
423
428
  function hasNoneOrValidComponentName(node, context) {
424
- const id2 = getFunctionComponentIdentifier(node, context);
425
- if (!id2) return true;
426
- 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;
427
432
  return name != null && isComponentName(name);
428
433
  }
429
434
 
@@ -454,19 +459,20 @@ function hasValidHierarchy(node, context, hint) {
454
459
  AST_NODE_TYPES.ClassBody
455
460
  ])
456
461
  );
457
- return !boundaryNode || boundaryNode.type !== AST_NODE_TYPES.JSXExpressionContainer;
462
+ return boundaryNode == null || boundaryNode.type !== AST_NODE_TYPES.JSXExpressionContainer;
458
463
  }
459
464
  function getComponentFlag(initPath) {
460
465
  let flag = ERFunctionComponentFlag.None;
461
- if (initPath && AST8.hasCallInFunctionInitPath("memo")(initPath)) {
466
+ if (initPath != null && AST8.hasCallInFunctionInitPath("memo", initPath)) {
462
467
  flag |= ERFunctionComponentFlag.Memo;
463
468
  }
464
- if (initPath && AST8.hasCallInFunctionInitPath("forwardRef")(initPath)) {
469
+ if (initPath != null && AST8.hasCallInFunctionInitPath("forwardRef", initPath)) {
465
470
  flag |= ERFunctionComponentFlag.ForwardRef;
466
471
  }
467
472
  return flag;
468
473
  }
469
- function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
474
+ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options = {}) {
475
+ const { collectDisplayName = false, collectHookCalls = false } = options;
470
476
  const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
471
477
  const components = /* @__PURE__ */ new Map();
472
478
  const functionEntries = [];
@@ -477,12 +483,12 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
477
483
  };
478
484
  const onFunctionExit = () => {
479
485
  const entry = functionEntries.at(-1);
480
- if (!entry) return;
486
+ if (entry == null) return;
481
487
  if (!entry.isComponent) {
482
488
  return functionEntries.pop();
483
489
  }
484
490
  const shouldDrop = AST8.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
485
- return context.sourceCode.getScope(r).block === entry.node && !!r.argument && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
491
+ return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3.isJSXValue(r.argument, jsxCtx, hint);
486
492
  });
487
493
  if (shouldDrop) {
488
494
  components.delete(entry.key);
@@ -504,21 +510,21 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
504
510
  ":function[type]:exit": onFunctionExit,
505
511
  "ArrowFunctionExpression[type][body.type!='BlockStatement']"() {
506
512
  const entry = getCurrentEntry();
507
- if (!entry) {
513
+ if (entry == null) {
508
514
  return;
509
515
  }
510
516
  const { body } = entry.node;
511
- 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);
512
518
  if (!isComponent) {
513
519
  return;
514
520
  }
515
521
  const initPath = AST8.getFunctionInitPath(entry.node);
516
- const id2 = getFunctionComponentIdentifier(entry.node, context);
517
- const name = id2 && getComponentNameFromIdentifier(id2);
522
+ const id = getFunctionComponentIdentifier(entry.node, context);
523
+ const name = getComponentNameFromIdentifier(id);
518
524
  const key = getId();
519
525
  components.set(key, {
520
- _: key,
521
- id: id2,
526
+ id,
527
+ key,
522
528
  kind: "function",
523
529
  name,
524
530
  node: entry.node,
@@ -529,46 +535,47 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
529
535
  initPath
530
536
  });
531
537
  },
532
- "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"(node) {
533
- const { left, right } = node;
534
- const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
535
- const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
536
- if (!component) {
537
- 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;
538
548
  }
539
- components.set(component._, {
540
- ...component,
541
- displayName: right
542
- });
543
- },
544
- "CallExpression[type]:exit"(node) {
545
- if (!isReactHookCall(node)) {
546
- return;
547
- }
548
- const entry = getCurrentEntry();
549
- if (!entry) {
550
- 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);
551
560
  }
552
- functionEntries.pop();
553
- functionEntries.push({ ...entry, hookCalls: [...entry.hookCalls, node] });
554
- },
561
+ } : {},
555
562
  "ReturnStatement[type]"(node) {
556
563
  const entry = getCurrentEntry();
557
- if (!entry) {
564
+ if (entry == null) {
558
565
  return;
559
566
  }
560
- 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);
561
568
  if (!isComponent) {
562
569
  return;
563
570
  }
564
571
  functionEntries.pop();
565
572
  functionEntries.push({ ...entry, isComponent });
566
573
  const initPath = AST8.getFunctionInitPath(entry.node);
567
- const id2 = getFunctionComponentIdentifier(entry.node, context);
568
- const name = id2 && getComponentNameFromIdentifier(id2);
574
+ const id = getFunctionComponentIdentifier(entry.node, context);
575
+ const name = getComponentNameFromIdentifier(id);
569
576
  components.set(entry.key, {
570
- _: entry.key,
571
- id: id2,
577
+ id,
578
+ key: entry.key,
572
579
  kind: "function",
573
580
  name,
574
581
  node: entry.node,
@@ -594,16 +601,16 @@ function useComponentCollectorLegacy() {
594
601
  if (!isClassComponent(node)) {
595
602
  return;
596
603
  }
597
- const id2 = AST8.getClassIdentifier(node);
604
+ const id = AST8.getClassIdentifier(node);
598
605
  const key = getId();
599
606
  const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
600
607
  components.set(
601
608
  key,
602
609
  {
603
- _: key,
604
- id: id2,
610
+ id,
611
+ key,
605
612
  kind: "class",
606
- name: id2?.name,
613
+ name: id?.name,
607
614
  node,
608
615
  // TODO: Get displayName of class component
609
616
  displayName: _,
@@ -620,60 +627,22 @@ function useComponentCollectorLegacy() {
620
627
  };
621
628
  return { ctx, listeners };
622
629
  }
623
- function isSetupFunction(node) {
624
- if (node === _) return _;
625
- 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);
626
- }
627
- function isCleanupFunction(node) {
628
- const nearReturn = AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.ReturnStatement));
629
- const nearFunction = AST8.findParentNodeGuard(node, AST8.isFunction);
630
- const nearFunctionOfReturn = AST8.findParentNodeGuard(nearReturn, AST8.isFunction);
631
- return nearFunction === nearFunctionOfReturn && isSetupFunction(nearFunction);
632
- }
633
- function isComponentDidMount(node) {
634
- return AST8.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
635
- }
636
- function isComponentWillUnmount(node) {
637
- return AST8.isOneOf([AST_NODE_TYPES.MethodDefinition, AST_NODE_TYPES.PropertyDefinition])(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
638
- }
639
- function isComponentDidMountFunction(node) {
640
- return AST8.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
641
- }
642
- function isComponentWillUnmountFunction(node) {
643
- return AST8.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
644
- }
645
630
  var ERPhaseRelevance = birecord({
646
631
  mount: "unmount",
647
632
  setup: "cleanup"
648
633
  });
649
634
  var isInversePhase = dual(2, (a, b) => ERPhaseRelevance.get(a) === b);
650
- function isDirectValueOfRenderPropertyLoose(node) {
651
- const matching = (node2) => {
652
- return node2.type === AST_NODE_TYPES.Property && node2.key.type === AST_NODE_TYPES.Identifier && node2.key.name.startsWith("render");
653
- };
654
- return matching(node) || !!node.parent && matching(node.parent);
655
- }
656
- function isDeclaredInRenderPropLoose(node) {
657
- if (isDirectValueOfRenderPropertyLoose(node)) {
658
- return true;
659
- }
660
- const parent = AST8.findParentNodeGuard(node, AST8.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
661
- if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
662
- return false;
663
- }
664
- return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
665
- }
666
635
  function isRenderFunctionLoose(node, context) {
667
636
  const { body, parent } = node;
668
637
  if (AST8.getFunctionIdentifier(node)?.name.startsWith("render")) {
669
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");
670
639
  }
671
- return JSX4.isJSXValue(
640
+ return JSX3.isJSXValue(
672
641
  body,
673
642
  {
674
643
  getScope: (node2) => context.sourceCode.getScope(node2)
675
644
  },
676
- 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
677
646
  );
678
647
  }
679
648
  function isRenderPropLoose(node, context) {
@@ -682,9 +651,35 @@ function isRenderPropLoose(node, context) {
682
651
  }
683
652
  return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST8.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
684
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
+ }
685
670
  function isThisSetState(node) {
686
671
  const { callee } = node;
687
672
  return callee.type === AST_NODE_TYPES.MemberExpression && AST8.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
688
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
+ }
689
684
 
690
- 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.0",
3
+ "version": "1.24.0-beta.16",
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",
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",
40
41
  "ts-pattern": "^5.6.0",
41
- "@eslint-react/ast": "1.24.0-beta.0",
42
- "@eslint-react/eff": "1.24.0-beta.0",
43
- "@eslint-react/jsx": "1.24.0-beta.0",
44
- "@eslint-react/shared": "1.24.0-beta.0",
45
- "@eslint-react/types": "1.24.0-beta.0",
46
- "@eslint-react/var": "1.24.0-beta.0"
42
+ "@eslint-react/eff": "1.24.0-beta.16",
43
+ "@eslint-react/jsx": "1.24.0-beta.16",
44
+ "@eslint-react/shared": "1.24.0-beta.16",
45
+ "@eslint-react/var": "1.24.0-beta.16",
46
+ "@eslint-react/ast": "1.24.0-beta.16"
47
47
  },
48
48
  "devDependencies": {
49
49
  "tsup": "^8.3.5",