diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectClasspath.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectClasspath.java index 9f562e910..de5e6b0c6 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectClasspath.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectClasspath.java @@ -22,7 +22,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.gradle.tooling.model.build.BuildEnvironment; +import org.gradle.tooling.model.eclipse.EclipseExternalDependency; import org.gradle.tooling.model.eclipse.EclipseProject; +import org.gradle.tooling.model.eclipse.EclipseProjectDependency; import org.springframework.ide.vscode.commons.jandex.JandexClasspath; import org.springframework.ide.vscode.commons.jandex.JandexIndex; import org.springframework.ide.vscode.commons.java.ClasspathData; @@ -30,9 +32,12 @@ import org.springframework.ide.vscode.commons.java.IClasspath; import org.springframework.ide.vscode.commons.java.IJavadocProvider; import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider; import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer; +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.util.Log; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; /** * Implementation of {@link IClasspath} for Gradle projects @@ -87,24 +92,29 @@ public class GradleProjectClasspath extends JandexClasspath { } @Override - public ImmutableList getClasspathEntries() throws Exception { + public ImmutableList getClasspathEntries() throws Exception { EclipseProject root = getRootProject(); if (project == null) { return ImmutableList.of(); } else { - ImmutableList classpathEntries = ImmutableList.copyOf(Stream.concat(project.getClasspath().stream().map(dep -> dep.getFile().toPath()), - project.getProjectDependencies().stream() - .map(d -> findPeer(root, d.getTargetProject().getName())) - .filter(o -> o.isPresent()) - .map(o -> o.get()) - .map(p -> p.getProjectDirectory().toPath().resolve(p.getOutputLocation().getPath())) - ).collect(Collectors.toList())); - return classpathEntries; + Builder entries = ImmutableList.builder(); + for (EclipseExternalDependency dep : project.getClasspath()) { + entries.add(new CPE(Classpath.ENTRY_KIND_BINARY, dep.getFile().toPath().toString())); + } + for (EclipseProjectDependency dep : project.getProjectDependencies()) { + EclipseProject peer = findPeer(root, dep.getTargetProject().getName()); + if (peer!=null) { + entries.add(new CPE(Classpath.ENTRY_KIND_BINARY, + peer.getProjectDirectory().toPath().resolve(peer.getOutputLocation().getPath()).toString() + )); + } + } + return entries.build(); } } - private Optional findPeer(EclipseProject root, String name) { - return root.getChildren().stream().filter(p -> p.getName().equals(name)).findFirst(); + private EclipseProject findPeer(EclipseProject root, String name) { + return root.getChildren().stream().filter(p -> p.getName().equals(name)).findFirst().orElse(null); } @Override diff --git a/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java b/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java index 7def43ca1..817b5afec 100644 --- a/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java +++ b/headless-services/commons/commons-gradle/src/test/java/org/springframework/ide/vscode/commons/gradle/GradleProjectTest.java @@ -33,6 +33,7 @@ import org.junit.Test; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService; import org.springframework.ide.vscode.commons.util.BasicFileObserver; @@ -76,7 +77,7 @@ public class GradleProjectTest { @Test public void testEclipseGradleProject() throws Exception { GradleJavaProject project = getGradleProject("empty-gradle-project"); - ImmutableList calculatedClassPath = project.getClasspath().getClasspathEntries(); + ImmutableList calculatedClassPath = project.getClasspath().getClasspathEntries(); assertEquals(48, calculatedClassPath.size()); } @@ -122,7 +123,7 @@ public class GradleProjectTest { GradleJavaProject cachedProject = manager.project(gradleFile); assertNotNull(cachedProject); - ImmutableList calculatedClassPath = cachedProject.getClasspath().getClasspathEntries(); + ImmutableList calculatedClassPath = cachedProject.getClasspath().getClasspathEntries(); assertEquals(48, calculatedClassPath.size()); fileObserver.notifyFileChanged(gradleFile.toURI().toString()); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java index cd130ce58..edd0554a3 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java @@ -12,6 +12,7 @@ package org.springframework.ide.vscode.commons.jandex; import java.io.File; import java.nio.file.Path; +import java.util.Collection; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -24,6 +25,7 @@ import org.springframework.ide.vscode.commons.util.Log; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; import reactor.core.publisher.Flux; import reactor.util.function.Tuple2; @@ -51,13 +53,16 @@ public abstract class JandexClasspath implements IClasspath { } protected JandexIndex createIndex() { - Stream classpathEntries = Stream.empty(); + Collection classpathEntries = ImmutableList.of(); try { - classpathEntries = getClasspathEntries().stream(); + classpathEntries = getClasspathEntryPaths(); + for (Path path : classpathEntries) { + System.out.println(path); + } } catch (Exception e) { Log.log(e); } - return new JandexIndex(classpathEntries.map(p -> p.toFile()).collect(Collectors.toList()), jarFile -> findIndexFile(jarFile), classpathResource -> { + return new JandexIndex(classpathEntries.stream().map(p -> p.toFile()).collect(Collectors.toList()), jarFile -> findIndexFile(jarFile), classpathResource -> { switch (providerType) { // case JAVA_PARSER: // return createParserJavadocProvider(classpathResource); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/BootProjectUtil.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/BootProjectUtil.java index f9545e954..d1e797ae3 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/BootProjectUtil.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/BootProjectUtil.java @@ -20,7 +20,7 @@ public class BootProjectUtil { try { IClasspath cp = jp.getClasspath(); if (cp!=null) { - return cp.getClasspathEntries().stream().anyMatch(cpe -> isBootEntry(cpe)); + return cp.getClasspathEntryPaths().stream().anyMatch(cpe -> isBootEntry(cpe)); } } catch (Exception e) { Log.log(e); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathData.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathData.java index ba7fa9653..f7c509933 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathData.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathData.java @@ -11,11 +11,13 @@ package org.springframework.ide.vscode.commons.java; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.util.Log; import com.google.common.base.Objects; @@ -25,18 +27,58 @@ public class ClasspathData { final public static ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(), Collections.emptySet(), null); - final public String name; - final public Set classpathEntries; - final public Set classpathResources; - final public Path outputFolder; + private String name; + private Set classpathEntries; + private Set classpathResources; + private String outputFolder; - public ClasspathData(String name, Set classpathEntries, Set classpathResources, Path outputFolder) { + public ClasspathData() { + } + + public ClasspathData(String name, Set classpathEntries, Set classpathResources, String outputFolder) { this.name = name; this.classpathEntries = classpathEntries; this.classpathResources = classpathResources; this.outputFolder = outputFolder; } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getClasspathEntries() { + return classpathEntries; + } + + public void setClasspathEntries(Set classpathEntries) { + this.classpathEntries = classpathEntries; + } + + public Set getClasspathResources() { + return classpathResources; + } + + public void setClasspathResources(Set classpathResources) { + this.classpathResources = classpathResources; + } + + public String getOutputFolder() { + return outputFolder; + } + + public void setOutputFolder(String outputFolder) { + this.outputFolder = outputFolder; + } + + public static ClasspathData getEmptyClasspathData() { + return EMPTY_CLASSPATH_DATA; + } + @Override public boolean equals(Object obj) { if (obj instanceof ClasspathData) { @@ -52,9 +94,12 @@ public class ClasspathData { return false; } - public static ClasspathData from(String name, Collection classpathEntries, + public static ClasspathData from(String name, Collection classpathEntries, Collection classpathResources, Path outputFolder) { - return new ClasspathData(name, new LinkedHashSet<>(classpathEntries), new LinkedHashSet<>(classpathResources), - outputFolder); + return new ClasspathData(name, + new LinkedHashSet<>(classpathEntries), + new LinkedHashSet<>(classpathResources), + outputFolder==null ? null : outputFolder.toString() + ); } } \ No newline at end of file diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathFileBasedCache.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathFileBasedCache.java index 896a6f5b1..eab66e9a3 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathFileBasedCache.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathFileBasedCache.java @@ -23,6 +23,8 @@ import org.json.JSONObject; import org.json.JSONTokener; import org.springframework.ide.vscode.commons.util.Log; +import com.fasterxml.jackson.databind.ObjectMapper; + public class ClasspathFileBasedCache { public static final ClasspathFileBasedCache NULL = new ClasspathFileBasedCache(null); @@ -45,13 +47,9 @@ public class ClasspathFileBasedCache { FileWriter writer = null; try { Files.createDirectories(file.getParentFile().toPath()); - JSONObject json = new JSONObject(); - json.put(NAME_PROPERTY, data.name); - json.put(CLASSPATH_ENTRIES_PROPERTY, data.classpathEntries.stream().map(e -> e.toString()).collect(Collectors.toList())); - json.put(CLASSPATH_RESOURCES_PROPERTY, data.classpathResources); - json.put(OUTPUT_FOLDER_PROPERTY, data.outputFolder); writer = new FileWriter(file); - json.write(writer); + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(writer, data); } catch (IOException e) { Log.log(e); } finally { @@ -69,30 +67,12 @@ public class ClasspathFileBasedCache { public boolean isCached() { return file != null && file.exists(); } - - public synchronized ClasspathData load() { + public synchronized ClasspathData load() { if (file != null && file.exists()) { + ObjectMapper mapper = new ObjectMapper(); try { - JSONObject json = new JSONObject(new JSONTokener(new FileInputStream(file))); - String name = json.getString(NAME_PROPERTY); - JSONArray classpathEntriesJson = json.optJSONArray(CLASSPATH_ENTRIES_PROPERTY); - JSONArray classpathResourcesJson = json.optJSONArray(CLASSPATH_RESOURCES_PROPERTY); - String outputFolderStr = json.optString(OUTPUT_FOLDER_PROPERTY); - - return new ClasspathData( - name, - classpathEntriesJson == null ? Collections.emptySet() : classpathEntriesJson.toList().stream() - .filter(o -> o instanceof String) - .map(o -> (String) o) - .map(s -> new File(s).toPath()) - .collect(Collectors.toSet()), - classpathResourcesJson == null ? Collections.emptySet() : classpathResourcesJson.toList().stream() - .filter(o -> o instanceof String) - .map(o -> (String) o) - .collect(Collectors.toSet()), - outputFolderStr == null ? null : new File(outputFolderStr).toPath() - ); + return mapper.readValue(file, ClasspathData.class); } catch (Throwable e) { Log.log(e); } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/DelegatingCachedClasspath.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/DelegatingCachedClasspath.java index f7d160015..21423c872 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/DelegatingCachedClasspath.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/DelegatingCachedClasspath.java @@ -13,11 +13,13 @@ package org.springframework.ide.vscode.commons.java; import java.io.File; import java.net.URL; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.util.Assert; import com.google.common.base.Objects; @@ -79,22 +81,23 @@ public class DelegatingCachedClasspath implements IClasspa @Override public String getName() { - return cachedData.get().name; + return cachedData.get().getName(); } @Override public Path getOutputFolder() { - return cachedData.get().outputFolder; + String of = cachedData.get().getOutputFolder(); + return of == null ? null : Paths.get(of); } @Override - public ImmutableList getClasspathEntries() throws Exception { - return ImmutableList.copyOf(cachedData.get().classpathEntries); + public ImmutableList getClasspathEntries() throws Exception { + return ImmutableList.copyOf(cachedData.get().getClasspathEntries()); } @Override public ImmutableList getClasspathResources() { - return ImmutableList.copyOf(cachedData.get().classpathResources); + return ImmutableList.copyOf(cachedData.get().getClasspathResources()); } public boolean isCached() { diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java index 5fcfd0951..bff3270ed 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java @@ -13,9 +13,15 @@ package org.springframework.ide.vscode.commons.java; import java.io.File; import java.net.URL; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.LinkedHashSet; import java.util.Optional; import java.util.function.Predicate; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; + import com.google.common.collect.ImmutableList; import reactor.core.publisher.Flux; @@ -50,7 +56,7 @@ public interface IClasspath { * @return collection of classpath entries in a form file/folder paths * @throws Exception */ - ImmutableList getClasspathEntries() throws Exception; + Collection getClasspathEntries() throws Exception; /** * Classpath resources paths relative to the source folder path @@ -67,4 +73,25 @@ public interface IClasspath { void reindex(); Optional sourceContainer(File classpathResource); + + @Deprecated + default Collection getClasspathEntryPaths() throws Exception { + LinkedHashSet entries = new LinkedHashSet<>(); + for (CPE cpe : this.getClasspathEntries()) { + if (Classpath.ENTRY_KIND_BINARY.equals(cpe.getKind())) { + entries.add(Paths.get(cpe.getPath())); + } else if (Classpath.ENTRY_KIND_SOURCE.equals(cpe.getKind())) { + String of = cpe.getOutputFolder(); + if (of!=null) { + entries.add(Paths.get(cpe.getOutputFolder())); + } else { + Path op = getOutputFolder(); + if (op!=null) { + entries.add(op); + } + } + } + } + return ImmutableList.copyOf(entries); + } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/jdt/ls/Classpath.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/jdt/ls/Classpath.java index 288ed2a26..6136ffc52 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/jdt/ls/Classpath.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/jdt/ls/Classpath.java @@ -4,10 +4,9 @@ package org.springframework.ide.vscode.commons.languageserver.jdt.ls; import java.util.List; public class Classpath { - + public static final String ENTRY_KIND_SOURCE = "source"; public static final String ENTRY_KIND_BINARY = "binary"; - public static final String OUTPUT_LOCATION = "output_location"; private List entries; private String defaultOutputFolder; @@ -43,6 +42,21 @@ public class Classpath { private String kind; private String path; + /** + * This only applies for 'source' entries. + */ + private String outputFolder; + + public String getOutputFolder() { + return outputFolder; + } + + public void setOutputFolder(String outputFolder) { + this.outputFolder = outputFolder; + } + + public CPE() {} + public CPE(String kind, String path) { super(); this.kind = kind; @@ -66,10 +80,50 @@ public class Classpath { } @Override - public String toString() { - return "CPE [kind=" + kind + ", path=" + path + "]\n"; + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((kind == null) ? 0 : kind.hashCode()); + result = prime * result + ((outputFolder == null) ? 0 : outputFolder.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + return result; } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CPE other = (CPE) obj; + if (kind == null) { + if (other.kind != null) + return false; + } else if (!kind.equals(other.kind)) + return false; + if (outputFolder == null) { + if (other.outputFolder != null) + return false; + } else if (!outputFolder.equals(other.outputFolder)) + return false; + if (path == null) { + if (other.path != null) + return false; + } else if (!path.equals(other.path)) + return false; + return true; + } + + @Override + public String toString() { + return "CPE [kind=" + kind + ", path=" + path + ", outputFolder=" + outputFolder + "]"; + } + } + + public static boolean isSource(CPE e) { + return e!=null && Classpath.ENTRY_KIND_SOURCE.equals(e.getKind()); } } \ No newline at end of file diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java index b5c3daecc..35a47a620 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java @@ -14,6 +14,7 @@ import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; @@ -33,10 +34,13 @@ import org.springframework.ide.vscode.commons.java.ClasspathData; import org.springframework.ide.vscode.commons.java.IJavadocProvider; import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider; import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer; +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.maven.MavenCore; import org.springframework.ide.vscode.commons.maven.MavenException; import org.springframework.ide.vscode.commons.util.Log; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; @@ -87,21 +91,22 @@ public class MavenProjectClasspath extends JandexClasspath { } public String getName() { - return cachedData != null ? cachedData.name : null; + return cachedData != null ? cachedData.getName() : null; } - private ImmutableList resolveClasspathEntries(MavenProject project) throws Exception { -// return Stream.concat(maven.resolveDependencies(project, null).stream().map(artifact -> { -// return artifact.getFile().toPath(); -// }), projectResolvedOutput()); - ImmutableList classpathEntries = ImmutableList.copyOf(Stream.concat(projectDependencies(project).stream().map(a -> a.getFile().toPath()), - projectOutput(project).stream().map(f -> f.toPath())).collect(Collectors.toList())); - return classpathEntries; + private ImmutableList resolveClasspathEntries(MavenProject project) throws Exception { + return ImmutableList.copyOf( + Stream.concat( + projectDependencies(project).stream().map(a -> a.getFile().toPath()), + projectOutput(project).stream().map(f -> f.toPath()) + ) + .map(path -> new CPE(Classpath.ENTRY_KIND_BINARY, path.toString())) + .collect(Collectors.toList())); } @Override - public ImmutableList getClasspathEntries() throws Exception { - return cachedData != null ? ImmutableList.copyOf(cachedData.classpathEntries) : ImmutableList.of(); + public ImmutableList getClasspathEntries() throws Exception { + return cachedData != null ? ImmutableList.copyOf(cachedData.getClasspathEntries()) : ImmutableList.of(); } private Set projectDependencies(MavenProject project) { @@ -121,7 +126,11 @@ public class MavenProjectClasspath extends JandexClasspath { } public Path getOutputFolder() { - return cachedData != null ? cachedData.outputFolder : null; + if (cachedData!=null) { + String of = cachedData.getOutputFolder(); + return of == null ? null : Paths.get(of); + } + return null; } private ImmutableList resolveClasspathResources(MavenProject project) { @@ -145,7 +154,7 @@ public class MavenProjectClasspath extends JandexClasspath { @Override public ImmutableList getClasspathResources() { - return cachedData != null ? ImmutableList.copyOf(cachedData.classpathResources) : ImmutableList.of(); + return cachedData != null ? ImmutableList.copyOf(cachedData.getClasspathResources()) : ImmutableList.of(); } /* @@ -265,7 +274,7 @@ public class MavenProjectClasspath extends JandexClasspath { public MavenClasspathData createClasspathData() throws Exception { MavenProject project = createMavenProject(); - ImmutableList entries = resolveClasspathEntries(project); + ImmutableList entries = resolveClasspathEntries(project); String name = project.getArtifact().getArtifactId(); ImmutableList resources = resolveClasspathResources(project); Path outputFolder = resolveOutputFolder(project); @@ -283,7 +292,7 @@ public class MavenProjectClasspath extends JandexClasspath { return data; } - class MavenClasspathData extends ClasspathData { + static class MavenClasspathData extends ClasspathData { private String testSourceDirectory; private List remoteArtifactRepositories; @@ -292,11 +301,10 @@ public class MavenProjectClasspath extends JandexClasspath { private String reportingOutputDirectory; private String outputDirectory; private String sourceDirectory; - - public MavenClasspathData(String name, Set classpathEntries, Set classpathResources, + public MavenClasspathData(String name, Set classpathEntries, Set classpathResources, Path outputFolder) { - super(name, classpathEntries, classpathResources, outputFolder); + super(name, classpathEntries, classpathResources, outputFolder == null ? null : outputFolder.toString()); } @Override diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java index b8313f1f9..98f437236 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java @@ -22,6 +22,7 @@ import java.util.stream.Stream; import org.springframework.ide.vscode.commons.java.ClasspathData; import org.springframework.ide.vscode.commons.java.IClasspath; import org.springframework.ide.vscode.commons.java.IType; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.maven.MavenCore; import com.google.common.collect.ImmutableList; @@ -36,6 +37,8 @@ import reactor.util.function.Tuple2; * */ public class FileClasspath implements IClasspath { + + //TODO: This is obsolete and no longer used. Should delete and anything taht uses it probably too. private Path classpathFilePath; @@ -44,10 +47,11 @@ public class FileClasspath implements IClasspath { } @Override - public ImmutableList getClasspathEntries() throws Exception { - return ImmutableList.copyOf(Stream.concat(MavenCore.readClassPathFile(classpathFilePath), - Stream.of(classpathFilePath.getParent().resolve("target/classes"), - classpathFilePath.getParent().resolve("target/test-classes"))).collect(Collectors.toList())); + public ImmutableList getClasspathEntries() throws Exception { + return ImmutableList.of(); +// return ImmutableList.copyOf(Stream.concat(MavenCore.readClassPathFile(classpathFilePath), +// Stream.of(classpathFilePath.getParent().resolve("target/classes"), +// classpathFilePath.getParent().resolve("target/test-classes"))).collect(Collectors.toList())); } @Override diff --git a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java index b2031ebb1..0fadbbb49 100644 --- a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java +++ b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java @@ -48,6 +48,7 @@ import org.springframework.ide.vscode.commons.languageserver.DiagnosticService; import org.springframework.ide.vscode.commons.languageserver.ProgressService; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageException; import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService; import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject; @@ -131,7 +132,7 @@ public class MavenProjectCacheTest { MavenJavaProject cachedProject = cache.project(pomFile); assertNotNull(cachedProject); - ImmutableList calculatedClassPath = cachedProject.getClasspath().getClasspathEntries(); + ImmutableList calculatedClassPath = cachedProject.getClasspath().getClasspathEntries(); assertEquals(48, calculatedClassPath.size()); fileObserver.notifyFileChanged(pomFile.toURI().toString()); diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/Classpath.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/Classpath.java index 7ef921e2c..330f621cc 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/Classpath.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/Classpath.java @@ -41,6 +41,17 @@ public class Classpath { public static class CPE { private String kind; private String path; + private String outputFolder; + + public String getOutputFolder() { + return outputFolder; + } + + public void setOutputFolder(String outputFolder) { + this.outputFolder = outputFolder; + } + + public CPE() {} public CPE(String kind, String path) { super(); @@ -66,9 +77,8 @@ public class Classpath { @Override public String toString() { - return "CPE [kind=" + kind + ", path=" + path + "]\n"; + return "CPE [kind=" + kind + ", path=" + path + ", outputFolder=" + outputFolder + "]"; } - } } \ No newline at end of file diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java index d2c44d6d6..c66f0aa3a 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/classpath/ClasspathUtil.java @@ -17,6 +17,9 @@ import static org.springframework.tooling.jdt.ls.commons.Logger.*; import java.util.ArrayList; import java.util.List; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragmentRoot; @@ -25,6 +28,7 @@ import org.springframework.tooling.jdt.ls.commons.classpath.Classpath.CPE; public class ClasspathUtil { public static Classpath resolve(IJavaProject javaProject) throws Exception { + //log("resolving classpath " + javaProject.getElementName() +" ..."); List cpEntries = new ArrayList<>(); IClasspathEntry[] entries = javaProject.getResolvedClasspath(true); @@ -32,15 +36,53 @@ public class ClasspathUtil { if (entries != null) { for (IClasspathEntry entry : entries) { String kind = toContentKind(entry); - String path = entry.getPath().toString(); - cpEntries.add(new CPE(kind, path)); + switch (kind) { + case Classpath.ENTRY_KIND_BINARY: { + String path = entry.getPath().toString(); + CPE cpe = new CPE(kind, path); + cpEntries.add(cpe); + break; + } + case Classpath.ENTRY_KIND_SOURCE: { + IPath sourcePath = entry.getPath(); + //log("source entry =" + sourcePath); + IPath absoluteSourcePath = resolveWorkspacePath(sourcePath); + //log("absoluteSourcePath =" + absoluteSourcePath); + if (absoluteSourcePath!=null) { + CPE cpe = new CPE(kind, absoluteSourcePath.toString()); + IPath of = entry.getOutputLocation(); + //log("outputFolder =" + of); + if (of!=null) { + IPath absoluteOutFolder = resolveWorkspacePath(of); + //log("absoluteOutFolder =" + absoluteOutFolder); + cpe.setOutputFolder(absoluteOutFolder.toString()); + } + cpEntries.add(cpe); + } + break; + } + default: + break; + } } } Classpath classpath = new Classpath(cpEntries, javaProject.getOutputLocation().toString()); log("classpath=" + classpath.getEntries().size() + " entries"); return classpath; } - + + private static IPath resolveWorkspacePath(IPath path) { + if (path.segmentCount()>0) { + String projectName = path.segment(0); + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + IPath projectRoot = project.getLocation(); + if (projectRoot!=null) { + return projectRoot.append(path.removeFirstSegments(1)); + } + } + return null; + } + private static String toContentKind(IClasspathEntry entry) { switch (entry.getContentKind()) { case IPackageFragmentRoot.K_BINARY: diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java index 7a57db932..ad4034d42 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java @@ -267,7 +267,7 @@ public class BootJavaHoverProvider implements HoverHandler { try { IClasspath classpath = project.getClasspath(); if (classpath!=null) { - return classpath.getClasspathEntries().stream().anyMatch(cpe -> { + return classpath.getClasspathEntryPaths().stream().anyMatch(cpe -> { String name = cpe.getFileName().toString(); return name.startsWith("spring-boot-actuator-"); }); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java index 7253da5ec..5ba18a169 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java @@ -125,7 +125,7 @@ public class BootJavaReferencesHandler implements ReferencesHandler { private String[] getClasspathEntries(IDocument doc) throws Exception { IJavaProject project = this.projectFinder.find(new TextDocumentIdentifier(doc.getUri())).get(); IClasspath classpath = project.getClasspath(); - Stream classpathEntries = classpath.getClasspathEntries().stream(); + Stream classpathEntries = classpath.getClasspathEntryPaths().stream(); return classpathEntries .filter(path -> path.toFile().exists()) .map(path -> path.toAbsolutePath().toString()).toArray(String[]::new); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/links/AbstractSourceLinks.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/links/AbstractSourceLinks.java index f955a170e..86d97b4aa 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/links/AbstractSourceLinks.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/links/AbstractSourceLinks.java @@ -83,37 +83,34 @@ public abstract class AbstractSourceLinks implements SourceLinks { private Optional javaSourceLinkUrl(IJavaProject project, String fqName, File containerFolder) { IClasspath classpath = project.getClasspath(); - if (containerFolder.toPath().startsWith(classpath.getOutputFolder())) { - return project.getClasspath().getSourceFolders().stream() - .map(sourceFolder -> { - try { - return Paths.get(sourceFolder).toUri().toURL(); - } catch (MalformedURLException e) { - LOG.get().warn("Failed to convert source folder " + sourceFolder + "to URI." + fqName, e); - return null; - } - }) - .map(url -> { - try { - return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER.sourceUrl(url, fqName); - } catch (Exception e) { - LOG.get().warn("Failed to determine source URL from url=" + url + " fqName=" + fqName, e); - return null; - } - }) - .map(url -> { - try { - return Paths.get(url.toURI()); - } catch (URISyntaxException e) { - LOG.get().warn("Failed to convert URL " + url + " to path." + fqName, e); - return null; - } - }) - .filter(sourcePath -> sourcePath != null && Files.exists(sourcePath)) - .findFirst() - .map(sourcePath -> javaSourceLinkUrl(project, sourcePath, fqName)); - } - return Optional.empty(); + return project.getClasspath().getSourceFolders().stream() + .map(sourceFolder -> { + try { + return Paths.get(sourceFolder).toUri().toURL(); + } catch (MalformedURLException e) { + LOG.get().warn("Failed to convert source folder " + sourceFolder + "to URI." + fqName, e); + return null; + } + }) + .map(url -> { + try { + return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER.sourceUrl(url, fqName); + } catch (Exception e) { + LOG.get().warn("Failed to determine source URL from url=" + url + " fqName=" + fqName, e); + return null; + } + }) + .map(url -> { + try { + return Paths.get(url.toURI()); + } catch (URISyntaxException e) { + LOG.get().warn("Failed to convert URL " + url + " to path." + fqName, e); + return null; + } + }) + .filter(sourcePath -> sourcePath != null && Files.exists(sourcePath)) + .findFirst() + .map(sourcePath -> javaSourceLinkUrl(project, sourcePath, fqName)); } private String javaSourceLinkUrl(IJavaProject project, Path sourcePath, String fqName) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java index adac0e6a8..88628a370 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java @@ -172,7 +172,7 @@ public final class CompilationUnitCache { return new String[0]; } else { IClasspath classpath = project.getClasspath(); - Stream classpathEntries = classpath.getClasspathEntries().stream(); + Stream classpathEntries = classpath.getClasspathEntryPaths().stream(); return classpathEntries .filter(path -> path.toFile().exists()) .map(path -> path.toAbsolutePath().toString()).toArray(String[]::new); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java index 7dbb1abb5..bb2298081 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexer.java @@ -619,7 +619,7 @@ public class SpringIndexer { private String[] getClasspathEntries(IJavaProject project) throws Exception { IClasspath classpath = project.getClasspath(); - Stream classpathEntries = classpath.getClasspathEntries().stream(); + Stream classpathEntries = classpath.getClasspathEntryPaths().stream(); return classpathEntries .filter(path -> path.toFile().exists()) .map(path -> path.toAbsolutePath().toString()).toArray(String[]::new); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java index 554ea5d34..2218d81ea 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java @@ -15,12 +15,14 @@ import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.slf4j.Logger; @@ -31,6 +33,7 @@ import org.springframework.ide.vscode.commons.java.IClasspath; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.IJavadocProvider; 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.languageserver.jdt.ls.ClasspathListener; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.util.Assert; @@ -41,6 +44,7 @@ import org.springframework.ide.vscode.commons.util.UriUtil; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import reactor.core.Disposable; @@ -250,13 +254,8 @@ public class JdtLsProjectCache implements JavaProjectsService { } @Override - public ImmutableList getClasspathEntries() throws Exception { - return classpath - .getEntries() - .stream() - .filter(cpe -> cpe.getKind().equals(Classpath.ENTRY_KIND_BINARY)) - .map(cpe -> Paths.get(cpe.getPath())) - .collect(CollectorUtil.toImmutableList()); + public Collection getClasspathEntries() throws Exception { + return classpath.getEntries(); } @Override @@ -267,8 +266,18 @@ public class JdtLsProjectCache implements JavaProjectsService { @Override public ImmutableList getSourceFolders() { - // TODO Auto-generated method stub - return null; + ImmutableList.Builder sourceEntries = ImmutableList.builder(); + try { + for (CPE e : getClasspathEntries()) { + if (Classpath.isSource(e)) { + sourceEntries.add(e.getPath()); + } + } + } catch (Exception e) { + log.error("", e); + } + return sourceEntries.build(); + } @Override diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java index 97a08a6f6..5a24f36da 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java @@ -55,7 +55,7 @@ public class PropertiesLoader { public ConfigurationMetadataRepository load(IClasspath classPath) { try { - classPath.getClasspathEntries().forEach(entry -> { + classPath.getClasspathEntryPaths().forEach(entry -> { //Log.info("Indexing "+entry); File fileEntry = entry.toFile(); if (fileEntry.exists()) { diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java index 9171b9e7d..154ef3a8a 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import org.junit.Ignore; import org.junit.Test; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.ProgressService; @@ -79,7 +80,7 @@ public class PropertiesIndexTest { assertEquals("port", propertyInfo.getName()); } - @Test + @Test @Ignore //ignore because classpath file is going to disapear and pieces already removed public void customPropertyPresent_ClasspathFile() throws Exception { SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager( ValueProviderRegistry.getDefault(), null); @@ -91,7 +92,7 @@ public class PropertiesIndexTest { assertEquals("user", propertyInfo.getName()); } - @Test + @Test @Ignore //ignore because classpath file is going to disapear and pieces already removed public void propertyNotPresent_ClasspathFile() throws Exception { SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager( ValueProviderRegistry.getDefault(), null);