@@ -63,10 +63,15 @@ export interface ITraverser {
6363 traverse ( node : TSESTree . Node , options : ITraverseOptions ) : void ;
6464}
6565
66+ export interface ITraverseMethods {
67+ break ( ) : void ;
68+ skip ( ) : void ;
69+ }
70+
6671export interface ITraverseOptions {
6772 visitorKeys : Record < string , string [ ] > ;
68- enter ( this : ITraverseOptions & { skip ( ) : void } , node : TSESTree . Node ) : void ;
69- leave ( this : ITraverseOptions & { skip ( ) : void } , node : TSESTree . Node ) : void ;
73+ enter ( this : ITraverseOptions & ITraverseMethods , node : TSESTree . Node ) : void ;
74+ leave ( this : ITraverseOptions & ITraverseMethods , node : TSESTree . Node ) : void ;
7075}
7176
7277interface ILinterInternalSlots {
@@ -244,23 +249,31 @@ function getScopeIdMap(
244249 let low : number = 0 ;
245250 let high : number = positions . length - 1 ;
246251
247- const boundsStack : [ number , number ] [ ] = [ ] ;
252+ const max : number = positions [ high ] ;
253+
254+ const highStack : number [ ] = [ ] ;
248255
249256 traverser . traverse ( sourceCode . ast , {
250257 visitorKeys : sourceCode . visitorKeys ,
251258 enter ( node : TSESTree . Node ) : void {
252- boundsStack . push ( [ low , high ] ) ;
253- if ( node . range [ 0 ] > positions [ high ] || node . range [ 1 ] <= positions [ low ] ) {
254- return this . skip ( ) ;
259+ const startInclusive : number = node . range [ 0 ] ;
260+ if ( startInclusive > max ) {
261+ // Future nodes irrelevant. We can break out of the traversal.
262+ return this . break ( ) ;
255263 }
256264
257- let newLow : number = binarySearch ( positions , node . range [ 0 ] , low , high ) ;
258- let newHigh : number = binarySearch ( positions , node . range [ 1 ] , low , high ) ;
265+ highStack . push ( high ) ;
266+ const endInclusive : number = node . range [ 1 ] - 1 ;
267+
268+ let newLow : number = binarySearch ( positions , startInclusive , low , high ) ;
269+ let newHigh : number = binarySearch ( positions , endInclusive , low , high ) ;
259270
260271 if ( newLow < 0 ) {
272+ // Start point before the current minimum gets excluded
261273 newLow = ~ newLow ;
262274 }
263275 if ( newHigh < 0 ) {
276+ // End point above the current maximum gets excluded
264277 newHigh = ~ newHigh - 1 ;
265278 }
266279
@@ -281,12 +294,11 @@ function getScopeIdMap(
281294 }
282295 }
283296 } ,
284- leave ( ) : void {
297+ leave ( node : TSESTree . Node ) : void {
285298 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
286- const [ oldLow , oldHigh ] = boundsStack . pop ( ) ! ;
287- low = oldLow ;
299+ const oldHigh : number = highStack . pop ( ) ! ;
300+ // Traversal has monotonically increasing positions, so no need to reduce low
288301 high = oldHigh ;
289- // Do nothing
290302 }
291303 } ) ;
292304
0 commit comments