@@ -27,10 +27,10 @@ import {
2727 withLatestFrom ,
2828} from 'rxjs/operators'
2929import { Key } from 'ts-key-enum'
30- import { Position } from 'vscode-languageserver-types'
31- import { asError , ErrorLike } from './errors'
30+ import { Position , Range } from 'vscode-languageserver-types'
31+ import { asError , ErrorLike , isErrorLike } from './errors'
3232import { isDefined } from './helpers'
33- import { isEmptyHover , overlayUIHasContent , scrollIntoCenterIfNeeded } from './helpers'
33+ import { overlayUIHasContent , scrollIntoCenterIfNeeded } from './helpers'
3434import { HoverOverlayProps , isJumpURL } from './HoverOverlay'
3535import { calculateOverlayPosition } from './overlay_position'
3636import { DiffPart , PositionEvent , SupportedMouseEvent } from './positions'
@@ -193,6 +193,11 @@ export interface HoverState {
193193 */
194194 hoverOverlayProps ?: Pick < HoverOverlayProps , Exclude < keyof HoverOverlayProps , 'linkComponent' > >
195195
196+ /**
197+ * The highlighted range, which is the range in the hover result or else the range of the hovered token.
198+ */
199+ highlightedRange ?: Range
200+
196201 /**
197202 * The currently selected position, if any.
198203 * Can be a single line number or a line range.
@@ -223,6 +228,11 @@ interface InternalHoverifierState<C extends object> {
223228 /** The currently hovered token */
224229 hoveredToken ?: HoveredToken & C
225230
231+ /**
232+ * The highlighted range, which is the range in the hoverOrError data or else the range of the hovered token.
233+ */
234+ highlightedRange ?: Range
235+
226236 mouseIsMoving : boolean
227237
228238 /**
@@ -244,6 +254,7 @@ const shouldRenderOverlay = (state: InternalHoverifierState<{}>): boolean =>
244254 */
245255const internalToExternalState = ( internalState : InternalHoverifierState < { } > ) : HoverState => ( {
246256 selectedPosition : internalState . selectedPosition ,
257+ highlightedRange : shouldRenderOverlay ( internalState ) ? internalState . highlightedRange : undefined ,
247258 hoverOverlayProps : shouldRenderOverlay ( internalState )
248259 ? {
249260 overlayPosition : internalState . hoverOverlayPosition ,
@@ -537,7 +548,7 @@ export function createHoverifier<C extends object>({
537548 target : HTMLElement
538549 adjustPosition ?: PositionAdjuster < C >
539550 codeView : HTMLElement
540- hoverOrError ?: typeof LOADING | HoverMerged | Error | null
551+ hoverOrError ?: typeof LOADING | HoverMerged | ErrorLike | null
541552 position ?: HoveredToken & C
542553 part ?: DiffPart
543554 } >
@@ -558,7 +569,7 @@ export function createHoverifier<C extends object>({
558569 ? hoverMergedOrNull
559570 : new Error ( `Invalid hover response: ${ JSON . stringify ( hoverMergedOrNull ) } ` )
560571 ) ,
561- catchError ( error => [ asError ( error ) ] ) ,
572+ catchError ( ( error ) : [ ErrorLike ] => [ asError ( error ) ] ) ,
562573 share ( )
563574 )
564575 // 1. Reset the hover content, so no old hover content is displayed at the new position while fetching
@@ -618,20 +629,35 @@ export function createHoverifier<C extends object>({
618629 } )
619630 )
620631 . subscribe ( ( { hoverOrError, position, codeView, dom, part } ) => {
632+ // Update the highlighted token if the hover result is successful. If the hover result specifies a
633+ // range, use that; otherwise use the hover position (which will be expanded into a full token in
634+ // getTokenAtPosition).
635+ let highlightedRange : Range | undefined
636+ if ( hoverOrError && ! isErrorLike ( hoverOrError ) && hoverOrError !== LOADING ) {
637+ if ( hoverOrError . range ) {
638+ highlightedRange = hoverOrError . range
639+ } else if ( position ) {
640+ highlightedRange = { start : position , end : position }
641+ }
642+ }
643+
621644 container . update ( {
622645 hoverOrError,
646+ highlightedRange,
623647 // Reset the hover position, it's gonna be repositioned after the hover was rendered
624648 hoverOverlayPosition : undefined ,
625649 } )
650+
651+ // Ensure the previously highlighted range is not highlighted and the new highlightedRange (if any)
652+ // is highlighted.
626653 const currentHighlighted = codeView . querySelector ( '.selection-highlight' )
627654 if ( currentHighlighted ) {
628655 currentHighlighted . classList . remove ( 'selection-highlight' )
629656 }
630- if ( ! position || ! hoverOrError || ( HoverMerged . is ( hoverOrError ) && isEmptyHover ( hoverOrError ) ) ) {
657+ if ( ! highlightedRange ) {
631658 return
632659 }
633-
634- const token = getTokenAtPosition ( codeView , position , dom , part )
660+ const token = getTokenAtPosition ( codeView , highlightedRange . start , dom , part )
635661 if ( ! token ) {
636662 return
637663 }
0 commit comments