0
# Scope Management
1
2
The ScopeManager class is the central manager for all scopes in analyzed code. It maintains scope hierarchies, variable mappings, and provides scope navigation and querying capabilities.
3
4
## Capabilities
5
6
### ScopeManager Class
7
8
The main class that manages all scopes created during AST analysis.
9
10
```typescript { .api }
11
/**
12
* Central manager for all scopes in analyzed code
13
* @see https://eslint.org/docs/latest/developer-guide/scope-manager-interface#scopemanager-interface
14
*/
15
class ScopeManager {
16
/** Current scope being processed during analysis */
17
currentScope: Scope | null;
18
19
/** WeakMap associating AST nodes with the variables they declare */
20
readonly declaredVariables: WeakMap<TSESTree.Node, Variable[]>;
21
22
/** The root scope (global scope) */
23
globalScope: GlobalScope | null;
24
25
/** WeakMap associating AST nodes with their scopes */
26
readonly nodeToScope: WeakMap<TSESTree.Node, Scope[]>;
27
28
/** All scopes in the analysis */
29
readonly scopes: Scope[];
30
31
/** All variables across all scopes */
32
get variables(): Variable[];
33
}
34
```
35
36
### Scope Environment Queries
37
38
Methods to determine the analysis environment and configuration.
39
40
```typescript { .api }
41
/**
42
* Check if ES6 features are enabled
43
* @returns Always true in TypeScript scope manager
44
*/
45
isES6(): boolean;
46
47
/**
48
* Check if global return is enabled
49
* @returns True if globalReturn option was set during analysis
50
*/
51
isGlobalReturn(): boolean;
52
53
/**
54
* Check if implied strict mode is enabled
55
* @returns True if impliedStrict option was set during analysis
56
*/
57
isImpliedStrict(): boolean;
58
59
/**
60
* Check if source is a module
61
* @returns True if sourceType was set to 'module' during analysis
62
*/
63
isModule(): boolean;
64
65
/**
66
* Check if strict mode is supported
67
* @returns Always true in TypeScript scope manager
68
*/
69
isStrictModeSupported(): boolean;
70
```
71
72
### Variable Discovery
73
74
Methods to find variables declared by specific AST nodes.
75
76
```typescript { .api }
77
/**
78
* Get the variables that a given AST node defines. The gotten variables'
79
* def[].node/def[].parent property is the node.
80
* If the node does not define any variable, this returns an empty array.
81
* @param node - An AST node to get their variables
82
* @returns Array of variables declared by the node
83
*/
84
getDeclaredVariables(node: TSESTree.Node): Variable[];
85
```
86
87
### Scope Navigation
88
89
Methods to navigate and query the scope hierarchy.
90
91
```typescript { .api }
92
/**
93
* Get the scope of a given AST node. The gotten scope's block property is the node.
94
* This method never returns function-expression-name scope. If the node does not
95
* have their scope, this returns null.
96
*
97
* @param node - An AST node to get their scope
98
* @param inner - If the node has multiple scopes, this returns the outermost scope normally.
99
* If inner is true then this returns the innermost scope.
100
* @returns The scope associated with the node, or null if none exists
101
*/
102
acquire(node: TSESTree.Node, inner?: boolean): Scope | null;
103
```
104
105
**Usage Examples:**
106
107
```typescript
108
import { analyze } from "@typescript-eslint/scope-manager";
109
import { parse } from "@typescript-eslint/parser";
110
111
const code = `
112
function outer(x: number) {
113
const y = x * 2;
114
115
function inner(z: number) {
116
return y + z;
117
}
118
119
return inner;
120
}
121
`;
122
123
const ast = parse(code);
124
const scopeManager = analyze(ast, { sourceType: 'module' });
125
126
// Check environment
127
console.log(scopeManager.isModule()); // true
128
console.log(scopeManager.isES6()); // true
129
130
// Get all scopes
131
console.log(`Total scopes: ${scopeManager.scopes.length}`);
132
scopeManager.scopes.forEach((scope, index) => {
133
console.log(`Scope ${index}: ${scope.type}`);
134
});
135
136
// Get variables in global scope
137
if (scopeManager.globalScope) {
138
console.log('Global variables:',
139
scopeManager.globalScope.variables.map(v => v.name)
140
);
141
}
142
143
// Find scope for a specific node
144
const functionNodes = []; // collect function nodes during AST traversal
145
functionNodes.forEach(node => {
146
const scope = scopeManager.acquire(node);
147
if (scope) {
148
console.log(`Function scope type: ${scope.type}`);
149
console.log(`Variables in scope: ${scope.variables.map(v => v.name)}`);
150
}
151
});
152
153
// Get declared variables for each node
154
const declarationNodes = []; // collect declaration nodes during AST traversal
155
declarationNodes.forEach(node => {
156
const variables = scopeManager.getDeclaredVariables(node);
157
variables.forEach(variable => {
158
console.log(`Variable ${variable.name} declared by node type ${node.type}`);
159
});
160
});
161
162
// Get all variables across all scopes
163
const allVariables = scopeManager.variables;
164
console.log(`Total variables: ${allVariables.length}`);
165
allVariables.forEach(variable => {
166
console.log(`${variable.name} in ${variable.scope.type} scope`);
167
});
168
```
169
170
### Scope Creation Methods
171
172
The ScopeManager provides methods to create different types of scopes during analysis. These are typically used internally but are part of the public API:
173
174
```typescript { .api }
175
// Block scopes
176
nestBlockScope(node: TSESTree.BlockStatement): BlockScope;
177
nestCatchScope(node: TSESTree.CatchClause): CatchScope;
178
nestForScope(node: TSESTree.ForStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement): ForScope;
179
nestSwitchScope(node: TSESTree.SwitchStatement): SwitchScope;
180
nestWithScope(node: TSESTree.WithStatement): WithScope;
181
182
// Function scopes
183
nestFunctionScope(node: TSESTree.Function, isMethodDefinition: boolean): FunctionScope;
184
nestFunctionExpressionNameScope(node: TSESTree.FunctionExpression): FunctionExpressionNameScope;
185
186
// Class and type scopes
187
nestClassScope(node: TSESTree.ClassDeclaration | TSESTree.ClassExpression): ClassScope;
188
nestClassFieldInitializerScope(node: TSESTree.PropertyDefinition): ClassFieldInitializerScope;
189
nestClassStaticBlockScope(node: TSESTree.StaticBlock): ClassStaticBlockScope;
190
nestTypeScope(node: TSESTree.TSTypeAnnotation): TypeScope;
191
nestFunctionTypeScope(node: TSESTree.TSFunctionType): FunctionTypeScope;
192
nestConditionalTypeScope(node: TSESTree.TSConditionalType): ConditionalTypeScope;
193
nestMappedTypeScope(node: TSESTree.TSMappedType): MappedTypeScope;
194
195
// Module and namespace scopes
196
nestModuleScope(node: TSESTree.Program): ModuleScope;
197
nestTSModuleScope(node: TSESTree.TSModuleDeclaration): TSModuleScope;
198
nestTSEnumScope(node: TSESTree.TSEnumDeclaration): TSEnumScope;
199
200
// Global scope
201
nestGlobalScope(node: TSESTree.Program): GlobalScope;
202
```
203
204
### Scope Hierarchy Navigation
205
206
```typescript
207
// Navigate scope hierarchy
208
const currentScope = scopeManager.currentScope;
209
if (currentScope) {
210
console.log(`Current scope: ${currentScope.type}`);
211
212
// Parent scope
213
if (currentScope.upper) {
214
console.log(`Parent scope: ${currentScope.upper.type}`);
215
}
216
217
// Child scopes
218
currentScope.childScopes.forEach((child, index) => {
219
console.log(`Child ${index}: ${child.type}`);
220
});
221
222
// Variables in current scope
223
currentScope.variables.forEach(variable => {
224
console.log(`Variable: ${variable.name}`);
225
console.log(`References: ${variable.references.length}`);
226
});
227
}
228
```