Skip to content

Commit 9150d2c

Browse files
committed
Support inlay hints for parameter names
This PR supports inlay hints for parameter names. Meanwhile, a new client setting 'java.inlayHints.parameterNames.enabled' is added to specify how the inlay hints will be displayed in editor, where: - none: disable parameter name hints - literals: enable parameter name hints only for literal arguments - all: enable parameter name hints for literal and non-literal arguments Signed-off-by: sheche <sheche@microsoft.com>
1 parent ca9e8cc commit 9150d2c

File tree

6 files changed

+184
-26
lines changed

6 files changed

+184
-26
lines changed

package-lock.json

Lines changed: 53 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"virtualWorkspaces": false
2424
},
2525
"engines": {
26-
"vscode": "^1.61.0"
26+
"vscode": "^1.65.0"
2727
},
2828
"repository": {
2929
"type": "git",
@@ -857,6 +857,22 @@
857857
"default": "line",
858858
"description": "Show quickfixes at the problem or line level.",
859859
"scope": "window"
860+
},
861+
"java.inlayHints.parameterNames.enabled": {
862+
"type": "string",
863+
"enum": [
864+
"none",
865+
"literals",
866+
"all"
867+
],
868+
"enumDescriptions": [
869+
"Disable parameter name hints",
870+
"Enable parameter name hints only for literal arguments",
871+
"Enable parameter name hints for literal and non-literal arguments"
872+
],
873+
"default": "literals",
874+
"markdownDescription": "Enable/disable inlay hints for parameter names:\n```java\n\nInteger.valueOf(/* s: */ '123', /* radix: */ 10)\n \n```\n",
875+
"scope": "window"
860876
}
861877
}
862878
},
@@ -1141,7 +1157,7 @@
11411157
"@types/mocha": "^5.2.5",
11421158
"@types/node": "^8.10.51",
11431159
"@types/semver": "^7.3.8",
1144-
"@types/vscode": "^1.53.0",
1160+
"@types/vscode": "^1.65.0",
11451161
"@types/winreg": "^1.2.30",
11461162
"@types/winston": "^2.4.4",
11471163
"gulp": "^4.0.2",

src/extension.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as path from 'path';
44
import * as os from 'os';
55
import * as fs from 'fs';
66
import * as fse from 'fs-extra';
7-
import { workspace, extensions, ExtensionContext, window, commands, ViewColumn, Uri, languages, IndentAction, InputBoxOptions, EventEmitter, OutputChannel, TextDocument, RelativePattern, ConfigurationTarget, WorkspaceConfiguration, env, UIKind, CodeActionContext, Diagnostic } from 'vscode';
7+
import { workspace, extensions, ExtensionContext, window, commands, ViewColumn, Uri, languages, IndentAction, InputBoxOptions, EventEmitter, OutputChannel, TextDocument, RelativePattern, ConfigurationTarget, WorkspaceConfiguration, env, UIKind, CodeActionContext, Diagnostic, CodeActionTriggerKind } from 'vscode';
88
import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClientOptions, RevealOutputChannelOn, ErrorHandler, Message, ErrorAction, CloseAction, DidChangeConfigurationNotification, CancellationToken, CodeActionRequest, CodeActionParams, Command } from 'vscode-languageclient';
99
import { LanguageClient } from 'vscode-languageclient/node';
1010
import { collectJavaExtensions, isContributedPartUpdated } from './plugin';
@@ -134,6 +134,11 @@ export class OutputInfoCollector implements OutputChannel {
134134
this.channel.appendLine(value);
135135
}
136136

137+
replace(value: string): void {
138+
this.clear();
139+
this.append(value);
140+
}
141+
137142
clear(): void {
138143
this.channel.clear();
139144
}
@@ -279,6 +284,7 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
279284
const codeActionContext: CodeActionContext = {
280285
diagnostics: allDiagnostics,
281286
only: context.only,
287+
triggerKind: CodeActionTriggerKind.Invoke,
282288
};
283289
params.context = client.code2ProtocolConverter.asCodeActionContext(codeActionContext);
284290
}

src/hoverAction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ class JavaHoverProvider implements HoverProvider {
7575

7676
const contributed = new MarkdownString(contributedCommands.map((command) => this.convertCommandToMarkdown(command)).join(' | '));
7777
contributed.isTrusted = true;
78-
let contents: MarkedString[] = [ contributed ];
78+
let contents: MarkdownString[] = [ contributed ];
7979
let range;
8080
if (serverHover && serverHover.contents) {
81-
contents = contents.concat(serverHover.contents);
81+
contents = contents.concat(serverHover.contents as MarkdownString[]);
8282
range = serverHover.range;
8383
}
8484
return new Hover(contents, range);

src/inlayHintsProvider.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { CancellationToken, EventEmitter, InlayHint, InlayHintKind, InlayHintsProvider, Range, TextDocument } from "vscode";
2+
import * as ls from 'vscode-languageserver-protocol';
3+
import { LanguageClient, RequestType } from "vscode-languageclient/node";
4+
5+
export class JavaInlayHintsProvider implements InlayHintsProvider {
6+
7+
private onDidChange = new EventEmitter<void>();
8+
public onDidChangeInlayHints = this.onDidChange.event;
9+
10+
constructor(private client: LanguageClient) {
11+
this.client.onRequest(InlayHintRefreshRequest.type, async () => {
12+
this.onDidChange.fire();
13+
});
14+
}
15+
16+
public async provideInlayHints(document: TextDocument, range: Range, token: CancellationToken): Promise<InlayHint[]> {
17+
const requestParams: InlayHintParams = {
18+
textDocument: this.client.code2ProtocolConverter.asTextDocumentIdentifier(document),
19+
range: this.client.code2ProtocolConverter.asRange(range)
20+
};
21+
try {
22+
const values = await this.client.sendRequest(InlayHintRequest.type, requestParams, token);
23+
if (token.isCancellationRequested) {
24+
return [];
25+
}
26+
return asInlayHints(values, this.client);
27+
} catch (error) {
28+
return this.client.handleFailedRequest(InlayHintRequest.type, token, error, []);
29+
}
30+
}
31+
}
32+
33+
/**
34+
* A parameter literal used in inlay hints requests.
35+
*
36+
* @since 3.17.0 - proposed state
37+
*/
38+
export type InlayHintParams = /*WorkDoneProgressParams &*/ {
39+
/**
40+
* The text document.
41+
*/
42+
textDocument: ls.TextDocumentIdentifier;
43+
44+
/**
45+
* The document range for which inlay hints should be computed.
46+
*/
47+
range: ls.Range;
48+
};
49+
50+
/**
51+
* Inlay hint information.
52+
*
53+
* @since 3.17.0 - proposed state
54+
*/
55+
export type LSInlayHint = {
56+
57+
/**
58+
* The position of this hint.
59+
*/
60+
position: ls.Position;
61+
62+
/**
63+
* The label of this hint. A human readable string or an array of
64+
* InlayHintLabelPart label parts.
65+
*
66+
* *Note* that neither the string nor the label part can be empty.
67+
*/
68+
label: string; // label: string | InlayHintLabelPart[];
69+
};
70+
71+
namespace InlayHintRequest {
72+
export const type: RequestType<InlayHintParams, LSInlayHint[], any> = new RequestType('textDocument/inlayHint');
73+
}
74+
75+
/**
76+
* @since 3.17.0 - proposed state
77+
*/
78+
namespace InlayHintRefreshRequest {
79+
export const type: RequestType<void, void, void> = new RequestType('workspace/inlayHint/refresh');
80+
}
81+
82+
async function asInlayHints(values: LSInlayHint[] | undefined | null, client: LanguageClient, ): Promise<InlayHint[] | undefined> {
83+
if (!Array.isArray(values)) {
84+
return undefined;
85+
}
86+
return values.map(lsHint => asInlayHint(lsHint, client));
87+
}
88+
89+
function asInlayHint(value: LSInlayHint, client: LanguageClient): InlayHint {
90+
const label = value.label;
91+
const result = new InlayHint(client.protocol2CodeConverter.asPosition(value.position), label);
92+
result.paddingRight = true;
93+
result.kind = InlayHintKind.Parameter;
94+
return result;
95+
}

src/standardLanguageClient.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { TypeHierarchyDirection, TypeHierarchyItem } from "./typeHierarchy/proto
3333
import { buildFilePatterns } from './plugin';
3434
import { pomCodeActionMetadata, PomCodeActionProvider } from "./pom/pomCodeActionProvider";
3535
import { findRuntimes, IJavaRuntime } from "jdk-utils";
36+
import { JavaInlayHintsProvider } from "./inlayHintsProvider";
3637

3738
const extensionName = 'Language Support for Java';
3839
const GRADLE_CHECKSUM = "gradle/checksum/prompt";
@@ -498,6 +499,14 @@ export class StandardLanguageClient {
498499
scheme: "file",
499500
pattern: "**/pom.xml"
500501
}, new PomCodeActionProvider(context), pomCodeActionMetadata);
502+
503+
if (languages.registerInlayHintsProvider) {
504+
context.subscriptions.push(languages.registerInlayHintsProvider([
505+
{ scheme: "file", language: "java", pattern: "**/*.java" },
506+
{ scheme: "jdt", language: "java", pattern: "**/*.class" },
507+
{ scheme: "untitled", language: "java", pattern: "**/*.java" }
508+
], new JavaInlayHintsProvider(this.languageClient)));
509+
}
501510
});
502511
}
503512

0 commit comments

Comments
 (0)