Skip to content

Commit 1443a66

Browse files
BoykoAlexmickaelistria
authored andcommitted
Rework LS completion proposals for JDT
1 parent 6478f60 commit 1443a66

12 files changed

Lines changed: 161 additions & 202 deletions

File tree

org.eclipse.lsp4e.jdt/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: JDT Integration for LSP4E
44
Bundle-SymbolicName: org.eclipse.lsp4e.jdt;singleton:=true
5-
Bundle-Version: 0.13.5.qualifier
5+
Bundle-Version: 0.13.6.qualifier
66
Automatic-Module-Name: org.eclipse.lsp4e.jdt
77
Bundle-RequiredExecutionEnvironment: JavaSE-17
88
Bundle-ClassPath: .

org.eclipse.lsp4e.jdt/src/org/eclipse/lsp4e/jdt/LSJavaCompletionProposalComputer.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
*******************************************************************************/
1212
package org.eclipse.lsp4e.jdt;
1313

14+
import java.util.Arrays;
1415
import java.util.List;
1516
import java.util.concurrent.CompletableFuture;
1617
import java.util.concurrent.ExecutionException;
@@ -22,10 +23,9 @@
2223
import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext;
2324
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer;
2425
import org.eclipse.jface.text.contentassist.ICompletionProposal;
25-
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
26-
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
2726
import org.eclipse.jface.text.contentassist.IContextInformation;
2827
import org.eclipse.lsp4e.LanguageServerPlugin;
28+
import org.eclipse.lsp4e.operations.completion.LSCompletionProposal;
2929
import org.eclipse.lsp4e.operations.completion.LSContentAssistProcessor;
3030

3131
@SuppressWarnings({ "restriction" })
@@ -51,7 +51,7 @@ public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocat
5151
lsContentAssistProcessor.computeCompletionProposals(viewer, context.getInvocationOffset()));
5252

5353
try {
54-
return List.of(asJavaProposals(future));
54+
return List.of(asJavaProposals(future, context));
5555
} catch (ExecutionException | TimeoutException e) {
5656
LanguageServerPlugin.logError(e);
5757
javaCompletionSpecificErrorMessage = createErrorMessage(e);
@@ -77,21 +77,12 @@ private String createErrorMessage(Exception ex) {
7777
* This method wraps around the LSCompletionProposal with a IJavaCompletionProposal, and it sets the relevance
7878
* number that JDT uses to sort proposals in a desired order.
7979
*/
80-
private ICompletionProposal[] asJavaProposals(CompletableFuture<ICompletionProposal[]> future)
80+
private ICompletionProposal[] asJavaProposals(CompletableFuture<ICompletionProposal[]> future, ContentAssistInvocationContext context)
8181
throws InterruptedException, ExecutionException, TimeoutException {
8282
ICompletionProposal[] originalProposals = future.get(TIMEOUT_LENGTH, TIMEOUT_UNIT);
8383

84-
final var javaProposals = new ICompletionProposal[originalProposals.length];
85-
for (int i = 0; i < originalProposals.length; i++) {
86-
if (originalProposals[i] instanceof ICompletionProposalExtension2) {
87-
javaProposals[i] = new LSJavaProposalExtension2(originalProposals[i]);
88-
} else if (originalProposals[i] instanceof ICompletionProposalExtension) {
89-
javaProposals[i] = new LSJavaProposalExtension(originalProposals[i]);
90-
} else {
91-
javaProposals[i] = new LSJavaProposal(originalProposals[i]);
92-
}
93-
}
94-
return javaProposals;
84+
return Arrays.stream(originalProposals).filter(LSCompletionProposal.class::isInstance).map(LSCompletionProposal.class::cast).map(LSJavaProposal::new).toArray(LSJavaProposal[]::new);
85+
9586
}
9687

9788
@Override

org.eclipse.lsp4e.jdt/src/org/eclipse/lsp4e/jdt/LSJavaProposal.java

Lines changed: 114 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,37 @@
1111
*******************************************************************************/
1212
package org.eclipse.lsp4e.jdt;
1313

14+
import java.io.BufferedReader;
15+
import java.io.IOException;
16+
import java.io.InputStreamReader;
17+
import java.net.URL;
18+
19+
import org.eclipse.core.runtime.FileLocator;
20+
import org.eclipse.core.runtime.IProgressMonitor;
1421
import org.eclipse.jdt.annotation.Nullable;
1522
import org.eclipse.jdt.internal.codeassist.RelevanceConstants;
23+
import org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal;
24+
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocBrowserInformationControlInput;
25+
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
26+
import org.eclipse.jdt.ui.PreferenceConstants;
1627
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
17-
import org.eclipse.jface.text.IDocument;
18-
import org.eclipse.jface.text.contentassist.ICompletionProposal;
19-
import org.eclipse.jface.text.contentassist.IContextInformation;
28+
import org.eclipse.jface.internal.text.html.BrowserInformationControl;
29+
import org.eclipse.jface.internal.text.html.HTMLPrinter;
30+
import org.eclipse.jface.resource.ColorRegistry;
31+
import org.eclipse.jface.resource.JFaceResources;
32+
import org.eclipse.jface.text.IInformationControlCreator;
33+
import org.eclipse.lsp4e.LanguageServerPlugin;
2034
import org.eclipse.lsp4e.operations.completion.LSCompletionProposal;
21-
import org.eclipse.swt.graphics.Image;
22-
import org.eclipse.swt.graphics.Point;
35+
import org.eclipse.lsp4e.ui.UI;
36+
import org.eclipse.swt.graphics.FontData;
37+
import org.eclipse.swt.graphics.RGB;
38+
import org.eclipse.swt.widgets.Shell;
39+
import org.eclipse.ui.IWorkbenchPart;
40+
import org.osgi.framework.Bundle;
41+
import org.osgi.framework.FrameworkUtil;
2342

2443
@SuppressWarnings("restriction")
25-
class LSJavaProposal implements IJavaCompletionProposal {
44+
class LSJavaProposal extends LSCompletionProposal implements IJavaCompletionProposal {
2645

2746
private static final int LS_DEFAULT_RELEVANCE = 18;
2847

@@ -33,51 +52,23 @@ class LSJavaProposal implements IJavaCompletionProposal {
3352

3453
private static final int RANGE_WITHIN_CATEGORY = Math.round((MAX_BASE_RELEVANCE - DEFAULT_RELEVANCE) / 4f);
3554

36-
protected ICompletionProposal delegate;
55+
private static @Nullable String fgCSSStyles = null;
56+
3757
private boolean relevanceComputed = false;
3858
private int relevance = -1;
39-
40-
public LSJavaProposal(ICompletionProposal delegate) {
41-
this.delegate = delegate;
42-
}
43-
44-
@Override
45-
public void apply(IDocument document) {
46-
delegate.apply(document);
47-
}
4859

49-
@Override
50-
public @Nullable String getAdditionalProposalInfo() {
51-
return delegate.getAdditionalProposalInfo();
52-
}
60+
private @Nullable IInformationControlCreator infoControlCreator = null;
5361

54-
@Override
55-
public @Nullable IContextInformation getContextInformation() {
56-
return delegate.getContextInformation();
57-
}
58-
59-
@Override
60-
public String getDisplayString() {
61-
return delegate.getDisplayString();
62-
}
63-
64-
@Override
65-
public @Nullable Image getImage() {
66-
return delegate.getImage();
67-
}
68-
69-
@Override
70-
public @Nullable Point getSelection(IDocument document) {
71-
return delegate.getSelection(document);
62+
public LSJavaProposal(LSCompletionProposal lsProposal) {
63+
super(lsProposal);
7264
}
7365

7466
@Override
7567
public int getRelevance() {
7668
if (!relevanceComputed) {
77-
if (delegate instanceof LSCompletionProposal c) {
7869
// Based on org.eclipse.jdt.internal.ui.text.java.RelevanceComputer
79-
relevance = computeBaseRelevance(c);
80-
switch (c.getItem().getKind()) {
70+
relevance = computeBaseRelevance();
71+
switch (getItem().getKind()) {
8172
case Class:
8273
relevance += 3;
8374
break;
@@ -94,18 +85,96 @@ public int getRelevance() {
9485
break;
9586
default:
9687
}
97-
}
9888
relevanceComputed = true;
9989
}
10090
return relevance;
10191
}
10292

103-
private int computeBaseRelevance(LSCompletionProposal c) {
93+
private int computeBaseRelevance() {
10494
// Incorporate LSP4E category and rank into base relevance.
105-
int base = MAX_BASE_RELEVANCE - (c.getRankCategory() - 1) * RANGE_WITHIN_CATEGORY;
106-
int rank = c.getRankScore();
95+
int base = MAX_BASE_RELEVANCE - (getRankCategory() - 1) * RANGE_WITHIN_CATEGORY;
96+
int rank = getRankScore();
10797
base -= (rank >= 0 && rank < RANGE_WITHIN_CATEGORY ? rank : RANGE_WITHIN_CATEGORY);
10898
return base;
10999
}
100+
101+
/*
102+
* Copied from org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.getInformationControlCreator()
103+
*/
104+
@Override
105+
public @Nullable IInformationControlCreator getInformationControlCreator() {
106+
Shell shell= UI.getActiveShell();
107+
if (shell == null || !BrowserInformationControl.isAvailable(shell))
108+
return null;
109+
110+
if (infoControlCreator == null) {
111+
/*
112+
* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232024
113+
*/
114+
IWorkbenchPart part = UI.getActivePart();
115+
JavadocHover.PresenterControlCreator presenterControlCreator= new JavadocHover.PresenterControlCreator(part == null ? null : part.getSite());
116+
infoControlCreator= new JavadocHover.HoverControlCreator(presenterControlCreator, true);
117+
}
118+
return infoControlCreator;
119+
}
120+
121+
/*
122+
* Copied from org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.getAdditionalProposalInfo(IProgressMonitor monitor)
123+
*/
124+
@Override
125+
public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
126+
StringBuilder buffer = new StringBuilder((String) super.getAdditionalProposalInfo(monitor));
127+
ColorRegistry registry= JFaceResources.getColorRegistry();
128+
RGB fgRGB= registry.getRGB("org.eclipse.jdt.ui.Javadoc.foregroundColor"); //$NON-NLS-1$
129+
RGB bgRGB= registry.getRGB("org.eclipse.jdt.ui.Javadoc.backgroundColor"); //$NON-NLS-1$
130+
HTMLPrinter.insertPageProlog(buffer, 0, fgRGB, bgRGB, getCSSStyles());
131+
HTMLPrinter.addPageEpilog(buffer);
132+
return new JavadocBrowserInformationControlInput(null, null, buffer.toString(), 0);
133+
134+
}
135+
136+
/**
137+
* Returns the style information for displaying HTML (Javadoc) content.
138+
* Copied from org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.getCSSStyles()
139+
*
140+
* @return the CSS styles
141+
*/
142+
private @Nullable String getCSSStyles() {
143+
if (fgCSSStyles == null) {
144+
Bundle bundle= FrameworkUtil.getBundle(AbstractJavaCompletionProposal.class);
145+
URL url= bundle == null ? null : bundle.getEntry("/JavadocHoverStyleSheet.css"); //$NON-NLS-1$
146+
if (url != null) {
147+
BufferedReader reader= null;
148+
try {
149+
url= FileLocator.toFileURL(url);
150+
reader= new BufferedReader(new InputStreamReader(url.openStream()));
151+
StringBuilder buffer= new StringBuilder(200);
152+
String line= reader.readLine();
153+
while (line != null) {
154+
buffer.append(line);
155+
buffer.append('\n');
156+
line= reader.readLine();
157+
}
158+
fgCSSStyles= buffer.toString();
159+
} catch (IOException ex) {
160+
LanguageServerPlugin.logError(ex);
161+
} finally {
162+
try {
163+
if (reader != null)
164+
reader.close();
165+
} catch (IOException e) {
166+
}
167+
}
168+
169+
}
170+
}
171+
String css= fgCSSStyles;
172+
if (css != null) {
173+
FontData fontData= JFaceResources.getFontRegistry().getFontData(PreferenceConstants.APPEARANCE_JAVADOC_FONT)[0];
174+
css= HTMLPrinter.convertTopLevelFont(css, fontData);
175+
}
176+
return css;
177+
}
178+
110179

111180
}

org.eclipse.lsp4e.jdt/src/org/eclipse/lsp4e/jdt/LSJavaProposalExtension.java

Lines changed: 0 additions & 56 deletions
This file was deleted.

org.eclipse.lsp4e.jdt/src/org/eclipse/lsp4e/jdt/LSJavaProposalExtension2.java

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)