Skip to content

Commit 72834bc

Browse files
authored
Merge pull request #860 from yamaton/fix-misplaced-hover-tooltip
Fix sporadic misplacement of hover tooltips
2 parents 8125308 + 0d225e4 commit 72834bc

File tree

1 file changed

+52
-32
lines changed
  • packages/jupyterlab-lsp/src/features

1 file changed

+52
-32
lines changed

packages/jupyterlab-lsp/src/features/hover.ts

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,10 @@ export class HoverCM extends CodeMirrorIntegration {
127127
private virtual_position: IVirtualPosition;
128128
protected cache: ResponseCache;
129129

130-
private debounced_get_hover: Throttler<
131-
Promise<lsProtocol.Hover | undefined | null>
132-
>;
130+
private debounced_get_hover: Throttler<Promise<lsProtocol.Hover | null>>;
133131
private tooltip: FreeTooltip;
134132
private _previousHoverRequest: Promise<
135-
Promise<lsProtocol.Hover | undefined | null>
133+
Promise<lsProtocol.Hover | null>
136134
> | null = null;
137135

138136
constructor(options: IEditorIntegrationOptions) {
@@ -251,13 +249,10 @@ export class HoverCM extends CodeMirrorIntegration {
251249
}
252250

253251
protected create_throttler() {
254-
return new Throttler<Promise<lsProtocol.Hover | undefined | null>>(
255-
this.on_hover,
256-
{
257-
limit: this.settings.composite.throttlerDelay,
258-
edge: 'trailing'
259-
}
260-
);
252+
return new Throttler<Promise<lsProtocol.Hover | null>>(this.on_hover, {
253+
limit: this.settings.composite.throttlerDelay,
254+
edge: 'trailing'
255+
});
261256
}
262257

263258
afterChange(change: IEditorChange, root_position: IRootPosition) {
@@ -268,26 +263,36 @@ export class HoverCM extends CodeMirrorIntegration {
268263
this.remove_range_highlight();
269264
}
270265

271-
protected on_hover = async () => {
266+
protected on_hover = async (
267+
virtual_position: IVirtualPosition,
268+
add_range_fn: (hover: lsProtocol.Hover) => lsProtocol.Hover
269+
): Promise<lsProtocol.Hover | null> => {
272270
if (
273271
!(
274272
this.connection.isReady &&
275273
this.connection.serverCapabilities?.hoverProvider
276274
)
277275
) {
278-
return;
276+
return null;
279277
}
280-
let position = this.virtual_position;
281-
return await this.connection.clientRequests['textDocument/hover'].request({
278+
let hover = await this.connection.clientRequests[
279+
'textDocument/hover'
280+
].request({
282281
textDocument: {
283282
// this might be wrong - should not it be using the specific virtual document?
284283
uri: this.virtual_document.document_info.uri
285284
},
286285
position: {
287-
line: position.line,
288-
character: position.ch
286+
line: virtual_position.line,
287+
character: virtual_position.ch
289288
}
290289
});
290+
291+
if (hover == null) {
292+
return null;
293+
}
294+
295+
return add_range_fn(hover);
291296
};
292297

293298
protected static get_markup_for_hover(
@@ -396,7 +401,7 @@ export class HoverCM extends CodeMirrorIntegration {
396401
// (only cells with code) instead, but this is more complex to implement right. In any case filtering
397402
// is needed to determine in hovered character belongs to this virtual document
398403

399-
let root_position = this.position_from_mouse(event);
404+
const root_position = this.position_from_mouse(event);
400405

401406
// happens because mousemove is attached to panel, not individual code cells,
402407
// and because some regions of the editor (between lines) have no characters
@@ -442,31 +447,46 @@ export class HoverCM extends CodeMirrorIntegration {
442447
let response_data = this.restore_from_cache(document, virtual_position);
443448

444449
if (response_data == null) {
445-
const promise = this.debounced_get_hover.invoke();
450+
const ce_editor =
451+
this.virtual_editor.get_editor_at_root_position(root_position);
452+
const cm_editor =
453+
this.virtual_editor.ce_editor_to_cm_editor.get(ce_editor)!;
454+
const add_range_fn = (hover: lsProtocol.Hover): lsProtocol.Hover => {
455+
const editor_range = this.get_editor_range(
456+
hover,
457+
root_position,
458+
token,
459+
cm_editor
460+
);
461+
return this.add_range_if_needed(hover, editor_range, ce_editor);
462+
};
463+
464+
const promise = this.debounced_get_hover.invoke(
465+
virtual_position,
466+
add_range_fn
467+
);
446468
this._previousHoverRequest = promise;
447469
let response = await promise;
448470
if (this._previousHoverRequest === promise) {
449471
this._previousHoverRequest = null;
450472
}
451-
if (response && this.is_useful_response(response)) {
452-
let ce_editor =
453-
this.virtual_editor.get_editor_at_root_position(root_position);
454-
let cm_editor =
455-
this.virtual_editor.ce_editor_to_cm_editor.get(ce_editor)!;
456-
457-
let editor_range = this.get_editor_range(
473+
if (
474+
response &&
475+
response.range &&
476+
ProtocolCoordinates.isWithinRange(
477+
{ line: virtual_position.line, character: virtual_position.ch },
478+
response.range
479+
) &&
480+
this.is_useful_response(response)
481+
) {
482+
const editor_range = this.get_editor_range(
458483
response,
459484
root_position,
460485
token,
461486
cm_editor
462487
);
463-
464488
response_data = {
465-
response: this.add_range_if_needed(
466-
response,
467-
editor_range,
468-
ce_editor
469-
),
489+
response: response,
470490
document: document,
471491
editor_range: editor_range,
472492
ce_editor: ce_editor

0 commit comments

Comments
 (0)