diff options
author | George Fraser <george@fivetran.com> | 2018-12-30 21:56:10 -0800 |
---|---|---|
committer | George Fraser <george@fivetran.com> | 2018-12-30 21:56:10 -0800 |
commit | bab1f5a754c72d6b10c6c43af2a17d25bd93cdef (patch) | |
tree | 8c0e4619a010b4d978cbe0420c20367cbdb8dda9 /src | |
parent | f903f5dec011e52189664d75012e9ca47318cd62 (diff) | |
download | java-language-server-bab1f5a754c72d6b10c6c43af2a17d25bd93cdef.zip |
Source path classes in the same dir are accessible
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/org/javacs/CompileFocus.java | 61 | ||||
-rw-r--r-- | src/main/java/org/javacs/JavaCompilerService.java | 15 | ||||
-rw-r--r-- | src/test/java/org/javacs/CompletionsBase.java | 4 | ||||
-rw-r--r-- | src/test/java/org/javacs/CompletionsTest.java | 27 | ||||
-rw-r--r-- | src/test/java/org/javacs/DocsTest.java | 4 | ||||
-rw-r--r-- | src/test/java/org/javacs/FindResource.java | 12 | ||||
-rw-r--r-- | src/test/java/org/javacs/JavaCompilerServiceTest.java | 29 | ||||
-rw-r--r-- | src/test/java/org/javacs/LanguageServerFixture.java | 2 | ||||
-rw-r--r-- | src/test/java/org/javacs/ParserFixImportsTest.java | 2 | ||||
-rw-r--r-- | src/test/test-project/simple/BuildUpScope.java (renamed from src/test/resources/BuildUpScope.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/ClassDoc.java (renamed from src/test/resources/ClassDoc.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/CompleteClass.java (renamed from src/test/resources/CompleteClass.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/CompleteExpression.java (renamed from src/test/resources/CompleteExpression.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/CompleteIdentifiers.java (renamed from src/test/resources/CompleteIdentifiers.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/CompleteImports.java (renamed from src/test/resources/CompleteImports.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/CompleteInMiddle.java (renamed from src/test/resources/CompleteInMiddle.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/CompleteMembers.java (renamed from src/test/resources/CompleteMembers.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/GotoDefinition.java (renamed from src/test/resources/GotoDefinition.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/HasError.java (renamed from src/test/resources/HasError.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/HasImport.java (renamed from src/test/resources/HasImport.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/HelloWorld.java (renamed from src/test/resources/HelloWorld.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/LocalMethodDoc.java (renamed from src/test/resources/LocalMethodDoc.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/MissingImport.java (renamed from src/test/resources/MissingImport.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/Overloads.java (renamed from src/test/resources/Overloads.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneDot.java (renamed from src/test/resources/PruneDot.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneDot_erased.java (renamed from src/test/resources/PruneDot_erased.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneMethods.java (renamed from src/test/resources/PruneMethods.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneMethods_erased.java (renamed from src/test/resources/PruneMethods_erased.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneMiddle.java (renamed from src/test/resources/PruneMiddle.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneMiddle_erased.java (renamed from src/test/resources/PruneMiddle_erased.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneToEndOfBlock.java (renamed from src/test/resources/PruneToEndOfBlock.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/simple/PruneToEndOfBlock_erased.java (renamed from src/test/resources/PruneToEndOfBlock_erased.java) | 0 | ||||
-rw-r--r-- | src/test/test-project/workspace/src/org/javacs/example/AutocompleteNewFile.java | 7 |
33 files changed, 113 insertions, 50 deletions
diff --git a/src/main/java/org/javacs/CompileFocus.java b/src/main/java/org/javacs/CompileFocus.java index 8acfa42..4cf3308 100644 --- a/src/main/java/org/javacs/CompileFocus.java +++ b/src/main/java/org/javacs/CompileFocus.java @@ -13,7 +13,6 @@ import java.util.function.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; -import java.util.stream.Stream; import javax.lang.model.element.*; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; @@ -707,40 +706,40 @@ public class CompileFocus { // Check sourcepath LOG.info("...checking source path"); - Predicate<Path> matchesFileName = file -> matchesPartialName(file.getFileName().toString(), partialName); - Predicate<Path> isPublic = - file -> { - var fileName = file.getFileName().toString(); - if (!fileName.endsWith(".java")) return true; - var simpleName = fileName.substring(0, fileName.length() - ".java".length()); - Stream<String> lines; - try { - lines = Files.lines(file); - } catch (IOException e) { - throw new RuntimeException(e); - } - return lines.anyMatch(line -> line.matches(".*public\\s+class\\s+" + simpleName + ".*")); - }; - for (var dir : parent.sourcePath) { - Function<Path, String> qualifiedName = - file -> { - var relative = dir.relativize(file).toString().replace('/', '.'); - if (!relative.endsWith(".java")) return "??? " + relative + " does not end in .java"; - return relative.substring(0, relative.length() - ".java".length()); - }; - for (var file : JavaCompilerService.javaSourcesInDir(dir)) { - if (tooManyItems(result.size())) return; - // Fast check, file name only - if (matchesFileName.test(file)) { - var c = qualifiedName.apply(file); - // Slow check, open file - if (matchesPartialName.test(c) && isPublic.test(file)) { - result.add(Completion.ofClassName(c, isImported(c))); - } + for (var file : parent.allJavaFiles.get()) { + if (tooManyItems(result.size())) return; + // If file is in the same package, any class defined in the file is accessible + var pathBasedPackageName = parent.pathBasedPackageName(file); + var samePackage = pathBasedPackageName.equals(packageName) || pathBasedPackageName.isEmpty(); + // If file is in a different package, only a public class with the same name as the file is accessible + var maybePublic = matchesPartialName(file.getFileName().toString(), partialName); + if (samePackage || maybePublic) { + result.addAll(accessibleClasses(file, partialName, packageName)); + } + } + } + } + + private List<Completion> accessibleClasses(Path file, String partialName, String fromPackage) { + var parse = Parser.parse(file); + var toPackage = Objects.toString(parse.getPackageName(), ""); + var samePackage = fromPackage.equals(toPackage) || toPackage.isEmpty(); + var result = new ArrayList<Completion>(); + for (var t : parse.getTypeDecls()) { + if (!(t instanceof ClassTree)) continue; + var cls = (ClassTree) t; + var isPublic = cls.getModifiers().getFlags().contains(Modifier.PUBLIC); + if (isPublic || samePackage) { + var name = cls.getSimpleName().toString(); + if (matchesPartialName(name, partialName)) { + if (parse.getPackageName() != null) { + name = parse.getPackageName() + "." + name; } + result.add(Completion.ofClassName(name, isImported(name))); } } } + return result; } private List<Element> staticImports(URI file, String contents, String partialName) { diff --git a/src/main/java/org/javacs/JavaCompilerService.java b/src/main/java/org/javacs/JavaCompilerService.java index ddcb82f..3dce659 100644 --- a/src/main/java/org/javacs/JavaCompilerService.java +++ b/src/main/java/org/javacs/JavaCompilerService.java @@ -89,6 +89,21 @@ public class JavaCompilerService { return list; } + String pathBasedPackageName(Path javaFile) { + if (!javaFile.getFileName().toString().endsWith(".java")) { + LOG.warning(javaFile + " does not end in .java"); + return "???"; + } + for (var dir : sourcePath) { + if (!javaFile.startsWith(dir)) continue; + var packageDir = javaFile.getParent(); + var relative = dir.relativize(packageDir); + return relative.toString().replace('/', '.'); + } + LOG.warning(javaFile + " is not in the source path " + sourcePath); + return "???"; + } + private Collection<Path> removeModuleInfo(Collection<Path> files) { var result = new ArrayList<Path>(); for (var f : files) { diff --git a/src/test/java/org/javacs/CompletionsBase.java b/src/test/java/org/javacs/CompletionsBase.java index 30af123..1a6b161 100644 --- a/src/test/java/org/javacs/CompletionsBase.java +++ b/src/test/java/org/javacs/CompletionsBase.java @@ -10,6 +10,8 @@ import org.javacs.lsp.*; public class CompletionsBase { protected static final Logger LOG = Logger.getLogger("main"); + protected static final JavaLanguageServer server = LanguageServerFixture.getJavaLanguageServer(); + protected Set<String> insertTemplate(String file, int row, int column) { var items = items(file, row, column); @@ -81,8 +83,6 @@ public class CompletionsBase { .collect(Collectors.toSet()); } - protected static final JavaLanguageServer server = LanguageServerFixture.getJavaLanguageServer(); - protected List<? extends CompletionItem> items(String file, int row, int column) { var uri = FindResource.uri(file); var position = diff --git a/src/test/java/org/javacs/CompletionsTest.java b/src/test/java/org/javacs/CompletionsTest.java index b09ae92..37e46f4 100644 --- a/src/test/java/org/javacs/CompletionsTest.java +++ b/src/test/java/org/javacs/CompletionsTest.java @@ -3,6 +3,10 @@ package org.javacs; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.List; import java.util.stream.Collectors; import org.javacs.lsp.*; import org.junit.Ignore; @@ -796,4 +800,27 @@ public class CompletionsTest extends CompletionsBase { assertThat(suggestions, hasItem(containsString("util"))); } + + @Test + public void newlyCreatedClass() throws IOException { + var file = FindResource.path("/org/javacs/example/NewlyCreatedFile.java"); + try { + // Create a file that didn't exist when we created the server + try (var writer = Files.newBufferedWriter(file, StandardOpenOption.CREATE_NEW)) { + writer.write("package org.javacs.example;\nclass NewlyCreatedFile { }"); + } + // Send a 'file created' notification + var created = new FileEvent(); + created.uri = file.toUri(); + created.type = FileChangeType.Created; + var changes = new DidChangeWatchedFilesParams(); + changes.changes = List.of(created); + server.didChangeWatchedFiles(changes); + // Autocomplete `New` + var suggestions = insertText("/org/javacs/example/AutocompleteNewFile.java", 5, 12); + assertThat(suggestions, hasItem(containsString("NewlyCreatedFile"))); + } finally { + Files.delete(file); + } + } } diff --git a/src/test/java/org/javacs/DocsTest.java b/src/test/java/org/javacs/DocsTest.java index 583dea0..dd89e46 100644 --- a/src/test/java/org/javacs/DocsTest.java +++ b/src/test/java/org/javacs/DocsTest.java @@ -9,7 +9,7 @@ import org.junit.Test; public class DocsTest { @Test public void classDoc() { - var sourcePath = Set.of(JavaCompilerServiceTest.resourcesDir()); + var sourcePath = Set.of(JavaCompilerServiceTest.simpleProjectSrc()); var docs = new Docs(sourcePath); var tree = docs.classDoc("ClassDoc"); assertTrue(tree.isPresent()); @@ -18,7 +18,7 @@ public class DocsTest { @Test public void memberDoc() { - var sourcePath = Set.of(JavaCompilerServiceTest.resourcesDir()); + var sourcePath = Set.of(JavaCompilerServiceTest.simpleProjectSrc()); var docs = new Docs(sourcePath); var tree = docs.memberDoc("LocalMethodDoc", "targetMethod"); assertTrue(tree.isPresent()); diff --git a/src/test/java/org/javacs/FindResource.java b/src/test/java/org/javacs/FindResource.java index 897f85b..ce07a04 100644 --- a/src/test/java/org/javacs/FindResource.java +++ b/src/test/java/org/javacs/FindResource.java @@ -1,18 +1,20 @@ package org.javacs; import java.net.URI; +import java.nio.file.Path; import java.nio.file.Paths; /** Find java sources in test-project/workspace/src */ public class FindResource { public static URI uri(String resourcePath) { - if (resourcePath.startsWith("/")) resourcePath = resourcePath.substring(1); + var path = path(resourcePath); - var path = Paths.get("./src/test/test-project/workspace/src").resolve(resourcePath).normalize(); - var file = path.toAbsolutePath().toFile(); + return path.toUri(); + } - if (!file.exists()) throw new RuntimeException(file + " does not exist"); + public static Path path(String resourcePath) { + if (resourcePath.startsWith("/")) resourcePath = resourcePath.substring(1); - return URI.create("file://" + file); + return Paths.get("./src/test/test-project/workspace/src").resolve(resourcePath).normalize(); } } diff --git a/src/test/java/org/javacs/JavaCompilerServiceTest.java b/src/test/java/org/javacs/JavaCompilerServiceTest.java index c211014..8c67cdf 100644 --- a/src/test/java/org/javacs/JavaCompilerServiceTest.java +++ b/src/test/java/org/javacs/JavaCompilerServiceTest.java @@ -30,22 +30,22 @@ public class JavaCompilerServiceTest { private JavaCompilerService compiler = new JavaCompilerService( - Collections.singleton(resourcesDir()), + Collections.singleton(simpleProjectSrc()), JavaCompilerServiceTest::allJavaFiles, Collections.emptySet(), Collections.emptySet()); - static Path resourcesDir() { - try { - return Paths.get(JavaCompilerServiceTest.class.getResource("/HelloWorld.java").toURI()).getParent(); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } + static Path mavenProjectSrc() { + return Paths.get("src/test/test-project/workspace/src").normalize(); + } + + static Path simpleProjectSrc() { + return Paths.get("src/test/test-project/simple").normalize(); } static Set<Path> allJavaFiles() { try { - return Files.walk(resourcesDir()) + return Files.walk(simpleProjectSrc()) .filter(f -> f.getFileName().toString().endsWith(".java")) .collect(Collectors.toSet()); } catch (IOException e) { @@ -319,4 +319,17 @@ public class JavaCompilerServiceTest { assertTrue(CompileFocus.matchesPartialName("foobar", "foo")); assertFalse(CompileFocus.matchesPartialName("foo", "foobar")); } + + @Test + public void packageName() { + var compiler = + new JavaCompilerService( + Collections.singleton(mavenProjectSrc()), + JavaCompilerServiceTest::allJavaFiles, + Collections.emptySet(), + Collections.emptySet()); + assertThat( + compiler.pathBasedPackageName(FindResource.path("/org/javacs/example/Goto.java")), + equalTo("org.javacs.example")); + } } diff --git a/src/test/java/org/javacs/LanguageServerFixture.java b/src/test/java/org/javacs/LanguageServerFixture.java index 2c93283..f2da3b7 100644 --- a/src/test/java/org/javacs/LanguageServerFixture.java +++ b/src/test/java/org/javacs/LanguageServerFixture.java @@ -9,7 +9,7 @@ import org.javacs.lsp.*; class LanguageServerFixture { - public static Path DEFAULT_WORKSPACE_ROOT = Paths.get("src/test/test-project/workspace").toAbsolutePath(); + public static Path DEFAULT_WORKSPACE_ROOT = Paths.get("src/test/test-project/workspace").normalize(); static { Main.setRootFormat(); diff --git a/src/test/java/org/javacs/ParserFixImportsTest.java b/src/test/java/org/javacs/ParserFixImportsTest.java index e935962..8eb1fcb 100644 --- a/src/test/java/org/javacs/ParserFixImportsTest.java +++ b/src/test/java/org/javacs/ParserFixImportsTest.java @@ -12,7 +12,7 @@ public class ParserFixImportsTest { @Test public void findExistingImports() throws IOException { var allJavaFiles = - Files.walk(JavaCompilerServiceTest.resourcesDir()) + Files.walk(JavaCompilerServiceTest.simpleProjectSrc()) .filter(f -> f.getFileName().toString().endsWith(".java")) .collect(Collectors.toSet()); assertThat(allJavaFiles, not(empty())); diff --git a/src/test/resources/BuildUpScope.java b/src/test/test-project/simple/BuildUpScope.java index 171d816..171d816 100644 --- a/src/test/resources/BuildUpScope.java +++ b/src/test/test-project/simple/BuildUpScope.java diff --git a/src/test/resources/ClassDoc.java b/src/test/test-project/simple/ClassDoc.java index 9106496..9106496 100644 --- a/src/test/resources/ClassDoc.java +++ b/src/test/test-project/simple/ClassDoc.java diff --git a/src/test/resources/CompleteClass.java b/src/test/test-project/simple/CompleteClass.java index 5f16fb8..5f16fb8 100644 --- a/src/test/resources/CompleteClass.java +++ b/src/test/test-project/simple/CompleteClass.java diff --git a/src/test/resources/CompleteExpression.java b/src/test/test-project/simple/CompleteExpression.java index 9b9dd00..9b9dd00 100644 --- a/src/test/resources/CompleteExpression.java +++ b/src/test/test-project/simple/CompleteExpression.java diff --git a/src/test/resources/CompleteIdentifiers.java b/src/test/test-project/simple/CompleteIdentifiers.java index 8ba5e39..8ba5e39 100644 --- a/src/test/resources/CompleteIdentifiers.java +++ b/src/test/test-project/simple/CompleteIdentifiers.java diff --git a/src/test/resources/CompleteImports.java b/src/test/test-project/simple/CompleteImports.java index 1b0dc80..1b0dc80 100644 --- a/src/test/resources/CompleteImports.java +++ b/src/test/test-project/simple/CompleteImports.java diff --git a/src/test/resources/CompleteInMiddle.java b/src/test/test-project/simple/CompleteInMiddle.java index 981e71e..981e71e 100644 --- a/src/test/resources/CompleteInMiddle.java +++ b/src/test/test-project/simple/CompleteInMiddle.java diff --git a/src/test/resources/CompleteMembers.java b/src/test/test-project/simple/CompleteMembers.java index 168dc65..168dc65 100644 --- a/src/test/resources/CompleteMembers.java +++ b/src/test/test-project/simple/CompleteMembers.java diff --git a/src/test/resources/GotoDefinition.java b/src/test/test-project/simple/GotoDefinition.java index 1f8866c..1f8866c 100644 --- a/src/test/resources/GotoDefinition.java +++ b/src/test/test-project/simple/GotoDefinition.java diff --git a/src/test/resources/HasError.java b/src/test/test-project/simple/HasError.java index ad2fbe2..ad2fbe2 100644 --- a/src/test/resources/HasError.java +++ b/src/test/test-project/simple/HasError.java diff --git a/src/test/resources/HasImport.java b/src/test/test-project/simple/HasImport.java index 2b4f66e..2b4f66e 100644 --- a/src/test/resources/HasImport.java +++ b/src/test/test-project/simple/HasImport.java diff --git a/src/test/resources/HelloWorld.java b/src/test/test-project/simple/HelloWorld.java index b86724f..b86724f 100644 --- a/src/test/resources/HelloWorld.java +++ b/src/test/test-project/simple/HelloWorld.java diff --git a/src/test/resources/LocalMethodDoc.java b/src/test/test-project/simple/LocalMethodDoc.java index a240753..a240753 100644 --- a/src/test/resources/LocalMethodDoc.java +++ b/src/test/test-project/simple/LocalMethodDoc.java diff --git a/src/test/resources/MissingImport.java b/src/test/test-project/simple/MissingImport.java index 79f0d92..79f0d92 100644 --- a/src/test/resources/MissingImport.java +++ b/src/test/test-project/simple/MissingImport.java diff --git a/src/test/resources/Overloads.java b/src/test/test-project/simple/Overloads.java index e686971..e686971 100644 --- a/src/test/resources/Overloads.java +++ b/src/test/test-project/simple/Overloads.java diff --git a/src/test/resources/PruneDot.java b/src/test/test-project/simple/PruneDot.java index 2ea5e1d..2ea5e1d 100644 --- a/src/test/resources/PruneDot.java +++ b/src/test/test-project/simple/PruneDot.java diff --git a/src/test/resources/PruneDot_erased.java b/src/test/test-project/simple/PruneDot_erased.java index 2ea5e1d..2ea5e1d 100644 --- a/src/test/resources/PruneDot_erased.java +++ b/src/test/test-project/simple/PruneDot_erased.java diff --git a/src/test/resources/PruneMethods.java b/src/test/test-project/simple/PruneMethods.java index 474cee2..474cee2 100644 --- a/src/test/resources/PruneMethods.java +++ b/src/test/test-project/simple/PruneMethods.java diff --git a/src/test/resources/PruneMethods_erased.java b/src/test/test-project/simple/PruneMethods_erased.java index e3d1a4b..e3d1a4b 100644 --- a/src/test/resources/PruneMethods_erased.java +++ b/src/test/test-project/simple/PruneMethods_erased.java diff --git a/src/test/resources/PruneMiddle.java b/src/test/test-project/simple/PruneMiddle.java index 1916250..1916250 100644 --- a/src/test/resources/PruneMiddle.java +++ b/src/test/test-project/simple/PruneMiddle.java diff --git a/src/test/resources/PruneMiddle_erased.java b/src/test/test-project/simple/PruneMiddle_erased.java index 5b208b3..5b208b3 100644 --- a/src/test/resources/PruneMiddle_erased.java +++ b/src/test/test-project/simple/PruneMiddle_erased.java diff --git a/src/test/resources/PruneToEndOfBlock.java b/src/test/test-project/simple/PruneToEndOfBlock.java index 9174589..9174589 100644 --- a/src/test/resources/PruneToEndOfBlock.java +++ b/src/test/test-project/simple/PruneToEndOfBlock.java diff --git a/src/test/resources/PruneToEndOfBlock_erased.java b/src/test/test-project/simple/PruneToEndOfBlock_erased.java index fafee1f..fafee1f 100644 --- a/src/test/resources/PruneToEndOfBlock_erased.java +++ b/src/test/test-project/simple/PruneToEndOfBlock_erased.java diff --git a/src/test/test-project/workspace/src/org/javacs/example/AutocompleteNewFile.java b/src/test/test-project/workspace/src/org/javacs/example/AutocompleteNewFile.java new file mode 100644 index 0000000..431f3cf --- /dev/null +++ b/src/test/test-project/workspace/src/org/javacs/example/AutocompleteNewFile.java @@ -0,0 +1,7 @@ +package org.javacs.example; + +class AutocompleteNewFile { + void main() { + New + } +}
\ No newline at end of file |