diff --git a/vscode-extensions/commons/commons-java/pom.xml b/vscode-extensions/commons/commons-java/pom.xml index abb8bdd51..b8cc94fc6 100644 --- a/vscode-extensions/commons/commons-java/pom.xml +++ b/vscode-extensions/commons/commons-java/pom.xml @@ -23,5 +23,10 @@ jandex 2.0.3.Final + + com.github.javaparser + javaparser-core + 2.5.1 + \ No newline at end of file diff --git a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java index c713c0ac4..871a6e7f0 100644 --- a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java +++ b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java @@ -6,11 +6,12 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.util.Iterator; +import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.jboss.jandex.CompositeIndex; +import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.IndexReader; import org.jboss.jandex.IndexView; @@ -24,12 +25,28 @@ import com.google.common.base.Suppliers; public class JandexIndex { + private static class Entry { + K key; + V value; + Entry(K key, V value) { + this.key = key; + this.value = value; + } + } + @FunctionalInterface public static interface IndexFileFinder { File findIndexFile(File jarFile); } - private Supplier index; + @FunctionalInterface + public static interface SourceContainerProvider { + File getSourceContainer(File container); + } + + private Supplier>> index; + + private SourceContainerProvider sourceContainerProvider; public JandexIndex(Stream classpathEntries) { this(classpathEntries, jarFile -> null, Optional.empty()); @@ -43,31 +60,38 @@ public class JandexIndex { this(classpathEntries, jarFile -> null, baseIndex); } + public void setSourceContainerProvider(SourceContainerProvider sourceContainerProvider) { + this.sourceContainerProvider = sourceContainerProvider; + } + + public SourceContainerProvider getSourceContainerProvider() { + return sourceContainerProvider; + } + public JandexIndex(Stream classpathEntries, IndexFileFinder indexFileFinder, Optional baseIndex) { index = Suppliers.memoize(() -> { + List> indices = buildIndex(classpathEntries, indexFileFinder).collect(Collectors.toList()); if (baseIndex.isPresent()) { - return CompositeIndex.create(baseIndex.get().index.get(), buildIndex(classpathEntries, indexFileFinder)); - } else { - return buildIndex(classpathEntries, indexFileFinder); + indices.addAll(baseIndex.get().index.get()); } + return indices; }); } - private static CompositeIndex buildIndex(Stream classpathEntries, IndexFileFinder indexFileFinder) { - return CompositeIndex.create(classpathEntries + private Stream> buildIndex(Stream classpathEntries, IndexFileFinder indexFileFinder) { + return classpathEntries .map(entry -> entry.toFile()) .map(file -> { + Optional index = Optional.empty(); if (file.isFile() && file.getName().endsWith(".jar")) { - return indexJar(file, indexFileFinder); + index = indexJar(file, indexFileFinder); } else if (file.isDirectory()) { - return indexFolder(file); - } else { - return Optional.empty(); + index = indexFolder(file); } + return new Entry<>(file, index); }) - .filter(o -> o.isPresent()) - .map(o -> o.get()) - .collect(Collectors.toList())); + .filter(e -> e.value.isPresent()) + .map(e -> new Entry<>(e.key, e.value.get())); } private static Optional indexFolder(File folder) { @@ -134,8 +158,16 @@ public class JandexIndex { } public IType findType(String fqName) { - IndexView compositeIndex = index.get(); - return Wrappers.wrap(compositeIndex, compositeIndex.getClassByName(DotName.createSimple(fqName))); + return getClassByName(DotName.createSimple(fqName)); + } + + IType getClassByName(DotName className) { + Optional> 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); + } else { + return null; + } } } diff --git a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java index 333d897ff..0d9e65476 100644 --- a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java +++ b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java @@ -2,6 +2,7 @@ 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; @@ -29,7 +30,7 @@ import org.springframework.ide.vscode.commons.util.HtmlSnippet; public class Wrappers { - public static IType wrap(IndexView index, ClassInfo info) { + public static IType wrap(JandexIndex index, ClassInfo info, File container) { if (info == null) { return null; } @@ -43,7 +44,7 @@ public class Wrappers { @Override public IType getDeclaringType() { DotName enclosingClass = info.enclosingClass(); - return enclosingClass == null ? null : wrap(index, index.getClassByName(enclosingClass)); + return enclosingClass == null ? null : index.getClassByName(enclosingClass); } @Override @@ -89,26 +90,26 @@ public class Wrappers { @Override public IField getField(String name) { - return wrap(index, info.field(name)); + return wrap(index, info.field(name), container); } @Override public Stream getFields() { return info.fields().stream().map(f -> { - return wrap(index, f); + return wrap(index, f, container); }); } @Override public IMethod getMethod(String name, Stream parameters) { List typeParameters = parameters.map(Wrappers::from).collect(Collectors.toList()); - return wrap(index, info.method(name, typeParameters.toArray(new Type[typeParameters.size()]))); + return wrap(index, info.method(name, typeParameters.toArray(new Type[typeParameters.size()])), container); } @Override public Stream getMethods() { return info.methods().stream().map(m -> { - return wrap(index, m); + return wrap(index, m, container); }); } @@ -120,7 +121,7 @@ public class Wrappers { }; } - public static IField wrap(IndexView index, FieldInfo field) { + public static IField wrap(JandexIndex index, FieldInfo field, File container) { if (field == null) { return null; } @@ -133,7 +134,7 @@ public class Wrappers { @Override public IType getDeclaringType() { - return wrap(index, field.declaringClass()); + return wrap(index, field.declaringClass(), container); } @Override @@ -170,7 +171,7 @@ public class Wrappers { }; } - public static IMethod wrap(IndexView index, MethodInfo method) { + public static IMethod wrap(JandexIndex index, MethodInfo method, File container) { isNotNull(index); isNotNull(method); return new IMethod() { @@ -182,7 +183,7 @@ public class Wrappers { @Override public IType getDeclaringType() { - return wrap(index, method.declaringClass()); + return wrap(index, method.declaringClass(), container); } @Override diff --git a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/CompilationUnitIndex.java b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/CompilationUnitIndex.java new file mode 100644 index 000000000..ce8b26028 --- /dev/null +++ b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/CompilationUnitIndex.java @@ -0,0 +1,13 @@ +package org.springframework.ide.vscode.commons.java.parser; + +import java.net.URL; + +import com.github.javaparser.ast.CompilationUnit; + +public interface CompilationUnitIndex { + + static final CompilationUnitIndex DEFAULT = new DefaultCompilationUnitIndex(); + + CompilationUnit getCompilationUnit(URL url); + +} diff --git a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/DefaultCompilationUnitIndex.java b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/DefaultCompilationUnitIndex.java new file mode 100644 index 000000000..7a74b6fdd --- /dev/null +++ b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/DefaultCompilationUnitIndex.java @@ -0,0 +1,44 @@ +package org.springframework.ide.vscode.commons.java.parser; + +import java.io.InputStream; +import java.net.URL; +import java.util.concurrent.ExecutionException; + +import org.springframework.ide.vscode.commons.util.Log; + +import com.github.javaparser.JavaParser; +import com.github.javaparser.ParseException; +import com.github.javaparser.ast.CompilationUnit; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +class DefaultCompilationUnitIndex implements CompilationUnitIndex { + + private LoadingCache cache = CacheBuilder.newBuilder().build(new CacheLoader() { + + @Override + public CompilationUnit load(URL url) throws Exception { + InputStream in = url.openStream(); + try { + return JavaParser.parse(in); + } catch (ParseException e) { + in.close(); + Log.log("Failed to parse java source file: " + url, e); + } + return null; + } + + }); + + @Override + public CompilationUnit getCompilationUnit(URL url) { + try { + return cache.get(url); + } catch (ExecutionException e) { + Log.log(e); + } + return null; + } + +}