summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Fraser <george@fivetran.com>2019-01-08 00:10:18 -0800
committerGeorge Fraser <george@fivetran.com>2019-01-08 00:10:18 -0800
commit46e72551e73f1de2417102fd3d7fbc358a42cfa6 (patch)
treec6bce16cec95ebd660657b4dd662cb3ec754a82a
parent297dd5f8fb1c72f5807595c3029acf40ce6afcd9 (diff)
downloadjava-language-server-46e72551e73f1de2417102fd3d7fbc358a42cfa6.zip
Hide module-info.java
-rw-r--r--src/main/java/org/javacs/FileStore.java9
-rw-r--r--src/main/java/org/javacs/Profiler.java27
-rw-r--r--src/main/java/org/javacs/SourceFileManager.java19
-rw-r--r--src/main/java/org/javacs/SourceFileObject.java1
-rw-r--r--src/main/java/org/javacs/SourcePath.java6
-rw-r--r--src/test/java/org/javacs/SourceFileManagerTest.java69
6 files changed, 103 insertions, 28 deletions
diff --git a/src/main/java/org/javacs/FileStore.java b/src/main/java/org/javacs/FileStore.java
index 7c5e2ad..3c10a64 100644
--- a/src/main/java/org/javacs/FileStore.java
+++ b/src/main/java/org/javacs/FileStore.java
@@ -25,6 +25,8 @@ import org.javacs.lsp.DidCloseTextDocumentParams;
import org.javacs.lsp.DidOpenTextDocumentParams;
import org.javacs.lsp.TextDocumentContentChangeEvent;
+// TODO get rid of SourcePath and track source path dynamically here
+
class FileStore {
private static final Map<URI, VersionedContent> activeDocuments = new HashMap<>();
@@ -60,7 +62,9 @@ class FileStore {
for (var file : afterDir) {
if (!SourcePath.isJavaFile(file)) continue;
if (!file.startsWith(dir)) break;
- if (file.startsWith(packageDir)) list.add(file);
+ if (file.getParent().equals(packageDir)) {
+ list.add(file);
+ }
}
return list;
}
@@ -141,8 +145,7 @@ class FileStore {
static String contents(URI file) {
if (!SourcePath.isJavaFile(file)) {
- LOG.warning("Ignoring non-java file " + file);
- return "";
+ throw new RuntimeException(file + " is not a java file");
}
if (activeDocuments.containsKey(file)) {
return activeDocuments.get(file).content;
diff --git a/src/main/java/org/javacs/Profiler.java b/src/main/java/org/javacs/Profiler.java
index b4fab4d..c7b6911 100644
--- a/src/main/java/org/javacs/Profiler.java
+++ b/src/main/java/org/javacs/Profiler.java
@@ -9,33 +9,38 @@ import java.util.logging.Logger;
class Profiler implements TaskListener {
Set<URI> files = new HashSet<>();
- Map<TaskEvent.Kind, Instant> started = new EnumMap<>(TaskEvent.Kind.class);
+ Map<URI, Map<TaskEvent.Kind, Instant>> started = new HashMap<>();
Map<TaskEvent.Kind, Duration> profile = new EnumMap<>(TaskEvent.Kind.class);
@Override
public void started(TaskEvent e) {
- started.put(e.getKind(), Instant.now());
- files.add(e.getSourceFile().toUri());
+ var uri = e.getSourceFile().toUri();
+ var kind = e.getKind();
+ var fileStarted = started.computeIfAbsent(uri, __ -> new EnumMap<>(TaskEvent.Kind.class));
+ fileStarted.put(kind, Instant.now());
+ files.add(uri);
// TODO show the user a warning when we're compiling a lot of files that aren't in the classpath
}
@Override
public void finished(TaskEvent e) {
- var k = e.getKind();
- var start = started.getOrDefault(k, Instant.now());
+ var uri = e.getSourceFile().toUri();
+ var kind = e.getKind();
+ var fileStarted = started.computeIfAbsent(uri, __ -> new HashMap<>());
+ var start = fileStarted.getOrDefault(kind, Instant.now());
var elapsed = Duration.between(start, Instant.now());
- var soFar = profile.getOrDefault(k, Duration.ZERO);
+ var soFar = profile.getOrDefault(kind, Duration.ZERO);
var total = soFar.plus(elapsed);
- profile.put(k, total);
+ profile.put(kind, total);
}
void print() {
var lines = new StringJoiner("; ");
- for (var k : TaskEvent.Kind.values()) {
- if (!profile.containsKey(k)) continue;
- var elapsed = profile.get(k);
+ for (var kind : TaskEvent.Kind.values()) {
+ if (!profile.containsKey(kind)) continue;
+ var elapsed = profile.get(kind);
var s = elapsed.getSeconds() + elapsed.getNano() / 1000.0 / 1000.0 / 1000.0;
- lines.add(String.format("%s: %.3fs", k, s));
+ lines.add(String.format("%s: %.3fs", kind, s));
}
// TODO log names if n is small
LOG.info(String.format("Compiled %d files: %s", files.size(), lines));
diff --git a/src/main/java/org/javacs/SourceFileManager.java b/src/main/java/org/javacs/SourceFileManager.java
index e457b40..c174d2b 100644
--- a/src/main/java/org/javacs/SourceFileManager.java
+++ b/src/main/java/org/javacs/SourceFileManager.java
@@ -10,7 +10,6 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.logging.Logger;
-import java.util.stream.Stream;
import javax.tools.*;
class SourceFileManager implements StandardJavaFileManager {
@@ -67,16 +66,7 @@ class SourceFileManager implements StandardJavaFileManager {
}
private boolean isJavaSource(JavaFileObject file) {
- return file.getName().endsWith(".java");
- }
-
- private Stream<Path> list(Path dir) {
- try {
- if (!Files.exists(dir)) return Stream.of();
- return Files.walk(dir).filter(Files::isRegularFile);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ return SourcePath.isJavaFile(file.toUri());
}
private JavaFileObject asJavaFileObject(Path file) {
@@ -105,7 +95,7 @@ class SourceFileManager implements StandardJavaFileManager {
private String binaryName(String relativePath) {
var slash = removeExtension(relativePath);
- return slash.replace('/', '.');
+ return slash.replace(File.separatorChar, '.');
}
private String removeExtension(String fileName) {
@@ -153,6 +143,7 @@ class SourceFileManager implements StandardJavaFileManager {
private JavaFileObject findFileForInput(Location location, String relative) {
for (var root : sourcePath) {
var absolute = root.resolve(relative);
+ if (!SourcePath.isJavaFile(absolute)) return null;
if (Files.exists(absolute)) {
return new SourceFileObject(absolute);
}
@@ -257,12 +248,12 @@ class SourceFileManager implements StandardJavaFileManager {
@Override
public void setLocation(Location location, Iterable<? extends File> files) throws IOException {
- throw new UnsupportedOperationException();
+ delegate.setLocation(location, files);
}
@Override
public Iterable<? extends File> getLocation(Location location) {
- throw new UnsupportedOperationException();
+ return delegate.getLocation(location);
}
private static final Logger LOG = Logger.getLogger("main");
diff --git a/src/main/java/org/javacs/SourceFileObject.java b/src/main/java/org/javacs/SourceFileObject.java
index 24e7608..46d652d 100644
--- a/src/main/java/org/javacs/SourceFileObject.java
+++ b/src/main/java/org/javacs/SourceFileObject.java
@@ -27,6 +27,7 @@ class SourceFileObject implements JavaFileObject {
}
SourceFileObject(Path path, String contents) {
+ if (!SourcePath.isJavaFile(path)) throw new RuntimeException(path + " is not a java source");
this.path = path;
this.contents = contents;
}
diff --git a/src/main/java/org/javacs/SourcePath.java b/src/main/java/org/javacs/SourcePath.java
index 60133bc..9c17252 100644
--- a/src/main/java/org/javacs/SourcePath.java
+++ b/src/main/java/org/javacs/SourcePath.java
@@ -96,6 +96,12 @@ class SourcePath {
static boolean isJavaFile(Path file) {
var name = file.getFileName().toString();
+ // We hide module-info.java from javac, because when javac sees module-info.java
+ // it goes into "module mode" and starts looking for classes on the module class path.
+ // This becomes evident when javac starts recompiling *way too much* on each task,
+ // because it doesn't realize there are already up-to-date .class files.
+ // The better solution would be for java-language server to detect the presence of module-info.java,
+ // and go into its own "module mode" where it infers a module source path and a module class path.
return name.endsWith(".java") && !name.equals("module-info.java");
}
diff --git a/src/test/java/org/javacs/SourceFileManagerTest.java b/src/test/java/org/javacs/SourceFileManagerTest.java
new file mode 100644
index 0000000..ab40c5e
--- /dev/null
+++ b/src/test/java/org/javacs/SourceFileManagerTest.java
@@ -0,0 +1,69 @@
+package org.javacs;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.logging.Logger;
+import javax.tools.*;
+import org.junit.Test;
+
+public class SourceFileManagerTest {
+ static final Path src = LanguageServerFixture.DEFAULT_WORKSPACE_ROOT.resolve("src");
+ static final Path classes = LanguageServerFixture.DEFAULT_WORKSPACE_ROOT.resolve("target/classes");
+ final SourceFileManager sourceFileManager = createSourceFileManager();
+ final StandardJavaFileManager standardFileManager = createDelegateFileManager();
+
+ private static SourceFileManager createSourceFileManager() {
+ var fileManager = new SourceFileManager(Set.of(src));
+ try {
+ fileManager.setLocationFromPaths(StandardLocation.SOURCE_PATH, List.of(src));
+ fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(classes));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return fileManager;
+ }
+
+ private static StandardJavaFileManager createDelegateFileManager() {
+ var compiler = ServiceLoader.load(JavaCompiler.class).iterator().next();
+ var fileManager =
+ compiler.getStandardFileManager(
+ err -> LOG.severe(err.getMessage(null)), null, Charset.defaultCharset());
+ try {
+ fileManager.setLocationFromPaths(StandardLocation.SOURCE_PATH, List.of(src));
+ fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(classes));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return fileManager;
+ }
+
+ @Test
+ public void binaryNameOfPackagePrivateClass() throws IOException {
+ var standardJava =
+ standardFileManager.getJavaFileForInput(
+ StandardLocation.SOURCE_PATH, "com.example.PackagePrivate", JavaFileObject.Kind.SOURCE);
+ var standardClass =
+ standardFileManager.getJavaFileForInput(
+ StandardLocation.CLASS_PATH, "com.example.PackagePrivate", JavaFileObject.Kind.CLASS);
+ var sourceJava =
+ sourceFileManager.getJavaFileForInput(
+ StandardLocation.SOURCE_PATH, "com.example.PackagePrivate", JavaFileObject.Kind.SOURCE);
+ var sourceClass =
+ sourceFileManager.getJavaFileForInput(
+ StandardLocation.CLASS_PATH, "com.example.PackagePrivate", JavaFileObject.Kind.CLASS);
+ var standardJavaName = standardFileManager.inferBinaryName(StandardLocation.SOURCE_PATH, standardJava);
+ var standardClassName = standardFileManager.inferBinaryName(StandardLocation.CLASS_PATH, standardClass);
+ var sourceJavaName = sourceFileManager.inferBinaryName(StandardLocation.SOURCE_PATH, sourceJava);
+ var sourceClassName = sourceFileManager.inferBinaryName(StandardLocation.CLASS_PATH, sourceClass);
+ assertThat(standardClassName, equalTo(standardJavaName));
+ assertThat(sourceJavaName, equalTo(standardJavaName));
+ assertThat(sourceClassName, equalTo(standardJavaName));
+ }
+
+ private static final Logger LOG = Logger.getLogger("main");
+}