Skip to content

Commit 78d336b

Browse files
committed
hover with detail levels
1 parent 7bddac1 commit 78d336b

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

client/src/languageserver.ts

+57
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as path from 'path';
22
import * as os from 'os';
33
import * as fs from 'fs';
44
import * as vscode from 'vscode';
5+
import * as LSP from 'vscode-languageserver-protocol';
56
import {
67
workspace as Workspace,
78
ExtensionContext,
@@ -156,6 +157,9 @@ class LuaClient extends Disposable {
156157
languageConfiguration: true,
157158
storagePath: this.context.globalStorageUri.fsPath,
158159
},
160+
middleware: {
161+
provideHover: async () => undefined,
162+
}
159163
};
160164

161165
const config = Workspace.getConfiguration(
@@ -194,6 +198,7 @@ class LuaClient extends Disposable {
194198
this.onCommand();
195199
this.statusBar();
196200
this.languageConfiguration();
201+
this.provideHover();
197202
}
198203

199204
private async getCommand(config: vscode.WorkspaceConfiguration) {
@@ -359,6 +364,58 @@ class LuaClient extends Disposable {
359364
})
360365
)
361366
}
367+
368+
private provideHover() {
369+
const client = this.client;
370+
const levelMap = new WeakMap<vscode.VerboseHover, number>();
371+
let provider = vscode.languages.registerHoverProvider('lua', {
372+
provideHover: async (document, position, token, context?: vscode.HoverContext) => {
373+
if (!client) {
374+
return null;
375+
}
376+
let level = 1;
377+
if (context?.previousHover) {
378+
level = levelMap.get(context.previousHover) ?? 0;
379+
if (context.verbosityDelta !== undefined) {
380+
level += context.verbosityDelta;
381+
}
382+
}
383+
let params = {
384+
level: level,
385+
...client.code2ProtocolConverter.asTextDocumentPositionParams(document, position),
386+
}
387+
return client?.sendRequest(
388+
LSP.HoverRequest.type,
389+
params,
390+
token,
391+
).then((result) => {
392+
if (token.isCancellationRequested) {
393+
return null;
394+
}
395+
if (result === null) {
396+
return null;
397+
}
398+
let verboseResult = result as LSP.Hover & { maxLevel?: number };
399+
let maxLevel = verboseResult.maxLevel ?? 0;
400+
let hover = client.protocol2CodeConverter.asHover(result);
401+
let verboseHover = new vscode.VerboseHover(
402+
hover.contents,
403+
hover.range,
404+
level < maxLevel,
405+
level > 0,
406+
);
407+
if (level > maxLevel) {
408+
level = maxLevel;
409+
}
410+
levelMap.set(verboseHover, level);
411+
return verboseHover;
412+
}, (error) => {
413+
return client.handleFailedRequest(LSP.HoverRequest.type, token, error, null);
414+
});
415+
}
416+
})
417+
this.disposables.push(provider)
418+
}
362419
}
363420

364421
export function activate(context: ExtensionContext) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
declare module 'vscode' {
7+
8+
/**
9+
* A hover represents additional information for a symbol or word. Hovers are
10+
* rendered in a tooltip-like widget.
11+
*/
12+
export class VerboseHover extends Hover {
13+
14+
/**
15+
* Can increase the verbosity of the hover
16+
*/
17+
canIncreaseVerbosity?: boolean;
18+
19+
/**
20+
* Can decrease the verbosity of the hover
21+
*/
22+
canDecreaseVerbosity?: boolean;
23+
24+
/**
25+
* Creates a new hover object.
26+
*
27+
* @param contents The contents of the hover.
28+
* @param range The range to which the hover applies.
29+
*/
30+
constructor(contents: MarkdownString | MarkedString | Array<MarkdownString | MarkedString>, range?: Range, canIncreaseVerbosity?: boolean, canDecreaseVerbosity?: boolean);
31+
}
32+
33+
export interface HoverContext {
34+
35+
/**
36+
* The delta by which to increase/decrease the hover verbosity level
37+
*/
38+
readonly verbosityDelta?: number;
39+
40+
/**
41+
* The previous hover sent for the same position
42+
*/
43+
readonly previousHover?: Hover;
44+
}
45+
46+
export enum HoverVerbosityAction {
47+
/**
48+
* Increase the hover verbosity
49+
*/
50+
Increase = 0,
51+
/**
52+
* Decrease the hover verbosity
53+
*/
54+
Decrease = 1
55+
}
56+
57+
/**
58+
* The hover provider class
59+
*/
60+
export interface HoverProvider {
61+
62+
/**
63+
* Provide a hover for the given position and document. Multiple hovers at the same
64+
* position will be merged by the editor. A hover can have a range which defaults
65+
* to the word range at the position when omitted.
66+
*
67+
* @param document The document in which the command was invoked.
68+
* @param position The position at which the command was invoked.
69+
* @param token A cancellation token.
70+
* @oaram context A hover context.
71+
* @returns A hover or a thenable that resolves to such. The lack of a result can be
72+
* signaled by returning `undefined` or `null`.
73+
*/
74+
provideHover(document: TextDocument, position: Position, token: CancellationToken, context?: HoverContext): ProviderResult<VerboseHover>;
75+
}
76+
}

0 commit comments

Comments
 (0)