@@ -207,29 +207,30 @@ export function isGlobalReference(node: ESTree.Node): boolean {
207207 }
208208
209209 const { name } = node ;
210+ // TODO: Is this check required? Isn't an `Identifier`'s `name` property always a string?
210211 if ( typeof name !== 'string' ) {
211212 return false ;
212213 }
213214
214215 if ( tsScopeManager === null ) initTsScopeManager ( ) ;
215- const globalScope = tsScopeManager . scopes [ 0 ] ;
216- if ( ! globalScope ) return false ;
216+
217+ const { scopes } = tsScopeManager ;
218+ if ( scopes . length === 0 ) return false ;
219+ const globalScope = scopes [ 0 ] ;
217220
218221 // If the identifier is a reference to a global variable, the global scope should have a variable with the name
219222 const variable = globalScope . set . get ( name ) ;
220223
221224 // Global variables are not defined by any node, so they should have no definitions
222- if ( ! variable || variable . defs . length > 0 ) {
225+ if ( variable === undefined || variable . defs . length > 0 ) {
223226 return false ;
224227 }
225228
226229 // If there is a variable by the same name exists in the global scope,
227230 // we need to check our node is one of its references
228231 const { references } = variable ;
229-
230- for ( let i = 0 ; i < references . length ; i ++ ) {
231- const reference = references [ i ] ;
232- if ( reference . identifier === node ) {
232+ for ( let i = 0 , len = references . length ; i < len ; i ++ ) {
233+ if ( references [ i ] . identifier === node ) {
233234 return true ;
234235 }
235236 }
@@ -266,20 +267,20 @@ export function getScope(node: ESTree.Node): Scope {
266267 const inner = node . type !== 'Program' ;
267268
268269 // Traverse up the AST to find a `Node` whose scope can be acquired.
269- for ( let current : any = node ; current ; current = current . parent ) {
270- const scope = tsScopeManager . acquire ( current , inner ) ;
271-
272- if ( scope ) {
273- if ( scope . type === 'function-expression-name' ) {
274- // @ts -expect-error // TODO: Our types don't quite align yet
275- return scope . childScopes [ 0 ] ;
276- }
277-
278- // @ts -expect-error // TODO: Our types don't quite align yet
279- return scope ;
270+ do {
271+ // @ts -expect-error // TODO: Our types don't quite align yet
272+ const scope = tsScopeManager . acquire ( node , inner ) as Scope ;
273+ if ( scope !== null ) {
274+ return scope . type === 'function-expression-name' ? scope . childScopes [ 0 ] : scope ;
280275 }
281- }
282276
277+ // TODO: AST nodes' `parent` property should not be optional.
278+ // TODO: `TSParameterProperty` type should have a `parent` property.
279+ // @ts -expect-error
280+ node = node . parent ;
281+ } while ( node !== null ) ;
282+
283+ // TODO: Is it possible to get here? Doesn't `Program` always have a scope?
283284 // @ts -expect-error // TODO: Our types don't quite align yet
284285 return tsScopeManager . scopes [ 0 ] ;
285286}
0 commit comments