@eslint-react/var 3.0.0-next.58 → 3.0.0-next.59
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 +43 -56
- package/dist/index.js +128 -157
- package/package.json +4 -4
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/find-enclosing-assignment-target.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* Finds the enclosing assignment target (variable, property, etc.) for a given node
|
|
9
9
|
*
|
|
@@ -16,18 +16,8 @@ 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
19
|
//#endregion
|
|
30
|
-
//#region src/
|
|
20
|
+
//#region src/find-import-source.d.ts
|
|
31
21
|
/**
|
|
32
22
|
* Find the import source of a variable
|
|
33
23
|
* @param name The variable name
|
|
@@ -36,26 +26,7 @@ declare function isAssignmentTargetEqual(context: RuleContext, a: TSESTree.Node,
|
|
|
36
26
|
*/
|
|
37
27
|
declare function findImportSource(name: string, initialScope: Scope): string | undefined;
|
|
38
28
|
//#endregion
|
|
39
|
-
//#region src/
|
|
40
|
-
/**
|
|
41
|
-
* Get the initializer expression or statement of a variable definition at a specified index
|
|
42
|
-
* @param variable The variable to get the initializer from
|
|
43
|
-
* @param at The index of the variable definition to get the initializer from
|
|
44
|
-
* @returns The initializer expression or statement of the variable definition at the specified index, or unit if not found
|
|
45
|
-
*/
|
|
46
|
-
declare function getVariableInitializer(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.Expression | TSESTree.FunctionDeclaration;
|
|
47
|
-
/**
|
|
48
|
-
* Get the initializer expression or statement of a variable definition at a specified index, or the function declaration if the variable is a parameter of a function
|
|
49
|
-
* @param variable The variable to get the initializer from
|
|
50
|
-
* @param at The index of the variable definition to get the initializer from
|
|
51
|
-
* @returns The initializer expression or statement of the variable definition at the specified index, or the function declaration if the variable is a parameter of a function, or unit if not found
|
|
52
|
-
*/
|
|
53
|
-
declare function getVariableInitializerLoose(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.Expression | TSESTree.FunctionDeclaration;
|
|
54
|
-
//#endregion
|
|
55
|
-
//#region src/binding-kind.d.ts
|
|
56
|
-
type BindingKind = "var" | "let" | "const" | "module" | "hoisted" | "param" | "local" | "unknown";
|
|
57
|
-
//#endregion
|
|
58
|
-
//#region src/helper.d.ts
|
|
29
|
+
//#region src/find-variable.d.ts
|
|
59
30
|
/**
|
|
60
31
|
* Find a variable by name or identifier node in the scope chain
|
|
61
32
|
* @param initialScope The scope to start searching from
|
|
@@ -70,29 +41,7 @@ declare const findVariable: {
|
|
|
70
41
|
(nameOrNode: string | TSESTree.Identifier | unit, initialScope: Scope): Variable | unit;
|
|
71
42
|
};
|
|
72
43
|
//#endregion
|
|
73
|
-
//#region src/
|
|
74
|
-
/**
|
|
75
|
-
* Determine whether node value equals to another node value
|
|
76
|
-
* @param a node to compare
|
|
77
|
-
* @param b node to compare
|
|
78
|
-
* @param initialScopes initial scopes of the two nodes
|
|
79
|
-
* @returns `true` if node value equal
|
|
80
|
-
*/
|
|
81
|
-
declare function isValueEqual(a: TSESTree.Node, b: TSESTree.Node, initialScopes: [aScope: Scope, bScope: Scope]): boolean;
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/value-property.d.ts
|
|
84
|
-
/**
|
|
85
|
-
* Find a property by name in an array of properties
|
|
86
|
-
* Handles spread elements by recursively resolving the referenced object
|
|
87
|
-
* @param name The property name to find
|
|
88
|
-
* @param properties The array of properties to search
|
|
89
|
-
* @param initialScope The scope to use for variable resolution
|
|
90
|
-
* @param seen Set of already seen variable names to prevent circular references
|
|
91
|
-
* @returns The found property or unit if not found
|
|
92
|
-
*/
|
|
93
|
-
declare function findProperty(name: string, properties: (TSESTree.Property | TSESTree.RestElement | TSESTree.SpreadElement)[], initialScope: Scope, seen?: Set<string>): (typeof properties)[number] | unit;
|
|
94
|
-
//#endregion
|
|
95
|
-
//#region src/value-type.d.ts
|
|
44
|
+
//#region src/get-object-type.d.ts
|
|
96
45
|
/**
|
|
97
46
|
* Represents the type classification of an object node
|
|
98
47
|
*/
|
|
@@ -130,4 +79,42 @@ type ObjectType = {
|
|
|
130
79
|
*/
|
|
131
80
|
declare function getObjectType(node: TSESTree.Node | unit, initialScope: Scope): ObjectType | unit;
|
|
132
81
|
//#endregion
|
|
133
|
-
|
|
82
|
+
//#region src/get-variable-initializer.d.ts
|
|
83
|
+
/**
|
|
84
|
+
* Get the initializer expression or statement of a variable definition at a specified index
|
|
85
|
+
* @param variable The variable to get the initializer from
|
|
86
|
+
* @param at The index of the variable definition to get the initializer from
|
|
87
|
+
* @returns The initializer expression or statement of the variable definition at the specified index, or unit if not found
|
|
88
|
+
*/
|
|
89
|
+
declare function getVariableInitializer(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.Expression | TSESTree.FunctionDeclaration;
|
|
90
|
+
/**
|
|
91
|
+
* Get the initializer expression or statement of a variable definition at a specified index, or the function declaration if the variable is a parameter of a function
|
|
92
|
+
* @param variable The variable to get the initializer from
|
|
93
|
+
* @param at The index of the variable definition to get the initializer from
|
|
94
|
+
* @returns The initializer expression or statement of the variable definition at the specified index, or the function declaration if the variable is a parameter of a function, or unit if not found
|
|
95
|
+
*/
|
|
96
|
+
declare function getVariableInitializerLoose(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.Expression | TSESTree.FunctionDeclaration;
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/is-assignment-target-equal.d.ts
|
|
99
|
+
/**
|
|
100
|
+
* Check if two assignment targets are equal
|
|
101
|
+
* Compares nodes directly or by their values
|
|
102
|
+
* @param context The rule context
|
|
103
|
+
* @param a The first node to compare
|
|
104
|
+
* @param b The second node to compare
|
|
105
|
+
* @returns True if the assignment targets are equal
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
108
|
+
declare function isAssignmentTargetEqual(context: RuleContext, a: TSESTree.Node, b: TSESTree.Node): boolean;
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/is-value-equal.d.ts
|
|
111
|
+
/**
|
|
112
|
+
* Determine whether node value equals to another node value
|
|
113
|
+
* @param a node to compare
|
|
114
|
+
* @param b node to compare
|
|
115
|
+
* @param initialScopes initial scopes of the two nodes
|
|
116
|
+
* @returns `true` if node value equal
|
|
117
|
+
*/
|
|
118
|
+
declare function isValueEqual(a: TSESTree.Node, b: TSESTree.Node, initialScopes: [aScope: Scope, bScope: Scope]): boolean;
|
|
119
|
+
//#endregion
|
|
120
|
+
export { AssignmentTarget, ObjectType, findEnclosingAssignmentTarget, findImportSource, findVariable, getObjectType, getVariableInitializer, getVariableInitializerLoose, isAssignmentTargetEqual, isValueEqual };
|
package/dist/index.js
CHANGED
|
@@ -1,46 +1,31 @@
|
|
|
1
|
-
import * as ast from "@eslint-react/ast";
|
|
2
1
|
import { dual, identity, unit } from "@eslint-react/eff";
|
|
3
2
|
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
3
|
+
import * as ast from "@eslint-react/ast";
|
|
4
|
+
import { P, match } from "ts-pattern";
|
|
4
5
|
import * as astUtils from "@typescript-eslint/utils/ast-utils";
|
|
5
6
|
import { getStaticValue } from "@typescript-eslint/utils/ast-utils";
|
|
6
7
|
import { DefinitionType } from "@typescript-eslint/scope-manager";
|
|
7
|
-
import { P, match } from "ts-pattern";
|
|
8
8
|
|
|
9
|
-
//#region src/
|
|
9
|
+
//#region src/find-enclosing-assignment-target.ts
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
11
|
+
* Finds the enclosing assignment target (variable, property, etc.) for a given node
|
|
12
|
+
*
|
|
13
|
+
* @todo Verify correctness and completeness of this function
|
|
14
|
+
* @param node The starting node
|
|
15
|
+
* @returns The enclosing assignment target node, or undefined if not found
|
|
15
16
|
*/
|
|
16
|
-
function
|
|
17
|
-
if (variable == null) return unit;
|
|
18
|
-
const def = variable.defs.at(at);
|
|
19
|
-
if (def == null) return unit;
|
|
17
|
+
function findEnclosingAssignmentTarget(node) {
|
|
20
18
|
switch (true) {
|
|
21
|
-
case
|
|
22
|
-
case
|
|
23
|
-
case
|
|
24
|
-
|
|
19
|
+
case node.type === AST_NODE_TYPES.VariableDeclarator: return node.id;
|
|
20
|
+
case node.type === AST_NODE_TYPES.AssignmentExpression: return node.left;
|
|
21
|
+
case node.type === AST_NODE_TYPES.PropertyDefinition: return node.key;
|
|
22
|
+
case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
|
|
23
|
+
default: return findEnclosingAssignmentTarget(node.parent);
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Get the initializer expression or statement of a variable definition at a specified index, or the function declaration if the variable is a parameter of a function
|
|
29
|
-
* @param variable The variable to get the initializer from
|
|
30
|
-
* @param at The index of the variable definition to get the initializer from
|
|
31
|
-
* @returns The initializer expression or statement of the variable definition at the specified index, or the function declaration if the variable is a parameter of a function, or unit if not found
|
|
32
|
-
*/
|
|
33
|
-
function getVariableInitializerLoose(variable, at) {
|
|
34
|
-
if (variable == null) return unit;
|
|
35
|
-
const node = getVariableInitializer(variable, at);
|
|
36
|
-
if (node != null) return node;
|
|
37
|
-
const def = variable.defs.at(at);
|
|
38
|
-
if (def?.type === DefinitionType.Parameter && ast.isFunction(def.node)) return def.node;
|
|
39
|
-
return unit;
|
|
40
|
-
}
|
|
41
26
|
|
|
42
27
|
//#endregion
|
|
43
|
-
//#region src/
|
|
28
|
+
//#region src/find-variable.ts
|
|
44
29
|
/**
|
|
45
30
|
* Find a variable by name or identifier node in the scope chain
|
|
46
31
|
* @param initialScope The scope to start searching from
|
|
@@ -56,105 +41,7 @@ const findVariable = dual(2, (nameOrNode, initialScope) => {
|
|
|
56
41
|
});
|
|
57
42
|
|
|
58
43
|
//#endregion
|
|
59
|
-
//#region src/
|
|
60
|
-
const thisBlockTypes = [
|
|
61
|
-
AST_NODE_TYPES.FunctionDeclaration,
|
|
62
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
63
|
-
AST_NODE_TYPES.ClassBody,
|
|
64
|
-
AST_NODE_TYPES.Program
|
|
65
|
-
];
|
|
66
|
-
/**
|
|
67
|
-
* Determine whether node value equals to another node value
|
|
68
|
-
* @param a node to compare
|
|
69
|
-
* @param b node to compare
|
|
70
|
-
* @param initialScopes initial scopes of the two nodes
|
|
71
|
-
* @returns `true` if node value equal
|
|
72
|
-
*/
|
|
73
|
-
function isValueEqual(a, b, initialScopes) {
|
|
74
|
-
a = ast.isTypeExpression(a) ? ast.getUnderlyingExpression(a) : a;
|
|
75
|
-
b = ast.isTypeExpression(b) ? ast.getUnderlyingExpression(b) : b;
|
|
76
|
-
const [aScope, bScope] = initialScopes;
|
|
77
|
-
switch (true) {
|
|
78
|
-
case a === b: return true;
|
|
79
|
-
case a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal: return a.value === b.value;
|
|
80
|
-
case a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement: return a.value.cooked === b.value.cooked;
|
|
81
|
-
case a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier: {
|
|
82
|
-
const aVar = findVariable(a, aScope);
|
|
83
|
-
const bVar = findVariable(b, bScope);
|
|
84
|
-
const aVarInit = getVariableInitializerLoose(aVar, 0);
|
|
85
|
-
const bVarInit = getVariableInitializerLoose(bVar, 0);
|
|
86
|
-
const aVarInitParent = aVarInit?.parent;
|
|
87
|
-
const bVarInitParent = bVarInit?.parent;
|
|
88
|
-
const aDef = aVar?.defs.at(0);
|
|
89
|
-
const bDef = bVar?.defs.at(0);
|
|
90
|
-
const aDefParentParent = aDef?.parent?.parent;
|
|
91
|
-
const bDefParentParent = bDef?.parent?.parent;
|
|
92
|
-
switch (true) {
|
|
93
|
-
case aVarInitParent?.type === AST_NODE_TYPES.CallExpression && bVarInitParent?.type === AST_NODE_TYPES.CallExpression && ast.isFunction(aVarInit) && ast.isFunction(bVarInit): {
|
|
94
|
-
if (!ast.isNodeEqual(aVarInitParent.callee, bVarInitParent.callee)) return false;
|
|
95
|
-
const aParams = aVarInit.params;
|
|
96
|
-
const bParams = bVarInit.params;
|
|
97
|
-
const aPos = aParams.findIndex((x) => ast.isNodeEqual(x, a));
|
|
98
|
-
const bPos = bParams.findIndex((x) => ast.isNodeEqual(x, b));
|
|
99
|
-
return aPos !== -1 && bPos !== -1 && aPos === bPos;
|
|
100
|
-
}
|
|
101
|
-
case aDefParentParent?.type === AST_NODE_TYPES.ForOfStatement && bDefParentParent?.type === AST_NODE_TYPES.ForOfStatement: {
|
|
102
|
-
const aLeft = aDefParentParent.left;
|
|
103
|
-
const bLeft = bDefParentParent.left;
|
|
104
|
-
if (aLeft.type !== bLeft.type) return false;
|
|
105
|
-
const aRight = aDefParentParent.right;
|
|
106
|
-
const bRight = bDefParentParent.right;
|
|
107
|
-
return ast.isNodeEqual(aRight, bRight);
|
|
108
|
-
}
|
|
109
|
-
default: return aVar != null && bVar != null && aVar === bVar;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
case a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression: return ast.isNodeEqual(a.property, b.property) && isValueEqual(a.object, b.object, initialScopes);
|
|
113
|
-
case a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression:
|
|
114
|
-
if (aScope.block === bScope.block) return true;
|
|
115
|
-
return ast.findParentNode(a, ast.isOneOf(thisBlockTypes)) === ast.findParentNode(b, ast.isOneOf(thisBlockTypes));
|
|
116
|
-
default: {
|
|
117
|
-
const aStatic = getStaticValue(a, aScope);
|
|
118
|
-
const bStatic = getStaticValue(b, bScope);
|
|
119
|
-
return aStatic != null && bStatic != null && aStatic.value === bStatic.value;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
//#endregion
|
|
125
|
-
//#region src/binding-assignment.ts
|
|
126
|
-
/** eslint-disable jsdoc/require-param */
|
|
127
|
-
/**
|
|
128
|
-
* Finds the enclosing assignment target (variable, property, etc.) for a given node
|
|
129
|
-
*
|
|
130
|
-
* @todo Verify correctness and completeness of this function
|
|
131
|
-
* @param node The starting node
|
|
132
|
-
* @returns The enclosing assignment target node, or undefined if not found
|
|
133
|
-
*/
|
|
134
|
-
function findEnclosingAssignmentTarget(node) {
|
|
135
|
-
switch (true) {
|
|
136
|
-
case node.type === AST_NODE_TYPES.VariableDeclarator: return node.id;
|
|
137
|
-
case node.type === AST_NODE_TYPES.AssignmentExpression: return node.left;
|
|
138
|
-
case node.type === AST_NODE_TYPES.PropertyDefinition: return node.key;
|
|
139
|
-
case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
|
|
140
|
-
default: return findEnclosingAssignmentTarget(node.parent);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Check if two assignment targets are equal
|
|
145
|
-
* Compares nodes directly or by their values
|
|
146
|
-
* @param context The rule context
|
|
147
|
-
* @param a The first node to compare
|
|
148
|
-
* @param b The second node to compare
|
|
149
|
-
* @returns True if the assignment targets are equal
|
|
150
|
-
* @internal
|
|
151
|
-
*/
|
|
152
|
-
function isAssignmentTargetEqual(context, a, b) {
|
|
153
|
-
return ast.isNodeEqual(a, b) || isValueEqual(a, b, [context.sourceCode.getScope(a), context.sourceCode.getScope(b)]);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
//#endregion
|
|
157
|
-
//#region src/binding-import.ts
|
|
44
|
+
//#region src/find-import-source.ts
|
|
158
45
|
/**
|
|
159
46
|
* Get the arguments of a require expression
|
|
160
47
|
* @param node The node to match
|
|
@@ -196,38 +83,41 @@ function findImportSource(name, initialScope) {
|
|
|
196
83
|
}
|
|
197
84
|
|
|
198
85
|
//#endregion
|
|
199
|
-
//#region src/
|
|
86
|
+
//#region src/get-variable-initializer.ts
|
|
200
87
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* @param
|
|
204
|
-
* @
|
|
205
|
-
* @param initialScope The scope to use for variable resolution
|
|
206
|
-
* @param seen Set of already seen variable names to prevent circular references
|
|
207
|
-
* @returns The found property or unit if not found
|
|
88
|
+
* Get the initializer expression or statement of a variable definition at a specified index
|
|
89
|
+
* @param variable The variable to get the initializer from
|
|
90
|
+
* @param at The index of the variable definition to get the initializer from
|
|
91
|
+
* @returns The initializer expression or statement of the variable definition at the specified index, or unit if not found
|
|
208
92
|
*/
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
93
|
+
function getVariableInitializer(variable, at) {
|
|
94
|
+
if (variable == null) return unit;
|
|
95
|
+
const def = variable.defs.at(at);
|
|
96
|
+
if (def == null) return unit;
|
|
97
|
+
switch (true) {
|
|
98
|
+
case def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration: return def.node;
|
|
99
|
+
case def.type === DefinitionType.ClassName && def.node.type === AST_NODE_TYPES.ClassDeclaration: return def.node;
|
|
100
|
+
case "init" in def.node && def.node.init != null && !("declarations" in def.node.init): return def.node.init;
|
|
101
|
+
default: return unit;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get the initializer expression or statement of a variable definition at a specified index, or the function declaration if the variable is a parameter of a function
|
|
106
|
+
* @param variable The variable to get the initializer from
|
|
107
|
+
* @param at The index of the variable definition to get the initializer from
|
|
108
|
+
* @returns The initializer expression or statement of the variable definition at the specified index, or the function declaration if the variable is a parameter of a function, or unit if not found
|
|
109
|
+
*/
|
|
110
|
+
function getVariableInitializerLoose(variable, at) {
|
|
111
|
+
if (variable == null) return unit;
|
|
112
|
+
const node = getVariableInitializer(variable, at);
|
|
113
|
+
if (node != null) return node;
|
|
114
|
+
const def = variable.defs.at(at);
|
|
115
|
+
if (def?.type === DefinitionType.Parameter && ast.isFunction(def.node)) return def.node;
|
|
116
|
+
return unit;
|
|
227
117
|
}
|
|
228
118
|
|
|
229
119
|
//#endregion
|
|
230
|
-
//#region src/
|
|
120
|
+
//#region src/get-object-type.ts
|
|
231
121
|
/**
|
|
232
122
|
* Detect the ObjectType of a given node
|
|
233
123
|
* @param node The node to check
|
|
@@ -298,4 +188,85 @@ function getObjectType(node, initialScope) {
|
|
|
298
188
|
}
|
|
299
189
|
|
|
300
190
|
//#endregion
|
|
301
|
-
|
|
191
|
+
//#region src/is-value-equal.ts
|
|
192
|
+
const thisBlockTypes = [
|
|
193
|
+
AST_NODE_TYPES.FunctionDeclaration,
|
|
194
|
+
AST_NODE_TYPES.FunctionExpression,
|
|
195
|
+
AST_NODE_TYPES.ClassBody,
|
|
196
|
+
AST_NODE_TYPES.Program
|
|
197
|
+
];
|
|
198
|
+
/**
|
|
199
|
+
* Determine whether node value equals to another node value
|
|
200
|
+
* @param a node to compare
|
|
201
|
+
* @param b node to compare
|
|
202
|
+
* @param initialScopes initial scopes of the two nodes
|
|
203
|
+
* @returns `true` if node value equal
|
|
204
|
+
*/
|
|
205
|
+
function isValueEqual(a, b, initialScopes) {
|
|
206
|
+
a = ast.isTypeExpression(a) ? ast.getUnderlyingExpression(a) : a;
|
|
207
|
+
b = ast.isTypeExpression(b) ? ast.getUnderlyingExpression(b) : b;
|
|
208
|
+
const [aScope, bScope] = initialScopes;
|
|
209
|
+
switch (true) {
|
|
210
|
+
case a === b: return true;
|
|
211
|
+
case a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal: return a.value === b.value;
|
|
212
|
+
case a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement: return a.value.cooked === b.value.cooked;
|
|
213
|
+
case a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier: {
|
|
214
|
+
const aVar = findVariable(a, aScope);
|
|
215
|
+
const bVar = findVariable(b, bScope);
|
|
216
|
+
const aVarInit = getVariableInitializerLoose(aVar, 0);
|
|
217
|
+
const bVarInit = getVariableInitializerLoose(bVar, 0);
|
|
218
|
+
const aVarInitParent = aVarInit?.parent;
|
|
219
|
+
const bVarInitParent = bVarInit?.parent;
|
|
220
|
+
const aDef = aVar?.defs.at(0);
|
|
221
|
+
const bDef = bVar?.defs.at(0);
|
|
222
|
+
const aDefParentParent = aDef?.parent?.parent;
|
|
223
|
+
const bDefParentParent = bDef?.parent?.parent;
|
|
224
|
+
switch (true) {
|
|
225
|
+
case aVarInitParent?.type === AST_NODE_TYPES.CallExpression && bVarInitParent?.type === AST_NODE_TYPES.CallExpression && ast.isFunction(aVarInit) && ast.isFunction(bVarInit): {
|
|
226
|
+
if (!ast.isNodeEqual(aVarInitParent.callee, bVarInitParent.callee)) return false;
|
|
227
|
+
const aParams = aVarInit.params;
|
|
228
|
+
const bParams = bVarInit.params;
|
|
229
|
+
const aPos = aParams.findIndex((x) => ast.isNodeEqual(x, a));
|
|
230
|
+
const bPos = bParams.findIndex((x) => ast.isNodeEqual(x, b));
|
|
231
|
+
return aPos !== -1 && bPos !== -1 && aPos === bPos;
|
|
232
|
+
}
|
|
233
|
+
case aDefParentParent?.type === AST_NODE_TYPES.ForOfStatement && bDefParentParent?.type === AST_NODE_TYPES.ForOfStatement: {
|
|
234
|
+
const aLeft = aDefParentParent.left;
|
|
235
|
+
const bLeft = bDefParentParent.left;
|
|
236
|
+
if (aLeft.type !== bLeft.type) return false;
|
|
237
|
+
const aRight = aDefParentParent.right;
|
|
238
|
+
const bRight = bDefParentParent.right;
|
|
239
|
+
return ast.isNodeEqual(aRight, bRight);
|
|
240
|
+
}
|
|
241
|
+
default: return aVar != null && bVar != null && aVar === bVar;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
case a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression: return ast.isNodeEqual(a.property, b.property) && isValueEqual(a.object, b.object, initialScopes);
|
|
245
|
+
case a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression:
|
|
246
|
+
if (aScope.block === bScope.block) return true;
|
|
247
|
+
return ast.findParentNode(a, ast.isOneOf(thisBlockTypes)) === ast.findParentNode(b, ast.isOneOf(thisBlockTypes));
|
|
248
|
+
default: {
|
|
249
|
+
const aStatic = getStaticValue(a, aScope);
|
|
250
|
+
const bStatic = getStaticValue(b, bScope);
|
|
251
|
+
return aStatic != null && bStatic != null && aStatic.value === bStatic.value;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/is-assignment-target-equal.ts
|
|
258
|
+
/**
|
|
259
|
+
* Check if two assignment targets are equal
|
|
260
|
+
* Compares nodes directly or by their values
|
|
261
|
+
* @param context The rule context
|
|
262
|
+
* @param a The first node to compare
|
|
263
|
+
* @param b The second node to compare
|
|
264
|
+
* @returns True if the assignment targets are equal
|
|
265
|
+
* @internal
|
|
266
|
+
*/
|
|
267
|
+
function isAssignmentTargetEqual(context, a, b) {
|
|
268
|
+
return ast.isNodeEqual(a, b) || isValueEqual(a, b, [context.sourceCode.getScope(a), context.sourceCode.getScope(b)]);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
//#endregion
|
|
272
|
+
export { findEnclosingAssignmentTarget, findImportSource, findVariable, getObjectType, getVariableInitializer, getVariableInitializerLoose, isAssignmentTargetEqual, isValueEqual };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/var",
|
|
3
|
-
"version": "3.0.0-next.
|
|
3
|
+
"version": "3.0.0-next.59",
|
|
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": {
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"@typescript-eslint/types": "canary",
|
|
35
35
|
"@typescript-eslint/utils": "canary",
|
|
36
36
|
"ts-pattern": "^5.9.0",
|
|
37
|
-
"@eslint-react/ast": "3.0.0-next.
|
|
38
|
-
"@eslint-react/eff": "3.0.0-next.
|
|
39
|
-
"@eslint-react/shared": "3.0.0-next.
|
|
37
|
+
"@eslint-react/ast": "3.0.0-next.59",
|
|
38
|
+
"@eslint-react/eff": "3.0.0-next.59",
|
|
39
|
+
"@eslint-react/shared": "3.0.0-next.59"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"tsdown": "^0.21.0-beta.2",
|