@eslint-react/core 1.27.1-next.6 → 1.27.1-next.8
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.d.mts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +72 -44
- package/dist/index.mjs +71 -43
- package/package.json +10 -10
package/dist/index.d.mts
CHANGED
|
@@ -369,7 +369,14 @@ declare namespace isCallFromReactMember {
|
|
|
369
369
|
}
|
|
370
370
|
declare function isCallFromReactMember(pragmaMemberName: string, name: string): isCallFromReactMember.ReturnType;
|
|
371
371
|
|
|
372
|
-
|
|
372
|
+
/**
|
|
373
|
+
* Check if an identifier is initialized from react
|
|
374
|
+
* @param name The top-level identifier's name
|
|
375
|
+
* @param source The import source to check against
|
|
376
|
+
* @param initialScope Initial scope to search for the identifier
|
|
377
|
+
* @returns Whether the identifier is initialized from react
|
|
378
|
+
*/
|
|
379
|
+
declare function isInitializedFromReact(name: string, source: string, initialScope: Scope): boolean;
|
|
373
380
|
|
|
374
381
|
/**********************************************
|
|
375
382
|
* DO NOT MODIFY THIS FILE MANUALLY *
|
|
@@ -1860,7 +1867,7 @@ declare interface TSImportEqualsRequireDeclaration extends TSImportEqualsDeclara
|
|
|
1860
1867
|
declare interface TSImportType extends BaseNode {
|
|
1861
1868
|
type: AST_NODE_TYPES.TSImportType;
|
|
1862
1869
|
argument: TypeNode;
|
|
1863
|
-
|
|
1870
|
+
options: ObjectExpression | null;
|
|
1864
1871
|
qualifier: EntityName | null;
|
|
1865
1872
|
typeArguments: TSTypeParameterInstantiation | null;
|
|
1866
1873
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -369,7 +369,14 @@ declare namespace isCallFromReactMember {
|
|
|
369
369
|
}
|
|
370
370
|
declare function isCallFromReactMember(pragmaMemberName: string, name: string): isCallFromReactMember.ReturnType;
|
|
371
371
|
|
|
372
|
-
|
|
372
|
+
/**
|
|
373
|
+
* Check if an identifier is initialized from react
|
|
374
|
+
* @param name The top-level identifier's name
|
|
375
|
+
* @param source The import source to check against
|
|
376
|
+
* @param initialScope Initial scope to search for the identifier
|
|
377
|
+
* @returns Whether the identifier is initialized from react
|
|
378
|
+
*/
|
|
379
|
+
declare function isInitializedFromReact(name: string, source: string, initialScope: Scope): boolean;
|
|
373
380
|
|
|
374
381
|
/**********************************************
|
|
375
382
|
* DO NOT MODIFY THIS FILE MANUALLY *
|
|
@@ -1860,7 +1867,7 @@ declare interface TSImportEqualsRequireDeclaration extends TSImportEqualsDeclara
|
|
|
1860
1867
|
declare interface TSImportType extends BaseNode {
|
|
1861
1868
|
type: AST_NODE_TYPES.TSImportType;
|
|
1862
1869
|
argument: TypeNode;
|
|
1863
|
-
|
|
1870
|
+
options: ObjectExpression | null;
|
|
1864
1871
|
qualifier: EntityName | null;
|
|
1865
1872
|
typeArguments: TSTypeParameterInstantiation | null;
|
|
1866
1873
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var AST9 = require('@eslint-react/ast');
|
|
4
4
|
var eff = require('@eslint-react/eff');
|
|
5
5
|
var JSX3 = require('@eslint-react/jsx');
|
|
6
6
|
var shared = require('@eslint-react/shared');
|
|
@@ -28,7 +28,7 @@ function _interopNamespace(e) {
|
|
|
28
28
|
return Object.freeze(n);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
var
|
|
31
|
+
var AST9__namespace = /*#__PURE__*/_interopNamespace(AST9);
|
|
32
32
|
var JSX3__namespace = /*#__PURE__*/_interopNamespace(JSX3);
|
|
33
33
|
var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
34
34
|
var birecord__default = /*#__PURE__*/_interopDefault(birecord);
|
|
@@ -45,12 +45,40 @@ function isDisplayNameAssignment(node) {
|
|
|
45
45
|
if (node == null) return false;
|
|
46
46
|
return node.type === types.AST_NODE_TYPES.AssignmentExpression && node.operator === "=" && node.left.type === types.AST_NODE_TYPES.MemberExpression && node.left.property.type === types.AST_NODE_TYPES.Identifier && node.left.property.name === "displayName";
|
|
47
47
|
}
|
|
48
|
-
function isInitializedFromReact(name,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
48
|
+
function isInitializedFromReact(name, source, initialScope) {
|
|
49
|
+
if (name.toLowerCase() === "react") return true;
|
|
50
|
+
const latestDef = VAR__namespace.findVariable(name, initialScope)?.defs.at(-1);
|
|
51
|
+
if (latestDef == null) return false;
|
|
52
|
+
const { node, parent } = latestDef;
|
|
53
|
+
if (node.type === types.AST_NODE_TYPES.VariableDeclarator && node.init != null) {
|
|
54
|
+
const { init } = node;
|
|
55
|
+
if (init.type === types.AST_NODE_TYPES.MemberExpression && init.object.type === types.AST_NODE_TYPES.Identifier) {
|
|
56
|
+
return isInitializedFromReact(init.object.name, source, initialScope);
|
|
57
|
+
}
|
|
58
|
+
if (init.type === types.AST_NODE_TYPES.Identifier) {
|
|
59
|
+
return isInitializedFromReact(init.name, source, initialScope);
|
|
60
|
+
}
|
|
61
|
+
const args = getRequireExpressionArguments(init);
|
|
62
|
+
const arg0 = args?.[0];
|
|
63
|
+
if (arg0 == null || !AST9__namespace.isStringLiteral(arg0)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return arg0.value === source || arg0.value.startsWith(`${source}/`);
|
|
67
|
+
}
|
|
68
|
+
return parent?.type === types.AST_NODE_TYPES.ImportDeclaration && parent.source.value === source;
|
|
69
|
+
}
|
|
70
|
+
function getRequireExpressionArguments(node) {
|
|
71
|
+
switch (true) {
|
|
72
|
+
// require('source')
|
|
73
|
+
case (node.type === types.AST_NODE_TYPES.CallExpression && node.callee.type === types.AST_NODE_TYPES.Identifier && node.callee.name === "require"): {
|
|
74
|
+
return node.arguments;
|
|
75
|
+
}
|
|
76
|
+
// require('source').variable
|
|
77
|
+
case node.type === types.AST_NODE_TYPES.MemberExpression: {
|
|
78
|
+
return getRequireExpressionArguments(node.object);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return eff._;
|
|
54
82
|
}
|
|
55
83
|
|
|
56
84
|
// src/utils/is-from-react.ts
|
|
@@ -108,7 +136,7 @@ function isCallFromReact(name) {
|
|
|
108
136
|
if (node.type !== types.AST_NODE_TYPES.CallExpression) {
|
|
109
137
|
return false;
|
|
110
138
|
}
|
|
111
|
-
if (!
|
|
139
|
+
if (!AST9__namespace.isOneOf([types.AST_NODE_TYPES.Identifier, types.AST_NODE_TYPES.MemberExpression])(node.callee)) {
|
|
112
140
|
return false;
|
|
113
141
|
}
|
|
114
142
|
return isFromReact(name)(node.callee, context);
|
|
@@ -119,7 +147,7 @@ function isCallFromReactMember(pragmaMemberName, name) {
|
|
|
119
147
|
if (node.type !== types.AST_NODE_TYPES.CallExpression) {
|
|
120
148
|
return false;
|
|
121
149
|
}
|
|
122
|
-
if (!
|
|
150
|
+
if (!AST9__namespace.is(types.AST_NODE_TYPES.MemberExpression)(node.callee)) {
|
|
123
151
|
return false;
|
|
124
152
|
}
|
|
125
153
|
return isFromReactMember(pragmaMemberName, name)(node.callee, context);
|
|
@@ -158,9 +186,9 @@ var isMemoCall = isReactAPICallWithName("memo");
|
|
|
158
186
|
|
|
159
187
|
// src/element/hierarchy.ts
|
|
160
188
|
function isInsideCreateElementProps(node, context) {
|
|
161
|
-
const call =
|
|
189
|
+
const call = AST9__namespace.findParentNode(node, isCreateElementCall(context));
|
|
162
190
|
if (call == null) return false;
|
|
163
|
-
const prop =
|
|
191
|
+
const prop = AST9__namespace.findParentNode(node, AST9__namespace.is(types.AST_NODE_TYPES.ObjectExpression));
|
|
164
192
|
if (prop == null) return false;
|
|
165
193
|
return prop === call.arguments[1];
|
|
166
194
|
}
|
|
@@ -180,7 +208,7 @@ function isReactHookName(name) {
|
|
|
180
208
|
// src/hook/is.ts
|
|
181
209
|
function isReactHook(node) {
|
|
182
210
|
if (node == null) return eff._;
|
|
183
|
-
const id =
|
|
211
|
+
const id = AST9__namespace.getFunctionIdentifier(node);
|
|
184
212
|
return id?.name != null && isReactHookName(id.name);
|
|
185
213
|
}
|
|
186
214
|
function isReactHookCall(node) {
|
|
@@ -272,13 +300,13 @@ var isUseTransitionCall = eff.flip(isReactHookCallWithName)("useTransition");
|
|
|
272
300
|
|
|
273
301
|
// src/hook/hierarchy.ts
|
|
274
302
|
function isInsideReactHook(node) {
|
|
275
|
-
return isReactHook(
|
|
303
|
+
return isReactHook(AST9__namespace.findParentNode(node, AST9__namespace.isFunction));
|
|
276
304
|
}
|
|
277
305
|
function useHookCollector() {
|
|
278
306
|
const hooks = /* @__PURE__ */ new Map();
|
|
279
307
|
const functionEntries = [];
|
|
280
308
|
const onFunctionEnter = (node) => {
|
|
281
|
-
const id =
|
|
309
|
+
const id = AST9__namespace.getFunctionIdentifier(node);
|
|
282
310
|
const key = shared.getId();
|
|
283
311
|
const name = id?.name;
|
|
284
312
|
if (name != null && isReactHookName(name)) {
|
|
@@ -374,7 +402,7 @@ function isComponentWrapperCall(node, context) {
|
|
|
374
402
|
return isMemoCall(node, context) || isForwardRefCall(node, context) || isReactHookCallWithNameLoose(node)("useCallback");
|
|
375
403
|
}
|
|
376
404
|
function getFunctionComponentIdentifier(node, context) {
|
|
377
|
-
const functionId =
|
|
405
|
+
const functionId = AST9__namespace.getFunctionIdentifier(node);
|
|
378
406
|
if (functionId != null) {
|
|
379
407
|
return functionId;
|
|
380
408
|
}
|
|
@@ -414,28 +442,28 @@ function isPureComponent(node) {
|
|
|
414
442
|
|
|
415
443
|
// src/component/component-lifecycle.ts
|
|
416
444
|
function isComponentDidMount(node) {
|
|
417
|
-
return
|
|
445
|
+
return AST9__namespace.isMethodOrProperty(node) && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
|
|
418
446
|
}
|
|
419
447
|
function isComponentWillUnmount(node) {
|
|
420
|
-
return
|
|
448
|
+
return AST9__namespace.isMethodOrProperty(node) && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
|
|
421
449
|
}
|
|
422
450
|
function isComponentDidCatch(node) {
|
|
423
|
-
return
|
|
451
|
+
return AST9__namespace.isMethodOrProperty(node) && !node.static && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
|
|
424
452
|
}
|
|
425
453
|
function isGetDerivedStateFromError(node) {
|
|
426
|
-
return
|
|
454
|
+
return AST9__namespace.isMethodOrProperty(node) && node.static && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
|
|
427
455
|
}
|
|
428
456
|
function isGetDerivedStateFromProps(node) {
|
|
429
|
-
return
|
|
457
|
+
return AST9__namespace.isMethodOrProperty(node) && node.static && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
|
|
430
458
|
}
|
|
431
459
|
function isFunctionOfComponentDidMount(node) {
|
|
432
|
-
return
|
|
460
|
+
return AST9__namespace.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
|
|
433
461
|
}
|
|
434
462
|
function isFunctionOfComponentWillUnmount(node) {
|
|
435
|
-
return
|
|
463
|
+
return AST9__namespace.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
|
|
436
464
|
}
|
|
437
465
|
function isRenderMethodLike(node) {
|
|
438
|
-
return
|
|
466
|
+
return AST9__namespace.isMethodOrProperty(node) && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === types.AST_NODE_TYPES.ClassDeclaration;
|
|
439
467
|
}
|
|
440
468
|
function isFunctionOfRenderMethod(node) {
|
|
441
469
|
if (!isRenderMethodLike(node.parent)) {
|
|
@@ -444,7 +472,7 @@ function isFunctionOfRenderMethod(node) {
|
|
|
444
472
|
return isClassComponent(node.parent.parent.parent);
|
|
445
473
|
}
|
|
446
474
|
function isInsideRenderMethod(node) {
|
|
447
|
-
return
|
|
475
|
+
return AST9__namespace.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
|
|
448
476
|
}
|
|
449
477
|
var RE_COMPONENT_NAME = /^_?[A-Z]/u;
|
|
450
478
|
function getComponentNameFromIdentifier(node) {
|
|
@@ -476,7 +504,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
476
504
|
const entry = functionEntries.at(-1);
|
|
477
505
|
if (entry == null) return;
|
|
478
506
|
if (!entry.isComponent) return functionEntries.pop();
|
|
479
|
-
const shouldDrop =
|
|
507
|
+
const shouldDrop = AST9__namespace.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
|
|
480
508
|
return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3__namespace.isJSXValue(r.argument, jsxCtx, hint);
|
|
481
509
|
});
|
|
482
510
|
if (shouldDrop) {
|
|
@@ -503,7 +531,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
503
531
|
const { body } = entry.node;
|
|
504
532
|
const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3__namespace.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
|
|
505
533
|
if (!isComponent) return;
|
|
506
|
-
const initPath =
|
|
534
|
+
const initPath = AST9__namespace.getFunctionInitPath(entry.node);
|
|
507
535
|
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
508
536
|
const name = getComponentNameFromIdentifier(id);
|
|
509
537
|
const key = shared.getId();
|
|
@@ -544,7 +572,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
544
572
|
const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3__namespace.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
|
|
545
573
|
if (!isComponent) return;
|
|
546
574
|
entry.isComponent = true;
|
|
547
|
-
const initPath =
|
|
575
|
+
const initPath = AST9__namespace.getFunctionInitPath(entry.node);
|
|
548
576
|
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
549
577
|
const name = getComponentNameFromIdentifier(id);
|
|
550
578
|
components.set(entry.key, {
|
|
@@ -567,21 +595,21 @@ function hasValidHierarchy(node, context, hint) {
|
|
|
567
595
|
if (isChildrenOfCreateElement(node, context) || isFunctionOfRenderMethod(node)) {
|
|
568
596
|
return false;
|
|
569
597
|
}
|
|
570
|
-
if (hint & ERComponentHint.SkipMapCallback &&
|
|
598
|
+
if (hint & ERComponentHint.SkipMapCallback && AST9__namespace.isMapCallLoose(node.parent)) {
|
|
571
599
|
return false;
|
|
572
600
|
}
|
|
573
|
-
if (hint & ERComponentHint.SkipObjectMethod &&
|
|
601
|
+
if (hint & ERComponentHint.SkipObjectMethod && AST9__namespace.isFunctionOfObjectMethod(node.parent)) {
|
|
574
602
|
return false;
|
|
575
603
|
}
|
|
576
|
-
if (hint & ERComponentHint.SkipClassMethod &&
|
|
604
|
+
if (hint & ERComponentHint.SkipClassMethod && AST9__namespace.isFunctionOfClassMethod(node.parent)) {
|
|
577
605
|
return false;
|
|
578
606
|
}
|
|
579
|
-
if (hint & ERComponentHint.SkipClassProperty &&
|
|
607
|
+
if (hint & ERComponentHint.SkipClassProperty && AST9__namespace.isFunctionOfClassProperty(node.parent)) {
|
|
580
608
|
return false;
|
|
581
609
|
}
|
|
582
|
-
const boundaryNode =
|
|
610
|
+
const boundaryNode = AST9__namespace.findParentNode(
|
|
583
611
|
node,
|
|
584
|
-
|
|
612
|
+
AST9__namespace.isOneOf([
|
|
585
613
|
types.AST_NODE_TYPES.JSXExpressionContainer,
|
|
586
614
|
types.AST_NODE_TYPES.ArrowFunctionExpression,
|
|
587
615
|
types.AST_NODE_TYPES.FunctionExpression,
|
|
@@ -593,10 +621,10 @@ function hasValidHierarchy(node, context, hint) {
|
|
|
593
621
|
}
|
|
594
622
|
function getComponentFlag(initPath) {
|
|
595
623
|
let flag = ERComponentFlag.None;
|
|
596
|
-
if (initPath != null &&
|
|
624
|
+
if (initPath != null && AST9__namespace.hasCallInFunctionInitPath("memo", initPath)) {
|
|
597
625
|
flag |= ERComponentFlag.Memo;
|
|
598
626
|
}
|
|
599
|
-
if (initPath != null &&
|
|
627
|
+
if (initPath != null && AST9__namespace.hasCallInFunctionInitPath("forwardRef", initPath)) {
|
|
600
628
|
flag |= ERComponentFlag.ForwardRef;
|
|
601
629
|
}
|
|
602
630
|
return flag;
|
|
@@ -613,7 +641,7 @@ function useComponentCollectorLegacy() {
|
|
|
613
641
|
if (!isClassComponent(node)) {
|
|
614
642
|
return;
|
|
615
643
|
}
|
|
616
|
-
const id =
|
|
644
|
+
const id = AST9__namespace.getClassIdentifier(node);
|
|
617
645
|
const key = shared.getId();
|
|
618
646
|
const flag = isPureComponent(node) ? ERComponentFlag.PureComponent : ERComponentFlag.None;
|
|
619
647
|
components.set(
|
|
@@ -646,7 +674,7 @@ var ERPhaseRelevance = birecord__default.default({
|
|
|
646
674
|
var isInversePhase = eff.dual(2, (a, b) => ERPhaseRelevance.get(a) === b);
|
|
647
675
|
function isRenderFunctionLoose(node, context) {
|
|
648
676
|
const { body, parent } = node;
|
|
649
|
-
if (
|
|
677
|
+
if (AST9__namespace.getFunctionIdentifier(node)?.name.startsWith("render")) {
|
|
650
678
|
return parent.type === types.AST_NODE_TYPES.JSXExpressionContainer && parent.parent.type === types.AST_NODE_TYPES.JSXAttribute && parent.parent.name.type === types.AST_NODE_TYPES.JSXIdentifier && parent.parent.name.name.startsWith("render");
|
|
651
679
|
}
|
|
652
680
|
return JSX3__namespace.isJSXValue(
|
|
@@ -661,7 +689,7 @@ function isRenderPropLoose(node, context) {
|
|
|
661
689
|
if (node.name.type !== types.AST_NODE_TYPES.JSXIdentifier) {
|
|
662
690
|
return false;
|
|
663
691
|
}
|
|
664
|
-
return node.name.name.startsWith("render") && node.value?.type === types.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
692
|
+
return node.name.name.startsWith("render") && node.value?.type === types.AST_NODE_TYPES.JSXExpressionContainer && AST9__namespace.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
|
|
665
693
|
}
|
|
666
694
|
function isDirectValueOfRenderPropertyLoose(node) {
|
|
667
695
|
const matching = (node2) => {
|
|
@@ -673,7 +701,7 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
673
701
|
if (isDirectValueOfRenderPropertyLoose(node)) {
|
|
674
702
|
return true;
|
|
675
703
|
}
|
|
676
|
-
const parent =
|
|
704
|
+
const parent = AST9__namespace.findParentNode(node, AST9__namespace.is(types.AST_NODE_TYPES.JSXExpressionContainer))?.parent;
|
|
677
705
|
if (parent?.type !== types.AST_NODE_TYPES.JSXAttribute) {
|
|
678
706
|
return false;
|
|
679
707
|
}
|
|
@@ -681,16 +709,16 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
681
709
|
}
|
|
682
710
|
function isThisSetState(node) {
|
|
683
711
|
const { callee } = node;
|
|
684
|
-
return callee.type === types.AST_NODE_TYPES.MemberExpression &&
|
|
712
|
+
return callee.type === types.AST_NODE_TYPES.MemberExpression && AST9__namespace.isThisExpression(callee.object) && callee.property.type === types.AST_NODE_TYPES.Identifier && callee.property.name === "setState";
|
|
685
713
|
}
|
|
686
714
|
function isFunctionOfUseEffectSetup(node) {
|
|
687
715
|
if (node == null) return eff._;
|
|
688
716
|
return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && node.parent.callee.type === types.AST_NODE_TYPES.Identifier && node.parent.arguments.at(0) === node && isUseEffectCallLoose(node.parent);
|
|
689
717
|
}
|
|
690
718
|
function isFunctionOfUseEffectCleanup(node) {
|
|
691
|
-
const nearReturn =
|
|
692
|
-
const nearFunction =
|
|
693
|
-
const nearFunctionOfReturn =
|
|
719
|
+
const nearReturn = AST9__namespace.findParentNode(node, AST9__namespace.is(types.AST_NODE_TYPES.ReturnStatement));
|
|
720
|
+
const nearFunction = AST9__namespace.findParentNode(node, AST9__namespace.isFunction);
|
|
721
|
+
const nearFunctionOfReturn = AST9__namespace.findParentNode(nearReturn, AST9__namespace.isFunction);
|
|
694
722
|
return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
|
|
695
723
|
}
|
|
696
724
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as AST9 from '@eslint-react/ast';
|
|
2
2
|
import { flip, dual, constFalse, _ } from '@eslint-react/eff';
|
|
3
3
|
import * as JSX3 from '@eslint-react/jsx';
|
|
4
4
|
import { unsafeDecodeSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
|
|
@@ -18,12 +18,40 @@ function isDisplayNameAssignment(node) {
|
|
|
18
18
|
if (node == null) return false;
|
|
19
19
|
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";
|
|
20
20
|
}
|
|
21
|
-
function isInitializedFromReact(name,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
)
|
|
21
|
+
function isInitializedFromReact(name, source, initialScope) {
|
|
22
|
+
if (name.toLowerCase() === "react") return true;
|
|
23
|
+
const latestDef = VAR.findVariable(name, initialScope)?.defs.at(-1);
|
|
24
|
+
if (latestDef == null) return false;
|
|
25
|
+
const { node, parent } = latestDef;
|
|
26
|
+
if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
|
|
27
|
+
const { init } = node;
|
|
28
|
+
if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) {
|
|
29
|
+
return isInitializedFromReact(init.object.name, source, initialScope);
|
|
30
|
+
}
|
|
31
|
+
if (init.type === AST_NODE_TYPES.Identifier) {
|
|
32
|
+
return isInitializedFromReact(init.name, source, initialScope);
|
|
33
|
+
}
|
|
34
|
+
const args = getRequireExpressionArguments(init);
|
|
35
|
+
const arg0 = args?.[0];
|
|
36
|
+
if (arg0 == null || !AST9.isStringLiteral(arg0)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return arg0.value === source || arg0.value.startsWith(`${source}/`);
|
|
40
|
+
}
|
|
41
|
+
return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === source;
|
|
42
|
+
}
|
|
43
|
+
function getRequireExpressionArguments(node) {
|
|
44
|
+
switch (true) {
|
|
45
|
+
// require('source')
|
|
46
|
+
case (node.type === AST_NODE_TYPES.CallExpression && node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "require"): {
|
|
47
|
+
return node.arguments;
|
|
48
|
+
}
|
|
49
|
+
// require('source').variable
|
|
50
|
+
case node.type === AST_NODE_TYPES.MemberExpression: {
|
|
51
|
+
return getRequireExpressionArguments(node.object);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return _;
|
|
27
55
|
}
|
|
28
56
|
|
|
29
57
|
// src/utils/is-from-react.ts
|
|
@@ -81,7 +109,7 @@ function isCallFromReact(name) {
|
|
|
81
109
|
if (node.type !== AST_NODE_TYPES.CallExpression) {
|
|
82
110
|
return false;
|
|
83
111
|
}
|
|
84
|
-
if (!
|
|
112
|
+
if (!AST9.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) {
|
|
85
113
|
return false;
|
|
86
114
|
}
|
|
87
115
|
return isFromReact(name)(node.callee, context);
|
|
@@ -92,7 +120,7 @@ function isCallFromReactMember(pragmaMemberName, name) {
|
|
|
92
120
|
if (node.type !== AST_NODE_TYPES.CallExpression) {
|
|
93
121
|
return false;
|
|
94
122
|
}
|
|
95
|
-
if (!
|
|
123
|
+
if (!AST9.is(AST_NODE_TYPES.MemberExpression)(node.callee)) {
|
|
96
124
|
return false;
|
|
97
125
|
}
|
|
98
126
|
return isFromReactMember(pragmaMemberName, name)(node.callee, context);
|
|
@@ -131,9 +159,9 @@ var isMemoCall = isReactAPICallWithName("memo");
|
|
|
131
159
|
|
|
132
160
|
// src/element/hierarchy.ts
|
|
133
161
|
function isInsideCreateElementProps(node, context) {
|
|
134
|
-
const call =
|
|
162
|
+
const call = AST9.findParentNode(node, isCreateElementCall(context));
|
|
135
163
|
if (call == null) return false;
|
|
136
|
-
const prop =
|
|
164
|
+
const prop = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.ObjectExpression));
|
|
137
165
|
if (prop == null) return false;
|
|
138
166
|
return prop === call.arguments[1];
|
|
139
167
|
}
|
|
@@ -153,7 +181,7 @@ function isReactHookName(name) {
|
|
|
153
181
|
// src/hook/is.ts
|
|
154
182
|
function isReactHook(node) {
|
|
155
183
|
if (node == null) return _;
|
|
156
|
-
const id =
|
|
184
|
+
const id = AST9.getFunctionIdentifier(node);
|
|
157
185
|
return id?.name != null && isReactHookName(id.name);
|
|
158
186
|
}
|
|
159
187
|
function isReactHookCall(node) {
|
|
@@ -245,13 +273,13 @@ var isUseTransitionCall = flip(isReactHookCallWithName)("useTransition");
|
|
|
245
273
|
|
|
246
274
|
// src/hook/hierarchy.ts
|
|
247
275
|
function isInsideReactHook(node) {
|
|
248
|
-
return isReactHook(
|
|
276
|
+
return isReactHook(AST9.findParentNode(node, AST9.isFunction));
|
|
249
277
|
}
|
|
250
278
|
function useHookCollector() {
|
|
251
279
|
const hooks = /* @__PURE__ */ new Map();
|
|
252
280
|
const functionEntries = [];
|
|
253
281
|
const onFunctionEnter = (node) => {
|
|
254
|
-
const id =
|
|
282
|
+
const id = AST9.getFunctionIdentifier(node);
|
|
255
283
|
const key = getId();
|
|
256
284
|
const name = id?.name;
|
|
257
285
|
if (name != null && isReactHookName(name)) {
|
|
@@ -347,7 +375,7 @@ function isComponentWrapperCall(node, context) {
|
|
|
347
375
|
return isMemoCall(node, context) || isForwardRefCall(node, context) || isReactHookCallWithNameLoose(node)("useCallback");
|
|
348
376
|
}
|
|
349
377
|
function getFunctionComponentIdentifier(node, context) {
|
|
350
|
-
const functionId =
|
|
378
|
+
const functionId = AST9.getFunctionIdentifier(node);
|
|
351
379
|
if (functionId != null) {
|
|
352
380
|
return functionId;
|
|
353
381
|
}
|
|
@@ -387,28 +415,28 @@ function isPureComponent(node) {
|
|
|
387
415
|
|
|
388
416
|
// src/component/component-lifecycle.ts
|
|
389
417
|
function isComponentDidMount(node) {
|
|
390
|
-
return
|
|
418
|
+
return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
|
|
391
419
|
}
|
|
392
420
|
function isComponentWillUnmount(node) {
|
|
393
|
-
return
|
|
421
|
+
return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
|
|
394
422
|
}
|
|
395
423
|
function isComponentDidCatch(node) {
|
|
396
|
-
return
|
|
424
|
+
return AST9.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
|
|
397
425
|
}
|
|
398
426
|
function isGetDerivedStateFromError(node) {
|
|
399
|
-
return
|
|
427
|
+
return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
|
|
400
428
|
}
|
|
401
429
|
function isGetDerivedStateFromProps(node) {
|
|
402
|
-
return
|
|
430
|
+
return AST9.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
|
|
403
431
|
}
|
|
404
432
|
function isFunctionOfComponentDidMount(node) {
|
|
405
|
-
return
|
|
433
|
+
return AST9.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
|
|
406
434
|
}
|
|
407
435
|
function isFunctionOfComponentWillUnmount(node) {
|
|
408
|
-
return
|
|
436
|
+
return AST9.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
|
|
409
437
|
}
|
|
410
438
|
function isRenderMethodLike(node) {
|
|
411
|
-
return
|
|
439
|
+
return AST9.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
|
|
412
440
|
}
|
|
413
441
|
function isFunctionOfRenderMethod(node) {
|
|
414
442
|
if (!isRenderMethodLike(node.parent)) {
|
|
@@ -417,7 +445,7 @@ function isFunctionOfRenderMethod(node) {
|
|
|
417
445
|
return isClassComponent(node.parent.parent.parent);
|
|
418
446
|
}
|
|
419
447
|
function isInsideRenderMethod(node) {
|
|
420
|
-
return
|
|
448
|
+
return AST9.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
|
|
421
449
|
}
|
|
422
450
|
var RE_COMPONENT_NAME = /^_?[A-Z]/u;
|
|
423
451
|
function getComponentNameFromIdentifier(node) {
|
|
@@ -449,7 +477,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
449
477
|
const entry = functionEntries.at(-1);
|
|
450
478
|
if (entry == null) return;
|
|
451
479
|
if (!entry.isComponent) return functionEntries.pop();
|
|
452
|
-
const shouldDrop =
|
|
480
|
+
const shouldDrop = AST9.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
|
|
453
481
|
return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3.isJSXValue(r.argument, jsxCtx, hint);
|
|
454
482
|
});
|
|
455
483
|
if (shouldDrop) {
|
|
@@ -476,7 +504,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
476
504
|
const { body } = entry.node;
|
|
477
505
|
const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
|
|
478
506
|
if (!isComponent) return;
|
|
479
|
-
const initPath =
|
|
507
|
+
const initPath = AST9.getFunctionInitPath(entry.node);
|
|
480
508
|
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
481
509
|
const name = getComponentNameFromIdentifier(id);
|
|
482
510
|
const key = getId();
|
|
@@ -517,7 +545,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
517
545
|
const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
|
|
518
546
|
if (!isComponent) return;
|
|
519
547
|
entry.isComponent = true;
|
|
520
|
-
const initPath =
|
|
548
|
+
const initPath = AST9.getFunctionInitPath(entry.node);
|
|
521
549
|
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
522
550
|
const name = getComponentNameFromIdentifier(id);
|
|
523
551
|
components.set(entry.key, {
|
|
@@ -540,21 +568,21 @@ function hasValidHierarchy(node, context, hint) {
|
|
|
540
568
|
if (isChildrenOfCreateElement(node, context) || isFunctionOfRenderMethod(node)) {
|
|
541
569
|
return false;
|
|
542
570
|
}
|
|
543
|
-
if (hint & ERComponentHint.SkipMapCallback &&
|
|
571
|
+
if (hint & ERComponentHint.SkipMapCallback && AST9.isMapCallLoose(node.parent)) {
|
|
544
572
|
return false;
|
|
545
573
|
}
|
|
546
|
-
if (hint & ERComponentHint.SkipObjectMethod &&
|
|
574
|
+
if (hint & ERComponentHint.SkipObjectMethod && AST9.isFunctionOfObjectMethod(node.parent)) {
|
|
547
575
|
return false;
|
|
548
576
|
}
|
|
549
|
-
if (hint & ERComponentHint.SkipClassMethod &&
|
|
577
|
+
if (hint & ERComponentHint.SkipClassMethod && AST9.isFunctionOfClassMethod(node.parent)) {
|
|
550
578
|
return false;
|
|
551
579
|
}
|
|
552
|
-
if (hint & ERComponentHint.SkipClassProperty &&
|
|
580
|
+
if (hint & ERComponentHint.SkipClassProperty && AST9.isFunctionOfClassProperty(node.parent)) {
|
|
553
581
|
return false;
|
|
554
582
|
}
|
|
555
|
-
const boundaryNode =
|
|
583
|
+
const boundaryNode = AST9.findParentNode(
|
|
556
584
|
node,
|
|
557
|
-
|
|
585
|
+
AST9.isOneOf([
|
|
558
586
|
AST_NODE_TYPES.JSXExpressionContainer,
|
|
559
587
|
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
560
588
|
AST_NODE_TYPES.FunctionExpression,
|
|
@@ -566,10 +594,10 @@ function hasValidHierarchy(node, context, hint) {
|
|
|
566
594
|
}
|
|
567
595
|
function getComponentFlag(initPath) {
|
|
568
596
|
let flag = ERComponentFlag.None;
|
|
569
|
-
if (initPath != null &&
|
|
597
|
+
if (initPath != null && AST9.hasCallInFunctionInitPath("memo", initPath)) {
|
|
570
598
|
flag |= ERComponentFlag.Memo;
|
|
571
599
|
}
|
|
572
|
-
if (initPath != null &&
|
|
600
|
+
if (initPath != null && AST9.hasCallInFunctionInitPath("forwardRef", initPath)) {
|
|
573
601
|
flag |= ERComponentFlag.ForwardRef;
|
|
574
602
|
}
|
|
575
603
|
return flag;
|
|
@@ -586,7 +614,7 @@ function useComponentCollectorLegacy() {
|
|
|
586
614
|
if (!isClassComponent(node)) {
|
|
587
615
|
return;
|
|
588
616
|
}
|
|
589
|
-
const id =
|
|
617
|
+
const id = AST9.getClassIdentifier(node);
|
|
590
618
|
const key = getId();
|
|
591
619
|
const flag = isPureComponent(node) ? ERComponentFlag.PureComponent : ERComponentFlag.None;
|
|
592
620
|
components.set(
|
|
@@ -619,7 +647,7 @@ var ERPhaseRelevance = birecord({
|
|
|
619
647
|
var isInversePhase = dual(2, (a, b) => ERPhaseRelevance.get(a) === b);
|
|
620
648
|
function isRenderFunctionLoose(node, context) {
|
|
621
649
|
const { body, parent } = node;
|
|
622
|
-
if (
|
|
650
|
+
if (AST9.getFunctionIdentifier(node)?.name.startsWith("render")) {
|
|
623
651
|
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");
|
|
624
652
|
}
|
|
625
653
|
return JSX3.isJSXValue(
|
|
@@ -634,7 +662,7 @@ function isRenderPropLoose(node, context) {
|
|
|
634
662
|
if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {
|
|
635
663
|
return false;
|
|
636
664
|
}
|
|
637
|
-
return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer &&
|
|
665
|
+
return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST9.isFunction(node.value.expression) && isRenderFunctionLoose(node.value.expression, context);
|
|
638
666
|
}
|
|
639
667
|
function isDirectValueOfRenderPropertyLoose(node) {
|
|
640
668
|
const matching = (node2) => {
|
|
@@ -646,7 +674,7 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
646
674
|
if (isDirectValueOfRenderPropertyLoose(node)) {
|
|
647
675
|
return true;
|
|
648
676
|
}
|
|
649
|
-
const parent =
|
|
677
|
+
const parent = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
|
|
650
678
|
if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
|
|
651
679
|
return false;
|
|
652
680
|
}
|
|
@@ -654,16 +682,16 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
654
682
|
}
|
|
655
683
|
function isThisSetState(node) {
|
|
656
684
|
const { callee } = node;
|
|
657
|
-
return callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
685
|
+
return callee.type === AST_NODE_TYPES.MemberExpression && AST9.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
|
|
658
686
|
}
|
|
659
687
|
function isFunctionOfUseEffectSetup(node) {
|
|
660
688
|
if (node == null) return _;
|
|
661
689
|
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);
|
|
662
690
|
}
|
|
663
691
|
function isFunctionOfUseEffectCleanup(node) {
|
|
664
|
-
const nearReturn =
|
|
665
|
-
const nearFunction =
|
|
666
|
-
const nearFunctionOfReturn =
|
|
692
|
+
const nearReturn = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.ReturnStatement));
|
|
693
|
+
const nearFunction = AST9.findParentNode(node, AST9.isFunction);
|
|
694
|
+
const nearFunctionOfReturn = AST9.findParentNode(nearReturn, AST9.isFunction);
|
|
667
695
|
return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
|
|
668
696
|
}
|
|
669
697
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/core",
|
|
3
|
-
"version": "1.27.1-next.
|
|
3
|
+
"version": "1.27.1-next.8",
|
|
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": {
|
|
@@ -35,17 +35,17 @@
|
|
|
35
35
|
"./package.json"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
39
|
-
"@typescript-eslint/type-utils": "^8.
|
|
40
|
-
"@typescript-eslint/types": "^8.
|
|
41
|
-
"@typescript-eslint/utils": "^8.
|
|
38
|
+
"@typescript-eslint/scope-manager": "^8.25.0",
|
|
39
|
+
"@typescript-eslint/type-utils": "^8.25.0",
|
|
40
|
+
"@typescript-eslint/types": "^8.25.0",
|
|
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.27.1-next.
|
|
45
|
-
"@eslint-react/eff": "1.27.1-next.
|
|
46
|
-
"@eslint-react/
|
|
47
|
-
"@eslint-react/
|
|
48
|
-
"@eslint-react/
|
|
44
|
+
"@eslint-react/ast": "1.27.1-next.8",
|
|
45
|
+
"@eslint-react/eff": "1.27.1-next.8",
|
|
46
|
+
"@eslint-react/shared": "1.27.1-next.8",
|
|
47
|
+
"@eslint-react/var": "1.27.1-next.8",
|
|
48
|
+
"@eslint-react/jsx": "1.27.1-next.8"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"tsup": "^8.3.6",
|