@eslint-react/var 3.0.0-next.63 → 3.0.0-next.64

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 CHANGED
@@ -1,4 +1,3 @@
1
- import { unit } from "@eslint-react/eff";
2
1
  import { Scope } from "@typescript-eslint/scope-manager";
3
2
  import { TSESTree } from "@typescript-eslint/types";
4
3
  import { RuleContext } from "@eslint-react/shared";
@@ -36,10 +35,9 @@ type ObjectType = {
36
35
  /**
37
36
  * Detect the ObjectType of a given node
38
37
  * @param node The node to check
39
- * @param initialScope The initial scope to check for variable declarations
40
38
  * @returns The ObjectType of the node, or undefined if not detected
41
39
  */
42
- declare function computeObjectType(node: TSESTree.Node | unit, initialScope: Scope): ObjectType | unit;
40
+ declare function computeObjectType(context: RuleContext, node: TSESTree.Node | null): ObjectType | null;
43
41
  //#endregion
44
42
  //#region src/find-enclosing-assignment-target.d.ts
45
43
  /**
@@ -47,9 +45,9 @@ declare function computeObjectType(node: TSESTree.Node | unit, initialScope: Sco
47
45
  *
48
46
  * @todo Verify correctness and completeness of this function
49
47
  * @param node The starting node
50
- * @returns The enclosing assignment target node, or undefined if not found
48
+ * @returns The enclosing assignment target node, or null if not found
51
49
  */
52
- declare function findEnclosingAssignmentTarget(node: TSESTree.Node): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | undefined;
50
+ declare function findEnclosingAssignmentTarget(node: TSESTree.Node): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | null;
53
51
  /**
54
52
  * Type representing the possible assignment targets returned by `findEnclosingAssignmentTarget`
55
53
  */
@@ -77,4 +75,36 @@ declare function isAssignmentTargetEqual(context: RuleContext, a: TSESTree.Node,
77
75
  */
78
76
  declare function isValueEqual(a: TSESTree.Node, b: TSESTree.Node, initialScopes: [aScope: Scope, bScope: Scope]): boolean;
79
77
  //#endregion
80
- export { AssignmentTarget, ObjectType, computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual, isValueEqual };
78
+ //#region src/resolve.d.ts
79
+ /**
80
+ * Resolves an identifier to the AST node that represents its value,
81
+ * suitable for use in ESLint rule analysis.
82
+ *
83
+ * The resolution follows these rules per definition type:
84
+ *
85
+ * | Definition type | `def.node` | Returns |
86
+ * |--------------------------|----------------------------------------------|------------------------------------|
87
+ * | `Variable` | `VariableDeclarator` | `def.node.init` (or `null`) |
88
+ * | `FunctionName` | `FunctionDeclaration` / `FunctionExpression` | `def.node` |
89
+ * | `ClassName` | `ClassDeclaration` / `ClassExpression` | `def.node` |
90
+ * | `Parameter` | containing function node | `def.node` (if a real function) |
91
+ * | `TSEnumName` | `TSEnumDeclaration` | `def.node` |
92
+ * | `TSEnumMember` | `TSEnumMember` | `def.node.initializer` (or `null`) |
93
+ * | `ImportBinding` | import specifier | `null` |
94
+ * | `CatchClause` | `CatchClause` | `null` |
95
+ * | `TSModuleName` | `TSModuleDeclaration` | `null` |
96
+ * | `Type` | type alias node | `null` |
97
+ * | `ImplicitGlobalVariable` | any node | `null` |
98
+ *
99
+ * @param context The ESLint rule context used for scope lookup.
100
+ * @param node The identifier to resolve.
101
+ * @param at Which definition to use when multiple exist (default: `0`; pass `-1` for the last).
102
+ * @param localOnly When `true`, look up the variable only in the node's own scope (faster, but
103
+ * will miss variables declared in an outer scope). When `false` (default), traverse the scope
104
+ * chain upward via `findVariable` so that references to outer-scope bindings are resolved
105
+ * correctly.
106
+ * @returns The resolved node, or `null` if the identifier cannot be resolved to a value node.
107
+ */
108
+ declare function resolve(context: RuleContext, node: TSESTree.Identifier, at?: number, localOnly?: boolean): TSESTree.Node | null;
109
+ //#endregion
110
+ export { AssignmentTarget, ObjectType, computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual, isValueEqual, resolve };
package/dist/index.js CHANGED
@@ -1,18 +1,74 @@
1
- import { unit } from "@eslint-react/eff";
2
1
  import { DefinitionType } from "@typescript-eslint/scope-manager";
3
2
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
4
3
  import * as ast from "@eslint-react/ast";
5
4
  import { findVariable, getStaticValue } from "@typescript-eslint/utils/ast-utils";
6
5
 
6
+ //#region src/resolve.ts
7
+ /**
8
+ * Resolves an identifier to the AST node that represents its value,
9
+ * suitable for use in ESLint rule analysis.
10
+ *
11
+ * The resolution follows these rules per definition type:
12
+ *
13
+ * | Definition type | `def.node` | Returns |
14
+ * |--------------------------|----------------------------------------------|------------------------------------|
15
+ * | `Variable` | `VariableDeclarator` | `def.node.init` (or `null`) |
16
+ * | `FunctionName` | `FunctionDeclaration` / `FunctionExpression` | `def.node` |
17
+ * | `ClassName` | `ClassDeclaration` / `ClassExpression` | `def.node` |
18
+ * | `Parameter` | containing function node | `def.node` (if a real function) |
19
+ * | `TSEnumName` | `TSEnumDeclaration` | `def.node` |
20
+ * | `TSEnumMember` | `TSEnumMember` | `def.node.initializer` (or `null`) |
21
+ * | `ImportBinding` | import specifier | `null` |
22
+ * | `CatchClause` | `CatchClause` | `null` |
23
+ * | `TSModuleName` | `TSModuleDeclaration` | `null` |
24
+ * | `Type` | type alias node | `null` |
25
+ * | `ImplicitGlobalVariable` | any node | `null` |
26
+ *
27
+ * @param context The ESLint rule context used for scope lookup.
28
+ * @param node The identifier to resolve.
29
+ * @param at Which definition to use when multiple exist (default: `0`; pass `-1` for the last).
30
+ * @param localOnly When `true`, look up the variable only in the node's own scope (faster, but
31
+ * will miss variables declared in an outer scope). When `false` (default), traverse the scope
32
+ * chain upward via `findVariable` so that references to outer-scope bindings are resolved
33
+ * correctly.
34
+ * @returns The resolved node, or `null` if the identifier cannot be resolved to a value node.
35
+ */
36
+ function resolve(context, node, at = 0, localOnly = false) {
37
+ const scope = context.sourceCode.getScope(node);
38
+ const variable = localOnly ? scope.set.get(node.name) : findVariable(scope, node);
39
+ if (variable == null) return null;
40
+ const def = variable.defs.at(at);
41
+ if (def == null) return null;
42
+ switch (def.type) {
43
+ case DefinitionType.FunctionName: return def.node;
44
+ case DefinitionType.ClassName: return def.node;
45
+ case DefinitionType.Variable: {
46
+ const { init } = def.node;
47
+ if (init == null) return null;
48
+ if ("declarations" in init) return null;
49
+ return init;
50
+ }
51
+ case DefinitionType.Parameter: return ast.isFunction(def.node) ? def.node : null;
52
+ case DefinitionType.TSEnumName: return def.node;
53
+ case DefinitionType.TSEnumMember: return def.node.initializer ?? null;
54
+ case DefinitionType.ImportBinding: return null;
55
+ case DefinitionType.CatchClause: return null;
56
+ case DefinitionType.TSModuleName: return null;
57
+ case DefinitionType.Type: return null;
58
+ case DefinitionType.ImplicitGlobalVariable: return null;
59
+ default: return null;
60
+ }
61
+ }
62
+
63
+ //#endregion
7
64
  //#region src/compute-object-type.ts
8
65
  /**
9
66
  * Detect the ObjectType of a given node
10
67
  * @param node The node to check
11
- * @param initialScope The initial scope to check for variable declarations
12
68
  * @returns The ObjectType of the node, or undefined if not detected
13
69
  */
14
- function computeObjectType(node, initialScope) {
15
- if (node == null) return unit;
70
+ function computeObjectType(context, node) {
71
+ if (node == null) return null;
16
72
  switch (node.type) {
17
73
  case AST_NODE_TYPES.JSXElement:
18
74
  case AST_NODE_TYPES.JSXFragment: return {
@@ -47,43 +103,35 @@ function computeObjectType(node, initialScope) {
47
103
  kind: "regexp",
48
104
  node
49
105
  };
50
- return unit;
106
+ return null;
51
107
  case AST_NODE_TYPES.Identifier: {
52
- const initNode = resolve(initialScope.set.get(node.name));
53
- if (initNode == null) return unit;
54
- return computeObjectType(initNode, initialScope);
108
+ if ((context.sourceCode.getScope(node).set.get(node.name)?.defs.at(-1))?.type === DefinitionType.Parameter) return null;
109
+ const initNode = resolve(context, node, -1, true);
110
+ if (initNode == null) return null;
111
+ return computeObjectType(context, initNode);
55
112
  }
56
113
  case AST_NODE_TYPES.MemberExpression:
57
- if (!("object" in node)) return unit;
58
- return computeObjectType(node.object, initialScope);
114
+ if (!("object" in node)) return null;
115
+ return computeObjectType(context, node.object);
59
116
  case AST_NODE_TYPES.AssignmentExpression:
60
117
  case AST_NODE_TYPES.AssignmentPattern:
61
- if (!("right" in node)) return unit;
62
- return computeObjectType(node.right, initialScope);
63
- case AST_NODE_TYPES.LogicalExpression: return computeObjectType(node.right, initialScope);
64
- case AST_NODE_TYPES.ConditionalExpression: return computeObjectType(node.consequent, initialScope) ?? computeObjectType(node.alternate, initialScope);
118
+ if (!("right" in node)) return null;
119
+ return computeObjectType(context, node.right);
120
+ case AST_NODE_TYPES.LogicalExpression: return computeObjectType(context, node.right);
121
+ case AST_NODE_TYPES.ConditionalExpression: return computeObjectType(context, node.consequent) ?? computeObjectType(context, node.alternate);
65
122
  case AST_NODE_TYPES.SequenceExpression:
66
- if (node.expressions.length === 0) return unit;
67
- return computeObjectType(node.expressions[node.expressions.length - 1], initialScope);
123
+ if (node.expressions.length === 0) return null;
124
+ return computeObjectType(context, node.expressions[node.expressions.length - 1] ?? null);
68
125
  case AST_NODE_TYPES.CallExpression: return {
69
126
  kind: "unknown",
70
127
  node,
71
128
  reason: "call-expression"
72
129
  };
73
130
  default:
74
- if (!("expression" in node) || typeof node.expression !== "object") return unit;
75
- return computeObjectType(node.expression, initialScope);
131
+ if (!("expression" in node) || typeof node.expression !== "object") return null;
132
+ return computeObjectType(context, node.expression);
76
133
  }
77
134
  }
78
- function resolve(v) {
79
- if (v == null) return unit;
80
- const def = v.defs.at(-1);
81
- if (def == null) return unit;
82
- if (def.type === DefinitionType.Variable) return def.node.init;
83
- if (def.type === DefinitionType.Parameter) return unit;
84
- if (def.type === DefinitionType.ImportBinding) return unit;
85
- return def.node;
86
- }
87
135
 
88
136
  //#endregion
89
137
  //#region src/find-enclosing-assignment-target.ts
@@ -92,14 +140,14 @@ function resolve(v) {
92
140
  *
93
141
  * @todo Verify correctness and completeness of this function
94
142
  * @param node The starting node
95
- * @returns The enclosing assignment target node, or undefined if not found
143
+ * @returns The enclosing assignment target node, or null if not found
96
144
  */
97
145
  function findEnclosingAssignmentTarget(node) {
98
146
  switch (true) {
99
147
  case node.type === AST_NODE_TYPES.VariableDeclarator: return node.id;
100
148
  case node.type === AST_NODE_TYPES.AssignmentExpression: return node.left;
101
149
  case node.type === AST_NODE_TYPES.PropertyDefinition: return node.key;
102
- case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
150
+ case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return null;
103
151
  default: return findEnclosingAssignmentTarget(node.parent);
104
152
  }
105
153
  }
@@ -131,7 +179,7 @@ function isValueEqual(a, b, initialScopes) {
131
179
  const aVar = findVariable(aScope, a);
132
180
  const bVar = findVariable(bScope, b);
133
181
  const resolve = (variable) => {
134
- if (variable == null) return unit;
182
+ if (variable == null) return null;
135
183
  const def = variable.defs.at(0);
136
184
  if (def != null) switch (true) {
137
185
  case def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration: return def.node;
@@ -139,7 +187,7 @@ function isValueEqual(a, b, initialScopes) {
139
187
  case "init" in def.node && def.node.init != null && !("declarations" in def.node.init): return def.node.init;
140
188
  }
141
189
  if (def?.type === DefinitionType.Parameter && ast.isFunction(def.node)) return def.node;
142
- return unit;
190
+ return null;
143
191
  };
144
192
  const aVarInit = resolve(aVar);
145
193
  const bVarInit = resolve(bVar);
@@ -197,4 +245,4 @@ function isAssignmentTargetEqual(context, a, b) {
197
245
  }
198
246
 
199
247
  //#endregion
200
- export { computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual, isValueEqual };
248
+ export { computeObjectType, findEnclosingAssignmentTarget, isAssignmentTargetEqual, isValueEqual, resolve };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/var",
3
- "version": "3.0.0-next.63",
3
+ "version": "3.0.0-next.64",
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,11 +34,12 @@
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.63",
38
- "@eslint-react/eff": "3.0.0-next.63",
39
- "@eslint-react/shared": "3.0.0-next.63"
37
+ "@eslint-react/ast": "3.0.0-next.64",
38
+ "@eslint-react/eff": "3.0.0-next.64",
39
+ "@eslint-react/shared": "3.0.0-next.64"
40
40
  },
41
41
  "devDependencies": {
42
+ "@typescript-eslint/typescript-estree": "canary",
42
43
  "tsdown": "^0.21.0-beta.2",
43
44
  "@local/configs": "0.0.0"
44
45
  },