@blumintinc/eslint-plugin-blumint 1.20.199 → 1.20.200
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/lib/index.js +1 -1
- package/lib/rules/enforce-firestore-doc-ref-generic.js +1 -1
- package/lib/rules/enforce-firestore-set-merge.js +4 -1
- package/lib/rules/no-direct-function-state.js +1 -1
- package/lib/rules/no-explicit-return-type.js +1 -1
- package/lib/rules/no-firestore-object-arrays.js +2 -2
- package/lib/rules/prefer-batch-operations.js +1 -1
- package/lib/rules/prefer-spread-over-reassembly.js +1 -1
- package/lib/rules/prevent-children-clobber.js +32 -11
- package/lib/rules/require-hooks-default-params.js +1 -1
- package/lib/rules/require-props-composition.js +1 -1
- package/lib/utils/lexicalScope.d.ts +61 -0
- package/lib/utils/lexicalScope.js +151 -1
- package/package.json +1 -1
- package/release-manifest.json +86 -0
package/lib/index.js
CHANGED
|
@@ -204,7 +204,7 @@ function typeDeclarationNamed(statement, name) {
|
|
|
204
204
|
* dropped the nested-`any` check rather than reporting anything.
|
|
205
205
|
*/
|
|
206
206
|
function declarationOfType(from, name) {
|
|
207
|
-
return (0, lexicalScope_1.
|
|
207
|
+
return (0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'type', (statements) => {
|
|
208
208
|
for (const statement of statements) {
|
|
209
209
|
const declaration = typeDeclarationNamed(statement, name);
|
|
210
210
|
if (declaration) {
|
|
@@ -408,7 +408,10 @@ exports.enforceFirestoreSetMerge = (0, createRule_1.createRule)({
|
|
|
408
408
|
* the shadow.
|
|
409
409
|
*/
|
|
410
410
|
function resolveClassBody(name, reference) {
|
|
411
|
-
return ((0, lexicalScope_1.
|
|
411
|
+
return ((0, lexicalScope_1.resolveNameInEnclosingScopes)(reference, name,
|
|
412
|
+
// `extends X` names X as a value, so a value binder — the parameter
|
|
413
|
+
// of a mixin factory — is what shadows a same-named outer class.
|
|
414
|
+
'value', (statements, container) => containerClasses(container, statements).get(name)) ?? null);
|
|
412
415
|
}
|
|
413
416
|
function enclosingClassBody(node) {
|
|
414
417
|
let current = node.parent;
|
|
@@ -40,7 +40,7 @@ function typeAliasNamed(statement, name) {
|
|
|
40
40
|
* hoisting of type declarations.
|
|
41
41
|
*/
|
|
42
42
|
function resolveTypeAlias(from, name) {
|
|
43
|
-
return (0, lexicalScope_1.
|
|
43
|
+
return (0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'type', (statements) => {
|
|
44
44
|
for (const statement of statements) {
|
|
45
45
|
const alias = typeAliasNamed(statement, name);
|
|
46
46
|
if (alias) {
|
|
@@ -493,7 +493,7 @@ function createReturnCycleResolver(visitorKeys) {
|
|
|
493
493
|
bindings.set(container, computed);
|
|
494
494
|
return computed;
|
|
495
495
|
};
|
|
496
|
-
const resolveFunctionInScope = (from, name) => (0, lexicalScope_1.
|
|
496
|
+
const resolveFunctionInScope = (from, name) => (0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'value', (statements, container) => {
|
|
497
497
|
const scope = bindingsOf(container, statements);
|
|
498
498
|
if (!scope.has(name))
|
|
499
499
|
return undefined;
|
|
@@ -366,7 +366,7 @@ exports.noFirestoreObjectArrays = (0, createRule_1.createRule)({
|
|
|
366
366
|
* declaration written below its own reference still resolves, matching
|
|
367
367
|
* TypeScript's hoisting of type declarations.
|
|
368
368
|
*/
|
|
369
|
-
const resolveTypeName = (from, name) => (0, lexicalScope_1.
|
|
369
|
+
const resolveTypeName = (from, name) => (0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'type', (statements) => typeDeclarationIn(statements, name), () => {
|
|
370
370
|
if (interfaceNames.has(name))
|
|
371
371
|
return { kind: 'interface' };
|
|
372
372
|
if (enumNames.has(name))
|
|
@@ -376,7 +376,7 @@ exports.noFirestoreObjectArrays = (0, createRule_1.createRule)({
|
|
|
376
376
|
? { kind: 'alias', typeAnnotation: aliased }
|
|
377
377
|
: undefined;
|
|
378
378
|
});
|
|
379
|
-
const resolveConstArray = (from, name) => (0, lexicalScope_1.
|
|
379
|
+
const resolveConstArray = (from, name) => (0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'value', (statements) => constArrayIn(statements, name), () => constArrayNameToLiteral.get(name));
|
|
380
380
|
// Keyed by resolved declaration rather than by name: one name can denote
|
|
381
381
|
// different declarations in different scopes, so a name-keyed memo would
|
|
382
382
|
// answer for whichever scope asked first.
|
|
@@ -272,7 +272,7 @@ function isMapInstance(node) {
|
|
|
272
272
|
* searched instead, and the first match wins, which is what shadowing requires.
|
|
273
273
|
*/
|
|
274
274
|
function findVariableDeclaration(node, varName) {
|
|
275
|
-
return (0, lexicalScope_1.
|
|
275
|
+
return (0, lexicalScope_1.resolveNameInEnclosingScopes)(node, varName, 'value', (statements) => {
|
|
276
276
|
for (const statement of statements) {
|
|
277
277
|
const declaration = (0, lexicalScope_1.declarationOf)(statement);
|
|
278
278
|
if (declaration.type !== utils_1.AST_NODE_TYPES.VariableDeclaration)
|
|
@@ -266,7 +266,7 @@ function typeDeclarationIn(statements, name) {
|
|
|
266
266
|
* find what the walk would have.
|
|
267
267
|
*/
|
|
268
268
|
function findLocalTypeDeclaration(program, from, name) {
|
|
269
|
-
return ((0, lexicalScope_1.
|
|
269
|
+
return ((0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'type', (statements) => typeDeclarationIn(statements, name) ?? undefined, () => typeDeclarationIn(program.body, name) ?? undefined) ?? null);
|
|
270
270
|
}
|
|
271
271
|
/**
|
|
272
272
|
* Finds a type alias or interface a module exports by writing `export` in front
|
|
@@ -154,36 +154,57 @@ function constArrayMembersNamed(statement, name) {
|
|
|
154
154
|
* type aliases hoist: a component declared above its own props alias must still
|
|
155
155
|
* resolve it.
|
|
156
156
|
*/
|
|
157
|
-
function aliasResolverFrom(
|
|
157
|
+
function aliasResolverFrom(frames, startIndex = 0, barrierFrom = 0) {
|
|
158
|
+
/**
|
|
159
|
+
* Walks the frames outward, stopping at the first binder that takes the name.
|
|
160
|
+
*
|
|
161
|
+
* A frame's `barriers` gate entry into it from the frame inside it, so a
|
|
162
|
+
* resumed resolver skips the barriers of the frame it resumes at: the alias
|
|
163
|
+
* body it is reading already sits there and never crosses them.
|
|
164
|
+
*/
|
|
165
|
+
const search = (name, namespace, found) => {
|
|
166
|
+
for (let index = startIndex; index < frames.length; index += 1) {
|
|
167
|
+
const frame = frames[index];
|
|
168
|
+
if (index >= barrierFrom &&
|
|
169
|
+
frame.barriers.some((barrier) => (0, lexicalScope_1.bindsNameOutsideStatements)(barrier, name, namespace))) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
const match = found(frame, index);
|
|
173
|
+
if (match !== undefined) {
|
|
174
|
+
return match;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
};
|
|
158
179
|
return {
|
|
159
180
|
typeAlias(name) {
|
|
160
|
-
|
|
161
|
-
for (const statement of
|
|
181
|
+
return search(name, 'type', (frame, index) => {
|
|
182
|
+
for (const statement of frame.statements) {
|
|
162
183
|
const declaration = aliasDeclarationNamed(statement, name);
|
|
163
184
|
if (declaration) {
|
|
164
185
|
return {
|
|
165
186
|
typeNode: declaration.typeAnnotation,
|
|
166
|
-
resolve: aliasResolverFrom(
|
|
187
|
+
resolve: aliasResolverFrom(frames, index, index + 1),
|
|
167
188
|
};
|
|
168
189
|
}
|
|
169
190
|
}
|
|
170
|
-
|
|
171
|
-
|
|
191
|
+
return undefined;
|
|
192
|
+
});
|
|
172
193
|
},
|
|
173
194
|
constArrayKeys(name) {
|
|
174
|
-
|
|
175
|
-
for (const statement of
|
|
195
|
+
return search(name, 'value', (frame) => {
|
|
196
|
+
for (const statement of frame.statements) {
|
|
176
197
|
const members = constArrayMembersNamed(statement, name);
|
|
177
198
|
if (members)
|
|
178
199
|
return members;
|
|
179
200
|
}
|
|
180
|
-
|
|
181
|
-
|
|
201
|
+
return undefined;
|
|
202
|
+
});
|
|
182
203
|
},
|
|
183
204
|
};
|
|
184
205
|
}
|
|
185
206
|
function aliasResolverAt(from) {
|
|
186
|
-
return aliasResolverFrom((0, lexicalScope_1.
|
|
207
|
+
return aliasResolverFrom((0, lexicalScope_1.enclosingScopeFrames)(from));
|
|
187
208
|
}
|
|
188
209
|
/**
|
|
189
210
|
* The property names a `Pick<T, K>` keep-list names, or `null` when the list is
|
|
@@ -303,7 +303,7 @@ exports.requireHooksDefaultParams = (0, createRule_1.createRule)({
|
|
|
303
303
|
* resolved fine (#1781).
|
|
304
304
|
*/
|
|
305
305
|
function resolveTypeDeclaration(from, name) {
|
|
306
|
-
return (0, lexicalScope_1.
|
|
306
|
+
return (0, lexicalScope_1.resolveNameInEnclosingScopes)(from, name, 'type', (statements) => {
|
|
307
307
|
for (const statement of statements) {
|
|
308
308
|
const found = typeDeclarationNamed(statement, name);
|
|
309
309
|
if (found) {
|
|
@@ -1842,7 +1842,7 @@ exports.requirePropsComposition = (0, createRule_1.createRule)({
|
|
|
1842
1842
|
* would instead hand one scope's verdict to another.
|
|
1843
1843
|
*/
|
|
1844
1844
|
function findPropsTypeAliasByName(scope, typeName) {
|
|
1845
|
-
return ((0, lexicalScope_1.
|
|
1845
|
+
return ((0, lexicalScope_1.resolveNameInEnclosingScopes)(scope, typeName, 'type', (statements) => {
|
|
1846
1846
|
for (const stmt of statements) {
|
|
1847
1847
|
const declaration = (0, lexicalScope_1.declarationOf)(stmt);
|
|
1848
1848
|
if (declaration.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration &&
|
|
@@ -82,3 +82,64 @@ export declare function resolveInEnclosingScopes<T>(from: TSESTree.Node, matchIn
|
|
|
82
82
|
* the scope that referenced the alias.
|
|
83
83
|
*/
|
|
84
84
|
export declare function enclosingStatementLists(from: TSESTree.Node): (readonly TSESTree.Node[])[];
|
|
85
|
+
/**
|
|
86
|
+
* One statement container on the chain, with the binders guarding entry to it.
|
|
87
|
+
*
|
|
88
|
+
* {@link enclosingStatementLists} loses the nodes BETWEEN two containers, and
|
|
89
|
+
* those are exactly the ones that bind a name without holding a statement — a
|
|
90
|
+
* function's parameters and type parameters sit on the function, not on the
|
|
91
|
+
* block that is its body. A caller that materialises the chain rather than
|
|
92
|
+
* walking it once therefore cannot ask the question {@link
|
|
93
|
+
* resolveNameInEnclosingScopes} asks, unless the frames carry them.
|
|
94
|
+
*
|
|
95
|
+
* `barriers` holds the nodes crossed to reach this frame from the one inside
|
|
96
|
+
* it, so a binder among them shadows the name for this frame and every frame
|
|
97
|
+
* outside it.
|
|
98
|
+
*/
|
|
99
|
+
export type ScopeFrame = {
|
|
100
|
+
statements: readonly TSESTree.Node[];
|
|
101
|
+
barriers: readonly TSESTree.Node[];
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The statement containers enclosing a node, innermost outward, each carrying
|
|
105
|
+
* the binders crossed to reach it.
|
|
106
|
+
*/
|
|
107
|
+
export declare function enclosingScopeFrames(from: TSESTree.Node): ScopeFrame[];
|
|
108
|
+
/**
|
|
109
|
+
* Which of TypeScript's two declaration spaces a name is being resolved in.
|
|
110
|
+
*
|
|
111
|
+
* The distinction is load-bearing rather than pedantic: `function f<Props>()`
|
|
112
|
+
* shadows a `type Props` for every type position inside `f` while leaving a
|
|
113
|
+
* `const Props` untouched, and a parameter `(batch) => …` does the reverse.
|
|
114
|
+
* Testing both spaces at once would decline on a collision that TypeScript does
|
|
115
|
+
* not consider one, turning a resolution hole into an over-decline.
|
|
116
|
+
*/
|
|
117
|
+
export type BindingNamespace = 'type' | 'value';
|
|
118
|
+
/**
|
|
119
|
+
* Whether a container binds `name` somewhere OTHER than its statement list.
|
|
120
|
+
*
|
|
121
|
+
* {@link statementsOf} recognises five containers, so every binder that is not a
|
|
122
|
+
* statement — a type parameter, a function parameter, a `catch` parameter, a
|
|
123
|
+
* `for` head, a function or class expression's own name — introduces a scope the
|
|
124
|
+
* walk cannot see. That makes the walk step straight past a shadow and let an
|
|
125
|
+
* outer declaration answer for a name the reference does not denote, which is
|
|
126
|
+
* precisely the failure move 3 of this module's contract forbids: an unrelated
|
|
127
|
+
* `type ToClose = () => void` answered for the type parameter of
|
|
128
|
+
* `function useThing<ToClose>(…)`, and `no-direct-function-state` reported —
|
|
129
|
+
* and rewrote — code whose state type it had never seen (#2257).
|
|
130
|
+
*
|
|
131
|
+
* A shadow is deliberately not a resolution. The binder proves only that the
|
|
132
|
+
* name is taken here, never what it denotes, so a caller must treat it exactly
|
|
133
|
+
* as {@link BOUND_UNPROVABLE} — stop, and answer nothing.
|
|
134
|
+
*/
|
|
135
|
+
export declare function bindsNameOutsideStatements(container: TSESTree.Node, name: string, namespace: BindingNamespace): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* {@link resolveInEnclosingScopes}, stopped by the binders it cannot see.
|
|
138
|
+
*
|
|
139
|
+
* The name and the space it is resolved in have to be stated by the caller
|
|
140
|
+
* because the shadow test needs them and `matchIn` only closes over them. That
|
|
141
|
+
* is the point of the separate entry rather than an optional argument: a caller
|
|
142
|
+
* resolving a name gets the shadow test by writing the name down, instead of by
|
|
143
|
+
* remembering that a hazard exists.
|
|
144
|
+
*/
|
|
145
|
+
export declare function resolveNameInEnclosingScopes<T>(from: TSESTree.Node, name: string, namespace: BindingNamespace, matchIn: (statements: readonly TSESTree.Node[], container: TSESTree.Node) => ScopeMatch<T>, fallback?: () => T | undefined): T | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.enclosingStatementLists = exports.resolveInEnclosingScopes = exports.BOUND_UNPROVABLE = exports.declarationOf = exports.statementsOf = void 0;
|
|
3
|
+
exports.resolveNameInEnclosingScopes = exports.bindsNameOutsideStatements = exports.enclosingScopeFrames = exports.enclosingStatementLists = exports.resolveInEnclosingScopes = exports.BOUND_UNPROVABLE = exports.declarationOf = exports.statementsOf = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
/**
|
|
6
6
|
* Same-file lexical resolution: what a name denotes at the point it is written.
|
|
@@ -128,4 +128,154 @@ function enclosingStatementLists(from) {
|
|
|
128
128
|
return lists;
|
|
129
129
|
}
|
|
130
130
|
exports.enclosingStatementLists = enclosingStatementLists;
|
|
131
|
+
/**
|
|
132
|
+
* The statement containers enclosing a node, innermost outward, each carrying
|
|
133
|
+
* the binders crossed to reach it.
|
|
134
|
+
*/
|
|
135
|
+
function enclosingScopeFrames(from) {
|
|
136
|
+
const frames = [];
|
|
137
|
+
let barriers = [];
|
|
138
|
+
let current = from;
|
|
139
|
+
while (current) {
|
|
140
|
+
const statements = statementsOf(current);
|
|
141
|
+
if (statements) {
|
|
142
|
+
frames.push({ statements, barriers });
|
|
143
|
+
barriers = [];
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
barriers.push(current);
|
|
147
|
+
}
|
|
148
|
+
current = current.parent;
|
|
149
|
+
}
|
|
150
|
+
return frames;
|
|
151
|
+
}
|
|
152
|
+
exports.enclosingScopeFrames = enclosingScopeFrames;
|
|
153
|
+
/**
|
|
154
|
+
* Whether a pattern binds `name`, looking through destructuring and defaults.
|
|
155
|
+
*/
|
|
156
|
+
function patternBindsName(node, name) {
|
|
157
|
+
if (!node) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
switch (node.type) {
|
|
161
|
+
case utils_1.AST_NODE_TYPES.Identifier:
|
|
162
|
+
return node.name === name;
|
|
163
|
+
case utils_1.AST_NODE_TYPES.ArrayPattern:
|
|
164
|
+
return node.elements.some((element) => patternBindsName(element, name));
|
|
165
|
+
case utils_1.AST_NODE_TYPES.ObjectPattern:
|
|
166
|
+
return node.properties.some((property) => patternBindsName(property.type === utils_1.AST_NODE_TYPES.RestElement
|
|
167
|
+
? property.argument
|
|
168
|
+
: property.value, name));
|
|
169
|
+
case utils_1.AST_NODE_TYPES.AssignmentPattern:
|
|
170
|
+
return patternBindsName(node.left, name);
|
|
171
|
+
case utils_1.AST_NODE_TYPES.RestElement:
|
|
172
|
+
return patternBindsName(node.argument, name);
|
|
173
|
+
default:
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Whether a `for` head declares `name`, for any of the three loop spellings.
|
|
179
|
+
*/
|
|
180
|
+
function forHeadBindsName(node, name) {
|
|
181
|
+
const head = node.type === utils_1.AST_NODE_TYPES.ForStatement
|
|
182
|
+
? node.init
|
|
183
|
+
: node.type === utils_1.AST_NODE_TYPES.ForOfStatement ||
|
|
184
|
+
node.type === utils_1.AST_NODE_TYPES.ForInStatement
|
|
185
|
+
? node.left
|
|
186
|
+
: undefined;
|
|
187
|
+
return head?.type === utils_1.AST_NODE_TYPES.VariableDeclaration
|
|
188
|
+
? head.declarations.some((declarator) => patternBindsName(declarator.id, name))
|
|
189
|
+
: false;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Whether a container binds `name` somewhere OTHER than its statement list.
|
|
193
|
+
*
|
|
194
|
+
* {@link statementsOf} recognises five containers, so every binder that is not a
|
|
195
|
+
* statement — a type parameter, a function parameter, a `catch` parameter, a
|
|
196
|
+
* `for` head, a function or class expression's own name — introduces a scope the
|
|
197
|
+
* walk cannot see. That makes the walk step straight past a shadow and let an
|
|
198
|
+
* outer declaration answer for a name the reference does not denote, which is
|
|
199
|
+
* precisely the failure move 3 of this module's contract forbids: an unrelated
|
|
200
|
+
* `type ToClose = () => void` answered for the type parameter of
|
|
201
|
+
* `function useThing<ToClose>(…)`, and `no-direct-function-state` reported —
|
|
202
|
+
* and rewrote — code whose state type it had never seen (#2257).
|
|
203
|
+
*
|
|
204
|
+
* A shadow is deliberately not a resolution. The binder proves only that the
|
|
205
|
+
* name is taken here, never what it denotes, so a caller must treat it exactly
|
|
206
|
+
* as {@link BOUND_UNPROVABLE} — stop, and answer nothing.
|
|
207
|
+
*/
|
|
208
|
+
function bindsNameOutsideStatements(container, name, namespace) {
|
|
209
|
+
const node = container;
|
|
210
|
+
if (namespace === 'type') {
|
|
211
|
+
// `typeParameters` names two unrelated things: the DECLARATION that binds
|
|
212
|
+
// `<T>` on a function or class, and the INSTANTIATION that supplies `<Foo>`
|
|
213
|
+
// at a call, `new`, or type reference. Only the first binds anything, and
|
|
214
|
+
// the second holds type nodes carrying no `name` at all, so reading one as
|
|
215
|
+
// the other throws on any ancestor that passes type arguments.
|
|
216
|
+
const declared = node.typeParameters?.type === utils_1.AST_NODE_TYPES.TSTypeParameterDeclaration
|
|
217
|
+
? node.typeParameters.params
|
|
218
|
+
: undefined;
|
|
219
|
+
return (declared?.some((parameter) => parameter.name.name === name) === true ||
|
|
220
|
+
(container.type === utils_1.AST_NODE_TYPES.ClassExpression &&
|
|
221
|
+
node.id?.name === name));
|
|
222
|
+
}
|
|
223
|
+
if ((container.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
|
|
224
|
+
container.type === utils_1.AST_NODE_TYPES.ClassExpression) &&
|
|
225
|
+
node.id?.name === name) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
if (container.type === utils_1.AST_NODE_TYPES.CatchClause &&
|
|
229
|
+
patternBindsName(container.param, name)) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
if (forHeadBindsName(container, name)) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
// `TSTypeParameterDeclaration` also carries `params`, of a node kind no
|
|
236
|
+
// pattern arm matches, so a type parameter cannot leak into this space.
|
|
237
|
+
return (isFunctionLike(container) &&
|
|
238
|
+
node.params?.some((parameter) => patternBindsName(parameter, name)) === true);
|
|
239
|
+
}
|
|
240
|
+
exports.bindsNameOutsideStatements = bindsNameOutsideStatements;
|
|
241
|
+
function isFunctionLike(node) {
|
|
242
|
+
return (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
243
|
+
node.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
|
|
244
|
+
node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
245
|
+
node.type === utils_1.AST_NODE_TYPES.TSDeclareFunction ||
|
|
246
|
+
node.type === utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* {@link resolveInEnclosingScopes}, stopped by the binders it cannot see.
|
|
250
|
+
*
|
|
251
|
+
* The name and the space it is resolved in have to be stated by the caller
|
|
252
|
+
* because the shadow test needs them and `matchIn` only closes over them. That
|
|
253
|
+
* is the point of the separate entry rather than an optional argument: a caller
|
|
254
|
+
* resolving a name gets the shadow test by writing the name down, instead of by
|
|
255
|
+
* remembering that a hazard exists.
|
|
256
|
+
*/
|
|
257
|
+
function resolveNameInEnclosingScopes(from, name, namespace, matchIn, fallback) {
|
|
258
|
+
let current = from;
|
|
259
|
+
while (current) {
|
|
260
|
+
const statements = statementsOf(current);
|
|
261
|
+
if (statements) {
|
|
262
|
+
const match = matchIn(statements, current);
|
|
263
|
+
if (match === exports.BOUND_UNPROVABLE) {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
if (match !== undefined) {
|
|
267
|
+
return match;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Tested after the statement list, so a container that both declares the
|
|
271
|
+
// name and binds it — `function f<T>() { type T = …; }` — resolves to the
|
|
272
|
+
// declaration the reference actually denotes.
|
|
273
|
+
if (bindsNameOutsideStatements(current, name, namespace)) {
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
current = current.parent;
|
|
277
|
+
}
|
|
278
|
+
return fallback?.();
|
|
279
|
+
}
|
|
280
|
+
exports.resolveNameInEnclosingScopes = resolveNameInEnclosingScopes;
|
|
131
281
|
//# sourceMappingURL=lexicalScope.js.map
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,90 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.200",
|
|
4
|
+
"date": "2026-09-01T14:50:44.328Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "enforce-firestore-doc-ref-generic",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
2258
|
|
11
|
+
],
|
|
12
|
+
"summary": "stop type resolution at a shadowing type parameter (closes #2258)"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "enforce-firestore-set-merge",
|
|
16
|
+
"changeType": "fix",
|
|
17
|
+
"issues": [
|
|
18
|
+
2266
|
|
19
|
+
],
|
|
20
|
+
"summary": "stop class resolution at a shadowing parameter (closes #2266)"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "no-direct-function-state",
|
|
24
|
+
"changeType": "fix",
|
|
25
|
+
"issues": [
|
|
26
|
+
2257
|
|
27
|
+
],
|
|
28
|
+
"summary": "stop alias resolution at a shadowing type parameter (closes #2257)"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "no-explicit-return-type",
|
|
32
|
+
"changeType": "fix",
|
|
33
|
+
"issues": [
|
|
34
|
+
2265
|
|
35
|
+
],
|
|
36
|
+
"summary": "stop function resolution at a shadowing parameter (closes #2265)"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "no-firestore-object-arrays",
|
|
40
|
+
"changeType": "fix",
|
|
41
|
+
"issues": [
|
|
42
|
+
2261
|
|
43
|
+
],
|
|
44
|
+
"summary": "stop resolution at a shadowing type parameter (closes #2261)"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "prefer-batch-operations",
|
|
48
|
+
"changeType": "fix",
|
|
49
|
+
"issues": [
|
|
50
|
+
2264
|
|
51
|
+
],
|
|
52
|
+
"summary": "stop setter resolution at a shadowing parameter (closes #2264)"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "prefer-spread-over-reassembly",
|
|
56
|
+
"changeType": "fix",
|
|
57
|
+
"issues": [
|
|
58
|
+
2259
|
|
59
|
+
],
|
|
60
|
+
"summary": "stop resolution at a shadowing type parameter (closes #2259)"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "prevent-children-clobber",
|
|
64
|
+
"changeType": "fix",
|
|
65
|
+
"issues": [
|
|
66
|
+
2263
|
|
67
|
+
],
|
|
68
|
+
"summary": "stop alias resolution at a shadowing parameter (closes #2263)"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "require-hooks-default-params",
|
|
72
|
+
"changeType": "fix",
|
|
73
|
+
"issues": [
|
|
74
|
+
2262
|
|
75
|
+
],
|
|
76
|
+
"summary": "stop type resolution at a shadowing type parameter (closes #2262)"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "require-props-composition",
|
|
80
|
+
"changeType": "fix",
|
|
81
|
+
"issues": [
|
|
82
|
+
2260
|
|
83
|
+
],
|
|
84
|
+
"summary": "stop props resolution at a shadowing type parameter (closes #2260)"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
},
|
|
2
88
|
{
|
|
3
89
|
"version": "1.20.199",
|
|
4
90
|
"date": "2026-09-01T09:29:27.682Z",
|