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

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