diff options
author | George Fraser <george@fivetran.com> | 2018-12-27 14:24:24 -0800 |
---|---|---|
committer | George Fraser <george@fivetran.com> | 2018-12-27 14:24:24 -0800 |
commit | 84982255bbcf53bec86e31b6cd4f7282169ccc5d (patch) | |
tree | a79362475400e039228ecb06ab3a415f0f23e86a /src | |
parent | 5b2339d7a7a33edd7fe6390181b2e26e167e3c92 (diff) | |
download | java-language-server-84982255bbcf53bec86e31b6cd4f7282169ccc5d.zip |
Fix enum completions, cache hovers
Diffstat (limited to 'src')
6 files changed, 81 insertions, 22 deletions
diff --git a/src/main/java/org/javacs/CompileFile.java b/src/main/java/org/javacs/CompileFile.java index 826f7e9..d928508 100644 --- a/src/main/java/org/javacs/CompileFile.java +++ b/src/main/java/org/javacs/CompileFile.java @@ -13,8 +13,8 @@ import org.eclipse.lsp4j.Range; public class CompileFile { private final JavaCompilerService parent; - private final URI file; - private final String contents; + final URI file; + final String contents; private final JavacTask task; private final Trees trees; private final CompilationUnitTree root; @@ -39,6 +39,12 @@ public class CompileFile { profiler.print(); } + public Optional<Element> element(int line, int character) { + var path = CompileFocus.findPath(task, root, line, character); + var el = trees.getElement(path); + return Optional.ofNullable(el); + } + public Optional<TreePath> find(Ptr target) { class FindPtr extends TreePathScanner<Void, Void> { TreePath found = null; diff --git a/src/main/java/org/javacs/CompileFocus.java b/src/main/java/org/javacs/CompileFocus.java index e8a9a27..4183faf 100644 --- a/src/main/java/org/javacs/CompileFocus.java +++ b/src/main/java/org/javacs/CompileFocus.java @@ -54,7 +54,7 @@ public class CompileFocus { throw new RuntimeException(e); } profiler.print(); - this.path = findPath(); + this.path = findPath(task, root, line, character); } /** Create a task that compiles a single file */ @@ -200,17 +200,21 @@ public class CompileFocus { /** Find all case options in the switch expression surrounding line:character */ public List<Completion> completeCases() { - // Find path to case - var types = task.getTypes(); + LOG.info(String.format("Complete enum constants following `%s`...", path.getLeaf())); + // Find surrounding switch var path = this.path; while (!(path.getLeaf() instanceof SwitchTree)) path = path.getParentPath(); var leaf = (SwitchTree) path.getLeaf(); path = new TreePath(path, leaf.getExpression()); + LOG.info(String.format("...found switch expression `%s`", leaf.getExpression())); + // Get members of switched type - var element = trees.getElement(path); - var type = element.asType(); + var type = trees.getTypeMirror(path); + LOG.info(String.format("...switched expression has type `%s`", type)); + var types = task.getTypes(); var definition = types.asElement(type); + LOG.info(String.format("...switched expression has definition `%s`", definition)); var result = new ArrayList<Completion>(); for (var member : definition.getEnclosedElements()) { if (member.getKind() == ElementKind.ENUM_CONSTANT) result.add(Completion.ofElement(member)); @@ -833,7 +837,8 @@ public class CompileFocus { } /** Find the smallest tree that includes the cursor */ - private TreePath findPath() { + static TreePath findPath(JavacTask task, CompilationUnitTree root, int line, int character) { + var trees = Trees.instance(task); var pos = trees.getSourcePositions(); var cursor = root.getLineMap().getPosition(line, character); @@ -868,7 +873,8 @@ public class CompileFocus { var find = new FindSmallest(); find.scan(root, null); if (find.found == null) { - var message = String.format("No TreePath to %s %d:%d", file, line, character); + var uri = root.getSourceFile().toUri(); + var message = String.format("No TreePath to %s %d:%d", uri, line, character); throw new RuntimeException(message); } return find.found; diff --git a/src/main/java/org/javacs/JavaTextDocumentService.java b/src/main/java/org/javacs/JavaTextDocumentService.java index c23244b..6707cd0 100644 --- a/src/main/java/org/javacs/JavaTextDocumentService.java +++ b/src/main/java/org/javacs/JavaTextDocumentService.java @@ -10,7 +10,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; -import java.lang.annotation.Annotation; import java.net.URI; import java.nio.file.Files; import java.nio.file.Paths; @@ -254,6 +253,9 @@ class JavaTextDocumentService implements TextDocumentService { case CLASS: result.append("class"); break; + case ENUM: + result.append("enum"); + break; default: LOG.warning("Don't know what to call type element " + t); result.append("???"); @@ -304,19 +306,39 @@ class JavaTextDocumentService implements TextDocumentService { } else return Optional.empty(); } + private CompileFile hoverCache; + + private void updateHoverCache(URI uri, String contents) { + if (hoverCache == null || !hoverCache.file.equals(uri) || !hoverCache.contents.equals(contents)) { + LOG.info("File has changed since last hover, recompiling"); + hoverCache = server.compiler.compileFile(uri, contents); + } + } + @Override public CompletableFuture<Hover> hover(TextDocumentPositionParams position) { + // Compile entire file if it's changed since last hover var uri = URI.create(position.getTextDocument().getUri()); var content = contents(uri).content; + updateHoverCache(uri, content); + + // Find element undeer cursor var line = position.getPosition().getLine() + 1; var column = position.getPosition().getCharacter() + 1; - var e = server.compiler.compileFocus(uri, content, line, column).element(); - if (e != null) { - List<Either<String, MarkedString>> result = new ArrayList<>(); - result.add(Either.forRight(new MarkedString("java.hover", hoverCode(e)))); - hoverDocs(e).ifPresent(doc -> result.add(Either.forLeft(doc))); - return CompletableFuture.completedFuture(new Hover(result)); - } else return CompletableFuture.completedFuture(new Hover(Collections.emptyList())); + var el = hoverCache.element(line, column); + if (el.isEmpty()) return CompletableFuture.completedFuture(new Hover(Collections.emptyList())); + + // Add code hover message + var result = new ArrayList<Either<String, MarkedString>>(); + var code = hoverCode(el.get()); + result.add(Either.forRight(new MarkedString("java.hover", code))); + // Add docs hover message + var docs = hoverDocs(el.get()); + if (docs.isPresent()) { + result.add(Either.forLeft(docs.get())); + } + + return CompletableFuture.completedFuture(new Hover(result)); } private List<ParameterInformation> signatureParamsFromDocs(MethodTree method, DocCommentTree doc) { diff --git a/src/test/java/org/javacs/CompletionsTest.java b/src/test/java/org/javacs/CompletionsTest.java index 569a620..1a8171d 100644 --- a/src/test/java/org/javacs/CompletionsTest.java +++ b/src/test/java/org/javacs/CompletionsTest.java @@ -667,14 +667,22 @@ public class CompletionsTest extends CompletionsBase { } @Test - public void switchCase() { + public void enumConstantFromSourcePath() { var file = "/org/javacs/example/AutocompleteCase.java"; - var suggestions = insertText(file, 8, 18); + var suggestions = insertText(file, 6, 18); assertThat("suggests enum options", suggestions, containsInAnyOrder("Foo", "Bar")); } @Test + public void enumConstantFromClassPath() { + var file = "/org/javacs/example/AutocompleteCaseFromClassPath.java"; + var suggestions = insertText(file, 8, 18); + + assertThat("suggests enum options", suggestions, containsInAnyOrder("FULL", "LONG", "MEDIUM", "SHORT")); + } + + @Test public void staticStarImport() { var file = "/org/javacs/example/AutocompleteStaticImport.java"; var suggestions = insertText(file, 9, 15); diff --git a/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCase.java b/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCase.java index 1a5788f..d8afd69 100644 --- a/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCase.java +++ b/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCase.java @@ -2,13 +2,15 @@ package org.javacs.example; class AutocompleteCase { void test() { - var e = MyEnum.Foo; - - switch (e) { + switch (myEnum()) { case } } + MyEnum myEnum() { + return MyEnum.Foo; + } + enum MyEnum { Foo, Bar diff --git a/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCaseFromClasspath.java b/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCaseFromClasspath.java new file mode 100644 index 0000000..6a893ae --- /dev/null +++ b/src/test/test-project/workspace/src/org/javacs/example/AutocompleteCaseFromClasspath.java @@ -0,0 +1,15 @@ +package org.javacs.example; + +import java.time.format.FormatStyle; + +class AutocompleteCaseFromClasspath { + public void main() { + switch (style()) { + case + } + } + + private FormatStyle style() { + return FormatStyle.FULL; + } +}
\ No newline at end of file |