@@ -360,7 +360,7 @@ namespace ts {
360
360
return find ( startNode || sourceFile ) ;
361
361
362
362
function findRightmostToken ( n : Node ) : Node {
363
- if ( isToken ( n ) ) {
363
+ if ( isToken ( n ) || n . kind === SyntaxKind . JsxText ) {
364
364
return n ;
365
365
}
366
366
@@ -371,24 +371,35 @@ namespace ts {
371
371
}
372
372
373
373
function find ( n : Node ) : Node {
374
- if ( isToken ( n ) ) {
374
+ if ( isToken ( n ) || n . kind === SyntaxKind . JsxText ) {
375
375
return n ;
376
376
}
377
377
378
- let children = n . getChildren ( ) ;
378
+ const children = n . getChildren ( ) ;
379
379
for ( let i = 0 , len = children . length ; i < len ; i ++ ) {
380
380
let child = children [ i ] ;
381
- if ( nodeHasTokens ( child ) ) {
382
- if ( position <= child . end ) {
383
- if ( child . getStart ( sourceFile ) >= position ) {
384
- // actual start of the node is past the position - previous token should be at the end of previous child
385
- let candidate = findRightmostChildNodeWithTokens ( children , /*exclusiveStartPosition*/ i ) ;
386
- return candidate && findRightmostToken ( candidate )
387
- }
388
- else {
389
- // candidate should be in this node
390
- return find ( child ) ;
391
- }
381
+ // condition 'position < child.end' checks if child node end after the position
382
+ // in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc'
383
+ // aaaa___bbbb___$__ccc
384
+ // after we found child node with end after the position we check if start of the node is after the position.
385
+ // if yes - then position is in the trivia and we need to look into the previous child to find the token in question.
386
+ // if no - position is in the node itself so we should recurse in it.
387
+ // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia).
388
+ // if this is the case - then we should assume that token in question is located in previous child.
389
+ if ( position < child . end && ( nodeHasTokens ( child ) || child . kind === SyntaxKind . JsxText ) ) {
390
+ const start = child . getStart ( sourceFile ) ;
391
+ const lookInPreviousChild =
392
+ ( start >= position ) || // cursor in the leading trivia
393
+ ( child . kind === SyntaxKind . JsxText && start === child . end ) ; // whitespace only JsxText
394
+
395
+ if ( lookInPreviousChild ) {
396
+ // actual start of the node is past the position - previous token should be at the end of previous child
397
+ let candidate = findRightmostChildNodeWithTokens ( children , /*exclusiveStartPosition*/ i ) ;
398
+ return candidate && findRightmostToken ( candidate )
399
+ }
400
+ else {
401
+ // candidate should be in this node
402
+ return find ( child ) ;
392
403
}
393
404
}
394
405
}
0 commit comments