@@ -428,26 +428,26 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN
428
428
}
429
429
430
430
var rightmostValidNode * ast.Node
431
- var rightmostVisitedNode * ast.Node
431
+ rightmostVisitedNodes := make ([] * ast.Node , 0 , 1 ) // Nodes after the last valid node.
432
432
hasChildren := false
433
- test := func (node * ast.Node ) bool {
434
- if node .Flags & ast .NodeFlagsReparsed != 0 ||
435
- node .End () > endPos || getStartOfNode (node , sourceFile , ! excludeJSDoc /*includeJSDoc*/ ) >= position {
436
- return false
437
- }
438
- rightmostVisitedNode = node
439
- if isValidPrecedingNode (node , sourceFile ) {
440
- rightmostValidNode = node
441
- return true
442
- }
443
- return false
433
+ shouldVisitNode := func (node * ast.Node ) bool {
434
+ // Node is synthetic or out of the desired range: don't visit it.
435
+ return ! (node .Flags & ast .NodeFlagsReparsed != 0 ||
436
+ node .End () > endPos || getStartOfNode (node , sourceFile , ! excludeJSDoc /*includeJSDoc*/ ) >= position )
444
437
}
445
438
visitNode := func (node * ast.Node , _ * ast.NodeVisitor ) * ast.Node {
446
439
if node == nil {
447
440
return node
448
441
}
449
442
hasChildren = true
450
- test (node )
443
+ if ! shouldVisitNode (node ) {
444
+ return node
445
+ }
446
+ rightmostVisitedNodes = append (rightmostVisitedNodes , node )
447
+ if isValidPrecedingNode (node , sourceFile ) {
448
+ rightmostValidNode = node
449
+ rightmostVisitedNodes = rightmostVisitedNodes [:0 ]
450
+ }
451
451
return node
452
452
}
453
453
visitNodes := func (nodeList * ast.NodeList , _ * ast.NodeVisitor ) * ast.NodeList {
@@ -462,11 +462,23 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN
462
462
}
463
463
return comparisonLessThan
464
464
})
465
+ validIndex := - 1
465
466
for i := index - 1 ; i >= 0 ; i -- {
466
- if test (nodeList .Nodes [i ]) {
467
+ if ! shouldVisitNode (nodeList .Nodes [i ]) {
468
+ continue
469
+ }
470
+ if isValidPrecedingNode (nodeList .Nodes [i ], sourceFile ) {
471
+ validIndex = i
472
+ rightmostValidNode = nodeList .Nodes [i ]
467
473
break
468
474
}
469
475
}
476
+ for i := validIndex + 1 ; i < index ; i ++ {
477
+ if ! shouldVisitNode (nodeList .Nodes [i ]) {
478
+ continue
479
+ }
480
+ rightmostVisitedNodes = append (rightmostVisitedNodes , nodeList .Nodes [i ])
481
+ }
470
482
}
471
483
return nodeList
472
484
}
@@ -485,19 +497,37 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN
485
497
486
498
// Three cases:
487
499
// 1. The answer is a token of `rightmostValidNode`.
488
- // 2. The answer is one of the unvisited tokens that occur after the last visited node.
500
+ // 2. The answer is one of the unvisited tokens that occur after the rightmost valid node.
489
501
// 3. The current node is a childless, token-less node. The answer is the current node.
490
502
491
- // Case 2: Look at trailing tokens.
503
+ // Case 2: Look at unvisited trailing tokens that occur in between the rightmost visited nodes .
492
504
if ! ast .IsJSDocCommentContainingNode (n ) { // JSDoc nodes don't include trivia tokens as children.
493
505
var startPos int
494
- if rightmostVisitedNode != nil {
495
- startPos = rightmostVisitedNode .End ()
506
+ if rightmostValidNode != nil {
507
+ startPos = rightmostValidNode .End ()
496
508
} else {
497
509
startPos = n .Pos ()
498
510
}
499
511
scanner := scanner .GetScannerForSourceFile (sourceFile , startPos )
500
512
var tokens []* ast.Node
513
+ for _ , visitedNode := range rightmostVisitedNodes {
514
+ // Trailing tokens that occur before this node.
515
+ for startPos < min (visitedNode .Pos (), position ) {
516
+ tokenStart := scanner .TokenStart ()
517
+ if tokenStart >= position {
518
+ break
519
+ }
520
+ token := scanner .Token ()
521
+ tokenFullStart := scanner .TokenFullStart ()
522
+ tokenEnd := scanner .TokenEnd ()
523
+ startPos = tokenEnd
524
+ tokens = append (tokens , sourceFile .GetOrCreateToken (token , tokenFullStart , tokenEnd , n ))
525
+ scanner .Scan ()
526
+ }
527
+ startPos = visitedNode .End ()
528
+ scanner .ResetPos (startPos )
529
+ }
530
+ // Trailing tokens after last visited node.
501
531
for startPos < min (endPos , position ) {
502
532
tokenStart := scanner .TokenStart ()
503
533
if tokenStart >= position {
@@ -510,6 +540,7 @@ func findRightmostValidToken(endPos int, sourceFile *ast.SourceFile, containingN
510
540
tokens = append (tokens , sourceFile .GetOrCreateToken (token , tokenFullStart , tokenEnd , n ))
511
541
scanner .Scan ()
512
542
}
543
+
513
544
lastToken := len (tokens ) - 1
514
545
// Find preceding valid token.
515
546
for i := lastToken ; i >= 0 ; i -- {
0 commit comments