From b9fb4a983f2aeaf2c2d8131cb87b8f584fc9609e Mon Sep 17 00:00:00 2001 From: Yamato Matsuoka Date: Sun, 25 Sep 2022 19:03:00 -0400 Subject: [PATCH] Fix sporadic misplacement of hover tooltips --- packages/jupyterlab-lsp/src/features/hover.ts | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/jupyterlab-lsp/src/features/hover.ts b/packages/jupyterlab-lsp/src/features/hover.ts index a9acdbaea..a7a74a01b 100644 --- a/packages/jupyterlab-lsp/src/features/hover.ts +++ b/packages/jupyterlab-lsp/src/features/hover.ts @@ -46,6 +46,11 @@ interface IResponseData { ce_editor: CodeEditor.IEditor; } +interface IOnHoverResponse { + hover: lsProtocol.Hover; + position: IVirtualPosition; +} + /** * Check whether mouse is close to given element (within a specified number of pixels) * @param what target element @@ -127,12 +132,10 @@ export class HoverCM extends CodeMirrorIntegration { private virtual_position: IVirtualPosition; protected cache: ResponseCache; - private debounced_get_hover: Throttler< - Promise - >; + private debounced_get_hover: Throttler>; private tooltip: FreeTooltip; private _previousHoverRequest: Promise< - Promise + Promise > | null = null; constructor(options: IEditorIntegrationOptions) { @@ -251,13 +254,10 @@ export class HoverCM extends CodeMirrorIntegration { } protected create_throttler() { - return new Throttler>( - this.on_hover, - { - limit: this.settings.composite.throttlerDelay, - edge: 'trailing' - } - ); + return new Throttler>(this.on_hover, { + limit: this.settings.composite.throttlerDelay, + edge: 'trailing' + }); } afterChange(change: IEditorChange, root_position: IRootPosition) { @@ -268,17 +268,20 @@ export class HoverCM extends CodeMirrorIntegration { this.remove_range_highlight(); } - protected on_hover = async () => { + protected on_hover = async ( + position: IVirtualPosition + ): Promise => { if ( !( this.connection.isReady && this.connection.serverCapabilities?.hoverProvider ) ) { - return; + return null; } - let position = this.virtual_position; - return await this.connection.clientRequests['textDocument/hover'].request({ + const hover = await this.connection.clientRequests[ + 'textDocument/hover' + ].request({ textDocument: { // this might be wrong - should not it be using the specific virtual document? uri: this.virtual_document.document_info.uri @@ -288,6 +291,15 @@ export class HoverCM extends CodeMirrorIntegration { character: position.ch } }); + + if (hover == null) { + return null; + } + + return { + hover: hover, + position: this.virtual_position + }; }; protected static get_markup_for_hover( @@ -443,20 +455,24 @@ export class HoverCM extends CodeMirrorIntegration { let response_data = this.restore_from_cache(document, virtual_position); if (response_data == null) { - const promise = this.debounced_get_hover.invoke(); + const promise = this.debounced_get_hover.invoke(virtual_position); this._previousHoverRequest = promise; let response = await promise; if (this._previousHoverRequest === promise) { this._previousHoverRequest = null; } - if (response && this.is_useful_response(response)) { + if ( + response && + is_equal(response.position, virtual_position) && + this.is_useful_response(response.hover) + ) { let ce_editor = this.virtual_editor.get_editor_at_root_position(root_position); let cm_editor = this.virtual_editor.ce_editor_to_cm_editor.get(ce_editor)!; let editor_range = this.get_editor_range( - response, + response.hover, root_position, token, cm_editor @@ -464,7 +480,7 @@ export class HoverCM extends CodeMirrorIntegration { response_data = { response: this.add_range_if_needed( - response, + response.hover, editor_range, ce_editor ),