forked from redhat-developer/vscode-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhoverAction.ts
More file actions
110 lines (93 loc) · 4.41 KB
/
hoverAction.ts
File metadata and controls
110 lines (93 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
'use strict';
import { HoverProvider, CancellationToken, Hover, Position, TextDocument, MarkdownString, MarkedString, Command } from "vscode";
import { TextDocumentPositionParams, HoverRequest } from "vscode-languageclient";
import { LanguageClient } from 'vscode-languageclient/node';
import { Commands as javaCommands } from "./commands";
import { FindLinks } from "./protocol";
import { ProvideHoverCommandFn } from "./extension.api";
import { logger } from "./log";
export function createClientHoverProvider(languageClient: LanguageClient): JavaHoverProvider {
const hoverProvider: JavaHoverProvider = new JavaHoverProvider(languageClient);
registerHoverCommand(async (params: TextDocumentPositionParams, token: CancellationToken) => {
return await provideHoverCommand(languageClient, params, token);
});
return hoverProvider;
}
async function provideHoverCommand(languageClient: LanguageClient, params: TextDocumentPositionParams, token: CancellationToken): Promise<Command[] | undefined> {
const response = await languageClient.sendRequest(FindLinks.type, {
type: 'superImplementation',
position: params,
}, token);
if (response && response.length) {
const location = response[0];
let tooltip;
if (location.kind === 'method') {
tooltip = `Go to super method '${location.displayName}'`;
} else {
tooltip = `Go to super implementation '${location.displayName}'`;
}
return [{
title: 'Go to Super Implementation',
command: javaCommands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND,
tooltip,
arguments: [{
uri: encodeBase64(location.uri),
range: location.range,
}],
}];
}
}
function encodeBase64(text: string): string {
return Buffer.from(text).toString('base64');
}
const hoverCommandRegistry: ProvideHoverCommandFn[] = [];
export function registerHoverCommand(callback: ProvideHoverCommandFn): void {
hoverCommandRegistry.push(callback);
}
class JavaHoverProvider implements HoverProvider {
constructor(readonly languageClient: LanguageClient) {
}
async provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise<Hover> {
const params = {
textDocument: this.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document),
position: this.languageClient.code2ProtocolConverter.asPosition(position),
};
// Fetch the javadoc from Java language server.
const hoverResponse = await this.languageClient.sendRequest(HoverRequest.type, params, token);
const serverHover = this.languageClient.protocol2CodeConverter.asHover(hoverResponse);
// Fetch the contributed hover commands from third party extensions.
const contributedCommands: Command[] = await this.getContributedHoverCommands(params, token);
if (!contributedCommands.length) {
return serverHover;
}
const contributed = new MarkdownString(contributedCommands.map((command) => this.convertCommandToMarkdown(command)).join(' | '));
contributed.isTrusted = true;
let contents: MarkdownString[] = [ contributed ];
let range;
if (serverHover && serverHover.contents) {
contents = contents.concat(serverHover.contents as MarkdownString[]);
range = serverHover.range;
}
return new Hover(contents, range);
}
private async getContributedHoverCommands(params: TextDocumentPositionParams, token: CancellationToken): Promise<Command[]> {
const contributedCommands: Command[] = [];
for (const provideFn of hoverCommandRegistry) {
try {
if (token.isCancellationRequested) {
break;
}
const commands = (await provideFn(params, token)) || [];
commands.forEach((command) => {
contributedCommands.push(command);
});
} catch (error) {
logger.error(`Failed to provide hover command ${String(error)}`);
}
}
return contributedCommands;
}
private convertCommandToMarkdown(command: Command): string {
return `[${command.title}](command:${command.command}?${encodeURIComponent(JSON.stringify(command.arguments || []))} "${command.tooltip || command.command}")`;
}
}