55import * as Acorn from '../../third_party/acorn/acorn.js' ;
66
77import { ECMA_VERSION } from './AcornTokenizer.js' ;
8- import { DefinitionKind , type ScopeTreeNode } from './FormatterActions.js' ;
8+ import { DefinitionKind , ScopeKind , type ScopeTreeNode } from './FormatterActions.js' ;
99
1010export function parseScopes ( expression : string , sourceType : 'module' | 'script' = 'script' ) : Scope | null {
1111 // Parse the expression and find variables and scopes.
@@ -36,12 +36,14 @@ export class Scope {
3636 readonly parent : Scope | null ;
3737 readonly start : number ;
3838 readonly end : number ;
39+ readonly kind : ScopeKind ;
3940 readonly children : Scope [ ] = [ ] ;
4041
41- constructor ( start : number , end : number , parent : Scope | null ) {
42+ constructor ( start : number , end : number , parent : Scope | null , kind : ScopeKind ) {
4243 this . start = start ;
4344 this . end = end ;
4445 this . parent = parent ;
46+ this . kind = kind ;
4547 if ( parent ) {
4648 parent . children . push ( this ) ;
4749 }
@@ -61,6 +63,7 @@ export class Scope {
6163 start : this . start ,
6264 end : this . end ,
6365 variables,
66+ kind : this . kind ,
6467 children,
6568 } ;
6669 }
@@ -137,7 +140,7 @@ export class ScopeVariableAnalysis {
137140
138141 constructor ( node : Acorn . ESTree . Node ) {
139142 this . #rootNode = node ;
140- this . #rootScope = new Scope ( node . start , node . end , null ) ;
143+ this . #rootScope = new Scope ( node . start , node . end , null , ScopeKind . GLOBAL ) ;
141144 this . #currentScope = this . #rootScope;
142145 }
143146
@@ -169,7 +172,7 @@ export class ScopeVariableAnalysis {
169172 node . elements . forEach ( item => this . #processNode( item ) ) ;
170173 break ;
171174 case 'ArrowFunctionExpression' : {
172- this . #pushScope( node . start , node . end ) ;
175+ this . #pushScope( node . start , node . end , ScopeKind . FUNCTION ) ;
173176 node . params . forEach ( this . #processNodeAsDefinition. bind ( this , DefinitionKind . VAR , false ) ) ;
174177 if ( node . body . type === 'BlockStatement' ) {
175178 // Include the body of the arrow function in the same scope as the arguments.
@@ -188,7 +191,7 @@ export class ScopeVariableAnalysis {
188191 this . #processNode( node . right ) ;
189192 break ;
190193 case 'BlockStatement' :
191- this . #pushScope( node . start , node . end ) ;
194+ this . #pushScope( node . start , node . end , ScopeKind . BLOCK ) ;
192195 node . body . forEach ( this . #processNode. bind ( this ) ) ;
193196 this . #popScope( false ) ;
194197 break ;
@@ -202,7 +205,7 @@ export class ScopeVariableAnalysis {
202205 break ;
203206 }
204207 case 'CatchClause' :
205- this . #pushScope( node . start , node . end ) ;
208+ this . #pushScope( node . start , node . end , ScopeKind . BLOCK ) ;
206209 this . #processNodeAsDefinition( DefinitionKind . LET , false , node . param ) ;
207210 this . #processNode( node . body ) ;
208211 this . #popScope( false ) ;
@@ -234,14 +237,14 @@ export class ScopeVariableAnalysis {
234237 break ;
235238 case 'ForInStatement' :
236239 case 'ForOfStatement' :
237- this . #pushScope( node . start , node . end ) ;
240+ this . #pushScope( node . start , node . end , ScopeKind . BLOCK ) ;
238241 this . #processNode( node . left ) ;
239242 this . #processNode( node . right ) ;
240243 this . #processNode( node . body ) ;
241244 this . #popScope( false ) ;
242245 break ;
243246 case 'ForStatement' :
244- this . #pushScope( node . start , node . end ) ;
247+ this . #pushScope( node . start , node . end , ScopeKind . BLOCK ) ;
245248 this . #processNode( node . init ?? null ) ;
246249 this . #processNode( node . test ?? null ) ;
247250 this . #processNode( node . update ?? null ) ;
@@ -250,7 +253,7 @@ export class ScopeVariableAnalysis {
250253 break ;
251254 case 'FunctionDeclaration' :
252255 this . #processNodeAsDefinition( DefinitionKind . VAR , false , node . id ) ;
253- this . #pushScope( node . id ?. end ?? node . start , node . end ) ;
256+ this . #pushScope( node . id ?. end ?? node . start , node . end , ScopeKind . FUNCTION ) ;
254257 this . #addVariable( 'this' , node . start , DefinitionKind . FIXED ) ;
255258 this . #addVariable( 'arguments' , node . start , DefinitionKind . FIXED ) ;
256259 node . params . forEach ( this . #processNodeAsDefinition. bind ( this , DefinitionKind . LET , false ) ) ;
@@ -259,7 +262,7 @@ export class ScopeVariableAnalysis {
259262 this . #popScope( true ) ;
260263 break ;
261264 case 'FunctionExpression' :
262- this . #pushScope( node . id ?. end ?? node . start , node . end ) ;
265+ this . #pushScope( node . id ?. end ?? node . start , node . end , ScopeKind . FUNCTION ) ;
263266 this . #addVariable( 'this' , node . start , DefinitionKind . FIXED ) ;
264267 this . #addVariable( 'arguments' , node . start , DefinitionKind . FIXED ) ;
265268 node . params . forEach ( this . #processNodeAsDefinition. bind ( this , DefinitionKind . LET , false ) ) ;
@@ -421,8 +424,8 @@ export class ScopeVariableAnalysis {
421424 return this . #allNames;
422425 }
423426
424- #pushScope( start : number , end : number ) : void {
425- this . #currentScope = new Scope ( start , end , this . #currentScope) ;
427+ #pushScope( start : number , end : number , kind : ScopeKind ) : void {
428+ this . #currentScope = new Scope ( start , end , this . #currentScope, kind ) ;
426429 }
427430
428431 #popScope( isFunctionContext : boolean ) : void {
0 commit comments