PT #162167333: Ask JDT server for hover links (Eclipse, VSCode)

This commit is contained in:
BoykoAlex
2018-12-11 16:59:40 -05:00
parent 02f45063b8
commit db429f9c21
60 changed files with 1496 additions and 209 deletions

View File

@@ -10,43 +10,77 @@
*******************************************************************************/
package org.springframework.tooling.boot.ls.jdt;
import org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover;
import org.eclipse.jface.text.IInformationControlCreator;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocBrowserInformationControlInput;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHoverExtension;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.lsp4e.operations.hover.LSBasedHover;
import org.eclipse.ui.IEditorPart;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class SpringBootJavaHoverProvider implements IJavaEditorTextHover, ITextHoverExtension {
public class SpringBootJavaHoverProvider extends JavadocHover {
private LSBasedHover lsBasedHover;
public SpringBootJavaHoverProvider() {
super();
lsBasedHover = new LSBasedHover();
}
@Override
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
return this.lsBasedHover.getHoverInfo(textViewer, hoverRegion);
public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
// Launch javadoc hover computation in async fashion
CompletableFuture<JavadocBrowserInformationControlInput> javadocHoverFuture = CompletableFuture.supplyAsync(
() -> (JavadocBrowserInformationControlInput) super.getHoverInfo2(textViewer, hoverRegion));
String content = this.lsBasedHover.getHoverInfo(textViewer, hoverRegion);
if (content != null && !content.isEmpty()) {
IJavaElement javaElement = null;
JavadocBrowserInformationControlInput previous = null;
int leadingImageWidth = 0;
JavadocBrowserInformationControlInput input;
String html = "";
try {
input = javadocHoverFuture.get(500, TimeUnit.MILLISECONDS);
if (input != null) {
previous = (JavadocBrowserInformationControlInput) input.getPrevious();
javaElement = input.getElement();
leadingImageWidth = input.getLeadingImageWidth();
html = input.getHtml();
}
} catch (InterruptedException e) {
html = noJavadocMessage("Javadoc unavailable.");
} catch (ExecutionException e) {
html = noJavadocMessage("Javadoc unavailable. Failed to obtain it.");
} catch (TimeoutException e) {
html = noJavadocMessage("Javadoc unavailable. Took too long to obtain it.");
}
content = content + html;
return new JavadocBrowserInformationControlInput(previous, javaElement, content, leadingImageWidth);
} else {
javadocHoverFuture.cancel(true);
}
return null;
}
private String noJavadocMessage(String message) {
StringBuilder sb = new StringBuilder();
sb.append("<h4>");
sb.append(message);
sb.append("</h4>");
return sb.toString();
}
@Override
public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
return this.lsBasedHover.getHoverRegion(textViewer, offset);
}
@Override
public void setEditor(IEditorPart editor) {
}
@Override
public IInformationControlCreator getHoverControlCreator() {
return this.lsBasedHover.getHoverControlCreator();
}
}

View File

@@ -21,8 +21,8 @@ import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.junit.After;
import org.junit.Test;
import org.springframework.tooling.jdt.ls.commons.java.JavaDataParams;
import org.springframework.tooling.jdt.ls.commons.javadoc.JavadocResponse;
import org.springframework.tooling.ls.eclipse.commons.JavadocParams;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageClientImpl;
public class JavadocTest {
@@ -44,7 +44,7 @@ public class JavadocTest {
String expectedBindingKey = "Lcom/sample/SampleJavadoc;";
assertEquals(expectedBindingKey, type.getKey());
JavadocParams params = new JavadocParams(project.getProject().getLocation().toFile().toURI().toString(), expectedBindingKey);
JavaDataParams params = new JavaDataParams(project.getProject().getLocation().toFile().toURI().toString(), expectedBindingKey);
JavadocResponse response = client.javadoc(params).get(1, TimeUnit.SECONDS);
assertEquals("**Sample class**", response.getContent());
}
@@ -61,7 +61,7 @@ public class JavadocTest {
String expectedBindingKey = "Lcom/sample/SampleJavadoc;.number";
assertEquals(expectedBindingKey, field.getKey());
JavadocParams params = new JavadocParams(project.getProject().getLocation().toFile().toURI().toString(), expectedBindingKey);
JavaDataParams params = new JavaDataParams(project.getProject().getLocation().toFile().toURI().toString(), expectedBindingKey);
JavadocResponse response = client.javadoc(params).get(1, TimeUnit.SECONDS);
assertEquals("**Sample field**", response.getContent());
}
@@ -78,7 +78,7 @@ public class JavadocTest {
String expectedBindingKey = "Lcom/sample/SampleJavadoc;.getNumber()V";
assertEquals(expectedBindingKey, method.getKey());
JavadocParams params = new JavadocParams(project.getProject().getLocation().toFile().toURI().toString(), expectedBindingKey);
JavaDataParams params = new JavaDataParams(project.getProject().getLocation().toFile().toURI().toString(), expectedBindingKey);
JavadocResponse response = client.javadoc(params).get(1, TimeUnit.SECONDS);
assertEquals("**Sample getter**", response.getContent());
}

View File

@@ -1,41 +0,0 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.commons;
public class JavadocParams {
private String projectUri;
private String bindingKey;
public JavadocParams(String projectUri, String bindingKey) {
super();
this.projectUri = projectUri;
this.bindingKey = bindingKey;
}
public String getProjectUri() {
return projectUri;
}
public void setProjectUri(String projectUri) {
this.projectUri = projectUri;
}
public String getBindingKey() {
return bindingKey;
}
public void setBindingKey(String bindingKey) {
this.bindingKey = bindingKey;
}
@Override
public String toString() {
return "JavadocParams [projectUri=" + projectUri + ", bindingKey=" + bindingKey + "]";
}
}

View File

@@ -15,6 +15,9 @@ import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
import org.eclipse.lsp4j.services.LanguageClient;
import org.springframework.tooling.jdt.ls.commons.java.JavaDataParams;
import org.springframework.tooling.jdt.ls.commons.java.JavaTypeResponse;
import org.springframework.tooling.jdt.ls.commons.java.JavadocHoverLinkResponse;
import org.springframework.tooling.jdt.ls.commons.javadoc.JavadocResponse;
/**
@@ -40,6 +43,12 @@ public interface STS4LanguageClient extends LanguageClient {
CompletableFuture<Object> removeClasspathListener(ClasspathListenerParams classpathListenerParams);
@JsonRequest("sts/javadoc")
CompletableFuture<JavadocResponse> javadoc(JavadocParams params);
CompletableFuture<JavadocResponse> javadoc(JavaDataParams params);
@JsonRequest("sts/javaType")
CompletableFuture<JavaTypeResponse> javaType(JavaDataParams params);
@JsonRequest("sts/javadocHoverLink")
CompletableFuture<JavadocHoverLinkResponse> javadocHoverLink(JavaDataParams params);
}

View File

@@ -20,6 +20,8 @@ import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
@@ -52,6 +54,10 @@ import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.springframework.tooling.jdt.ls.commons.Logger;
import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathListenerHandler;
import org.springframework.tooling.jdt.ls.commons.java.JavaData;
import org.springframework.tooling.jdt.ls.commons.java.JavaDataParams;
import org.springframework.tooling.jdt.ls.commons.java.JavaTypeResponse;
import org.springframework.tooling.jdt.ls.commons.java.JavadocHoverLinkResponse;
import org.springframework.tooling.jdt.ls.commons.javadoc.JavadocResponse;
import org.springframework.tooling.jdt.ls.commons.javadoc.JavadocUtils;
import org.springframework.tooling.ls.eclipse.commons.javadoc.JavaDoc2MarkdownConverter;
@@ -69,6 +75,8 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
() -> new ProjectSorter()
);
private static JavaData JAVA_DATA = new JavaData(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance));
private static final String ANNOTION_TYPE_ID = "org.springframework.tooling.bootinfo";
private static final String ALT_ANNOTATION_DRAWING_STRATEGY_ID = "boot.hint.strategy";
@@ -277,7 +285,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
}
@Override
public CompletableFuture<JavadocResponse> javadoc(JavadocParams params) {
public CompletableFuture<JavadocResponse> javadoc(JavaDataParams params) {
JavadocResponse response = new JavadocResponse();
try {
String content = JavadocUtils.javadoc(JavaDoc2MarkdownConverter::getMarkdownContentReader,
@@ -314,4 +322,24 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
return CompletableFuture.completedFuture("ok");
}
@Override
public CompletableFuture<JavaTypeResponse> javaType(JavaDataParams params) {
JavaTypeResponse response = new JavaTypeResponse(JAVA_DATA.typeData(params.getProjectUri(), params.getBindingKey()));
return CompletableFuture.completedFuture(response);
}
@Override
public CompletableFuture<JavadocHoverLinkResponse> javadocHoverLink(JavaDataParams params) {
JavadocHoverLinkResponse response = new JavadocHoverLinkResponse(null);
try {
IJavaElement element = JavaData.findElement(URI.create(params.getProjectUri()), params.getBindingKey());
if (element != null) {
response.setLink(JavaElementLinks.createURI(JavaElementLinks.OPEN_LINK_SCHEME, element));
}
} catch (Exception e) {
LanguageServerCommonsActivator.logError(e, "Failed to find java element for key " + params.getBindingKey());
}
return CompletableFuture.completedFuture(response);
}
}