summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Fraser <george@fivetran.com>2018-09-16 10:30:38 -0700
committerGeorge Fraser <george@fivetran.com>2018-09-16 10:30:38 -0700
commite60ee6dc55943e0252cc3dbb66a5ffcc453d4b78 (patch)
tree04bee4226dcb4e356ece4569899563e9e37514b0
parent2f20929eaa41bb0af83340b935e9ccd0361e51a3 (diff)
downloadjava-language-server-e60ee6dc55943e0252cc3dbb66a5ffcc453d4b78.zip
Revive externalDependencies and classPath
-rwxr-xr-xscripts/build.sh2
-rw-r--r--scripts/build.sh~HEAD3
-rw-r--r--scripts/test.sh3
-rw-r--r--src/main/java/org/javacs/InferConfig.java131
-rw-r--r--src/main/java/org/javacs/JavaLanguageServer.java36
-rw-r--r--src/main/java/org/javacs/JavaWorkspaceService.java19
-rw-r--r--src/test/java/org/javacs/InferBazelConfigTest.java4
-rw-r--r--src/test/java/org/javacs/InferConfigTest.java62
8 files changed, 209 insertions, 51 deletions
diff --git a/scripts/build.sh b/scripts/build.sh
index 2e6adf4..bb64d2d 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -4,8 +4,6 @@
# You will need java, maven, vsce, and visual studio code to run this script
set -e
-export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
-
# Needed once
npm install
diff --git a/scripts/build.sh~HEAD b/scripts/build.sh~HEAD
deleted file mode 100644
index 559c330..0000000
--- a/scripts/build.sh~HEAD
+++ /dev/null
@@ -1,3 +0,0 @@
-export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
-
-mvn compile \ No newline at end of file
diff --git a/scripts/test.sh b/scripts/test.sh
deleted file mode 100644
index 15facd5..0000000
--- a/scripts/test.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
-
-mvn test \ No newline at end of file
diff --git a/src/main/java/org/javacs/InferConfig.java b/src/main/java/org/javacs/InferConfig.java
index 341eb0f..5803260 100644
--- a/src/main/java/org/javacs/InferConfig.java
+++ b/src/main/java/org/javacs/InferConfig.java
@@ -25,22 +25,36 @@ class InferConfig {
/** Root of the workspace that is currently open in VSCode */
private final Path workspaceRoot;
+ /** External dependencies specified manually by the user */
+ private final Collection<String> externalDependencies;
/** Location of the maven repository, usually ~/.m2 */
private final Path mavenHome;
+ /** Location of the gradle cache, usually ~/.gradle */
+ private final Path gradleHome;
- InferConfig(Path workspaceRoot, Path mavenHome) {
+ InferConfig(Path workspaceRoot, Collection<String> externalDependencies, Path mavenHome, Path gradleHome) {
this.workspaceRoot = workspaceRoot;
+ this.externalDependencies = externalDependencies;
this.mavenHome = mavenHome;
+ this.gradleHome = gradleHome;
+ }
+
+ InferConfig(Path workspaceRoot, Collection<String> externalDependencies) {
+ this(workspaceRoot, externalDependencies, defaultMavenHome(), defaultGradleHome());
}
InferConfig(Path workspaceRoot) {
- this(workspaceRoot, defaultMavenHome());
+ this(workspaceRoot, Collections.emptySet(), defaultMavenHome(), defaultGradleHome());
}
private static Path defaultMavenHome() {
return Paths.get(System.getProperty("user.home")).resolve(".m2");
}
+ private static Path defaultGradleHome() {
+ return Paths.get(System.getProperty("user.home")).resolve(".gradle");
+ }
+
Set<Path> classPath() {
var result = new HashSet<Path>();
result.addAll(buildClassPath());
@@ -50,24 +64,32 @@ class InferConfig {
/** Find .jar files for external dependencies, for examples maven dependencies in ~/.m2 or jars in bazel-genfiles */
Set<Path> buildClassPath() {
- var result = new HashSet<Path>();
+ // externalDependencies
+ if (!externalDependencies.isEmpty()) {
+ var result = new HashSet<Path>();
+ for (var id : externalDependencies) {
+ var a = Artifact.parse(id);
+ var found = findAnyJar(a, false);
+ if (found.isPresent()) result.add(found.get());
+ else LOG.warning(String.format("Couldn't find jar for %s in %s or %s", a, mavenHome, gradleHome));
+ }
+ return result;
+ }
// Maven
- var as = mvnDependencies();
- if (!as.isEmpty()) {
- LOG.info("Looking for artifacts:");
- for (var a : as) {
- System.err.println(" " + a);
+ if (Files.exists(workspaceRoot.resolve("pom.xml"))) {
+ var result = new HashSet<Path>();
+ for (var a : mvnDependencies()) {
+ var found = findMavenJar(a, false);
+ if (found.isPresent()) result.add(found.get());
+ else LOG.warning(String.format("Couldn't find jar for %s in %s", a, mavenHome));
}
- }
- for (var a : as) {
- var found = findMavenJar(a, false);
- if (found.isPresent()) result.add(found.get());
- else LOG.warning(String.format("Couldn't find jar for %s in %s", a, mavenHome));
+ return result;
}
// Bazel
if (Files.exists(workspaceRoot.resolve("WORKSPACE"))) {
+ var result = new HashSet<Path>();
var bazelGenFiles = workspaceRoot.resolve("bazel-genfiles");
if (Files.exists(bazelGenFiles) && Files.isSymbolicLink(bazelGenFiles)) {
@@ -76,9 +98,10 @@ class InferConfig {
LOG.info(String.format("Found %d generated-files directories", jars.size()));
result.addAll(jars);
}
+ return result;
}
- return result;
+ return Collections.emptySet();
}
/**
@@ -86,6 +109,20 @@ class InferConfig {
* target/classes
*/
Set<Path> workspaceClassPath() {
+ // externalDependencies
+ if (!externalDependencies.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ // Maven
+ if (Files.exists(workspaceRoot.resolve("pom.xml"))) {
+ try {
+ return Files.walk(workspaceRoot).flatMap(this::outputDirectory).collect(Collectors.toSet());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
// Bazel
if (Files.exists(workspaceRoot.resolve("WORKSPACE"))) {
var bazelBin = workspaceRoot.resolve("bazel-bin");
@@ -95,12 +132,7 @@ class InferConfig {
}
}
- // Maven
- try {
- return Files.walk(workspaceRoot).flatMap(this::outputDirectory).collect(Collectors.toSet());
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ return Collections.emptySet();
}
/** Recognize build root files like pom.xml and return compiler output directories */
@@ -173,15 +205,39 @@ class InferConfig {
}
}
- /** Find source .jar files for `externalDependencies` in local maven / gradle repository. */
+ /** Find source .jar files in local maven repository. */
Set<Path> buildDocPath() {
- var result = new HashSet<Path>();
+ // externalDependencies
+ if (!externalDependencies.isEmpty()) {
+ var result = new HashSet<Path>();
+ for (var id : externalDependencies) {
+ var a = Artifact.parse(id);
+ var found = findAnyJar(a, true);
+ if (found.isPresent()) result.add(found.get());
+ else LOG.warning(String.format("Couldn't find doc jar for %s in %s or %s", a, mavenHome, gradleHome));
+ }
+ return result;
+ }
+
// Maven
- for (var a : mvnDependencies()) {
- findMavenJar(a, true).ifPresent(result::add);
+ if (Files.exists(workspaceRoot.resolve("pom.xml"))) {
+ var result = new HashSet<Path>();
+ for (var a : mvnDependencies()) {
+ findMavenJar(a, true).ifPresent(result::add);
+ }
+ return result;
}
+
// TODO Bazel
- return result;
+
+ return Collections.emptySet();
+ }
+
+ private Optional<Path> findAnyJar(Artifact artifact, boolean source) {
+ Optional<Path> maven = findMavenJar(artifact, source);
+
+ if (maven.isPresent()) return maven;
+ else return findGradleJar(artifact, source);
}
Optional<Path> findMavenJar(Artifact artifact, boolean source) {
@@ -197,6 +253,30 @@ class InferConfig {
else return Optional.empty();
}
+ private Optional<Path> findGradleJar(Artifact artifact, boolean source) {
+ // Search for caches/modules-*/files-*/groupId/artifactId/version/*/artifactId-version[-sources].jar
+ var base = gradleHome.resolve("caches");
+ var pattern =
+ "glob:"
+ + String.join(
+ File.separator,
+ base.toString(),
+ "modules-*",
+ "files-*",
+ artifact.groupId,
+ artifact.artifactId,
+ artifact.version,
+ "*",
+ fileName(artifact, source));
+ var match = FileSystems.getDefault().getPathMatcher(pattern);
+
+ try {
+ return Files.walk(base, 7).filter(match::matches).findFirst();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private String fileName(Artifact artifact, boolean source) {
return artifact.artifactId + '-' + artifact.version + (source ? "-sources" : "") + ".jar";
}
@@ -237,7 +317,6 @@ class InferConfig {
}
}
- /** Get external dependencies from this.externalDependencies if available, or try to infer them. */
private Collection<Artifact> mvnDependencies() {
var pomXml = workspaceRoot.resolve("pom.xml");
diff --git a/src/main/java/org/javacs/JavaLanguageServer.java b/src/main/java/org/javacs/JavaLanguageServer.java
index 01e301d..eb2d68f 100644
--- a/src/main/java/org/javacs/JavaLanguageServer.java
+++ b/src/main/java/org/javacs/JavaLanguageServer.java
@@ -6,8 +6,10 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -19,8 +21,11 @@ import org.eclipse.lsp4j.services.*;
class JavaLanguageServer implements LanguageServer {
private static final Logger LOG = Logger.getLogger("main");
- Path workspaceRoot;
- LanguageClient client;
+ private Path workspaceRoot;
+ private LanguageClient client;
+ private Set<String> externalDependencies = Set.of();
+ private Set<Path> classPath = Set.of();
+
JavaCompilerService compiler;
final JavaTextDocumentService textDocuments = new JavaTextDocumentService(this);
final JavaWorkspaceService workspace = new JavaWorkspaceService(this);
@@ -84,9 +89,30 @@ class JavaLanguageServer implements LanguageServer {
private JavaCompilerService createCompiler() {
Objects.requireNonNull(workspaceRoot, "Can't create compiler because workspaceRoot has not been initialized");
- var infer = new InferConfig(workspaceRoot);
- return new JavaCompilerService(
- InferSourcePath.sourcePath(workspaceRoot), infer.classPath(), infer.buildDocPath());
+
+ // If classpath is specified by the user, don't infer anything
+ if (!classPath.isEmpty()) {
+ return new JavaCompilerService(
+ InferSourcePath.sourcePath(workspaceRoot), classPath, Collections.emptySet());
+ }
+ // Otherwise, combine inference with user-specified external dependencies
+ else {
+ var infer = new InferConfig(workspaceRoot, externalDependencies);
+ return new JavaCompilerService(
+ InferSourcePath.sourcePath(workspaceRoot), infer.classPath(), infer.buildDocPath());
+ }
+ }
+
+ void setExternalDependencies(Set<String> externalDependencies) {
+ var changed = this.externalDependencies.isEmpty() != externalDependencies.isEmpty();
+ this.externalDependencies = externalDependencies;
+ if (changed) this.compiler = createCompiler();
+ }
+
+ void setClassPath(Set<Path> classPath) {
+ var changed = this.classPath.isEmpty() != classPath.isEmpty();
+ this.classPath = classPath;
+ if (changed) this.compiler = createCompiler();
}
@Override
diff --git a/src/main/java/org/javacs/JavaWorkspaceService.java b/src/main/java/org/javacs/JavaWorkspaceService.java
index 13c5e70..998fb5c 100644
--- a/src/main/java/org/javacs/JavaWorkspaceService.java
+++ b/src/main/java/org/javacs/JavaWorkspaceService.java
@@ -1,5 +1,9 @@
package org.javacs;
+import com.google.gson.JsonObject;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
@@ -37,7 +41,20 @@ class JavaWorkspaceService implements WorkspaceService {
}
@Override
- public void didChangeConfiguration(DidChangeConfigurationParams change) {}
+ public void didChangeConfiguration(DidChangeConfigurationParams change) {
+ var settings = (JsonObject) change.getSettings();
+ var java = settings.getAsJsonObject("java");
+
+ var externalDependencies = java.getAsJsonArray("externalDependencies");
+ var strings = new HashSet<String>();
+ for (var each : externalDependencies) strings.add(each.getAsString());
+ server.setExternalDependencies(strings);
+
+ var classPath = java.getAsJsonArray("classPath");
+ var paths = new HashSet<Path>();
+ for (var each : classPath) paths.add(Paths.get(each.getAsString()).toAbsolutePath());
+ server.setClassPath(paths);
+ }
@Override
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {}
diff --git a/src/test/java/org/javacs/InferBazelConfigTest.java b/src/test/java/org/javacs/InferBazelConfigTest.java
index d3e04fc..f5dcd80 100644
--- a/src/test/java/org/javacs/InferBazelConfigTest.java
+++ b/src/test/java/org/javacs/InferBazelConfigTest.java
@@ -7,6 +7,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -15,7 +16,8 @@ public class InferBazelConfigTest {
private Path bazelWorkspace = Paths.get("src/test/test-project/bazel-workspace"),
bazelTemp = Paths.get("src/test/test-project/bazel-temp");
- private InferConfig bazel = new InferConfig(bazelWorkspace, Paths.get("nowhere"));
+ private InferConfig bazel =
+ new InferConfig(bazelWorkspace, Collections.emptySet(), Paths.get("nowhere"), Paths.get("nowhere"));
private Path bazelBin = bazelWorkspace.resolve("bazel-bin"),
bazelBinTarget = bazelTemp.resolve("xyz/execroot/test/bazel-out/local-fastbuild/bin").toAbsolutePath(),
bazelGenfiles = bazelWorkspace.resolve("bazel-genfiles"),
diff --git a/src/test/java/org/javacs/InferConfigTest.java b/src/test/java/org/javacs/InferConfigTest.java
index 2a951cc..debd6db 100644
--- a/src/test/java/org/javacs/InferConfigTest.java
+++ b/src/test/java/org/javacs/InferConfigTest.java
@@ -5,40 +5,82 @@ import static org.junit.Assert.*;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Set;
import org.junit.Test;
public class InferConfigTest {
private Path workspaceRoot = Paths.get("src/test/test-project/workspace");
private Path mavenHome = Paths.get("src/test/test-project/home/.m2");
- private Artifact externalArtifact = new Artifact("com.external", "external-library", "1.2");
- private InferConfig infer = new InferConfig(workspaceRoot, mavenHome);
+ private Path gradleHome = Paths.get("src/test/test-project/home/.gradle");
+ private Set<String> externalDependencies = Set.of("com.external:external-library:1.2");
+ private InferConfig both = new InferConfig(workspaceRoot, externalDependencies, mavenHome, gradleHome);
+ private InferConfig gradle = new InferConfig(workspaceRoot, externalDependencies, Paths.get("nowhere"), gradleHome);
+ private InferConfig onlyPomXml =
+ new InferConfig(
+ Paths.get("src/test/test-project/only-pom-xml"),
+ Collections.emptySet(),
+ mavenHome,
+ Paths.get("nowhere"));
@Test
public void mavenClassPath() {
- var found = infer.findMavenJar(externalArtifact, false);
- assertTrue(found.isPresent());
assertThat(
- found.get(),
- equalTo(mavenHome.resolve("repository/com/external/external-library/1.2/external-library-1.2.jar")));
+ both.buildClassPath(),
+ contains(mavenHome.resolve("repository/com/external/external-library/1.2/external-library-1.2.jar")));
+ // v1.1 should be ignored
+ }
+
+ @Test
+ public void gradleClasspath() {
+ assertThat(
+ gradle.buildClassPath(),
+ contains(
+ gradleHome.resolve(
+ "caches/modules-2/files-2.1/com.external/external-library/1.2/xxx/external-library-1.2.jar")));
// v1.1 should be ignored
}
@Test
public void mavenDocPath() {
- var found = infer.findMavenJar(externalArtifact, true);
- assertTrue(found.isPresent());
assertThat(
- found.get(),
- equalTo(
+ both.buildDocPath(),
+ contains(
mavenHome.resolve(
"repository/com/external/external-library/1.2/external-library-1.2-sources.jar")));
// v1.1 should be ignored
}
@Test
+ public void gradleDocPath() {
+ assertThat(
+ gradle.buildDocPath(),
+ contains(
+ gradleHome.resolve(
+ "caches/modules-2/files-2.1/com.external/external-library/1.2/yyy/external-library-1.2-sources.jar")));
+ // v1.1 should be ignored
+ }
+
+ @Test
public void dependencyList() {
assertThat(
InferConfig.dependencyList(Paths.get("pom.xml")),
hasItem(new Artifact("org.hamcrest", "hamcrest-all", "1.3")));
}
+
+ @Test
+ public void onlyPomXmlClassPath() {
+ assertThat(
+ onlyPomXml.buildClassPath(),
+ contains(mavenHome.resolve("repository/com/external/external-library/1.2/external-library-1.2.jar")));
+ }
+
+ @Test
+ public void onlyPomXmlDocPath() {
+ assertThat(
+ onlyPomXml.buildDocPath(),
+ contains(
+ mavenHome.resolve(
+ "repository/com/external/external-library/1.2/external-library-1.2-sources.jar")));
+ }
}