@eslint-react/core 1.28.0-beta.1 → 1.28.0-beta.4

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,28 +1,17 @@
1
- import * as AST9 from '@eslint-react/ast';
1
+ import * as AST8 from '@eslint-react/ast';
2
2
  import { flip, dual, constFalse, identity, _ } from '@eslint-react/eff';
3
3
  import * as JSX3 from '@eslint-react/jsx';
4
- import { unsafeDecodeSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
4
+ import { DEFAULT_ESLINT_REACT_SETTINGS, unsafeDecodeSettings, getId } from '@eslint-react/shared';
5
5
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
6
6
  import * as VAR from '@eslint-react/var';
7
7
  import { match, P } from 'ts-pattern';
8
8
  import birecord from 'birecord';
9
9
 
10
10
  // src/component/component-collector.ts
11
- var DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
12
- "AssignmentExpression",
13
- "[type]",
14
- "[operator='=']",
15
- "[left.type='MemberExpression']",
16
- "[left.property.name='displayName']"
17
- ].join("");
18
- function isDisplayNameAssignment(node) {
19
- if (node == null) return false;
20
- 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";
21
- }
22
11
  function getRequireExpressionArguments(node) {
23
12
  return match(node).with({ type: AST_NODE_TYPES.CallExpression, arguments: P.select(), callee: { type: AST_NODE_TYPES.Identifier, name: "require" } }, identity).with({ type: AST_NODE_TYPES.MemberExpression, object: P.select() }, getRequireExpressionArguments).otherwise(() => _);
24
13
  }
25
- function isInitializedFromReact(name, source, initialScope) {
14
+ function isInitializedFromReact(name, importSource, initialScope) {
26
15
  if (name.toLowerCase() === "react") return true;
27
16
  const latestDef = VAR.findVariable(name, initialScope)?.defs.at(-1);
28
17
  if (latestDef == null) return false;
@@ -30,81 +19,101 @@ function isInitializedFromReact(name, source, initialScope) {
30
19
  if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
31
20
  const { init } = node;
32
21
  if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) {
33
- return isInitializedFromReact(init.object.name, source, initialScope);
22
+ return isInitializedFromReact(init.object.name, importSource, initialScope);
34
23
  }
35
24
  if (init.type === AST_NODE_TYPES.Identifier) {
36
- return isInitializedFromReact(init.name, source, initialScope);
25
+ return isInitializedFromReact(init.name, importSource, initialScope);
37
26
  }
38
27
  const args = getRequireExpressionArguments(init);
39
28
  const arg0 = args?.[0];
40
- if (arg0 == null || !AST9.isStringLiteral(arg0)) {
29
+ if (arg0 == null || !AST8.isKindOfLiteral(arg0, "string")) {
41
30
  return false;
42
31
  }
43
- return arg0.value === source || arg0.value.startsWith(`${source}/`);
32
+ return arg0.value === importSource || arg0.value.startsWith(`${importSource}/`);
44
33
  }
45
- return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === source;
34
+ return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === importSource;
46
35
  }
47
36
 
48
37
  // src/utils/is-from-react.ts
38
+ var defaultImportSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource;
39
+ function isFromReactLoose(node, name) {
40
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
41
+ return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name;
42
+ }
43
+ return node.name === name;
44
+ }
45
+ function isFromReactStrict(node, name, importSource, initialScope) {
46
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
47
+ 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);
48
+ }
49
+ if (node.name === name) {
50
+ return isInitializedFromReact(name, importSource, initialScope);
51
+ }
52
+ return false;
53
+ }
49
54
  function isFromReact(name) {
50
- return (node, context) => {
51
- const settings = unsafeDecodeSettings(context.settings);
52
- if (!settings.strictImportCheck) {
53
- if (node.type === AST_NODE_TYPES.MemberExpression) {
54
- return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name;
55
- }
56
- return node.name === name;
57
- }
58
- const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
59
- const initialScope = context.sourceCode.getScope(node);
60
- if (node.type === AST_NODE_TYPES.MemberExpression) {
61
- 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);
62
- }
63
- if (node.name === name) {
64
- return isInitializedFromReact(name, importSource, initialScope);
65
- }
66
- return false;
55
+ return (context, node) => {
56
+ const { importSource = defaultImportSource, strictImportCheck = false } = unsafeDecodeSettings(context.settings);
57
+ if (!strictImportCheck) return isFromReactLoose(node, name);
58
+ return isFromReactStrict(node, name, importSource, context.sourceCode.getScope(node));
67
59
  };
68
60
  }
69
- function isFromReactMember(memberName, name) {
70
- return (node, context) => {
71
- const settings = unsafeDecodeSettings(context.settings);
72
- if (!settings.strictImportCheck) {
73
- if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
74
- if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) return true;
75
- if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && node.object.property.type === AST_NODE_TYPES.Identifier) {
76
- return node.object.property.name === memberName;
77
- }
78
- return false;
79
- }
80
- const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
81
- const initialScope = context.sourceCode.getScope(node);
82
- if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) {
83
- return false;
84
- }
85
- if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
86
- return isInitializedFromReact(node.object.name, importSource, initialScope);
87
- }
88
- 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) {
89
- return node.object.property.name === memberName;
90
- }
61
+ function isFromReactMemberLoose(node, memberName, name) {
62
+ const { object, property } = node;
63
+ if (property.type !== AST_NODE_TYPES.Identifier || property.name !== name) return false;
64
+ if (object.type === AST_NODE_TYPES.Identifier && object.name === memberName) return true;
65
+ if (object.type === AST_NODE_TYPES.MemberExpression && object.object.type === AST_NODE_TYPES.Identifier && object.property.type === AST_NODE_TYPES.Identifier) {
66
+ return object.property.name === memberName;
67
+ }
68
+ return false;
69
+ }
70
+ function isFromReactMemberStrict(node, memberName, name, importSource, initialScope) {
71
+ const { object, property } = node;
72
+ if (property.type !== AST_NODE_TYPES.Identifier || property.name !== name) {
91
73
  return false;
74
+ }
75
+ if (object.type === AST_NODE_TYPES.Identifier && object.name === memberName) {
76
+ return isInitializedFromReact(object.name, importSource, initialScope);
77
+ }
78
+ if (object.type === AST_NODE_TYPES.MemberExpression && object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(object.object.name, importSource, initialScope) && object.property.type === AST_NODE_TYPES.Identifier) {
79
+ return object.property.name === memberName;
80
+ }
81
+ return false;
82
+ }
83
+ function isFromReactMember(memberName, name) {
84
+ return (context, node) => {
85
+ const { importSource = defaultImportSource, strictImportCheck = false } = unsafeDecodeSettings(context.settings);
86
+ if (!strictImportCheck) return isFromReactMemberLoose(node, memberName, name);
87
+ return isFromReactMemberStrict(node, memberName, name, importSource, context.sourceCode.getScope(node));
92
88
  };
93
89
  }
90
+
91
+ // src/utils/is-call-from-react.ts
94
92
  function isCallFromReact(name) {
95
- return dual(2, (node, context) => {
93
+ return dual(2, (context, node) => {
96
94
  if (node.type !== AST_NODE_TYPES.CallExpression) return false;
97
- if (!AST9.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) return false;
98
- return isFromReact(name)(node.callee, context);
95
+ if (!AST8.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) return false;
96
+ return isFromReact(name)(context, node.callee);
99
97
  });
100
98
  }
101
99
  function isCallFromReactMember(pragmaMemberName, name) {
102
- return dual(2, (node, context) => {
100
+ return dual(2, (context, node) => {
103
101
  if (node.type !== AST_NODE_TYPES.CallExpression) return false;
104
- if (!AST9.is(AST_NODE_TYPES.MemberExpression)(node.callee)) return false;
105
- return isFromReactMember(pragmaMemberName, name)(node.callee, context);
102
+ if (!AST8.is(AST_NODE_TYPES.MemberExpression)(node.callee)) return false;
103
+ return isFromReactMember(pragmaMemberName, name)(context, node.callee);
106
104
  });
107
105
  }
106
+ var DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
107
+ "AssignmentExpression",
108
+ "[type]",
109
+ "[operator='=']",
110
+ "[left.type='MemberExpression']",
111
+ "[left.property.name='displayName']"
112
+ ].join("");
113
+ function isDisplayNameAssignment(node) {
114
+ if (node == null) return false;
115
+ 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";
116
+ }
108
117
 
109
118
  // src/utils/is-react-api.ts
110
119
  function isReactAPIWithName(name, member) {
@@ -136,21 +145,6 @@ var isCreateRefCall = isReactAPICallWithName("createRef");
136
145
  var isForwardRefCall = isReactAPICallWithName("forwardRef");
137
146
  var isMemoCall = isReactAPICallWithName("memo");
138
147
 
139
- // src/element/hierarchy.ts
140
- function isInsideCreateElementProps(node, context) {
141
- const call = AST9.findParentNode(node, isCreateElementCall(context));
142
- if (call == null) return false;
143
- const prop = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.ObjectExpression));
144
- if (prop == null) return false;
145
- return prop === call.arguments[1];
146
- }
147
- function isChildrenOfCreateElement(node, context) {
148
- const parent = node.parent;
149
- if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
150
- if (!isCreateElementCall(parent, context)) return false;
151
- return parent.arguments.slice(2).some((arg) => arg === node);
152
- }
153
-
154
148
  // src/hook/hook-name.ts
155
149
  var RE_HOOK_NAME = /^use[A-Z\d]/u;
156
150
  function isReactHookName(name) {
@@ -160,7 +154,7 @@ function isReactHookName(name) {
160
154
  // src/hook/is.ts
161
155
  function isReactHook(node) {
162
156
  if (node == null) return _;
163
- const id = AST9.getFunctionIdentifier(node);
157
+ const id = AST8.getFunctionIdentifier(node);
164
158
  return id?.name != null && isReactHookName(id.name);
165
159
  }
166
160
  function isReactHookCall(node) {
@@ -176,7 +170,7 @@ function isReactHookCall(node) {
176
170
  }
177
171
  return false;
178
172
  }
179
- function isReactHookCallWithName(node, context) {
173
+ function isReactHookCallWithName(context, node) {
180
174
  if (node == null) return constFalse;
181
175
  const settings = unsafeDecodeSettings(context.settings);
182
176
  const importSource = settings.importSource ?? "react";
@@ -205,7 +199,7 @@ function isReactHookCallWithNameLoose(node) {
205
199
  }
206
200
  };
207
201
  }
208
- function isReactHookCallWithNameAlias(name, context, alias) {
202
+ function isReactHookCallWithNameAlias(context, name, alias) {
209
203
  const settings = unsafeDecodeSettings(context);
210
204
  const importSource = settings.importSource ?? "react";
211
205
  return (node) => {
@@ -252,13 +246,13 @@ var isUseTransitionCall = flip(isReactHookCallWithName)("useTransition");
252
246
 
253
247
  // src/hook/hierarchy.ts
254
248
  function isInsideReactHook(node) {
255
- return isReactHook(AST9.findParentNode(node, AST9.isFunction));
249
+ return isReactHook(AST8.findParentNode(node, AST8.isFunction));
256
250
  }
257
251
  function useHookCollector() {
258
252
  const hooks = /* @__PURE__ */ new Map();
259
253
  const functionEntries = [];
260
254
  const onFunctionEnter = (node) => {
261
- const id = AST9.getFunctionIdentifier(node);
255
+ const id = AST8.getFunctionIdentifier(node);
262
256
  const key = getId();
263
257
  const name = id?.name;
264
258
  if (name != null && isReactHookName(name)) {
@@ -347,26 +341,53 @@ var ERComponentFlag = {
347
341
  ForwardRef: 1n << 3n,
348
342
  Async: 1n << 4n
349
343
  };
350
- function isComponentWrapperCall(node, context) {
344
+ function isComponentWrapperCall(context, node) {
351
345
  if (node.type !== AST_NODE_TYPES.CallExpression) {
352
346
  return false;
353
347
  }
354
- return isMemoCall(node, context) || isForwardRefCall(node, context) || isReactHookCallWithNameLoose(node)("useCallback");
348
+ return isMemoCall(context, node) || isForwardRefCall(context, node) || isReactHookCallWithNameLoose(node)("useCallback");
355
349
  }
356
- function getFunctionComponentIdentifier(node, context) {
357
- const functionId = AST9.getFunctionIdentifier(node);
350
+ function getFunctionComponentIdentifier(context, node) {
351
+ const functionId = AST8.getFunctionIdentifier(node);
358
352
  if (functionId != null) {
359
353
  return functionId;
360
354
  }
361
355
  const { parent } = node;
362
- 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) {
356
+ if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent) && parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.id.type === AST_NODE_TYPES.Identifier) {
363
357
  return parent.parent.id;
364
358
  }
365
- if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(parent, context) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(parent.parent, context) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
359
+ if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
366
360
  return parent.parent.parent.id;
367
361
  }
368
362
  return _;
369
363
  }
364
+ var RE_COMPONENT_NAME = /^_?[A-Z]/u;
365
+ function getComponentNameFromIdentifier(node) {
366
+ if (node == null) return _;
367
+ return Array.isArray(node) ? node.map((n) => n.name).join(".") : node.name;
368
+ }
369
+ function isComponentName(name) {
370
+ return RE_COMPONENT_NAME.test(name);
371
+ }
372
+ function hasNoneOrValidComponentName(context, node) {
373
+ const id = getFunctionComponentIdentifier(context, node);
374
+ if (id == null) return true;
375
+ const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
376
+ return name != null && isComponentName(name);
377
+ }
378
+ function isInsideCreateElementProps(context, node) {
379
+ const call = AST8.findParentNode(node, isCreateElementCall(context));
380
+ if (call == null) return false;
381
+ const prop = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
382
+ if (prop == null) return false;
383
+ return prop === call.arguments[1];
384
+ }
385
+ function isChildrenOfCreateElement(context, node) {
386
+ const parent = node.parent;
387
+ if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
388
+ if (!isCreateElementCall(context, parent)) return false;
389
+ return parent.arguments.slice(2).some((arg) => arg === node);
390
+ }
370
391
  function isClassComponent(node) {
371
392
  if ("superClass" in node && node.superClass != null) {
372
393
  const re = /^(?:Pure)?Component$/u;
@@ -394,28 +415,28 @@ function isPureComponent(node) {
394
415
 
395
416
  // src/component/component-lifecycle.ts
396
417
  function isComponentDidMount(node) {
397
- return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
418
+ return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
398
419
  }
399
420
  function isComponentWillUnmount(node) {
400
- return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
421
+ return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
401
422
  }
402
423
  function isComponentDidCatch(node) {
403
- return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
424
+ return AST8.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
404
425
  }
405
426
  function isGetDerivedStateFromError(node) {
406
- return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
427
+ return AST8.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
407
428
  }
408
429
  function isGetDerivedStateFromProps(node) {
409
- return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
430
+ return AST8.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
410
431
  }
411
432
  function isFunctionOfComponentDidMount(node) {
412
- return AST9.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
433
+ return AST8.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
413
434
  }
414
435
  function isFunctionOfComponentWillUnmount(node) {
415
- return AST9.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
436
+ return AST8.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
416
437
  }
417
438
  function isRenderMethodLike(node) {
418
- return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
439
+ return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
419
440
  }
420
441
  function isFunctionOfRenderMethod(node) {
421
442
  if (!isRenderMethodLike(node.parent)) {
@@ -424,21 +445,46 @@ function isFunctionOfRenderMethod(node) {
424
445
  return isClassComponent(node.parent.parent.parent);
425
446
  }
426
447
  function isInsideRenderMethod(node) {
427
- return AST9.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
448
+ return AST8.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
428
449
  }
429
- var RE_COMPONENT_NAME = /^_?[A-Z]/u;
430
- function getComponentNameFromIdentifier(node) {
431
- if (node == null) return _;
432
- return Array.isArray(node) ? node.map((n) => n.name).join(".") : node.name;
450
+
451
+ // src/component/hierarchy.ts
452
+ function hasValidHierarchy(context, node, hint) {
453
+ if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) {
454
+ return false;
455
+ }
456
+ if (hint & ERComponentHint.SkipMapCallback && AST8.isMapCallLoose(node.parent)) {
457
+ return false;
458
+ }
459
+ if (hint & ERComponentHint.SkipObjectMethod && isFunctionOfObjectMethod(node.parent)) {
460
+ return false;
461
+ }
462
+ if (hint & ERComponentHint.SkipClassMethod && isFunctionOfClassMethod(node.parent)) {
463
+ return false;
464
+ }
465
+ if (hint & ERComponentHint.SkipClassProperty && isFunctionOfClassProperty(node.parent)) {
466
+ return false;
467
+ }
468
+ const boundaryNode = AST8.findParentNode(
469
+ node,
470
+ AST8.isOneOf([
471
+ AST_NODE_TYPES.JSXExpressionContainer,
472
+ AST_NODE_TYPES.ArrowFunctionExpression,
473
+ AST_NODE_TYPES.FunctionExpression,
474
+ AST_NODE_TYPES.Property,
475
+ AST_NODE_TYPES.ClassBody
476
+ ])
477
+ );
478
+ return boundaryNode == null || boundaryNode.type !== AST_NODE_TYPES.JSXExpressionContainer;
433
479
  }
434
- function isComponentName(name) {
435
- return RE_COMPONENT_NAME.test(name);
480
+ function isFunctionOfClassMethod(node) {
481
+ return (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression) && node.parent.type === AST_NODE_TYPES.MethodDefinition;
436
482
  }
437
- function hasNoneOrValidComponentName(node, context) {
438
- const id = getFunctionComponentIdentifier(node, context);
439
- if (id == null) return true;
440
- const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
441
- return name != null && isComponentName(name);
483
+ function isFunctionOfClassProperty(node) {
484
+ return (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression) && node.parent.type === AST_NODE_TYPES.Property;
485
+ }
486
+ function isFunctionOfObjectMethod(node) {
487
+ return (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression) && node.parent.type === AST_NODE_TYPES.Property && node.parent.parent.type === AST_NODE_TYPES.ObjectExpression;
442
488
  }
443
489
 
444
490
  // src/component/component-collector.ts
@@ -456,7 +502,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
456
502
  const entry = functionEntries.at(-1);
457
503
  if (entry == null) return;
458
504
  if (!entry.isComponent) return functionEntries.pop();
459
- const shouldDrop = AST9.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
505
+ const shouldDrop = AST8.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
460
506
  return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3.isJSXValue(r.argument, jsxCtx, hint);
461
507
  });
462
508
  if (shouldDrop) {
@@ -481,10 +527,10 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
481
527
  const entry = getCurrentEntry();
482
528
  if (entry == null) return;
483
529
  const { body } = entry.node;
484
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
530
+ const isComponent = hasNoneOrValidComponentName(context, entry.node) && JSX3.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(context, entry.node, hint);
485
531
  if (!isComponent) return;
486
- const initPath = AST9.getFunctionInitPath(entry.node);
487
- const id = getFunctionComponentIdentifier(entry.node, context);
532
+ const initPath = AST8.getFunctionInitPath(entry.node);
533
+ const id = getFunctionComponentIdentifier(context, entry.node);
488
534
  const name = getComponentNameFromIdentifier(id);
489
535
  const key = getId();
490
536
  components.set(key, {
@@ -521,11 +567,11 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
521
567
  "ReturnStatement[type]"(node) {
522
568
  const entry = getCurrentEntry();
523
569
  if (entry == null) return;
524
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
570
+ const isComponent = hasNoneOrValidComponentName(context, entry.node) && JSX3.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(context, entry.node, hint);
525
571
  if (!isComponent) return;
526
572
  entry.isComponent = true;
527
- const initPath = AST9.getFunctionInitPath(entry.node);
528
- const id = getFunctionComponentIdentifier(entry.node, context);
573
+ const initPath = AST8.getFunctionInitPath(entry.node);
574
+ const id = getFunctionComponentIdentifier(context, entry.node);
529
575
  const name = getComponentNameFromIdentifier(id);
530
576
  components.set(entry.key, {
531
577
  id,
@@ -543,40 +589,12 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
543
589
  };
544
590
  return { ctx, listeners };
545
591
  }
546
- function hasValidHierarchy(node, context, hint) {
547
- if (isChildrenOfCreateElement(node, context) || isFunctionOfRenderMethod(node)) {
548
- return false;
549
- }
550
- if (hint & ERComponentHint.SkipMapCallback && AST9.isMapCallLoose(node.parent)) {
551
- return false;
552
- }
553
- if (hint & ERComponentHint.SkipObjectMethod && AST9.isFunctionOfObjectMethod(node.parent)) {
554
- return false;
555
- }
556
- if (hint & ERComponentHint.SkipClassMethod && AST9.isFunctionOfClassMethod(node.parent)) {
557
- return false;
558
- }
559
- if (hint & ERComponentHint.SkipClassProperty && AST9.isFunctionOfClassProperty(node.parent)) {
560
- return false;
561
- }
562
- const boundaryNode = AST9.findParentNode(
563
- node,
564
- AST9.isOneOf([
565
- AST_NODE_TYPES.JSXExpressionContainer,
566
- AST_NODE_TYPES.ArrowFunctionExpression,
567
- AST_NODE_TYPES.FunctionExpression,
568
- AST_NODE_TYPES.Property,
569
- AST_NODE_TYPES.ClassBody
570
- ])
571
- );
572
- return boundaryNode == null || boundaryNode.type !== AST_NODE_TYPES.JSXExpressionContainer;
573
- }
574
592
  function getComponentFlag(initPath) {
575
593
  let flag = ERComponentFlag.None;
576
- if (initPath != null && AST9.hasCallInFunctionInitPath("memo", initPath)) {
594
+ if (initPath != null && AST8.hasCallInFunctionInitPath("memo", initPath)) {
577
595
  flag |= ERComponentFlag.Memo;
578
596
  }
579
- if (initPath != null && AST9.hasCallInFunctionInitPath("forwardRef", initPath)) {
597
+ if (initPath != null && AST8.hasCallInFunctionInitPath("forwardRef", initPath)) {
580
598
  flag |= ERComponentFlag.ForwardRef;
581
599
  }
582
600
  return flag;
@@ -593,7 +611,7 @@ function useComponentCollectorLegacy() {
593
611
  if (!isClassComponent(node)) {
594
612
  return;
595
613
  }
596
- const id = AST9.getClassIdentifier(node);
614
+ const id = AST8.getClassIdentifier(node);
597
615
  const key = getId();
598
616
  const flag = isPureComponent(node) ? ERComponentFlag.PureComponent : ERComponentFlag.None;
599
617
  components.set(
@@ -624,9 +642,9 @@ var ERPhaseRelevance = birecord({
624
642
  setup: "cleanup"
625
643
  });
626
644
  var isInversePhase = dual(2, (a, b) => ERPhaseRelevance.get(a) === b);
627
- function isRenderFunctionLoose(node, context) {
645
+ function isRenderFunctionLoose(context, node) {
628
646
  const { body, parent } = node;
629
- if (AST9.getFunctionIdentifier(node)?.name.startsWith("render")) {
647
+ if (AST8.getFunctionIdentifier(node)?.name.startsWith("render")) {
630
648
  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");
631
649
  }
632
650
  return JSX3.isJSXValue(
@@ -637,11 +655,11 @@ function isRenderFunctionLoose(node, context) {
637
655
  JSX3.JSXValueHint.SkipNullLiteral | JSX3.JSXValueHint.SkipUndefined | JSX3.JSXValueHint.StrictLogical | JSX3.JSXValueHint.StrictConditional
638
656
  );
639
657
  }
640
- function isRenderPropLoose(node, context) {
658
+ function isRenderPropLoose(context, node) {
641
659
  if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {
642
660
  return false;
643
661
  }
644
- return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST9.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
662
+ return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST8.isFunction(node.value.expression) && isRenderFunctionLoose(context, node.value.expression);
645
663
  }
646
664
  function isDirectValueOfRenderPropertyLoose(node) {
647
665
  const matching = (node2) => {
@@ -653,7 +671,7 @@ function isDeclaredInRenderPropLoose(node) {
653
671
  if (isDirectValueOfRenderPropertyLoose(node)) {
654
672
  return true;
655
673
  }
656
- const parent = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
674
+ const parent = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
657
675
  if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
658
676
  return false;
659
677
  }
@@ -661,17 +679,17 @@ function isDeclaredInRenderPropLoose(node) {
661
679
  }
662
680
  function isThisSetState(node) {
663
681
  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";
682
+ return callee.type === AST_NODE_TYPES.MemberExpression && AST8.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
665
683
  }
666
684
  function isFunctionOfUseEffectSetup(node) {
667
685
  if (node == null) return _;
668
686
  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);
669
687
  }
670
688
  function isFunctionOfUseEffectCleanup(node) {
671
- const nearReturn = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.ReturnStatement));
672
- const nearFunction = AST9.findParentNode(node, AST9.isFunction);
673
- const nearFunctionOfReturn = AST9.findParentNode(nearReturn, AST9.isFunction);
689
+ const nearReturn = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ReturnStatement));
690
+ const nearFunction = AST8.findParentNode(node, AST8.isFunction);
691
+ const nearFunctionOfReturn = AST8.findParentNode(nearReturn, AST8.isFunction);
674
692
  return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
675
693
  }
676
694
 
677
- export { DEFAULT_COMPONENT_HINT, DISPLAY_NAME_ASSIGNMENT_SELECTOR, ERComponentFlag, ERComponentHint, 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, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isDisplayNameAssignment, 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 };
695
+ export { DEFAULT_COMPONENT_HINT, DISPLAY_NAME_ASSIGNMENT_SELECTOR, ERComponentFlag, ERComponentHint, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, hasValidHierarchy, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isDisplayNameAssignment, isForwardRef, isForwardRefCall, isFromReact, isFromReactLoose, isFromReactMember, isFromReactMemberLoose, isFromReactMemberStrict, isFromReactStrict, 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.28.0-beta.1",
3
+ "version": "1.28.0-beta.4",
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": {
@@ -41,11 +41,11 @@
41
41
  "@typescript-eslint/utils": "^8.25.0",
42
42
  "birecord": "^0.1.1",
43
43
  "ts-pattern": "^5.6.2",
44
- "@eslint-react/ast": "1.28.0-beta.1",
45
- "@eslint-react/eff": "1.28.0-beta.1",
46
- "@eslint-react/shared": "1.28.0-beta.1",
47
- "@eslint-react/var": "1.28.0-beta.1",
48
- "@eslint-react/jsx": "1.28.0-beta.1"
44
+ "@eslint-react/ast": "1.28.0-beta.4",
45
+ "@eslint-react/eff": "1.28.0-beta.4",
46
+ "@eslint-react/shared": "1.28.0-beta.4",
47
+ "@eslint-react/jsx": "1.28.0-beta.4",
48
+ "@eslint-react/var": "1.28.0-beta.4"
49
49
  },
50
50
  "devDependencies": {
51
51
  "tsup": "^8.3.6",