Javadoc for source folders and maven atrifact jars

This commit is contained in:
BoykoAlex
2016-11-16 19:26:00 -05:00
parent 1e2af95da5
commit afd3762fe4
16 changed files with 553 additions and 145 deletions

View File

@@ -8,6 +8,7 @@ import java.nio.file.Path;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -17,11 +18,14 @@ import org.jboss.jandex.IndexReader;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;
import org.jboss.jandex.JarIndexer;
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
public class JandexIndex {
@@ -40,35 +44,29 @@ public class JandexIndex {
}
@FunctionalInterface
public static interface SourceContainerProvider {
File getSourceContainer(File container);
public static interface JavadocProviderFactory {
IJavadocProvider createJavadocProvider(File jarContainer);
}
private Supplier<List<Entry<File, IndexView>>> index;
private SourceContainerProvider sourceContainerProvider;
private JavadocProviderFactory javadocProviderFactory;
public JandexIndex(Stream<Path> classpathEntries) {
this(classpathEntries, jarFile -> null, Optional.empty());
private Cache<File, IJavadocProvider> javadocProvidersCache = CacheBuilder.newBuilder().build();
public JandexIndex(Stream<Path> classpathEntries, IndexFileFinder indexFileFinder, JavadocProviderFactory javadocProviderFactory) {
this(classpathEntries, indexFileFinder, Optional.empty(), javadocProviderFactory);
}
public JandexIndex(Stream<Path> classpathEntries, IndexFileFinder indexFileFinder) {
this(classpathEntries, indexFileFinder, Optional.empty());
public void setJvadocProviderFactory(JavadocProviderFactory sourceContainerProvider) {
this.javadocProviderFactory = sourceContainerProvider;
}
public JandexIndex(Stream<Path> classpathEntries, Optional<JandexIndex> baseIndex) {
this(classpathEntries, jarFile -> null, baseIndex);
public JavadocProviderFactory getJavadocProviderFactory() {
return javadocProviderFactory;
}
public void setSourceContainerProvider(SourceContainerProvider sourceContainerProvider) {
this.sourceContainerProvider = sourceContainerProvider;
}
public SourceContainerProvider getSourceContainerProvider() {
return sourceContainerProvider;
}
public JandexIndex(Stream<Path> classpathEntries, IndexFileFinder indexFileFinder, Optional<JandexIndex> baseIndex) {
public JandexIndex(Stream<Path> classpathEntries, IndexFileFinder indexFileFinder, Optional<JandexIndex> baseIndex, JavadocProviderFactory javadocProviderFactory) {
index = Suppliers.memoize(() -> {
List<Entry<File, IndexView>> indices = buildIndex(classpathEntries, indexFileFinder).collect(Collectors.toList());
if (baseIndex.isPresent()) {
@@ -76,6 +74,7 @@ public class JandexIndex {
}
return indices;
});
this.javadocProviderFactory = javadocProviderFactory;
}
private Stream<Entry<File, IndexView>> buildIndex(Stream<Path> classpathEntries, IndexFileFinder indexFileFinder) {
@@ -164,7 +163,14 @@ public class JandexIndex {
IType getClassByName(DotName className) {
Optional<Entry<File, ClassInfo>> pair = index.get().stream().map(e -> new Entry<>(e.key, e.value.getClassByName(className))).filter(e -> e.value != null).findFirst();
if (pair.isPresent()) {
return Wrappers.wrap(this, pair.get().value, pair.get().key);
File classpathResource = pair.get().key;
IJavadocProvider javadocProvider = null;
try {
javadocProvider = javadocProvidersCache.get(pair.get().key, () -> javadocProviderFactory == null ? null : javadocProviderFactory.createJavadocProvider(classpathResource));
} catch (ExecutionException e) {
Log.log(e);
}
return Wrappers.wrap(this, pair.get().value, javadocProvider);
} else {
return null;
}

View File

@@ -2,7 +2,6 @@ package org.springframework.ide.vscode.commons.jandex;
import static org.springframework.ide.vscode.commons.util.Assert.isNotNull;
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -21,16 +20,17 @@ import org.springframework.ide.vscode.commons.java.Flags;
import org.springframework.ide.vscode.commons.java.IAnnotation;
import org.springframework.ide.vscode.commons.java.IField;
import org.springframework.ide.vscode.commons.java.IJavaType;
import org.springframework.ide.vscode.commons.java.IJavadoc;
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
import org.springframework.ide.vscode.commons.java.IMemberValuePair;
import org.springframework.ide.vscode.commons.java.IMethod;
import org.springframework.ide.vscode.commons.java.IPrimitiveType;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.java.IVoidType;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
public class Wrappers {
public static IType wrap(JandexIndex index, ClassInfo info, File container) {
public static IType wrap(JandexIndex index, ClassInfo info, IJavadocProvider javadocProvider) {
if (info == null) {
return null;
}
@@ -49,12 +49,12 @@ public class Wrappers {
@Override
public String getElementName() {
return info.simpleName();
return info.simpleName() == null ? info.name().local() : info.simpleName();
}
@Override
public HtmlSnippet getJavaDoc() {
throw new UnsupportedOperationException("Not yet implemented");
public IJavadoc getJavaDoc() {
return javadocProvider == null ? null : javadocProvider.getJavadoc(this);
}
@Override
@@ -65,7 +65,7 @@ public class Wrappers {
@Override
public Stream<IAnnotation> getAnnotations() {
// TODO: check correctness!
return info.annotations().get(info.name()).stream().map(Wrappers::wrap);
return info.annotations().get(info.name()).stream().map(a -> wrap(a, javadocProvider));
}
@Override
@@ -90,26 +90,26 @@ public class Wrappers {
@Override
public IField getField(String name) {
return wrap(index, info.field(name), container);
return wrap(index, info.field(name), javadocProvider);
}
@Override
public Stream<IField> getFields() {
return info.fields().stream().map(f -> {
return wrap(index, f, container);
return wrap(index, f, javadocProvider);
});
}
@Override
public IMethod getMethod(String name, Stream<IJavaType> parameters) {
List<Type> typeParameters = parameters.map(Wrappers::from).collect(Collectors.toList());
return wrap(index, info.method(name, typeParameters.toArray(new Type[typeParameters.size()])), container);
return wrap(index, info.method(name, typeParameters.toArray(new Type[typeParameters.size()])), javadocProvider);
}
@Override
public Stream<IMethod> getMethods() {
return info.methods().stream().map(m -> {
return wrap(index, m, container);
return wrap(index, m, javadocProvider);
});
}
@@ -121,7 +121,7 @@ public class Wrappers {
};
}
public static IField wrap(JandexIndex index, FieldInfo field, File container) {
public static IField wrap(JandexIndex index, FieldInfo field, IJavadocProvider javadocProvider) {
if (field == null) {
return null;
}
@@ -134,7 +134,7 @@ public class Wrappers {
@Override
public IType getDeclaringType() {
return wrap(index, field.declaringClass(), container);
return wrap(index, field.declaringClass(), javadocProvider);
}
@Override
@@ -143,8 +143,8 @@ public class Wrappers {
}
@Override
public HtmlSnippet getJavaDoc() {
throw new UnsupportedOperationException("Not yet implemented");
public IJavadoc getJavaDoc() {
return javadocProvider == null ? null : javadocProvider.getJavadoc(this);
}
@Override
@@ -155,7 +155,7 @@ public class Wrappers {
@Override
public Stream<IAnnotation> getAnnotations() {
return field.annotations().stream().map(a -> {
return wrap(a);
return wrap(a, javadocProvider);
});
}
@@ -171,7 +171,7 @@ public class Wrappers {
};
}
public static IMethod wrap(JandexIndex index, MethodInfo method, File container) {
public static IMethod wrap(JandexIndex index, MethodInfo method, IJavadocProvider javadocProvider) {
isNotNull(index);
isNotNull(method);
return new IMethod() {
@@ -183,7 +183,7 @@ public class Wrappers {
@Override
public IType getDeclaringType() {
return wrap(index, method.declaringClass(), container);
return wrap(index, method.declaringClass(), javadocProvider);
}
@Override
@@ -192,8 +192,8 @@ public class Wrappers {
}
@Override
public HtmlSnippet getJavaDoc() {
throw new UnsupportedOperationException("Not yet implemented");
public IJavadoc getJavaDoc() {
return javadocProvider == null ? null : javadocProvider.getJavadoc(this);
}
@Override
@@ -203,7 +203,7 @@ public class Wrappers {
@Override
public Stream<IAnnotation> getAnnotations() {
return method.annotations().stream().map(Wrappers::wrap);
return method.annotations().stream().map(a -> wrap(a, javadocProvider));
}
@Override
@@ -233,7 +233,7 @@ public class Wrappers {
};
}
public static IAnnotation wrap(AnnotationInstance annotation) {
public static IAnnotation wrap(AnnotationInstance annotation, IJavadocProvider javadocProvider) {
isNotNull(annotation);
return new IAnnotation() {
@@ -243,8 +243,8 @@ public class Wrappers {
}
@Override
public HtmlSnippet getJavaDoc() {
throw new UnsupportedOperationException("Not yet implemented");
public IJavadoc getJavaDoc() {
return javadocProvider == null ? null : javadocProvider.getJavadoc(this);
}
@Override

View File

@@ -1,9 +1,7 @@
package org.springframework.ide.vscode.commons.java;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
public interface IJavaElement {
String getElementName();
HtmlSnippet getJavaDoc();
IJavadoc getJavaDoc();
boolean exists();
}

View File

@@ -0,0 +1,13 @@
package org.springframework.ide.vscode.commons.java;
public interface IJavadoc {
String raw();
String plainText();
String html();
String markdown();
}

View File

@@ -0,0 +1,12 @@
package org.springframework.ide.vscode.commons.java;
public interface IJavadocProvider {
IJavadoc getJavadoc(IType type);
IJavadoc getJavadoc(IField field);
IJavadoc getJavadoc(IMethod method);
IJavadoc getJavadoc(IAnnotation method);
}

View File

@@ -0,0 +1,160 @@
package org.springframework.ide.vscode.commons.java.parser;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Optional;
import org.springframework.ide.vscode.commons.java.IAnnotation;
import org.springframework.ide.vscode.commons.java.IField;
import org.springframework.ide.vscode.commons.java.IJavadoc;
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
import org.springframework.ide.vscode.commons.java.IMethod;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.util.Log;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.visitor.GenericVisitorAdapter;
public abstract class AbstractJavadocProvider implements IJavadocProvider {
public IJavadoc getJavadoc(IType type) {
if (type.isEnum()) {
EnumDeclaration declaration = getEnumDeclaration(type);
return declaration.getJavaDoc() == null ? null : new Javadoc(declaration.getJavaDoc());
} else {
ClassOrInterfaceDeclaration declaration = getClassOrInterfaceDeclaration(type);
return declaration.getJavaDoc() == null ? null : new Javadoc(declaration.getJavaDoc());
}
}
public IJavadoc getJavadoc(IField field) {
IType declaringType = field.getDeclaringType();
if (declaringType.isEnum()) {
FieldDeclaration declaration = createVisitorToFindField(field).visit(getEnumDeclaration(declaringType), null);
return declaration.getJavaDoc() == null ? null : new Javadoc(declaration.getJavaDoc());
} else {
FieldDeclaration declaration = createVisitorToFindField(field).visit(getClassOrInterfaceDeclaration(declaringType), null);
return declaration.getJavaDoc() == null ? null : new Javadoc(declaration.getJavaDoc());
}
}
public IJavadoc getJavadoc(IMethod method) {
if (method.parameters().findFirst().isPresent()) {
throw new UnsupportedOperationException("Only methods with no parameters are supported");
}
IType declaringType = method.getDeclaringType();
if (declaringType.isEnum()) {
MethodDeclaration declaration = createVisitorToFindMethod(method).visit(getEnumDeclaration(declaringType), null);
return declaration.getJavaDoc() == null ? null : new Javadoc(declaration.getJavaDoc());
} else {
MethodDeclaration declaration = createVisitorToFindMethod(method).visit(getClassOrInterfaceDeclaration(declaringType), null);
return declaration.getJavaDoc() == null ? null : new Javadoc(declaration.getJavaDoc());
}
}
public IJavadoc getJavadoc(IAnnotation annotation) {
throw new UnsupportedOperationException("Not yet implemented");
}
private CompilationUnit getCompilationUnit(IType type) {
try {
URL sourceUrl = createSourceUrl(type);
return CompilationUnitIndex.DEFAULT.getCompilationUnit(sourceUrl);
} catch (MalformedURLException e) {
Log.log("Invalid source URL for type " + type, e);
return null;
}
}
private EnumDeclaration getEnumDeclaration(IType type) {
IType parent = type.getDeclaringType();
if (parent == null) {
CompilationUnit cu = getCompilationUnit(type);
return createVisitorToFindEnum(type).visit(cu, null);
} else {
if (parent.isEnum()) {
EnumDeclaration declaration = getEnumDeclaration(parent);
return createVisitorToFindEnum(type).visit(declaration, null);
} else {
ClassOrInterfaceDeclaration declaration = getClassOrInterfaceDeclaration(parent);
return createVisitorToFindEnum(type).visit(declaration, null);
}
}
}
private ClassOrInterfaceDeclaration getClassOrInterfaceDeclaration(IType type) {
IType parent = type.getDeclaringType();
if (parent == null) {
CompilationUnit cu = getCompilationUnit(type);
return createVisitorToFindClassOrInterface(type).visit(cu, null);
} else {
if (parent.isEnum()) {
EnumDeclaration declaration = getEnumDeclaration(parent);
return createVisitorToFindClassOrInterface(type).visit(declaration, null);
} else {
ClassOrInterfaceDeclaration declaration = getClassOrInterfaceDeclaration(parent);
return createVisitorToFindClassOrInterface(type).visit(declaration, null);
}
}
}
private GenericVisitorAdapter<ClassOrInterfaceDeclaration, Object> createVisitorToFindClassOrInterface(IType type) {
return new GenericVisitorAdapter<ClassOrInterfaceDeclaration, Object>() {
@Override
public ClassOrInterfaceDeclaration visit(ClassOrInterfaceDeclaration n, Object arg) {
if (n.getName().equals(type.getElementName())) {
return n;
} else {
return super.visit(n, arg);
}
}
};
}
private GenericVisitorAdapter<EnumDeclaration, Object> createVisitorToFindEnum(IType type) {
return new GenericVisitorAdapter<EnumDeclaration, Object>() {
@Override
public EnumDeclaration visit(EnumDeclaration n, Object arg) {
if (n.getName().equals(type.getElementName())) {
return n;
} else {
return super.visit(n, arg);
}
}
};
}
private GenericVisitorAdapter<MethodDeclaration, Object> createVisitorToFindMethod(IMethod method) {
return new GenericVisitorAdapter<MethodDeclaration, Object>() {
@Override
public MethodDeclaration visit(MethodDeclaration n, Object arg) {
if (n.getParameters().isEmpty() && n.getName().equals(method.getElementName())) {
return n;
}
return null;
}
};
}
private GenericVisitorAdapter<FieldDeclaration, Object> createVisitorToFindField(IField field) {
return new GenericVisitorAdapter<FieldDeclaration, Object>() {
@Override
public FieldDeclaration visit(FieldDeclaration n, Object arg) {
Optional<VariableDeclarator> variable = n.getVariables().stream().filter(v -> v.getId().getName().equals(field.getElementName())).findFirst();
return variable.isPresent() ? n : null;
}
};
}
abstract protected URL createSourceUrl(IType type) throws MalformedURLException;
}

View File

@@ -0,0 +1,31 @@
package org.springframework.ide.vscode.commons.java.parser;
import java.net.MalformedURLException;
import java.net.URL;
import org.springframework.ide.vscode.commons.java.IType;
import com.google.common.base.Supplier;
public class JarSourcesJavadocProvider extends AbstractJavadocProvider {
private Supplier<URL> sourcesJarUrl;
public JarSourcesJavadocProvider(Supplier<URL> sourcesJarUrl) {
super();
this.sourcesJarUrl = sourcesJarUrl;
}
@Override
protected URL createSourceUrl(IType type) throws MalformedURLException {
StringBuilder sourceUrlStr = new StringBuilder();
sourceUrlStr.append("jar:");
sourceUrlStr.append(sourcesJarUrl.get());
sourceUrlStr.append("!");
sourceUrlStr.append('/');
sourceUrlStr.append(type.getFullyQualifiedName().replaceAll("\\.", "/"));
sourceUrlStr.append(".java");
return new URL(sourceUrlStr.toString());
}
}

View File

@@ -0,0 +1,35 @@
package org.springframework.ide.vscode.commons.java.parser;
import org.springframework.ide.vscode.commons.java.IJavadoc;
import com.github.javaparser.ast.comments.JavadocComment;
final class Javadoc implements IJavadoc {
private JavadocComment javadocComment;
Javadoc(JavadocComment javadocComment) {
this.javadocComment = javadocComment;
}
@Override
public String raw() {
return javadocComment.getContent();
}
@Override
public String plainText() {
throw new UnsupportedOperationException("Not yet implemnted");
}
@Override
public String html() {
throw new UnsupportedOperationException("Not yet implemnted");
}
@Override
public String markdown() {
throw new UnsupportedOperationException("Not yet implemnted");
}
}

View File

@@ -0,0 +1,23 @@
package org.springframework.ide.vscode.commons.java.parser;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.springframework.ide.vscode.commons.java.IType;
public class SourceFolderJavadocProvider extends AbstractJavadocProvider {
private File sourceFolder;
public SourceFolderJavadocProvider(File sourceFolder) {
super();
this.sourceFolder = sourceFolder;
}
@Override
protected URL createSourceUrl(IType type) throws MalformedURLException {
return new File(sourceFolder, type.getFullyQualifiedName().replaceAll("\\.", "/") + ".java").toURI().toURL();
}
}