PT #156965730: Get Javadoc from JDT LS or eclipse client via sts/javadoc

This commit is contained in:
BoykoAlex
2018-05-30 17:10:34 -04:00
parent d27856da64
commit 1b33036794
63 changed files with 1555 additions and 590 deletions

View File

@@ -26,9 +26,12 @@ import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.jandex.JandexIndex.JavadocProviderFactory;
import org.springframework.ide.vscode.commons.java.ClasspathData;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.JavaProject;
import org.springframework.ide.vscode.commons.javadoc.JdtLsJavadocProvider;
import org.springframework.ide.vscode.commons.languageserver.JavadocParams;
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListener;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -52,7 +55,7 @@ public class JdtLsProjectCache implements JavaProjectsService {
private List<Listener> listeners = new ArrayList<>();
private final Supplier<JavaProjectsService> fallback;
public JdtLsProjectCache(SimpleLanguageServer server, Supplier<JavaProjectsService> fallback) {
Assert.isNotNull(fallback);
this.fallback = Suppliers.memoize(fallback);
@@ -81,7 +84,8 @@ public class JdtLsProjectCache implements JavaProjectsService {
}
} else {
log.debug("deleted = false");
JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()));
JdtLsJavadocProvider javadocProvider = new JdtLsJavadocProvider(server.getClient(), uri);
JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()), classpathResource -> javadocProvider);
JavaProject oldProject = table.put(uri, newProject);
if (oldProject != null) {
notifyChanged(newProject);

View File

@@ -147,7 +147,7 @@ public class ClassReferenceProvider extends CachingValueProvider {
.fuzzySearchTypes(query, type -> allSubclasses.contains(type))
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.flatMapIterable(l -> l)
.map(t -> StsValueHint.create(t.getT1()));
.map(t -> StsValueHint.create(javaProject, t.getT1()));
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2017 Pivotal, Inc.
* Copyright (c) 2016, 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
@@ -42,7 +42,7 @@ public class LoggerNameProvider extends CachingValueProvider {
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())),
javaProject.getIndex()
.fuzzySearchTypes(query, null)
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2()))
.map(t -> Tuples.of(StsValueHint.create(javaProject, t.getT1()), t.getT2()))
)
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.flatMapIterable(l -> l)

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2017 Pivotal, Inc.
* Copyright (c) 2016, 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
@@ -13,12 +13,14 @@ package org.springframework.ide.vscode.boot.metadata.hints;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation;
import org.springframework.ide.vscode.boot.configurationmetadata.ValueHint;
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.util.DeprecationUtil;
import org.springframework.ide.vscode.boot.metadata.util.PropertyDocUtils;
import org.springframework.ide.vscode.commons.java.IJavaElement;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.Renderable;
@@ -58,8 +60,8 @@ public class StsValueHint {
/**
* Creates a hint out of an IJavaElement.
*/
public static StsValueHint create(String value, IJavaElement javaElement) {
return new StsValueHint(value, javaDocSnippet(javaElement), DeprecationUtil.extract(javaElement)) {
public static StsValueHint create(String value, IJavaProject project, IJavaElement javaElement) {
return new StsValueHint(value, javaDocSnippet(project, javaElement), DeprecationUtil.extract(javaElement)) {
@Override
public IJavaElement getJavaElement() {
return javaElement;
@@ -81,7 +83,7 @@ public class StsValueHint {
if (jp!=null) {
IType type = jp.findType(fqName);
if (type!=null) {
return create(type);
return create(jp, type);
}
}
} catch (Exception e) {
@@ -90,8 +92,8 @@ public class StsValueHint {
return null;
}
public static StsValueHint create(IType klass) {
return new StsValueHint(klass.getFullyQualifiedName(), javaDocSnippet(klass), DeprecationUtil.extract(klass)) {
public static StsValueHint create(IJavaProject project, IType klass) {
return new StsValueHint(klass.getFullyQualifiedName(), javaDocSnippet(project, klass), DeprecationUtil.extract(klass)) {
@Override
public IJavaElement getJavaElement() {
return klass;
@@ -117,14 +119,10 @@ public class StsValueHint {
return description;
}
private static Renderable javaDocSnippet(IJavaElement je) {
private static Renderable javaDocSnippet(IJavaProject project, IJavaElement je) {
return Renderables.lazy(() -> {
IJavadoc jdoc = je.getJavaDoc();
if (jdoc != null) {
return jdoc.getRenderable();
} else {
return Renderables.NO_DESCRIPTION;
}
SourceLinks sourceLinks = SourceLinkFactory.createSourceLinks(null);
return PropertyDocUtils.documentation(sourceLinks, project, je);
});
}

View File

@@ -122,7 +122,7 @@ public class TypeUtil {
}
private IJavaProject javaProject;
public TypeUtil(IJavaProject jp) {
//Note javaProject is allowed to be null, but only in unit testing context
// (This is so some tests can be run without an explicit jp needing to be created)
@@ -313,10 +313,10 @@ public class TypeUtil {
type.getFields().filter(f -> f.isEnumConstant()).forEach(f -> {
String rawName = f.getElementName();
if (addOriginal) {
enums.add(StsValueHint.create(rawName, f));
enums.add(StsValueHint.create(rawName, javaProject, f));
}
if (addLowerCased) {
enums.add(StsValueHint.create(StringUtil.upperCaseToHyphens(rawName), f));
enums.add(StsValueHint.create(StringUtil.upperCaseToHyphens(rawName), javaProject, f));
}
});
return enums.build();

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
* 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.ide.vscode.boot.metadata.util;
import java.util.Optional;
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.commons.java.IJavaElement;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.IMember;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
/**
* Boot properties documentation info utils
*
* @author Alex Boyko
*
*/
public class PropertyDocUtils {
/**
* Generates documentation for boot property coming from java element
*
* @param sourceLinks
* @param project
* @param je
* @return
*/
public static Renderable documentation(SourceLinks sourceLinks, IJavaProject project, IJavaElement je) {
IJavadoc javadoc = je.getJavaDoc();
Builder<Renderable> renderableBuilder = ImmutableList.builder();
renderableBuilder.add(javadoc == null ? Renderables.NO_DESCRIPTION: javadoc.getRenderable());
if (je instanceof IMember) {
IType containingType = je instanceof IType ? (IType) je : ((IMember)je).getDeclaringType();
if (je != null) {
renderableBuilder.add(Renderables.lineBreak());
renderableBuilder.add(Renderables.text("Type: "));
String type = containingType.getFullyQualifiedName();
Optional<String> url = SourceLinkFactory.createSourceLinks(null).sourceLinkUrlForFQName(project, type);
if (url.isPresent()) {
renderableBuilder.add(Renderables.link(type, url.get()));
} else {
renderableBuilder.add(Renderables.inlineSnippet(Renderables.text(type)));
}
}
}
return Renderables.concat(renderableBuilder.build());
}
}

View File

@@ -130,19 +130,25 @@ class PropertiesHoverCalculator {
private Renderable createRenderable(StsValueHint hint) {
Renderable description = hint.getDescription();
/*
* HACK: javadoc comment from HTML javadoc provider coming from
* generated HTML javadoc is very rich and decorating it further
* with some header like labels just makes it look worse
*/
if (description.toHtml().indexOf("<h") == -1) {
Builder<Renderable> renderableBuilder = ImmutableList.builder();
renderableBuilder.add(bold(text(hint.getValue())));
renderableBuilder.add(paragraph(description));
return concat(renderableBuilder.build());
} else {
return description;
try {
/**
* TODO: remove in the future once javadoc is obtained via the client from JDT LS
*/
/*
* HACK: javadoc comment from HTML javadoc provider coming from
* generated HTML javadoc is very rich and decorating it further
* with some header like labels just makes it look worse
*/
if (description.toHtml().indexOf("<h") == -1) {
Builder<Renderable> renderableBuilder = ImmutableList.builder();
renderableBuilder.add(bold(text(hint.getValue())));
renderableBuilder.add(paragraph(description));
return concat(renderableBuilder.build());
}
} catch (Throwable t) {
// Ignore. Might be that HTML content not supported
}
return description;
}
/**

View File

@@ -10,6 +10,8 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.yaml.completions;
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_EXISTS;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -18,10 +20,13 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.common.InformationTemplates;
import org.springframework.ide.vscode.boot.common.PropertyCompletionFactory;
import org.springframework.ide.vscode.boot.common.RelaxedNameConfig;
import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation;
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
import org.springframework.ide.vscode.boot.metadata.IndexNavigator;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
import org.springframework.ide.vscode.boot.metadata.hints.HintProvider;
@@ -33,10 +38,10 @@ import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil.BeanPropertyNameMode;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil.EnumCaseMode;
import org.springframework.ide.vscode.boot.metadata.types.TypedProperty;
import org.springframework.ide.vscode.boot.metadata.util.PropertyDocUtils;
import org.springframework.ide.vscode.commons.java.IField;
import org.springframework.ide.vscode.commons.java.IJavaElement;
import org.springframework.ide.vscode.commons.java.IMember;
import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.LazyProposalApplier;
@@ -44,12 +49,11 @@ import org.springframework.ide.vscode.commons.languageserver.completion.Scoreabl
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
import org.springframework.ide.vscode.commons.yaml.completion.AbstractYamlAssistContext;
import org.springframework.ide.vscode.commons.yaml.completion.TopLevelAssistContext;
import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContext;
@@ -66,13 +70,13 @@ import org.springframework.ide.vscode.commons.yaml.util.YamlUtil;
import com.google.common.collect.ImmutableList;
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.*;
/**
* Represents a context insied a "application.yml" file relative to which we can provide
* content assistance.
*/
public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistContext {
private static Logger log = LoggerFactory.getLogger(ApplicationYamlAssistContext.class);
protected final RelaxedNameConfig conf;
@@ -241,7 +245,7 @@ public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistCon
}
}
} catch (Exception e) {
Log.log(e);
log.error("", e);
}
return Collections.emptySet();
}
@@ -545,15 +549,12 @@ public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistCon
if (jes != null) {
for (IJavaElement je : jes) {
if (je instanceof IMember) {
IJavadoc javadoc = je.getJavaDoc();
if (javadoc != null) {
return javadoc.getRenderable();
}
return PropertyDocUtils.documentation(SourceLinkFactory.createSourceLinks(null), typeUtil.getJavaProject(), je);
}
}
}
} catch (Exception e) {
Log.log(e);
log.error("", e);
}
return Renderables.NO_DESCRIPTION;
}

View File

@@ -21,9 +21,7 @@ import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.JavaProject;
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
import org.springframework.ide.vscode.commons.java.LegacyJavaProject;
import org.springframework.ide.vscode.commons.maven.MavenBuilder;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
@@ -91,7 +89,7 @@ public class ProjectsHarness {
}
public static final IJavaProject dummyProject() throws URISyntaxException {
return new JavaProject(new BasicFileObserver(), new URI("file:///someplace/nonexistent"), new DelegatingCachedClasspath(() -> null, null));
return new LegacyJavaProject(new BasicFileObserver(), new URI("file:///someplace/nonexistent"), null, new DelegatingCachedClasspath(() -> null, null));
}
private ProjectsHarness(FileObserver fileObserver) {