@eslint-react/core 2.0.0-beta.18 → 2.0.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.d.ts +28 -28
- package/dist/index.js +20 -13
- package/package.json +12 -12
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { RuleContext } from '@eslint-react/kit';
|
|
|
2
2
|
import { TSESTree } from '@typescript-eslint/types';
|
|
3
3
|
import { ESLintUtils, TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
|
|
4
4
|
import * as AST from '@eslint-react/ast';
|
|
5
|
-
import {
|
|
5
|
+
import { unit } from '@eslint-react/eff';
|
|
6
6
|
import * as birecord from 'birecord';
|
|
7
7
|
import { Scope } from '@typescript-eslint/scope-manager';
|
|
8
8
|
import * as VAR from '@eslint-react/var';
|
|
@@ -80,10 +80,10 @@ interface SemanticEntry {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
interface SemanticNode {
|
|
83
|
-
id:
|
|
83
|
+
id: unit | TSESTree.Identifier | TSESTree.Identifier[];
|
|
84
84
|
key: string;
|
|
85
85
|
kind: string;
|
|
86
|
-
name:
|
|
86
|
+
name: unit | string;
|
|
87
87
|
node: TSESTree.Node;
|
|
88
88
|
flag: bigint;
|
|
89
89
|
hint: bigint;
|
|
@@ -100,23 +100,23 @@ declare const ComponentFlag: {
|
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
interface FunctionComponent extends SemanticNode {
|
|
103
|
-
id:
|
|
103
|
+
id: unit | TSESTree.Identifier | TSESTree.Identifier[];
|
|
104
104
|
kind: "function";
|
|
105
105
|
node: AST.TSESTreeFunction;
|
|
106
106
|
flag: ComponentFlag;
|
|
107
107
|
hint: ComponentDetectionHint;
|
|
108
|
-
initPath:
|
|
108
|
+
initPath: unit | AST.FunctionInitPath;
|
|
109
109
|
hookCalls: TSESTree.CallExpression[];
|
|
110
|
-
displayName:
|
|
110
|
+
displayName: unit | TSESTree.Expression;
|
|
111
111
|
}
|
|
112
112
|
interface ClassComponent extends SemanticNode {
|
|
113
|
-
id:
|
|
113
|
+
id: unit | TSESTree.Identifier;
|
|
114
114
|
kind: "class";
|
|
115
115
|
node: AST.TSESTreeClass;
|
|
116
116
|
flag: ComponentFlag;
|
|
117
117
|
hint: ComponentDetectionHint;
|
|
118
118
|
methods: AST.TSESTreeMethodOrProperty[];
|
|
119
|
-
displayName:
|
|
119
|
+
displayName: unit | TSESTree.Expression;
|
|
120
120
|
}
|
|
121
121
|
type Component = ClassComponent | FunctionComponent;
|
|
122
122
|
|
|
@@ -136,7 +136,7 @@ declare namespace useComponentCollector {
|
|
|
136
136
|
ctx: {
|
|
137
137
|
getAllComponents: (node: TSESTree.Program) => Map<string, FunctionComponent>;
|
|
138
138
|
getCurrentEntries: () => FunctionEntry[];
|
|
139
|
-
getCurrentEntry: () => FunctionEntry |
|
|
139
|
+
getCurrentEntry: () => FunctionEntry | unit;
|
|
140
140
|
};
|
|
141
141
|
listeners: ESLintUtils.RuleListener;
|
|
142
142
|
};
|
|
@@ -178,7 +178,7 @@ declare function useComponentCollectorLegacy(): useComponentCollectorLegacy.Retu
|
|
|
178
178
|
declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
|
|
179
179
|
declare function isValidComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
|
|
180
180
|
|
|
181
|
-
declare function getFunctionComponentId(context: RuleContext, node: AST.TSESTreeFunction): TSESTree.Identifier | TSESTree.Identifier[] |
|
|
181
|
+
declare function getFunctionComponentId(context: RuleContext, node: AST.TSESTreeFunction): TSESTree.Identifier | TSESTree.Identifier[] | unit;
|
|
182
182
|
|
|
183
183
|
declare function getComponentFlagFromInitPath(initPath: FunctionComponent["initPath"]): bigint;
|
|
184
184
|
|
|
@@ -217,7 +217,7 @@ declare function isGetDerivedStateFromError(node: TSESTree.Node): node is AST.TS
|
|
|
217
217
|
|
|
218
218
|
declare function isComponentName(name: string): boolean;
|
|
219
219
|
declare function isComponentNameLoose(name: string): boolean;
|
|
220
|
-
declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] |
|
|
220
|
+
declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | unit): string | undefined;
|
|
221
221
|
declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
|
|
222
222
|
|
|
223
223
|
/**
|
|
@@ -332,7 +332,7 @@ declare function isComponentWrapperCallLoose(context: RuleContext, node: TSESTre
|
|
|
332
332
|
type EffectKind = "useEffect" | "useLayoutEffect" | "useInsertionEffect";
|
|
333
333
|
|
|
334
334
|
interface Hook extends SemanticNode {
|
|
335
|
-
id: TSESTree.Identifier |
|
|
335
|
+
id: TSESTree.Identifier | unit;
|
|
336
336
|
node: AST.TSESTreeFunction;
|
|
337
337
|
name: string;
|
|
338
338
|
hookCalls: TSESTree.CallExpression[];
|
|
@@ -350,17 +350,17 @@ declare function useHookCollector(): useHookCollector.ReturnType;
|
|
|
350
350
|
|
|
351
351
|
declare function isReactHookId(id: TSESTree.Identifier | TSESTree.MemberExpression): boolean;
|
|
352
352
|
|
|
353
|
-
declare function isReactHook(node: AST.TSESTreeFunction |
|
|
353
|
+
declare function isReactHook(node: AST.TSESTreeFunction | unit): boolean;
|
|
354
354
|
/**
|
|
355
355
|
* Check if the given node is a React Hook call by its name.
|
|
356
356
|
* @param node The node to check.
|
|
357
357
|
* @returns `true` if the node is a React Hook call, `false` otherwise.
|
|
358
358
|
*/
|
|
359
|
-
declare function isReactHookCall(node: TSESTree.Node |
|
|
360
|
-
declare function isReactHookCallWithName(context: RuleContext, node: TSESTree.Node |
|
|
361
|
-
declare function isReactHookCallWithNameLoose(node: TSESTree.Node |
|
|
362
|
-
declare function isReactHookCallWithNameAlias(context: RuleContext, name: string, alias?:
|
|
363
|
-
declare function isUseEffectCallLoose(node: TSESTree.Node |
|
|
359
|
+
declare function isReactHookCall(node: TSESTree.Node | unit): boolean;
|
|
360
|
+
declare function isReactHookCallWithName(context: RuleContext, node: TSESTree.Node | unit): (name: string) => boolean;
|
|
361
|
+
declare function isReactHookCallWithNameLoose(node: TSESTree.Node | unit): (name: string) => boolean;
|
|
362
|
+
declare function isReactHookCallWithNameAlias(context: RuleContext, name: string, alias?: unit | string[]): (node: TSESTree.CallExpression) => boolean;
|
|
363
|
+
declare function isUseEffectCallLoose(node: TSESTree.Node | unit): boolean;
|
|
364
364
|
declare const isUseCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
|
|
365
365
|
declare const isUseActionStateCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
|
|
366
366
|
declare const isUseCallbackCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
|
|
@@ -398,7 +398,7 @@ declare function isReactHookName(name: string): boolean;
|
|
|
398
398
|
* @param initialScope The initial scope to use for variable resolution
|
|
399
399
|
* @returns The JSX attribute node or undefined
|
|
400
400
|
*/
|
|
401
|
-
declare function getAttribute(context: RuleContext, name: string, attributes: (TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute)[], initialScope?: Scope): TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute |
|
|
401
|
+
declare function getAttribute(context: RuleContext, name: string, attributes: (TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute)[], initialScope?: Scope): TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute | unit;
|
|
402
402
|
|
|
403
403
|
/**
|
|
404
404
|
* Get the stringified name of a JSX attribute
|
|
@@ -441,7 +441,7 @@ declare const DEFAULT_JSX_DETECTION_HINT: bigint;
|
|
|
441
441
|
* @param node The AST node to check
|
|
442
442
|
* @returns `true` if the node is a `JSXText` or a `Literal` node
|
|
443
443
|
*/
|
|
444
|
-
declare function isJsxText(node: TSESTree$1.Node | null |
|
|
444
|
+
declare function isJsxText(node: TSESTree$1.Node | null | unit): node is TSESTree$1.JSXText | TSESTree$1.Literal;
|
|
445
445
|
/**
|
|
446
446
|
* Heuristic decision to determine if a node is a JSX-like node.
|
|
447
447
|
* @param code The sourceCode object
|
|
@@ -452,7 +452,7 @@ declare function isJsxText(node: TSESTree$1.Node | null | _): node is TSESTree$1
|
|
|
452
452
|
*/
|
|
453
453
|
declare function isJsxLike(code: {
|
|
454
454
|
getScope: (node: TSESTree$1.Node) => Scope;
|
|
455
|
-
}, node: TSESTree$1.Node |
|
|
455
|
+
}, node: TSESTree$1.Node | unit | null, hint?: JSXDetectionHint): boolean;
|
|
456
456
|
|
|
457
457
|
/**
|
|
458
458
|
* Get the stringified type of a JSX element
|
|
@@ -472,12 +472,12 @@ declare function hasEveryAttribute(context: RuleContext, names: string[], attrib
|
|
|
472
472
|
* @param test The test to apply to the parent attribute
|
|
473
473
|
* @returns The parent attribute node or undefined
|
|
474
474
|
*/
|
|
475
|
-
declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute |
|
|
475
|
+
declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | unit;
|
|
476
476
|
|
|
477
477
|
declare function isHostElement(context: RuleContext, node: TSESTree.Node): boolean;
|
|
478
478
|
declare function isKeyedElement(context: RuleContext, node: TSESTree.Node, initialScope?: Scope): boolean;
|
|
479
|
-
declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null |
|
|
480
|
-
declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null |
|
|
479
|
+
declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null | unit, allowJSXFragment?: false): node is TSESTree.JSXElement;
|
|
480
|
+
declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null | unit, allowJSXFragment?: true): node is TSESTree.JSXElement | TSESTree.JSXFragment;
|
|
481
481
|
|
|
482
482
|
/**
|
|
483
483
|
* Get the stringified representation of a JSX node
|
|
@@ -503,15 +503,15 @@ declare function isInstanceIdEqual(context: RuleContext, a: TSESTree.Node, b: TS
|
|
|
503
503
|
|
|
504
504
|
declare namespace isReactAPI {
|
|
505
505
|
type ReturnType = {
|
|
506
|
-
(context: RuleContext, node:
|
|
507
|
-
(context: RuleContext): (node:
|
|
506
|
+
(context: RuleContext, node: unit | null | TSESTree.Node): node is TSESTree.Identifier | TSESTree.MemberExpression;
|
|
507
|
+
(context: RuleContext): (node: unit | null | TSESTree.Node) => node is TSESTree.MemberExpression | TSESTree.Identifier;
|
|
508
508
|
};
|
|
509
509
|
}
|
|
510
510
|
declare function isReactAPI(api: string): isReactAPI.ReturnType;
|
|
511
511
|
declare namespace isReactAPICall {
|
|
512
512
|
type ReturnType = {
|
|
513
|
-
(context: RuleContext, node:
|
|
514
|
-
(context: RuleContext): (node:
|
|
513
|
+
(context: RuleContext, node: unit | null | TSESTree.Node): node is TSESTree.CallExpression;
|
|
514
|
+
(context: RuleContext): (node: unit | null | TSESTree.Node) => node is TSESTree.CallExpression;
|
|
515
515
|
};
|
|
516
516
|
}
|
|
517
517
|
declare function isReactAPICall(api: string): isReactAPICall.ReturnType;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
2
2
|
import * as AST14 from '@eslint-react/ast';
|
|
3
|
-
import { flip, dual, constFalse, identity, constTrue,
|
|
3
|
+
import { flip, dual, constFalse, identity, constTrue, unit } from '@eslint-react/eff';
|
|
4
4
|
import { RegExp, Selector } from '@eslint-react/kit';
|
|
5
5
|
import { coerceSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
|
|
6
6
|
import * as VAR3 from '@eslint-react/var';
|
|
@@ -70,7 +70,7 @@ function getInstanceId(node, prev) {
|
|
|
70
70
|
case (node.type === AST_NODE_TYPES.PropertyDefinition && node.value === prev):
|
|
71
71
|
return node.key;
|
|
72
72
|
case (node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node):
|
|
73
|
-
return
|
|
73
|
+
return unit;
|
|
74
74
|
default:
|
|
75
75
|
return getInstanceId(node.parent, node);
|
|
76
76
|
}
|
|
@@ -432,6 +432,9 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
432
432
|
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
433
433
|
}
|
|
434
434
|
case AST_NODE_TYPES.ArrayExpression: {
|
|
435
|
+
if (node.elements.length === 0) {
|
|
436
|
+
return !(hint & JSXDetectionHint.SkipEmptyArray);
|
|
437
|
+
}
|
|
435
438
|
if (hint & JSXDetectionHint.StrictArray) {
|
|
436
439
|
return node.elements.every((n) => isJsxLike(code, n, hint));
|
|
437
440
|
}
|
|
@@ -664,7 +667,7 @@ function getFunctionComponentId(context, node) {
|
|
|
664
667
|
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
|
|
665
668
|
return parent.parent.parent.id;
|
|
666
669
|
}
|
|
667
|
-
return
|
|
670
|
+
return unit;
|
|
668
671
|
}
|
|
669
672
|
|
|
670
673
|
// src/component/component-flag.ts
|
|
@@ -695,7 +698,7 @@ function isComponentNameLoose(name) {
|
|
|
695
698
|
return RegExp.COMPONENT_NAME_LOOSE.test(name);
|
|
696
699
|
}
|
|
697
700
|
function getComponentNameFromId(id) {
|
|
698
|
-
if (id == null) return
|
|
701
|
+
if (id == null) return unit;
|
|
699
702
|
return Array.isArray(id) ? id.map((n) => n.name).join(".") : id.name;
|
|
700
703
|
}
|
|
701
704
|
function hasNoneOrLooseComponentName(context, fn) {
|
|
@@ -723,11 +726,15 @@ function useComponentCollector(context, options = {}) {
|
|
|
723
726
|
const entry = functionEntries.at(-1);
|
|
724
727
|
if (entry == null) return;
|
|
725
728
|
if (!entry.isComponent) return functionEntries.pop();
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
729
|
+
const rets = AST14.getNestedReturnStatements(entry.node.body);
|
|
730
|
+
for (let i = rets.length - 1; i >= 0; i--) {
|
|
731
|
+
const ret = rets[i];
|
|
732
|
+
if (ret == null) continue;
|
|
733
|
+
const shouldDrop = context.sourceCode.getScope(ret).block === entry.node && ret.argument != null && !isJsxLike(context.sourceCode, ret.argument, hint);
|
|
734
|
+
if (shouldDrop) {
|
|
735
|
+
components.delete(entry.key);
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
731
738
|
}
|
|
732
739
|
return functionEntries.pop();
|
|
733
740
|
};
|
|
@@ -760,7 +767,7 @@ function useComponentCollector(context, options = {}) {
|
|
|
760
767
|
kind: "function",
|
|
761
768
|
name,
|
|
762
769
|
node: entry.node,
|
|
763
|
-
displayName:
|
|
770
|
+
displayName: unit,
|
|
764
771
|
flag: getComponentFlagFromInitPath(initPath),
|
|
765
772
|
hint,
|
|
766
773
|
hookCalls: entry.hookCalls,
|
|
@@ -771,7 +778,7 @@ function useComponentCollector(context, options = {}) {
|
|
|
771
778
|
[Selector.DISPLAY_NAME_ASSIGNMENT_EXPRESSION](node) {
|
|
772
779
|
const { left, right } = node;
|
|
773
780
|
if (left.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
774
|
-
const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name :
|
|
781
|
+
const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : unit;
|
|
775
782
|
const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
|
|
776
783
|
if (component == null) return;
|
|
777
784
|
component.displayName = right;
|
|
@@ -800,7 +807,7 @@ function useComponentCollector(context, options = {}) {
|
|
|
800
807
|
kind: "function",
|
|
801
808
|
name,
|
|
802
809
|
node: entry.node,
|
|
803
|
-
displayName:
|
|
810
|
+
displayName: unit,
|
|
804
811
|
flag: getComponentFlagFromInitPath(initPath),
|
|
805
812
|
hint,
|
|
806
813
|
hookCalls: entry.hookCalls,
|
|
@@ -834,7 +841,7 @@ function useComponentCollectorLegacy() {
|
|
|
834
841
|
name: id?.name,
|
|
835
842
|
node,
|
|
836
843
|
// TODO: Get displayName of class component
|
|
837
|
-
displayName:
|
|
844
|
+
displayName: unit,
|
|
838
845
|
flag,
|
|
839
846
|
hint: 0n,
|
|
840
847
|
// TODO: Get methods of class component
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.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": {
|
|
@@ -27,20 +27,20 @@
|
|
|
27
27
|
"./package.json"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
31
|
-
"@typescript-eslint/type-utils": "^8.
|
|
32
|
-
"@typescript-eslint/types": "^8.
|
|
33
|
-
"@typescript-eslint/utils": "^8.
|
|
30
|
+
"@typescript-eslint/scope-manager": "^8.35.0",
|
|
31
|
+
"@typescript-eslint/type-utils": "^8.35.0",
|
|
32
|
+
"@typescript-eslint/types": "^8.35.0",
|
|
33
|
+
"@typescript-eslint/utils": "^8.35.0",
|
|
34
34
|
"birecord": "^0.1.1",
|
|
35
|
-
"ts-pattern": "^5.7.
|
|
36
|
-
"@eslint-react/ast": "2.0.0-beta.
|
|
37
|
-
"@eslint-react/eff": "2.0.0-beta.
|
|
38
|
-
"@eslint-react/
|
|
39
|
-
"@eslint-react/
|
|
40
|
-
"@eslint-react/var": "2.0.0-beta.
|
|
35
|
+
"ts-pattern": "^5.7.1",
|
|
36
|
+
"@eslint-react/ast": "2.0.0-beta.4",
|
|
37
|
+
"@eslint-react/eff": "2.0.0-beta.4",
|
|
38
|
+
"@eslint-react/kit": "2.0.0-beta.4",
|
|
39
|
+
"@eslint-react/shared": "2.0.0-beta.4",
|
|
40
|
+
"@eslint-react/var": "2.0.0-beta.4"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"tsup": "^8.
|
|
43
|
+
"tsup": "^8.5.0",
|
|
44
44
|
"@local/configs": "0.0.0"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|