@@ -360,7 +360,7 @@ namespace ts {
360360 return find ( startNode || sourceFile ) ;
361361
362362 function findRightmostToken ( n : Node ) : Node {
363- if ( isToken ( n ) ) {
363+ if ( isToken ( n ) || n . kind === SyntaxKind . JsxText ) {
364364 return n ;
365365 }
366366
@@ -371,24 +371,35 @@ namespace ts {
371371 }
372372
373373 function find ( n : Node ) : Node {
374- if ( isToken ( n ) ) {
374+ if ( isToken ( n ) || n . kind === SyntaxKind . JsxText ) {
375375 return n ;
376376 }
377377
378- let children = n . getChildren ( ) ;
378+ const children = n . getChildren ( ) ;
379379 for ( let i = 0 , len = children . length ; i < len ; i ++ ) {
380380 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 ) ;
392403 }
393404 }
394405 }
0 commit comments