-
Notifications
You must be signed in to change notification settings - Fork 350
/
Copy pathhoverProvider.ts
86 lines (74 loc) · 3.68 KB
/
hoverProvider.ts
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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { CancellationToken, Command, Disposable, Hover, HoverProvider, languages, MarkdownString, Position, ProviderResult, TextDocument,
Uri, window } from "vscode";
import { instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper";
import { JAVA_LANGID } from "./constants";
import { startDebugging } from "./debugCodeLensProvider";
import { resolveElementAtSelection } from "./languageServerPlugin";
const JAVA_HOVER_RUN_COMMAND = "java.debug.runHover";
const MAIN_METHOD_REGEX = /^(public|static|final|synchronized|\s+){4,}void\s+main\s*\(\s*String\s*\[\s*\]\s*\w+\s*\)\s*($|\{)/;
export function initializeHoverProvider(): Disposable {
return new DebugHoverProvider();
}
class DebugHoverProvider implements Disposable {
private runHoverCommand: Disposable;
private hoverProvider: Disposable | undefined;
constructor() {
this.runHoverCommand = instrumentOperationAsVsCodeCommand(JAVA_HOVER_RUN_COMMAND, async (noDebug: boolean, uri: string, position: any) => {
const element = await resolveElementAtSelection(uri, position.line, position.character);
if (element && element.hasMainMethod) {
startDebugging(element.declaringType, element.projectName, Uri.parse(uri), noDebug);
} else {
window.showErrorMessage("The hovered element is not a main method.");
}
});
this.hoverProvider = languages.registerHoverProvider(JAVA_LANGID, new InternalDebugHoverProvider());
}
public dispose() {
if (this.runHoverCommand) {
this.runHoverCommand.dispose();
}
if (this.hoverProvider) {
this.hoverProvider.dispose();
}
}
}
class InternalDebugHoverProvider implements HoverProvider {
public provideHover(document: TextDocument, position: Position, _token: CancellationToken): ProviderResult<Hover> {
const range = document.getWordRangeAtPosition(position, /\w+/);
if (!range || document.getText(range) !== "main") {
return undefined;
}
const line = document.lineAt(position);
if (MAIN_METHOD_REGEX.test(line.text.trim()) && this.isMainMethod(line.text.trim())) {
const commands: Command[] = [
{
title: "Run",
command: JAVA_HOVER_RUN_COMMAND,
tooltip: "Run Java Program",
arguments: [ true, document.uri.toString(), { line: position.line, character: position.character }],
},
{
title: "Debug",
command: JAVA_HOVER_RUN_COMMAND,
tooltip: "Debug Java Program",
arguments: [ false, document.uri.toString(), { line: position.line, character: position.character }],
},
];
const contributed = new MarkdownString(commands.map((command) => this.convertCommandToMarkdown(command)).join(" | "));
contributed.isTrusted = true;
return new Hover(contributed);
}
return undefined;
}
private isMainMethod(line: string): boolean {
const modifier: string = line.substring(0, line.indexOf("main"));
const modifiers: string[] = modifier.split(/\s+/);
return modifiers.indexOf("public") >= 0 && modifiers.indexOf("static") >= 0;
}
private convertCommandToMarkdown(command: Command): string {
return `[${command.title}](command:${command.command}?` +
`${encodeURIComponent(JSON.stringify(command.arguments || []))} "${command.tooltip || command.command}")`;
}
}