@eslint-react/var 2.14.0-next.0 → 3.0.0-next.0
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 +52 -56
- package/dist/index.js +166 -172
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { TSESTree } from "@typescript-eslint/types";
|
|
|
3
3
|
import { Scope, Variable } from "@typescript-eslint/scope-manager";
|
|
4
4
|
import { RuleContext } from "@eslint-react/shared";
|
|
5
5
|
|
|
6
|
-
//#region src/
|
|
6
|
+
//#region src/var-assignment-target.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* Finds the enclosing assignment target (variable, property, etc.) for a given node
|
|
9
9
|
*
|
|
@@ -16,8 +16,35 @@ declare function findEnclosingAssignmentTarget(node: TSESTree.Node): TSESTree.Ar
|
|
|
16
16
|
* Type representing the possible assignment targets returned by `findEnclosingAssignmentTarget`
|
|
17
17
|
*/
|
|
18
18
|
type AssignmentTarget = ReturnType<typeof findEnclosingAssignmentTarget>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if two assignment targets are equal
|
|
21
|
+
* Compares nodes directly or by their values
|
|
22
|
+
* @param context The rule context
|
|
23
|
+
* @param a The first node to compare
|
|
24
|
+
* @param b The second node to compare
|
|
25
|
+
* @returns True if the assignment targets are equal
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
declare function isAssignmentTargetEqual(context: RuleContext, a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/var-definition.d.ts
|
|
31
|
+
/**
|
|
32
|
+
* Get the definition node of a variable at a specific definition index
|
|
33
|
+
* @param variable The variable to get the definition node from
|
|
34
|
+
* @param at The index of the definition to retrieve (negative index supported)
|
|
35
|
+
* @returns The definition node or unit if not found
|
|
36
|
+
*/
|
|
37
|
+
declare function getVariableDefinitionNode(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.ClassDeclarationWithName | TSESTree.ClassDeclarationWithOptionalName | TSESTree.Expression | TSESTree.FunctionDeclaration | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName;
|
|
38
|
+
/**
|
|
39
|
+
* Get the definition node of a variable at a specific definition index (loose version)
|
|
40
|
+
* Also returns the function node if the definition is a parameter
|
|
41
|
+
* @param variable The variable to get the definition node from
|
|
42
|
+
* @param at The index of the definition to retrieve
|
|
43
|
+
* @returns The definition node or unit if not found
|
|
44
|
+
*/
|
|
45
|
+
declare function getVariableDefinitionNodeLoose(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.ClassDeclarationWithName | TSESTree.ClassDeclarationWithOptionalName | TSESTree.Expression | TSESTree.FunctionDeclaration | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName;
|
|
19
46
|
//#endregion
|
|
20
|
-
//#region src/
|
|
47
|
+
//#region src/var-import-source.d.ts
|
|
21
48
|
/**
|
|
22
49
|
* Find the import source of a variable
|
|
23
50
|
* @param name The variable name
|
|
@@ -26,27 +53,17 @@ type AssignmentTarget = ReturnType<typeof findEnclosingAssignmentTarget>;
|
|
|
26
53
|
*/
|
|
27
54
|
declare function findImportSource(name: string, initialScope: Scope): string | undefined;
|
|
28
55
|
//#endregion
|
|
29
|
-
//#region src/
|
|
30
|
-
/**
|
|
31
|
-
* Find a property by name in an array of properties
|
|
32
|
-
* Handles spread elements by recursively resolving the referenced object
|
|
33
|
-
* @param name The property name to find
|
|
34
|
-
* @param properties The array of properties to search
|
|
35
|
-
* @param initialScope The scope to use for variable resolution
|
|
36
|
-
* @param seen Set of already seen variable names to prevent circular references
|
|
37
|
-
* @returns The found property or unit if not found
|
|
38
|
-
*/
|
|
39
|
-
declare function findProperty(name: string, properties: (TSESTree.Property | TSESTree.RestElement | TSESTree.SpreadElement)[], initialScope: Scope, seen?: Set<string>): (typeof properties)[number] | unit;
|
|
40
|
-
//#endregion
|
|
41
|
-
//#region src/get-child-scopes.d.ts
|
|
56
|
+
//#region src/var-node-equality.d.ts
|
|
42
57
|
/**
|
|
43
|
-
*
|
|
44
|
-
* @param
|
|
45
|
-
* @
|
|
58
|
+
* Determine whether node value equals to another node value
|
|
59
|
+
* @param a node to compare
|
|
60
|
+
* @param b node to compare
|
|
61
|
+
* @param initialScopes initial scopes of the two nodes
|
|
62
|
+
* @returns `true` if node value equal
|
|
46
63
|
*/
|
|
47
|
-
declare function
|
|
64
|
+
declare function isNodeEqual(a: TSESTree.Node, b: TSESTree.Node, initialScopes: [aScope: Scope, bScope: Scope]): boolean;
|
|
48
65
|
//#endregion
|
|
49
|
-
//#region src/
|
|
66
|
+
//#region src/var-object-type.d.ts
|
|
50
67
|
/**
|
|
51
68
|
* Represents the type classification of an object node
|
|
52
69
|
*/
|
|
@@ -84,24 +101,19 @@ type ObjectType = {
|
|
|
84
101
|
*/
|
|
85
102
|
declare function getObjectType(node: TSESTree.Node | unit, initialScope: Scope): ObjectType | unit;
|
|
86
103
|
//#endregion
|
|
87
|
-
//#region src/
|
|
104
|
+
//#region src/var-property.d.ts
|
|
88
105
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* @param
|
|
92
|
-
* @
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* Get the definition node of a variable at a specific definition index (loose version)
|
|
97
|
-
* Also returns the function node if the definition is a parameter
|
|
98
|
-
* @param variable The variable to get the definition node from
|
|
99
|
-
* @param at The index of the definition to retrieve
|
|
100
|
-
* @returns The definition node or unit if not found
|
|
106
|
+
* Find a property by name in an array of properties
|
|
107
|
+
* Handles spread elements by recursively resolving the referenced object
|
|
108
|
+
* @param name The property name to find
|
|
109
|
+
* @param properties The array of properties to search
|
|
110
|
+
* @param initialScope The scope to use for variable resolution
|
|
111
|
+
* @param seen Set of already seen variable names to prevent circular references
|
|
112
|
+
* @returns The found property or unit if not found
|
|
101
113
|
*/
|
|
102
|
-
declare function
|
|
114
|
+
declare function findProperty(name: string, properties: (TSESTree.Property | TSESTree.RestElement | TSESTree.SpreadElement)[], initialScope: Scope, seen?: Set<string>): (typeof properties)[number] | unit;
|
|
103
115
|
//#endregion
|
|
104
|
-
//#region src/
|
|
116
|
+
//#region src/var-scope.d.ts
|
|
105
117
|
/**
|
|
106
118
|
* Get all variables from the given scope up to the global scope
|
|
107
119
|
* @param initialScope The scope to start from
|
|
@@ -121,27 +133,11 @@ declare const findVariable: {
|
|
|
121
133
|
(initialScope: Scope): (nameOrNode: string | TSESTree.Identifier | unit) => Variable | unit;
|
|
122
134
|
(nameOrNode: string | TSESTree.Identifier | unit, initialScope: Scope): Variable | unit;
|
|
123
135
|
};
|
|
124
|
-
//#endregion
|
|
125
|
-
//#region src/is-assignment-target-equal.d.ts
|
|
126
|
-
/**
|
|
127
|
-
* Check if two assignment targets are equal
|
|
128
|
-
* Compares nodes directly or by their values
|
|
129
|
-
* @param context The rule context
|
|
130
|
-
* @param a The first node to compare
|
|
131
|
-
* @param b The second node to compare
|
|
132
|
-
* @returns True if the assignment targets are equal
|
|
133
|
-
* @internal
|
|
134
|
-
*/
|
|
135
|
-
declare function isAssignmentTargetEqual(context: RuleContext, a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
136
|
-
//#endregion
|
|
137
|
-
//#region src/is-node-value-equal.d.ts
|
|
138
136
|
/**
|
|
139
|
-
*
|
|
140
|
-
* @param
|
|
141
|
-
* @
|
|
142
|
-
* @param initialScopes initial scopes of the two nodes
|
|
143
|
-
* @returns `true` if node value equal
|
|
137
|
+
* Get all child scopes recursively from a given scope
|
|
138
|
+
* @param scope The scope to get child scopes from
|
|
139
|
+
* @returns Array of all child scopes including the input scope
|
|
144
140
|
*/
|
|
145
|
-
declare function
|
|
141
|
+
declare function getChildScopes(scope: Scope): readonly Scope[];
|
|
146
142
|
//#endregion
|
|
147
|
-
export { AssignmentTarget, ObjectType, findEnclosingAssignmentTarget, findImportSource, findProperty, findVariable, getChildScopes, getObjectType, getVariableDefinitionNode, getVariableDefinitionNodeLoose, getVariables, isAssignmentTargetEqual,
|
|
143
|
+
export { AssignmentTarget, ObjectType, findEnclosingAssignmentTarget, findImportSource, findProperty, findVariable, getChildScopes, getObjectType, getVariableDefinitionNode, getVariableDefinitionNodeLoose, getVariables, isAssignmentTargetEqual, isNodeEqual };
|
package/dist/index.js
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
1
|
+
import * as ast from "@eslint-react/ast";
|
|
1
2
|
import { dual, identity, unit } from "@eslint-react/eff";
|
|
2
3
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
3
|
-
import * as ast from "@eslint-react/ast";
|
|
4
|
-
import { P, match } from "ts-pattern";
|
|
5
|
-
import { DefinitionType, ScopeType } from "@typescript-eslint/scope-manager";
|
|
6
4
|
import * as astUtils from "@typescript-eslint/utils/ast-utils";
|
|
7
5
|
import { getStaticValue } from "@typescript-eslint/utils/ast-utils";
|
|
6
|
+
import { DefinitionType, ScopeType } from "@typescript-eslint/scope-manager";
|
|
7
|
+
import { P, match } from "ts-pattern";
|
|
8
8
|
|
|
9
|
-
//#region src/
|
|
10
|
-
/** eslint-disable jsdoc/require-param */
|
|
9
|
+
//#region src/var-definition.ts
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @returns The enclosing assignment target node, or undefined if not found
|
|
11
|
+
* Get the definition node of a variable at a specific definition index
|
|
12
|
+
* @param variable The variable to get the definition node from
|
|
13
|
+
* @param at The index of the definition to retrieve (negative index supported)
|
|
14
|
+
* @returns The definition node or unit if not found
|
|
17
15
|
*/
|
|
18
|
-
function
|
|
16
|
+
function getVariableDefinitionNode(variable, at) {
|
|
17
|
+
if (variable == null) return unit;
|
|
18
|
+
const def = variable.defs.at(at);
|
|
19
|
+
if (def == null) return unit;
|
|
19
20
|
switch (true) {
|
|
20
|
-
case node.type === AST_NODE_TYPES.
|
|
21
|
-
case node.type === AST_NODE_TYPES.
|
|
22
|
-
case node.
|
|
23
|
-
|
|
24
|
-
default: return findEnclosingAssignmentTarget(node.parent);
|
|
21
|
+
case def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration: return def.node;
|
|
22
|
+
case def.type === DefinitionType.ClassName && def.node.type === AST_NODE_TYPES.ClassDeclaration: return def.node;
|
|
23
|
+
case "init" in def.node && def.node.init != null && !("declarations" in def.node.init): return def.node.init;
|
|
24
|
+
default: return unit;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the definition node of a variable at a specific definition index (loose version)
|
|
29
|
+
* Also returns the function node if the definition is a parameter
|
|
30
|
+
* @param variable The variable to get the definition node from
|
|
31
|
+
* @param at The index of the definition to retrieve
|
|
32
|
+
* @returns The definition node or unit if not found
|
|
33
|
+
*/
|
|
34
|
+
function getVariableDefinitionNodeLoose(variable, at) {
|
|
35
|
+
if (variable == null) return unit;
|
|
36
|
+
const node = getVariableDefinitionNode(variable, at);
|
|
37
|
+
if (node != null) return node;
|
|
38
|
+
const def = variable.defs.at(at);
|
|
39
|
+
if (def?.type === DefinitionType.Parameter && ast.isFunction(def.node)) return def.node;
|
|
40
|
+
return unit;
|
|
41
|
+
}
|
|
27
42
|
|
|
28
43
|
//#endregion
|
|
29
|
-
//#region src/
|
|
44
|
+
//#region src/var-scope.ts
|
|
30
45
|
/**
|
|
31
46
|
* Get all variables from the given scope up to the global scope
|
|
32
47
|
* @param initialScope The scope to start from
|
|
@@ -54,9 +69,117 @@ const findVariable = dual(2, (nameOrNode, initialScope) => {
|
|
|
54
69
|
if (nameOrNode == null) return unit;
|
|
55
70
|
return astUtils.findVariable(initialScope, nameOrNode) ?? unit;
|
|
56
71
|
});
|
|
72
|
+
/**
|
|
73
|
+
* Get all child scopes recursively from a given scope
|
|
74
|
+
* @param scope The scope to get child scopes from
|
|
75
|
+
* @returns Array of all child scopes including the input scope
|
|
76
|
+
*/
|
|
77
|
+
function getChildScopes(scope) {
|
|
78
|
+
const scopes = [scope];
|
|
79
|
+
for (const childScope of scope.childScopes) scopes.push(...getChildScopes(childScope));
|
|
80
|
+
return scopes;
|
|
81
|
+
}
|
|
57
82
|
|
|
58
83
|
//#endregion
|
|
59
|
-
//#region src/
|
|
84
|
+
//#region src/var-node-equality.ts
|
|
85
|
+
const thisBlockTypes = [
|
|
86
|
+
AST_NODE_TYPES.FunctionDeclaration,
|
|
87
|
+
AST_NODE_TYPES.FunctionExpression,
|
|
88
|
+
AST_NODE_TYPES.ClassBody,
|
|
89
|
+
AST_NODE_TYPES.Program
|
|
90
|
+
];
|
|
91
|
+
/**
|
|
92
|
+
* Determine whether node value equals to another node value
|
|
93
|
+
* @param a node to compare
|
|
94
|
+
* @param b node to compare
|
|
95
|
+
* @param initialScopes initial scopes of the two nodes
|
|
96
|
+
* @returns `true` if node value equal
|
|
97
|
+
*/
|
|
98
|
+
function isNodeEqual(a, b, initialScopes) {
|
|
99
|
+
a = ast.isTypeExpression(a) ? ast.getUnderlyingExpression(a) : a;
|
|
100
|
+
b = ast.isTypeExpression(b) ? ast.getUnderlyingExpression(b) : b;
|
|
101
|
+
const [aScope, bScope] = initialScopes;
|
|
102
|
+
switch (true) {
|
|
103
|
+
case a === b: return true;
|
|
104
|
+
case a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal: return a.value === b.value;
|
|
105
|
+
case a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement: return a.value.cooked === b.value.cooked;
|
|
106
|
+
case a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier: {
|
|
107
|
+
const aVar = findVariable(a, aScope);
|
|
108
|
+
const bVar = findVariable(b, bScope);
|
|
109
|
+
const aVarNode = getVariableDefinitionNodeLoose(aVar, 0);
|
|
110
|
+
const bVarNode = getVariableDefinitionNodeLoose(bVar, 0);
|
|
111
|
+
const aVarNodeParent = aVarNode?.parent;
|
|
112
|
+
const bVarNodeParent = bVarNode?.parent;
|
|
113
|
+
const aDef = aVar?.defs.at(0);
|
|
114
|
+
const bDef = bVar?.defs.at(0);
|
|
115
|
+
const aDefParentParent = aDef?.parent?.parent;
|
|
116
|
+
const bDefParentParent = bDef?.parent?.parent;
|
|
117
|
+
switch (true) {
|
|
118
|
+
case aVarNodeParent?.type === AST_NODE_TYPES.CallExpression && bVarNodeParent?.type === AST_NODE_TYPES.CallExpression && ast.isFunction(aVarNode) && ast.isFunction(bVarNode): {
|
|
119
|
+
if (!ast.isNodeEqual(aVarNodeParent.callee, bVarNodeParent.callee)) return false;
|
|
120
|
+
const aParams = aVarNode.params;
|
|
121
|
+
const bParams = bVarNode.params;
|
|
122
|
+
const aPos = aParams.findIndex((x) => ast.isNodeEqual(x, a));
|
|
123
|
+
const bPos = bParams.findIndex((x) => ast.isNodeEqual(x, b));
|
|
124
|
+
return aPos !== -1 && bPos !== -1 && aPos === bPos;
|
|
125
|
+
}
|
|
126
|
+
case aDefParentParent?.type === AST_NODE_TYPES.ForOfStatement && bDefParentParent?.type === AST_NODE_TYPES.ForOfStatement: {
|
|
127
|
+
const aLeft = aDefParentParent.left;
|
|
128
|
+
const bLeft = bDefParentParent.left;
|
|
129
|
+
if (aLeft.type !== bLeft.type) return false;
|
|
130
|
+
const aRight = aDefParentParent.right;
|
|
131
|
+
const bRight = bDefParentParent.right;
|
|
132
|
+
return ast.isNodeEqual(aRight, bRight);
|
|
133
|
+
}
|
|
134
|
+
default: return aVar != null && bVar != null && aVar === bVar;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
case a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression: return ast.isNodeEqual(a.property, b.property) && isNodeEqual(a.object, b.object, initialScopes);
|
|
138
|
+
case a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression:
|
|
139
|
+
if (aScope.block === bScope.block) return true;
|
|
140
|
+
return ast.findParentNode(a, ast.isOneOf(thisBlockTypes)) === ast.findParentNode(b, ast.isOneOf(thisBlockTypes));
|
|
141
|
+
default: {
|
|
142
|
+
const aStatic = getStaticValue(a, aScope);
|
|
143
|
+
const bStatic = getStaticValue(b, bScope);
|
|
144
|
+
return aStatic != null && bStatic != null && aStatic.value === bStatic.value;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/var-assignment-target.ts
|
|
151
|
+
/** eslint-disable jsdoc/require-param */
|
|
152
|
+
/**
|
|
153
|
+
* Finds the enclosing assignment target (variable, property, etc.) for a given node
|
|
154
|
+
*
|
|
155
|
+
* @todo Verify correctness and completeness of this function
|
|
156
|
+
* @param node The starting node
|
|
157
|
+
* @returns The enclosing assignment target node, or undefined if not found
|
|
158
|
+
*/
|
|
159
|
+
function findEnclosingAssignmentTarget(node) {
|
|
160
|
+
switch (true) {
|
|
161
|
+
case node.type === AST_NODE_TYPES.VariableDeclarator: return node.id;
|
|
162
|
+
case node.type === AST_NODE_TYPES.AssignmentExpression: return node.left;
|
|
163
|
+
case node.type === AST_NODE_TYPES.PropertyDefinition: return node.key;
|
|
164
|
+
case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
|
|
165
|
+
default: return findEnclosingAssignmentTarget(node.parent);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if two assignment targets are equal
|
|
170
|
+
* Compares nodes directly or by their values
|
|
171
|
+
* @param context The rule context
|
|
172
|
+
* @param a The first node to compare
|
|
173
|
+
* @param b The second node to compare
|
|
174
|
+
* @returns True if the assignment targets are equal
|
|
175
|
+
* @internal
|
|
176
|
+
*/
|
|
177
|
+
function isAssignmentTargetEqual(context, a, b) {
|
|
178
|
+
return ast.isNodeEqual(a, b) || isNodeEqual(a, b, [context.sourceCode.getScope(a), context.sourceCode.getScope(b)]);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/var-import-source.ts
|
|
60
183
|
/**
|
|
61
184
|
* Get the arguments of a require expression
|
|
62
185
|
* @param node The node to match
|
|
@@ -98,86 +221,7 @@ function findImportSource(name, initialScope) {
|
|
|
98
221
|
}
|
|
99
222
|
|
|
100
223
|
//#endregion
|
|
101
|
-
//#region src/
|
|
102
|
-
/**
|
|
103
|
-
* Get the definition node of a variable at a specific definition index
|
|
104
|
-
* @param variable The variable to get the definition node from
|
|
105
|
-
* @param at The index of the definition to retrieve (negative index supported)
|
|
106
|
-
* @returns The definition node or unit if not found
|
|
107
|
-
*/
|
|
108
|
-
function getVariableDefinitionNode(variable, at) {
|
|
109
|
-
if (variable == null) return unit;
|
|
110
|
-
const def = variable.defs.at(at);
|
|
111
|
-
if (def == null) return unit;
|
|
112
|
-
switch (true) {
|
|
113
|
-
case def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration: return def.node;
|
|
114
|
-
case def.type === DefinitionType.ClassName && def.node.type === AST_NODE_TYPES.ClassDeclaration: return def.node;
|
|
115
|
-
case "init" in def.node && def.node.init != null && !("declarations" in def.node.init): return def.node.init;
|
|
116
|
-
default: return unit;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Get the definition node of a variable at a specific definition index (loose version)
|
|
121
|
-
* Also returns the function node if the definition is a parameter
|
|
122
|
-
* @param variable The variable to get the definition node from
|
|
123
|
-
* @param at The index of the definition to retrieve
|
|
124
|
-
* @returns The definition node or unit if not found
|
|
125
|
-
*/
|
|
126
|
-
function getVariableDefinitionNodeLoose(variable, at) {
|
|
127
|
-
if (variable == null) return unit;
|
|
128
|
-
const node = getVariableDefinitionNode(variable, at);
|
|
129
|
-
if (node != null) return node;
|
|
130
|
-
const def = variable.defs.at(at);
|
|
131
|
-
if (def?.type === DefinitionType.Parameter && ast.isFunction(def.node)) return def.node;
|
|
132
|
-
return unit;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
//#endregion
|
|
136
|
-
//#region src/find-property.ts
|
|
137
|
-
/**
|
|
138
|
-
* Find a property by name in an array of properties
|
|
139
|
-
* Handles spread elements by recursively resolving the referenced object
|
|
140
|
-
* @param name The property name to find
|
|
141
|
-
* @param properties The array of properties to search
|
|
142
|
-
* @param initialScope The scope to use for variable resolution
|
|
143
|
-
* @param seen Set of already seen variable names to prevent circular references
|
|
144
|
-
* @returns The found property or unit if not found
|
|
145
|
-
*/
|
|
146
|
-
function findProperty(name, properties, initialScope, seen = /* @__PURE__ */ new Set()) {
|
|
147
|
-
return properties.findLast((prop) => {
|
|
148
|
-
if (prop.type === AST_NODE_TYPES.Property) return "name" in prop.key && prop.key.name === name;
|
|
149
|
-
if (prop.type === AST_NODE_TYPES.SpreadElement) switch (prop.argument.type) {
|
|
150
|
-
case AST_NODE_TYPES.Identifier: {
|
|
151
|
-
if (seen.has(prop.argument.name)) return false;
|
|
152
|
-
const variableNode = getVariableDefinitionNode(findVariable(prop.argument.name, initialScope), 0);
|
|
153
|
-
if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) {
|
|
154
|
-
seen.add(prop.argument.name);
|
|
155
|
-
return findProperty(name, variableNode.properties, initialScope, seen) != null;
|
|
156
|
-
}
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
case AST_NODE_TYPES.ObjectExpression: return findProperty(name, prop.argument.properties, initialScope, seen) != null;
|
|
160
|
-
default: return false;
|
|
161
|
-
}
|
|
162
|
-
return false;
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
//#endregion
|
|
167
|
-
//#region src/get-child-scopes.ts
|
|
168
|
-
/**
|
|
169
|
-
* Get all child scopes recursively from a given scope
|
|
170
|
-
* @param scope The scope to get child scopes from
|
|
171
|
-
* @returns Array of all child scopes including the input scope
|
|
172
|
-
*/
|
|
173
|
-
function getChildScopes(scope) {
|
|
174
|
-
const scopes = [scope];
|
|
175
|
-
for (const childScope of scope.childScopes) scopes.push(...getChildScopes(childScope));
|
|
176
|
-
return scopes;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
//#endregion
|
|
180
|
-
//#region src/get-object-type.ts
|
|
224
|
+
//#region src/var-object-type.ts
|
|
181
225
|
/**
|
|
182
226
|
* Detect the ObjectType of a given node
|
|
183
227
|
* @param node The node to check
|
|
@@ -248,85 +292,35 @@ function getObjectType(node, initialScope) {
|
|
|
248
292
|
}
|
|
249
293
|
|
|
250
294
|
//#endregion
|
|
251
|
-
//#region src/
|
|
252
|
-
const thisBlockTypes = [
|
|
253
|
-
AST_NODE_TYPES.FunctionDeclaration,
|
|
254
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
255
|
-
AST_NODE_TYPES.ClassBody,
|
|
256
|
-
AST_NODE_TYPES.Program
|
|
257
|
-
];
|
|
295
|
+
//#region src/var-property.ts
|
|
258
296
|
/**
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* @param
|
|
262
|
-
* @param
|
|
263
|
-
* @
|
|
297
|
+
* Find a property by name in an array of properties
|
|
298
|
+
* Handles spread elements by recursively resolving the referenced object
|
|
299
|
+
* @param name The property name to find
|
|
300
|
+
* @param properties The array of properties to search
|
|
301
|
+
* @param initialScope The scope to use for variable resolution
|
|
302
|
+
* @param seen Set of already seen variable names to prevent circular references
|
|
303
|
+
* @returns The found property or unit if not found
|
|
264
304
|
*/
|
|
265
|
-
function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const bVar = findVariable(b, bScope);
|
|
276
|
-
const aVarNode = getVariableDefinitionNodeLoose(aVar, 0);
|
|
277
|
-
const bVarNode = getVariableDefinitionNodeLoose(bVar, 0);
|
|
278
|
-
const aVarNodeParent = aVarNode?.parent;
|
|
279
|
-
const bVarNodeParent = bVarNode?.parent;
|
|
280
|
-
const aDef = aVar?.defs.at(0);
|
|
281
|
-
const bDef = bVar?.defs.at(0);
|
|
282
|
-
const aDefParentParent = aDef?.parent?.parent;
|
|
283
|
-
const bDefParentParent = bDef?.parent?.parent;
|
|
284
|
-
switch (true) {
|
|
285
|
-
case aVarNodeParent?.type === AST_NODE_TYPES.CallExpression && bVarNodeParent?.type === AST_NODE_TYPES.CallExpression && ast.isFunction(aVarNode) && ast.isFunction(bVarNode): {
|
|
286
|
-
if (!ast.isNodeEqual(aVarNodeParent.callee, bVarNodeParent.callee)) return false;
|
|
287
|
-
const aParams = aVarNode.params;
|
|
288
|
-
const bParams = bVarNode.params;
|
|
289
|
-
const aPos = aParams.findIndex((x) => ast.isNodeEqual(x, a));
|
|
290
|
-
const bPos = bParams.findIndex((x) => ast.isNodeEqual(x, b));
|
|
291
|
-
return aPos !== -1 && bPos !== -1 && aPos === bPos;
|
|
292
|
-
}
|
|
293
|
-
case aDefParentParent?.type === AST_NODE_TYPES.ForOfStatement && bDefParentParent?.type === AST_NODE_TYPES.ForOfStatement: {
|
|
294
|
-
const aLeft = aDefParentParent.left;
|
|
295
|
-
const bLeft = bDefParentParent.left;
|
|
296
|
-
if (aLeft.type !== bLeft.type) return false;
|
|
297
|
-
const aRight = aDefParentParent.right;
|
|
298
|
-
const bRight = bDefParentParent.right;
|
|
299
|
-
return ast.isNodeEqual(aRight, bRight);
|
|
305
|
+
function findProperty(name, properties, initialScope, seen = /* @__PURE__ */ new Set()) {
|
|
306
|
+
return properties.findLast((prop) => {
|
|
307
|
+
if (prop.type === AST_NODE_TYPES.Property) return "name" in prop.key && prop.key.name === name;
|
|
308
|
+
if (prop.type === AST_NODE_TYPES.SpreadElement) switch (prop.argument.type) {
|
|
309
|
+
case AST_NODE_TYPES.Identifier: {
|
|
310
|
+
if (seen.has(prop.argument.name)) return false;
|
|
311
|
+
const variableNode = getVariableDefinitionNode(findVariable(prop.argument.name, initialScope), 0);
|
|
312
|
+
if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) {
|
|
313
|
+
seen.add(prop.argument.name);
|
|
314
|
+
return findProperty(name, variableNode.properties, initialScope, seen) != null;
|
|
300
315
|
}
|
|
301
|
-
|
|
316
|
+
return false;
|
|
302
317
|
}
|
|
318
|
+
case AST_NODE_TYPES.ObjectExpression: return findProperty(name, prop.argument.properties, initialScope, seen) != null;
|
|
319
|
+
default: return false;
|
|
303
320
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (aScope.block === bScope.block) return true;
|
|
307
|
-
return ast.findParentNode(a, ast.isOneOf(thisBlockTypes)) === ast.findParentNode(b, ast.isOneOf(thisBlockTypes));
|
|
308
|
-
default: {
|
|
309
|
-
const aStatic = getStaticValue(a, aScope);
|
|
310
|
-
const bStatic = getStaticValue(b, bScope);
|
|
311
|
-
return aStatic != null && bStatic != null && aStatic.value === bStatic.value;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
//#endregion
|
|
317
|
-
//#region src/is-assignment-target-equal.ts
|
|
318
|
-
/**
|
|
319
|
-
* Check if two assignment targets are equal
|
|
320
|
-
* Compares nodes directly or by their values
|
|
321
|
-
* @param context The rule context
|
|
322
|
-
* @param a The first node to compare
|
|
323
|
-
* @param b The second node to compare
|
|
324
|
-
* @returns True if the assignment targets are equal
|
|
325
|
-
* @internal
|
|
326
|
-
*/
|
|
327
|
-
function isAssignmentTargetEqual(context, a, b) {
|
|
328
|
-
return ast.isNodeEqual(a, b) || isNodeValueEqual(a, b, [context.sourceCode.getScope(a), context.sourceCode.getScope(b)]);
|
|
321
|
+
return false;
|
|
322
|
+
});
|
|
329
323
|
}
|
|
330
324
|
|
|
331
325
|
//#endregion
|
|
332
|
-
export { findEnclosingAssignmentTarget, findImportSource, findProperty, findVariable, getChildScopes, getObjectType, getVariableDefinitionNode, getVariableDefinitionNodeLoose, getVariables, isAssignmentTargetEqual,
|
|
326
|
+
export { findEnclosingAssignmentTarget, findImportSource, findProperty, findVariable, getChildScopes, getObjectType, getVariableDefinitionNode, getVariableDefinitionNodeLoose, getVariables, isAssignmentTargetEqual, isNodeEqual };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/var",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-next.0",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module for static analysis of variables.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"./package.json"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
34
|
-
"@typescript-eslint/types": "^8.
|
|
35
|
-
"@typescript-eslint/utils": "^8.
|
|
33
|
+
"@typescript-eslint/scope-manager": "^8.56.0",
|
|
34
|
+
"@typescript-eslint/types": "^8.56.0",
|
|
35
|
+
"@typescript-eslint/utils": "^8.56.0",
|
|
36
36
|
"ts-pattern": "^5.9.0",
|
|
37
|
-
"@eslint-react/ast": "
|
|
38
|
-
"@eslint-react/eff": "
|
|
39
|
-
"@eslint-react/shared": "
|
|
37
|
+
"@eslint-react/ast": "3.0.0-next.0",
|
|
38
|
+
"@eslint-react/eff": "3.0.0-next.0",
|
|
39
|
+
"@eslint-react/shared": "3.0.0-next.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"tsdown": "^0.20.3",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"typescript": ">=4.8.4 <6.0.0"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
|
-
"node": ">=
|
|
50
|
+
"node": ">=22.0.0"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "tsdown --dts-resolve",
|