@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.
Files changed (3) hide show
  1. package/dist/index.d.ts +52 -56
  2. package/dist/index.js +166 -172
  3. 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/find-enclosing-assignment-target.d.ts
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/find-import-source.d.ts
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/find-property.d.ts
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
- * Get all child scopes recursively from a given scope
44
- * @param scope The scope to get child scopes from
45
- * @returns Array of all child scopes including the input scope
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 getChildScopes(scope: Scope): readonly Scope[];
64
+ declare function isNodeEqual(a: TSESTree.Node, b: TSESTree.Node, initialScopes: [aScope: Scope, bScope: Scope]): boolean;
48
65
  //#endregion
49
- //#region src/get-object-type.d.ts
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/get-variable-definition-node.d.ts
104
+ //#region src/var-property.d.ts
88
105
  /**
89
- * Get the definition node of a variable at a specific definition index
90
- * @param variable The variable to get the definition node from
91
- * @param at The index of the definition to retrieve (negative index supported)
92
- * @returns The definition node or unit if not found
93
- */
94
- declare function getVariableDefinitionNode(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.ClassDeclarationWithName | TSESTree.ClassDeclarationWithOptionalName | TSESTree.Expression | TSESTree.FunctionDeclaration | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName;
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 getVariableDefinitionNodeLoose(variable: Variable | unit, at: number): unit | TSESTree.ClassDeclaration | TSESTree.ClassDeclarationWithName | TSESTree.ClassDeclarationWithOptionalName | TSESTree.Expression | TSESTree.FunctionDeclaration | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName;
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/get-variables-from-scope.d.ts
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
- * Determine whether node value equals to another node value
140
- * @param a node to compare
141
- * @param b node to compare
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 isNodeValueEqual(a: TSESTree.Node, b: TSESTree.Node, initialScopes: [aScope: Scope, bScope: Scope]): boolean;
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, isNodeValueEqual };
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/find-enclosing-assignment-target.ts
10
- /** eslint-disable jsdoc/require-param */
9
+ //#region src/var-definition.ts
11
10
  /**
12
- * Finds the enclosing assignment target (variable, property, etc.) for a given node
13
- *
14
- * @todo Verify correctness and completeness of this function
15
- * @param node The starting node
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 findEnclosingAssignmentTarget(node) {
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.VariableDeclarator: return node.id;
21
- case node.type === AST_NODE_TYPES.AssignmentExpression: return node.left;
22
- case node.type === AST_NODE_TYPES.PropertyDefinition: return node.key;
23
- case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
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/get-variables-from-scope.ts
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/find-import-source.ts
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/get-variable-definition-node.ts
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/is-node-value-equal.ts
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
- * Determine whether node value equals to another node value
260
- * @param a node to compare
261
- * @param b node to compare
262
- * @param initialScopes initial scopes of the two nodes
263
- * @returns `true` if node value equal
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 isNodeValueEqual(a, b, initialScopes) {
266
- a = ast.isTypeExpression(a) ? ast.getUnderlyingExpression(a) : a;
267
- b = ast.isTypeExpression(b) ? ast.getUnderlyingExpression(b) : b;
268
- const [aScope, bScope] = initialScopes;
269
- switch (true) {
270
- case a === b: return true;
271
- case a.type === AST_NODE_TYPES.Literal && b.type === AST_NODE_TYPES.Literal: return a.value === b.value;
272
- case a.type === AST_NODE_TYPES.TemplateElement && b.type === AST_NODE_TYPES.TemplateElement: return a.value.cooked === b.value.cooked;
273
- case a.type === AST_NODE_TYPES.Identifier && b.type === AST_NODE_TYPES.Identifier: {
274
- const aVar = findVariable(a, aScope);
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
- default: return aVar != null && bVar != null && aVar === bVar;
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
- case a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression: return ast.isNodeEqual(a.property, b.property) && isNodeValueEqual(a.object, b.object, initialScopes);
305
- case a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression:
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, isNodeValueEqual };
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": "2.14.0-next.0",
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.55.0",
34
- "@typescript-eslint/types": "^8.55.0",
35
- "@typescript-eslint/utils": "^8.55.0",
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": "2.14.0-next.0",
38
- "@eslint-react/eff": "2.14.0-next.0",
39
- "@eslint-react/shared": "2.14.0-next.0"
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": ">=20.19.0"
50
+ "node": ">=22.0.0"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsdown --dts-resolve",