@eslint-react/var 5.28.2 → 5.28.3
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 +19 -4
- package/dist/index.js +23 -12
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -181,7 +181,12 @@ export declare function isValueEqual(context: RuleContext, a: TSESTree.Node, b:
|
|
|
181
181
|
* - `localOnly`: If `true`, only consider variables declared in the same scope as the identifier
|
|
182
182
|
* (this will miss variables declared in an outer scope). When `false` (default), traverse the
|
|
183
183
|
* scope chain upward via `findVariable` so that references to outer-scope bindings are resolved
|
|
184
|
-
* correctly.
|
|
184
|
+
* correctly. Ignored when `boundary` is set.
|
|
185
|
+
* - `boundary`: A node (typically the enclosing component or hook function) that bounds the
|
|
186
|
+
* scope-chain traversal. The identifier is resolved only if its binding is declared in a scope
|
|
187
|
+
* between the identifier's own scope and the boundary's scope (inclusive); bindings declared
|
|
188
|
+
* outside the boundary (e.g. module-level constants, which are stable across renders) are
|
|
189
|
+
* treated as unresolvable. The boundary node must be an ancestor of `node`.
|
|
185
190
|
* @returns The resolved node, or `null` if the identifier cannot be resolved to a value node.
|
|
186
191
|
*
|
|
187
192
|
* For origin/pedigree tracking that maps destructured bindings to the declarator's
|
|
@@ -189,6 +194,7 @@ export declare function isValueEqual(context: RuleContext, a: TSESTree.Node, b:
|
|
|
189
194
|
*/
|
|
190
195
|
export declare function resolve(context: RuleContext, node: TSESTree.Identifier, options?: Partial<{
|
|
191
196
|
at: number;
|
|
197
|
+
boundary: TSESTree.Node;
|
|
192
198
|
localOnly: boolean;
|
|
193
199
|
}>): TSESTree.Node | null;
|
|
194
200
|
//#endregion
|
|
@@ -200,7 +206,7 @@ export type EnclosingAssignmentTarget = ReturnType<typeof resolveEnclosingAssign
|
|
|
200
206
|
* @param node The starting node for the upward search.
|
|
201
207
|
* @returns The enclosing assignment target node, or `null` when not found.
|
|
202
208
|
*/
|
|
203
|
-
export declare function resolveEnclosingAssignmentTarget(node: TSESTree.Node): TSESTree.
|
|
209
|
+
export declare function resolveEnclosingAssignmentTarget(node: TSESTree.Node): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpressionWithBlockBody | TSESTree.ArrowFunctionExpressionWithExpressionBody | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassDeclarationWithOptionalName | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | 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.TSDeclareFunctionNoDeclare | TSESTree.TSDeclareFunctionWithDeclare | TSESTree.TSEnumDeclaration | TSESTree.TSInstantiationExpression | TSESTree.TSInterfaceDeclaration | TSESTree.TSModuleDeclarationGlobal | TSESTree.TSModuleDeclarationModuleWithIdentifierId | TSESTree.TSModuleDeclarationModuleWithStringIdDeclared | TSESTree.TSModuleDeclarationModuleWithStringIdNotDeclared | TSESTree.TSModuleDeclarationNamespace | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAliasDeclaration | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.ConstDeclaration | TSESTree.LetOrVarDeclaredDeclaration | TSESTree.LetOrVarNonDeclaredDeclaration | TSESTree.UsingInForOfDeclaration | TSESTree.UsingInNormalContextDeclaration | TSESTree.YieldNoStarExpression | TSESTree.YieldStarExpression | null;
|
|
204
210
|
//#endregion
|
|
205
211
|
//#region src/resolve-import-source.d.ts
|
|
206
212
|
/**
|
|
@@ -227,7 +233,7 @@ export type ObjectType = {
|
|
|
227
233
|
node: TSESTree.ObjectExpression | TSESTree.CallExpression;
|
|
228
234
|
} | {
|
|
229
235
|
kind: "class";
|
|
230
|
-
node: TSESTree.ClassExpression;
|
|
236
|
+
node: TSESTree.ClassDeclaration | TSESTree.ClassExpression;
|
|
231
237
|
} | {
|
|
232
238
|
kind: "instance";
|
|
233
239
|
node: TSESTree.NewExpression | TSESTree.ThisExpression;
|
|
@@ -246,9 +252,18 @@ export type ObjectType = {
|
|
|
246
252
|
* Resolve the object type of the node.
|
|
247
253
|
* @param context The ESLint rule context.
|
|
248
254
|
* @param node The node to resolve.
|
|
255
|
+
* @param options Optional settings:
|
|
256
|
+
* - `boundary`: A node (typically the enclosing component or hook function) that bounds
|
|
257
|
+
* identifier resolution. Identifiers are resolved through their initializer only when the
|
|
258
|
+
* binding is declared within the boundary — this catches render-scoped constructions referenced
|
|
259
|
+
* from nested callbacks, while values declared outside the boundary (e.g. module-level
|
|
260
|
+
* constants, which are stable across renders) are treated as unresolvable. When omitted, only
|
|
261
|
+
* the identifier's own scope is searched.
|
|
249
262
|
* @returns The object type of the node, or `null` when it cannot be resolved.
|
|
250
263
|
*/
|
|
251
|
-
export declare function resolveObjectType(context: RuleContext, node: TSESTree.Node | null | undefined
|
|
264
|
+
export declare function resolveObjectType(context: RuleContext, node: TSESTree.Node | null | undefined, options?: Partial<{
|
|
265
|
+
boundary: TSESTree.Node;
|
|
266
|
+
}>): ObjectType | null;
|
|
252
267
|
//#endregion
|
|
253
268
|
//#region src/resolve-origin.d.ts
|
|
254
269
|
/**
|
package/dist/index.js
CHANGED
|
@@ -318,9 +318,9 @@ function isInitializedFromReactNative(name, initialScope, importSource = "react-
|
|
|
318
318
|
//#endregion
|
|
319
319
|
//#region src/resolve.ts
|
|
320
320
|
function resolve(context, node, options) {
|
|
321
|
-
const { at = 0, localOnly = false } = options ?? {};
|
|
321
|
+
const { at = 0, boundary, localOnly = false } = options ?? {};
|
|
322
322
|
const scope = context.sourceCode.getScope(node);
|
|
323
|
-
const variable = localOnly ? scope.set.get(node.name) : findVariable(scope, node);
|
|
323
|
+
const variable = boundary != null ? findVariableWithinBoundary(scope, node.name, context.sourceCode.getScope(boundary)) : localOnly ? scope.set.get(node.name) : findVariable(scope, node);
|
|
324
324
|
if (variable == null) return null;
|
|
325
325
|
const def = variable.defs.at(at);
|
|
326
326
|
if (def == null) return null;
|
|
@@ -345,6 +345,14 @@ function resolve(context, node, options) {
|
|
|
345
345
|
default: return null;
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
|
+
function findVariableWithinBoundary(scope, name, boundaryScope) {
|
|
349
|
+
while (scope != null) {
|
|
350
|
+
const variable = scope.set.get(name);
|
|
351
|
+
if (variable != null || scope === boundaryScope) return variable ?? null;
|
|
352
|
+
scope = scope.upper;
|
|
353
|
+
}
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
348
356
|
//#endregion
|
|
349
357
|
//#region src/resolve-enclosing-assignment-target.ts
|
|
350
358
|
function resolveEnclosingAssignmentTarget(node) {
|
|
@@ -360,7 +368,7 @@ function resolveEnclosingAssignmentTarget(node) {
|
|
|
360
368
|
}
|
|
361
369
|
//#endregion
|
|
362
370
|
//#region src/resolve-object-type.ts
|
|
363
|
-
function resolveObjectType(context, node) {
|
|
371
|
+
function resolveObjectType(context, node, options) {
|
|
364
372
|
if (node == null) return null;
|
|
365
373
|
switch (node.type) {
|
|
366
374
|
case AST_NODE_TYPES.JSXElement:
|
|
@@ -376,6 +384,7 @@ function resolveObjectType(context, node) {
|
|
|
376
384
|
kind: "plain",
|
|
377
385
|
node
|
|
378
386
|
};
|
|
387
|
+
case AST_NODE_TYPES.ClassDeclaration:
|
|
379
388
|
case AST_NODE_TYPES.ClassExpression: return {
|
|
380
389
|
kind: "class",
|
|
381
390
|
node
|
|
@@ -398,22 +407,24 @@ function resolveObjectType(context, node) {
|
|
|
398
407
|
};
|
|
399
408
|
return null;
|
|
400
409
|
case AST_NODE_TYPES.Identifier: {
|
|
401
|
-
|
|
402
|
-
|
|
410
|
+
const initNode = options?.boundary != null ? resolve(context, node, {
|
|
411
|
+
at: -1,
|
|
412
|
+
boundary: options.boundary
|
|
413
|
+
}) : resolve(context, node, {
|
|
403
414
|
at: -1,
|
|
404
415
|
localOnly: true
|
|
405
416
|
});
|
|
406
417
|
if (initNode == null) return null;
|
|
407
|
-
return resolveObjectType(context, initNode);
|
|
418
|
+
return resolveObjectType(context, initNode, options);
|
|
408
419
|
}
|
|
409
|
-
case AST_NODE_TYPES.MemberExpression: return resolveObjectType(context, node.object);
|
|
420
|
+
case AST_NODE_TYPES.MemberExpression: return resolveObjectType(context, node.object, options);
|
|
410
421
|
case AST_NODE_TYPES.AssignmentExpression:
|
|
411
|
-
case AST_NODE_TYPES.AssignmentPattern: return resolveObjectType(context, node.right);
|
|
412
|
-
case AST_NODE_TYPES.LogicalExpression: return resolveObjectType(context, node.left) ?? resolveObjectType(context, node.right);
|
|
413
|
-
case AST_NODE_TYPES.ConditionalExpression: return resolveObjectType(context, node.consequent) ?? resolveObjectType(context, node.alternate);
|
|
422
|
+
case AST_NODE_TYPES.AssignmentPattern: return resolveObjectType(context, node.right, options);
|
|
423
|
+
case AST_NODE_TYPES.LogicalExpression: return resolveObjectType(context, node.left, options) ?? resolveObjectType(context, node.right, options);
|
|
424
|
+
case AST_NODE_TYPES.ConditionalExpression: return resolveObjectType(context, node.consequent, options) ?? resolveObjectType(context, node.alternate, options);
|
|
414
425
|
case AST_NODE_TYPES.SequenceExpression:
|
|
415
426
|
if (node.expressions.length === 0) return null;
|
|
416
|
-
return resolveObjectType(context, node.expressions.at(-1) ?? null);
|
|
427
|
+
return resolveObjectType(context, node.expressions.at(-1) ?? null, options);
|
|
417
428
|
case AST_NODE_TYPES.CallExpression: {
|
|
418
429
|
const callee = Extract.unwrap(node.callee);
|
|
419
430
|
switch (true) {
|
|
@@ -457,7 +468,7 @@ function resolveObjectType(context, node) {
|
|
|
457
468
|
}
|
|
458
469
|
default:
|
|
459
470
|
if (!hasProperty(node, "expression") || typeof node.expression !== "object") return null;
|
|
460
|
-
return resolveObjectType(context, node.expression);
|
|
471
|
+
return resolveObjectType(context, node.expression, options);
|
|
461
472
|
}
|
|
462
473
|
}
|
|
463
474
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/var",
|
|
3
|
-
"version": "5.28.
|
|
3
|
+
"version": "5.28.3",
|
|
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": {
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@eslint-react/ast": "5.28.
|
|
33
|
-
"@eslint-react/eslint": "5.28.
|
|
34
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
35
|
-
"@typescript-eslint/types": "^8.
|
|
36
|
-
"@typescript-eslint/utils": "^8.
|
|
32
|
+
"@eslint-react/ast": "5.28.3",
|
|
33
|
+
"@eslint-react/eslint": "5.28.3",
|
|
34
|
+
"@typescript-eslint/scope-manager": "^8.72.0",
|
|
35
|
+
"@typescript-eslint/types": "^8.72.0",
|
|
36
|
+
"@typescript-eslint/utils": "^8.72.0",
|
|
37
37
|
"ts-pattern": "^5.9.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@local/testkit": "0.0.0",
|
|
43
43
|
"@tsconfig/node20": "^20.1.10",
|
|
44
44
|
"@types/node": "^20.19.43",
|
|
45
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
45
|
+
"@typescript-eslint/typescript-estree": "^8.72.0",
|
|
46
46
|
"eslint": "^10.13.0",
|
|
47
47
|
"tsdown": "^0.23.1",
|
|
48
48
|
"typescript": "6.0.3",
|