Skip to content

Commit 105eea1

Browse files
committed
Adding inlay hints in the VS Code extension.
1 parent 1f315f9 commit 105eea1

File tree

11 files changed

+555
-43
lines changed

11 files changed

+555
-43
lines changed

ide/api.lsp/apichanges.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@
5151
<!-- ACTUAL CHANGES BEGIN HERE: -->
5252

5353
<changes>
54+
<change id="InlayHintsProvider">
55+
<api name="LSP_API"/>
56+
<summary>Adding InlayHintsProvider</summary>
57+
<version major="1" minor="34"/>
58+
<date day="9" month="2" year="2025"/>
59+
<author login="jlahoda"/>
60+
<compatibility binary="compatible" source="compatible" addition="yes" deletion="no" />
61+
<description>
62+
The <code>InlayHintsProvider</code> is introduced to provide inlay
63+
hints for the LSP protocol.
64+
</description>
65+
<class package="org.netbeans.spi.lsp" name="InlayHintsProvider"/>
66+
</change>
5467
<change id="RegisterLSPServices">
5568
<api name="LSP_API"/>
5669
<summary>Adding RegisterLSPServices annotation</summary>

ide/api.lsp/manifest.mf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Manifest-Version: 1.0
22
OpenIDE-Module: org.netbeans.api.lsp/1
33
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/lsp/Bundle.properties
4-
OpenIDE-Module-Specification-Version: 1.33
4+
OpenIDE-Module-Specification-Version: 1.34
55
AutoUpdate-Show-In-Client: false
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.netbeans.api.lsp;
20+
21+
/**
22+
* An inlay hint.
23+
*
24+
* @since 1.34
25+
*/
26+
public class InlayHint {
27+
private final Position position;
28+
private final String text;
29+
30+
/**
31+
* Create a new instance of InlayHint
32+
*
33+
* @param position the position where the hint should appear
34+
* @param text the text fo the hint
35+
*/
36+
public InlayHint(Position position, String text) {
37+
this.position = position;
38+
this.text = text;
39+
}
40+
41+
/**
42+
* Returns the position of the hint
43+
*
44+
* @return the position of the hint
45+
*/
46+
public Position getPosition() {
47+
return position;
48+
}
49+
50+
/**
51+
* Returns the text of the hint
52+
*
53+
* @return the text of the hint
54+
*/
55+
56+
public String getText() {
57+
return text;
58+
}
59+
60+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.netbeans.spi.lsp;
20+
21+
import java.util.List;
22+
import java.util.Set;
23+
import java.util.concurrent.CompletableFuture;
24+
import org.netbeans.api.annotations.common.CheckForNull;
25+
import org.netbeans.api.annotations.common.NonNull;
26+
import org.netbeans.api.annotations.common.NullAllowed;
27+
import org.netbeans.api.lsp.InlayHint;
28+
import org.netbeans.api.lsp.Range;
29+
import org.netbeans.spi.editor.mimelookup.MimeLocation;
30+
import org.openide.filesystems.FileObject;
31+
import org.openide.util.Parameters;
32+
33+
/**
34+
* A provider for code lens for a given document.
35+
*
36+
* @since 1.34
37+
*/
38+
@MimeLocation(subfolderName = "CodeLensProvider")
39+
public interface InlayHintsProvider {
40+
41+
/**
42+
* Return a set of types of hints supported by this provider.
43+
*
44+
* The {@code codeLens} method will only be called if at least one
45+
* of the hint type is enabled in the settings.
46+
*
47+
* @return a set of the hint types supported by this provider.
48+
*/
49+
public Set<String> supportedHintTypes();
50+
51+
/**
52+
* Provide {@code CodeLens} for the given document.
53+
*
54+
* @param doc the document
55+
* @return the (future) code lens.
56+
*/
57+
public CompletableFuture<List<? extends InlayHint>> inlayHints(@NonNull Context context);
58+
59+
/**
60+
* Context in which the inlay hints should be evaluated.
61+
*/
62+
public static final class Context {
63+
private final @NonNull FileObject file;
64+
private final @NullAllowed Range range;
65+
private final @NonNull Set<String> requestedHintTypes;
66+
67+
/**
68+
* Create the Context.
69+
*
70+
* @param file a file in which the inlay hints should be evaluated
71+
* @param range the range for which the hints should be computed
72+
* @param requestedHintTypes the types of hints that should be computed
73+
*/
74+
public Context(@NonNull FileObject file, @NullAllowed Range range, @NonNull Set<String> requestedHintTypes) {
75+
Parameters.notNull("file", file);
76+
Parameters.notNull("range", range);
77+
Parameters.notNull("requestedHintTypes", requestedHintTypes);
78+
79+
this.file = file;
80+
this.range = range;
81+
this.requestedHintTypes = Set.copyOf(requestedHintTypes);
82+
}
83+
84+
/**
85+
* The file for which the inlay hints should be computed.
86+
*
87+
* @return the file for which the inlay hints should be computed
88+
*/
89+
public @NonNull FileObject getFile() {
90+
return file;
91+
}
92+
93+
/**
94+
* The range for which the inlay hints should be computed.
95+
*
96+
* @return the range for which the inlay hints should be computed
97+
*/
98+
public @CheckForNull Range getRange() {
99+
return range;
100+
}
101+
102+
/**
103+
* The types of hints that should be computed.
104+
*
105+
* @return the types of hints that should be computed
106+
*/
107+
public @NonNull Set<String> getRequestedHintTypes() {
108+
return requestedHintTypes;
109+
}
110+
111+
}
112+
}

java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -97,39 +97,6 @@ public abstract class SemanticHighlighterBase extends JavaParserResultTask {
9797
public static final String JAVA_INLINE_HINT_CHAINED_TYPES = "javaInlineHintChainedTypes"; //NOI18N
9898
public static final String JAVA_INLINE_HINT_VAR_TYPE = "javaInlineHintVarType"; //NOI18N
9999

100-
private static final Map<String, Boolean> DEFAULT_VALUES;
101-
102-
static {
103-
Map<String, Boolean> defaultValuesBuilder = new HashMap<>();
104-
defaultValuesBuilder.put(JAVA_INLINE_HINT_PARAMETER_NAME, true);
105-
defaultValuesBuilder.put(JAVA_INLINE_HINT_CHAINED_TYPES, false);
106-
defaultValuesBuilder.put(JAVA_INLINE_HINT_VAR_TYPE, false);
107-
DEFAULT_VALUES = Collections.unmodifiableMap(defaultValuesBuilder);
108-
}
109-
110-
private static boolean javaInlineHintParameterName;
111-
private static boolean javaInlineHintChainedTypes;
112-
private static boolean javaInlineHintVarType;
113-
114-
private static boolean isJavaInlineHintParameterName() {
115-
return javaInlineHintParameterName;
116-
}
117-
118-
private static boolean isJavaInlineHintChainedTypes() {
119-
return javaInlineHintChainedTypes;
120-
}
121-
122-
private static boolean isJavaInlineHintVarType() {
123-
return javaInlineHintVarType;
124-
}
125-
126-
private static void updateFromPreferences() {
127-
Preferences preferences = NbPreferences.root().node("/org/netbeans/modules/java/editor/InlineHints/default");
128-
javaInlineHintParameterName = preferences.getBoolean(JAVA_INLINE_HINT_PARAMETER_NAME, DEFAULT_VALUES.get(JAVA_INLINE_HINT_PARAMETER_NAME));
129-
javaInlineHintChainedTypes = preferences.getBoolean(JAVA_INLINE_HINT_CHAINED_TYPES, DEFAULT_VALUES.get(JAVA_INLINE_HINT_CHAINED_TYPES));
130-
javaInlineHintVarType = preferences.getBoolean(JAVA_INLINE_HINT_VAR_TYPE, DEFAULT_VALUES.get(JAVA_INLINE_HINT_VAR_TYPE));
131-
}
132-
133100
private AtomicBoolean cancel = new AtomicBoolean();
134101

135102
protected SemanticHighlighterBase() {
@@ -189,9 +156,11 @@ public Class<? extends Scheduler> getSchedulerClass() {
189156
protected abstract boolean process(CompilationInfo info, final Document doc);
190157

191158
protected boolean process(CompilationInfo info, final Document doc, ErrorDescriptionSetter setter) {
192-
updateFromPreferences();
159+
return process(info, doc, Settings.getDefault(), setter);
160+
}
193161

194-
DetectorVisitor v = new DetectorVisitor(info, doc, cancel);
162+
protected boolean process(CompilationInfo info, final Document doc, Settings settings, ErrorDescriptionSetter setter) {
163+
DetectorVisitor v = new DetectorVisitor(info, doc, settings, cancel);
195164

196165
Map<Token, Coloring> newColoring = new IdentityHashMap<>();
197166

@@ -315,8 +284,9 @@ public String toString() {
315284

316285
private static class DetectorVisitor extends CancellableTreePathScanner<Void, Void> {
317286

318-
private org.netbeans.api.java.source.CompilationInfo info;
319-
private Document doc;
287+
private final org.netbeans.api.java.source.CompilationInfo info;
288+
private final Document doc;
289+
private final Settings settings;
320290
private Map<Element, List<Use>> type2Uses;
321291
private Map<Tree, List<Token>> tree2Tokens;
322292
private List<Token> contextKeywords;
@@ -327,11 +297,12 @@ private static class DetectorVisitor extends CancellableTreePathScanner<Void, Vo
327297
private SourcePositions sourcePositions;
328298
private ExecutableElement recursionDetector;
329299

330-
private DetectorVisitor(org.netbeans.api.java.source.CompilationInfo info, final Document doc, AtomicBoolean cancel) {
300+
private DetectorVisitor(org.netbeans.api.java.source.CompilationInfo info, final Document doc, Settings settings, AtomicBoolean cancel) {
331301
super(cancel);
332302

333303
this.info = info;
334304
this.doc = doc;
305+
this.settings = settings;
335306
type2Uses = new HashMap<Element, List<Use>>();
336307
tree2Tokens = new IdentityHashMap<Tree, List<Token>>();
337308
contextKeywords = new ArrayList<>();
@@ -787,7 +758,7 @@ public Void visitMethodInvocation(MethodInvocationTree tree, Void p) {
787758
}
788759

789760
private void addChainedTypes(TreePath current) {
790-
if(! isJavaInlineHintChainedTypes()) {
761+
if (!settings.javaInlineHintChainedTypes) {
791762
return;
792763
}
793764
List<TreePath> chain = new ArrayList<>(); //TODO: avoid creating an instance if possible!
@@ -963,7 +934,7 @@ public Void visitVariable(VariableTree tree, Void p) {
963934

964935
tl.moveNext();
965936

966-
if (info.getTreeUtilities().isVarType(getCurrentPath()) && isJavaInlineHintVarType()) {
937+
if (info.getTreeUtilities().isVarType(getCurrentPath()) && settings.javaInlineHintVarType) {
967938
int afterName = tl.offset();
968939
TypeMirror type = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), tree.getType()));
969940

@@ -1156,7 +1127,7 @@ private int leadingIndent(String line) {
11561127
}
11571128

11581129
private void addParameterInlineHint(Tree tree) {
1159-
if(! isJavaInlineHintParameterName()) {
1130+
if (!settings.javaInlineHintParameterName) {
11601131
return;
11611132
}
11621133
TreePath pp = getCurrentPath().getParentPath();
@@ -1197,5 +1168,35 @@ public static interface ErrorDescriptionSetter {
11971168

11981169
public void setHighlights(Document doc, Collection<Pair<int[], Coloring>> highlights, Map<int[], String> preText);
11991170
public void setColorings(Document doc, Map<Token, Coloring> colorings);
1200-
}
1171+
}
1172+
1173+
public static class Settings {
1174+
private static final Map<String, Boolean> DEFAULT_VALUES;
1175+
1176+
static {
1177+
Map<String, Boolean> defaultValuesBuilder = new HashMap<>();
1178+
defaultValuesBuilder.put(JAVA_INLINE_HINT_PARAMETER_NAME, true);
1179+
defaultValuesBuilder.put(JAVA_INLINE_HINT_CHAINED_TYPES, false);
1180+
defaultValuesBuilder.put(JAVA_INLINE_HINT_VAR_TYPE, false);
1181+
DEFAULT_VALUES = Collections.unmodifiableMap(defaultValuesBuilder);
1182+
}
1183+
1184+
public final boolean javaInlineHintParameterName;
1185+
public final boolean javaInlineHintChainedTypes;
1186+
public final boolean javaInlineHintVarType;
1187+
1188+
public Settings(boolean javaInlineHintParameterName, boolean javaInlineHintChainedTypes, boolean javaInlineHintVarType) {
1189+
this.javaInlineHintParameterName = javaInlineHintParameterName;
1190+
this.javaInlineHintChainedTypes = javaInlineHintChainedTypes;
1191+
this.javaInlineHintVarType = javaInlineHintVarType;
1192+
}
1193+
1194+
public static Settings getDefault() {
1195+
Preferences preferences = NbPreferences.root().node("/org/netbeans/modules/java/editor/InlineHints/default");
1196+
return new Settings(preferences.getBoolean(JAVA_INLINE_HINT_PARAMETER_NAME, DEFAULT_VALUES.get(JAVA_INLINE_HINT_PARAMETER_NAME)),
1197+
preferences.getBoolean(JAVA_INLINE_HINT_CHAINED_TYPES, DEFAULT_VALUES.get(JAVA_INLINE_HINT_CHAINED_TYPES)),
1198+
preferences.getBoolean(JAVA_INLINE_HINT_VAR_TYPE, DEFAULT_VALUES.get(JAVA_INLINE_HINT_VAR_TYPE)));
1199+
}
1200+
1201+
}
12011202
}

0 commit comments

Comments
 (0)