summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Fraser <george@fivetran.com>2017-03-19 13:38:40 -0700
committerGeorge Fraser <george@fivetran.com>2017-03-19 13:38:40 -0700
commit69328dca64e15d6acea74866555de7feb462db5b (patch)
treef4e882432695eacdeb0b32545575c56ad6e6d84e /src
parent139784693f4bef6078fdc58e7ce17a9416e1a6c8 (diff)
downloadjava-language-server-69328dca64e15d6acea74866555de7feb462db5b.zip
Fixed most tests
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/javacs/CompilationResult.java17
-rw-r--r--src/main/java/org/javacs/GetResourceFileObject.java44
-rw-r--r--src/main/java/org/javacs/JavaLanguageServer.java28
-rw-r--r--src/main/java/org/javacs/JavacHolder.java232
-rw-r--r--src/main/java/org/javacs/SymbolIndex.java9
-rw-r--r--src/test/java/org/javacs/AutocompleteTest.java23
-rw-r--r--src/test/java/org/javacs/CompilerProfiling.java27
-rw-r--r--src/test/java/org/javacs/ContextPrinter.java218
-rw-r--r--src/test/java/org/javacs/FindResource.java24
-rw-r--r--src/test/java/org/javacs/GotoTest.java23
-rw-r--r--src/test/java/org/javacs/JavaCompilerTest.java15
-rw-r--r--src/test/java/org/javacs/JavacHolderTest.java30
-rw-r--r--src/test/java/org/javacs/LanguageServerFixture.java (renamed from src/test/java/org/javacs/Fixtures.java)10
-rw-r--r--src/test/java/org/javacs/LinterTest.java127
-rw-r--r--src/test/java/org/javacs/ParserTest.java22
-rw-r--r--src/test/java/org/javacs/RecompileTest.java99
-rw-r--r--src/test/java/org/javacs/SymbolIndexTest.java42
-rw-r--r--src/test/java/org/javacs/SymbolUnderCursorTest.java24
-rw-r--r--src/test/resources/org/javacs/example/FixParseErrorAfter.java1
-rw-r--r--src/test/resources/org/javacs/example/FixParseErrorBefore.java1
-rw-r--r--src/test/resources/org/javacs/example/FixTypeErrorAfter.java1
-rw-r--r--src/test/resources/org/javacs/example/FixTypeErrorBefore.java1
22 files changed, 593 insertions, 425 deletions
diff --git a/src/main/java/org/javacs/CompilationResult.java b/src/main/java/org/javacs/CompilationResult.java
new file mode 100644
index 0000000..a3f0930
--- /dev/null
+++ b/src/main/java/org/javacs/CompilationResult.java
@@ -0,0 +1,17 @@
+package org.javacs;
+
+import com.sun.tools.javac.tree.JCTree;
+
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaFileObject;
+import java.util.Collection;
+
+class CompilationResult {
+ final Collection<JCTree.JCCompilationUnit> trees;
+ final DiagnosticCollector<JavaFileObject> errors;
+
+ CompilationResult(Collection<JCTree.JCCompilationUnit> trees, DiagnosticCollector<JavaFileObject> errors) {
+ this.trees = trees;
+ this.errors = errors;
+ }
+}
diff --git a/src/main/java/org/javacs/GetResourceFileObject.java b/src/main/java/org/javacs/GetResourceFileObject.java
deleted file mode 100644
index 79ed08a..0000000
--- a/src/main/java/org/javacs/GetResourceFileObject.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.javacs;
-
-import com.google.common.io.CharStreams;
-
-import javax.tools.SimpleJavaFileObject;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * Represents a java source on the system resource path.
- */
-public class GetResourceFileObject extends SimpleJavaFileObject {
- public final String path;
-
- public GetResourceFileObject(String path) {
- super(getResourceUri(path), Kind.SOURCE);
-
- this.path = path;
- }
-
- private static URI getResourceUri(String path) {
- try {
- return GetResourceFileObject.class.getResource(path).toURI();
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
- try (Reader r = new InputStreamReader(openInputStream())) {
- return CharStreams.toString(r);
- }
- }
-
- @Override
- public InputStream openInputStream() throws IOException {
- return GetResourceFileObject.class.getResourceAsStream(path);
- }
-}
diff --git a/src/main/java/org/javacs/JavaLanguageServer.java b/src/main/java/org/javacs/JavaLanguageServer.java
index f22156d..4611b96 100644
--- a/src/main/java/org/javacs/JavaLanguageServer.java
+++ b/src/main/java/org/javacs/JavaLanguageServer.java
@@ -9,7 +9,6 @@ import org.eclipse.lsp4j.services.WorkspaceService;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
-import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -283,7 +282,9 @@ class JavaLanguageServer implements LanguageServer {
}
files.forEach((config, configFiles) -> {
- publishDiagnostics(paths, findCompilerForConfig(config).update(configFiles));
+ CompilationResult compile = findCompilerForConfig(config).compile(configFiles);
+
+ publishDiagnostics(compile);
});
}
@@ -324,7 +325,9 @@ class JavaLanguageServer implements LanguageServer {
activeDocuments.remove(uri);
findCompiler(uri).ifPresent(compiler -> {
- compiler.delete(uri);
+ CompilationResult result = compiler.delete(uri);
+
+ publishDiagnostics(result);
});
}
}
@@ -336,12 +339,16 @@ class JavaLanguageServer implements LanguageServer {
};
}
- private void publishDiagnostics(Collection<URI> paths, DiagnosticCollector<JavaFileObject> errors) {
+ private void publishDiagnostics(CompilationResult result) {
+ List<URI> touched = result.trees
+ .stream()
+ .map(tree -> tree.getSourceFile().toUri())
+ .collect(Collectors.toList());
Map<URI, PublishDiagnosticsParams> files = new HashMap<>();
+
+ touched.forEach(p -> files.put(p, newPublishDiagnostics(p)));
- paths.forEach(p -> files.put(p, newPublishDiagnostics(p)));
-
- errors.getDiagnostics().forEach(error -> {
+ result.errors.getDiagnostics().forEach(error -> {
if (error.getStartPosition() != javax.tools.Diagnostic.NOPOS) {
URI uri = error.getSource().toUri();
PublishDiagnosticsParams publish = files.computeIfAbsent(uri, this::newPublishDiagnostics);
@@ -670,6 +677,13 @@ class JavaLanguageServer implements LanguageServer {
.orElse(Collections.emptyList());
}
+ public Optional<Symbol> findSymbol(URI file, int line, int character) {
+ Optional<String> content = activeContent(file);
+ long cursor = findOffset(file, line, character);
+
+ return findCompiler(file).flatMap(compiler -> compiler.symbolAt(file, content, cursor));
+ }
+
private List<? extends SymbolInformation> findDocumentSymbols(DocumentSymbolParams params) {
URI uri = URI.create(params.getTextDocument().getUri());
diff --git a/src/main/java/org/javacs/JavacHolder.java b/src/main/java/org/javacs/JavacHolder.java
index d0ac625..0fd9ada 100644
--- a/src/main/java/org/javacs/JavacHolder.java
+++ b/src/main/java/org/javacs/JavacHolder.java
@@ -106,7 +106,7 @@ public class JavacHolder {
log.multipleErrors = true;
}
- public final JavacFileManager fileManager = new JavacFileManager(context, true, null);
+ private final JavacFileManager fileManager = new JavacFileManager(context, true, null);
private final ForgivingAttr attr = ForgivingAttr.instance(context);
private final Check check = Check.instance(context);
private final FuzzyParserFactory parserFactory = FuzzyParserFactory.instance(context);
@@ -129,7 +129,7 @@ public class JavacHolder {
// Set up SymbolIndex
/**
- * Index of symbols that gets updated every time you call update
+ * Index of symbols that gets updated every time you call compile
*/
public final SymbolIndex index = new SymbolIndex(this);
@@ -139,6 +139,10 @@ public class JavacHolder {
public final CompletableFuture<Void> initialIndexComplete;
public JavacHolder(Set<Path> classPath, Set<Path> sourcePath, Path outputDirectory) {
+ this(classPath, sourcePath, outputDirectory, true);
+ }
+
+ public JavacHolder(Set<Path> classPath, Set<Path> sourcePath, Path outputDirectory, boolean index) {
this.classPath = Collections.unmodifiableSet(classPath);
this.sourcePath = Collections.unmodifiableSet(sourcePath);
this.outputDirectory = outputDirectory;
@@ -151,7 +155,10 @@ public class JavacHolder {
ensureOutputDirectory(outputDirectory);
clearOutputDirectory(outputDirectory);
- initialIndexComplete = startIndexingSourcePath();
+ if (index)
+ initialIndexComplete = startIndexingSourcePath();
+ else
+ initialIndexComplete = CompletableFuture.completedFuture(null);
}
private void logStartStopEvents() {
@@ -179,22 +186,22 @@ public class JavacHolder {
private CompletableFuture<Void> startIndexingSourcePath() {
CompletableFuture<Void> done = new CompletableFuture<>();
Thread worker = new Thread("InitialIndex") {
- List<JCTree.JCCompilationUnit> parsed = new ArrayList<>();
- List<Path> paths = new ArrayList<>();
-
@Override
public void run() {
+ List<URI> objects = new ArrayList<>();
+
// Parse each file
- sourcePath.forEach(s -> parseAll(s, parsed, paths));
+ sourcePath.forEach(s -> findAllFiles(s, objects));
// Compile all parsed files
- compile(parsed);
+ Map<URI, Optional<String>> files = objects.stream().collect(Collectors.toMap(key -> key, key -> Optional.empty()));
+ CompilationResult result = doCompile(files);
- parsed.forEach(index::update);
+ result.trees.forEach(index::update);
// TODO minimize memory use during this process
- // Instead of doing parse-all / compile-all,
- // queue all files, then do parse / compile on each
+ // Instead of doing parse-all / compileFileObjects-all,
+ // queue all files, then do parse / compileFileObjects on each
// If invoked correctly, javac should avoid reparsing the same file twice
// Then, use the same mechanism as the desugar / generate phases to remove method bodies,
// to reclaim memory as we go
@@ -207,19 +214,16 @@ public class JavacHolder {
/**
* Look for .java files and invalidate them
*/
- private void parseAll(Path path, List<JCTree.JCCompilationUnit> trees, List<Path> paths) {
+ private void findAllFiles(Path path, List<URI> uris) {
if (Files.isDirectory(path)) try {
- Files.list(path).forEach(p -> parseAll(p, trees, paths));
+ Files.list(path).forEach(p -> findAllFiles(p, uris));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
else if (path.getFileName().toString().endsWith(".java")) {
LOG.info("Index " + path);
- JavaFileObject file = fileManager.getRegularFile(path.toFile());
-
- trees.add(parse(file));
- paths.add(path);
+ uris.add(path.toUri());
}
}
};
@@ -269,19 +273,18 @@ public class JavacHolder {
* @param cursor Offset in file where the cursor is
*/
public List<CompletionItem> autocomplete(URI file, Optional<String> textContent, long cursor) {
+ initialIndexComplete.join();
+
JavaFileObject object = findFile(file, textContent);
object = TreePruner.putSemicolonAfterCursor(object, file, cursor);
- JCTree.JCCompilationUnit tree = parse(object);
-
- // Remove all statements after the cursor
- // There are often parse errors after the cursor, which can generate unrecoverable type errors
- new TreePruner(tree, context).removeStatementsAfterCursor(cursor);
-
- compile(Collections.singleton(tree));
+ JCTree.JCCompilationUnit compiled = compileSimple(
+ object,
+ tree -> new TreePruner(tree, context).removeStatementsAfterCursor(cursor)
+ );
- return doAutocomplete(object, tree, cursor);
+ return doAutocomplete(object, compiled, cursor);
}
private List<CompletionItem> doAutocomplete(JavaFileObject object, JCTree.JCCompilationUnit pruned, long cursor) {
@@ -300,6 +303,8 @@ public class JavacHolder {
* @param cursor Offset in file where the cursor is
*/
public List<Location> findReferences(URI file, Optional<String> textContent, long cursor) {
+ initialIndexComplete.join();
+
JCTree.JCCompilationUnit tree = findTree(file, textContent);
return findSymbol(tree, cursor)
@@ -316,6 +321,8 @@ public class JavacHolder {
}
public Optional<Location> gotoDefinition(URI file, Optional<String> textContent, long cursor) {
+ initialIndexComplete.join();
+
JCTree.JCCompilationUnit tree = findTree(file, textContent);
return findSymbol(tree, cursor)
@@ -334,13 +341,7 @@ public class JavacHolder {
}
private JCTree.JCCompilationUnit findTree(URI file, Optional<String> textContent) {
- JCTree.JCCompilationUnit tree = parse(findFile(file, textContent));
-
- compile(Collections.singleton(tree));
-
- index.update(tree, context);
-
- return tree;
+ return compileSimple(findFile(file, textContent), parsed -> {});
}
private Optional<Symbol> findSymbol(JCTree.JCCompilationUnit tree, long cursor) {
@@ -353,48 +354,27 @@ public class JavacHolder {
}
public Optional<Symbol> symbolAt(URI file, Optional<String> textContent, long cursor) {
+ initialIndexComplete.join();
+
JCTree.JCCompilationUnit tree = findTree(file, textContent);
return findSymbol(tree, cursor);
}
/**
- * Clear files and all their dependents, recompile, update the index, and report any errors.
+ * File has been deleted
*/
- public DiagnosticCollector<JavaFileObject> update(Map<URI, Optional<String>> files) {
- List<JavaFileObject> objects = files
- .entrySet()
- .stream()
- .map(e -> findFile(e.getKey(), e.getValue()))
- .collect(Collectors.toList());
-
- return doUpdate(objects);
- }
+ public CompilationResult delete(URI uri) {
+ initialIndexComplete.join();
- /**
- * Exposed for testing only!
- */
- public DiagnosticCollector<JavaFileObject> doUpdate(Collection<JavaFileObject> objects) {
- List<JCTree.JCCompilationUnit> parsed = objects
+ JavaFileObject object = findFile(uri, Optional.empty());
+ Map<URI, Optional<String>> deps = dependencies(Collections.singleton(object))
.stream()
- .map(f -> {
- clear(f);
+ .collect(Collectors.toMap(o -> o.toUri(), o -> Optional.empty()));
- return f;
- })
- .map(this::parse)
- .collect(Collectors.toList());
-
- // TODO add all dependents
+ clear(object);
- return compile(parsed);
- }
-
- /**
- * File has been deleted
- */
- public void delete(URI uri) {
- // TODO
+ return compile(deps);
}
private JavaFileObject findFile(URI file, Optional<String> text) {
@@ -403,58 +383,113 @@ public class JavacHolder {
.orElse(fileManager.getRegularFile(new File(file)));
}
- /**
- * Parse the indicated source file, and its dependencies if they have been modified.
- */
- public JCTree.JCCompilationUnit parse(JavaFileObject source) {
- clear(source);
+ private DiagnosticCollector<JavaFileObject> startCollectingErrors() {
+ DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- JCTree.JCCompilationUnit result = compiler.parse(source);
+ onErrorDelegate = error -> {
+ if (error.getStartPosition() != Diagnostic.NOPOS)
+ errors.report(error);
+ else
+ LOG.warning("Skipped " + error.getMessage(null));
+ };
+ return errors;
+ }
- return result;
+ private void stopCollectingErrors() {
+ onErrorDelegate = error -> {};
}
/**
- * Compile a set of parsed files.
- *
- * If these files reference un-parsed dependencies, those dependencies will also be parsed and compiled.
+ * Clear files and all their dependents, recompile, compile the index, and report any errors.
+ *
+ * If these files reference un-compiled dependencies, those dependencies will also be parsed and compiled.
*/
- public DiagnosticCollector<JavaFileObject> compile(Collection<JCTree.JCCompilationUnit> parsed) {
- try {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
+ public CompilationResult compile(Map<URI, Optional<String>> files) {
+ initialIndexComplete.join();
- onErrorDelegate = error -> {
- if (error.getStartPosition() != Diagnostic.NOPOS)
- errors.report(error);
- };
+ return doCompile(files);
+ }
+
+ private CompilationResult doCompile(Map<URI, Optional<String>> files) {
+ List<JavaFileObject> objects = files
+ .entrySet()
+ .stream()
+ .map(e -> findFile(e.getKey(), e.getValue()))
+ .collect(Collectors.toList());
- compiler.processAnnotations(compiler.enterTrees(com.sun.tools.javac.util.List.from(parsed)));
+ objects.addAll(dependencies(objects));
- while (!todo.isEmpty()) {
- Env<AttrContext> next = todo.remove();
+ // Clear javac caches
+ objects.forEach(this::clear);
- try {
- // We don't do the desugar or generate phases, because they remove method bodies and methods
- Env<AttrContext> attributedTree = compiler.attribute(next);
- Queue<Env<AttrContext>> analyzedTree = compiler.flow(attributedTree);
- } catch (Exception e) {
- LOG.log(Level.SEVERE, "Error compiling " + next.toplevel.sourcefile.getName(), e);
+ try {
+ DiagnosticCollector<JavaFileObject> errors = startCollectingErrors();
- // Keep going
- }
- }
+ List<JCTree.JCCompilationUnit> parsed = objects.stream()
+ .map(compiler::parse)
+ .collect(Collectors.toList());
- return errors;
+ compileTrees(parsed);
+
+ parsed.forEach(index::update);
+
+ return new CompilationResult(parsed, errors);
} finally {
- onErrorDelegate = error -> {};
+ stopCollectingErrors();
}
}
+ private void compileTrees(Collection<JCTree.JCCompilationUnit> parsed) {
+ compiler.processAnnotations(compiler.enterTrees(com.sun.tools.javac.util.List.from(parsed)));
+
+ while (!todo.isEmpty()) {
+ Env<AttrContext> next = todo.remove();
+
+ try {
+ // We don't do the desugar or generate phases, because they remove method bodies and methods
+ Env<AttrContext> attributedTree = compiler.attribute(next);
+ Queue<Env<AttrContext>> analyzedTree = compiler.flow(attributedTree);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Error compiling " + next.toplevel.sourcefile.getName(), e);
+
+ // Keep going
+ }
+ }
+ }
+
+ /**
+ * Compile without updating dependencies, index, collecting errors.
+ * Useful for operations like autocomplete.
+ */
+ private JCTree.JCCompilationUnit compileSimple(JavaFileObject read, Consumer<JCTree.JCCompilationUnit> afterParse) {
+ clear(read);
+
+ JCTree.JCCompilationUnit parse = compiler.parse(read);
+
+ afterParse.accept(parse);
+ compileTrees(Collections.singleton(parse));
+
+ return parse;
+ }
+
+ private Collection<JavaFileObject> dependencies(Collection<JavaFileObject> files) {
+ // TODO
+ return Collections.emptyList();
+ }
+
+ /**
+ * Clear file from javac's caches.
+ * This is automatically invoked by other methods of this class; it's exposed only for testing.
+ */
+ public void clear(URI file) {
+ clear(findFile(file, Optional.empty()));
+ }
+
/**
* Clear a file from javac's internal caches
*/
private void clear(JavaFileObject source) {
- // TODO clear dependencies as well (dependencies should get stored in SymbolIndex)
+ index.clear(source.toUri());
// Forget about this file
Consumer<JavaFileObject> removeFromLog = logRemover(log);
@@ -471,14 +506,13 @@ public class JavacHolder {
Consumer<Type> removeFromClosureCache = closureCacheRemover(types);
check.compiled.forEach((name, symbol) -> {
- if (symbol.sourcefile.getName().equals(source.getName()))
+ if (symbol.sourcefile.getName().equals(source.getName())) {
+ removeFromClosureCache.accept(symbol.type);
remove.add(name);
-
- removeFromClosureCache.accept(symbol.type);
+ }
});
remove.forEach(check.compiled::remove);
-
}
/**
diff --git a/src/main/java/org/javacs/SymbolIndex.java b/src/main/java/org/javacs/SymbolIndex.java
index d2fd1c1..40d79ae 100644
--- a/src/main/java/org/javacs/SymbolIndex.java
+++ b/src/main/java/org/javacs/SymbolIndex.java
@@ -443,15 +443,6 @@ public class SymbolIndex {
}
/**
- * Update the index when a files changes
- */
- public void update(JCTree.JCCompilationUnit tree, Context context) {
- Indexer indexer = new Indexer(context);
-
- tree.accept(indexer);
- }
-
- /**
* Clear a file from the index when it is deleted
*/
public void clear(URI sourceFile) {
diff --git a/src/test/java/org/javacs/AutocompleteTest.java b/src/test/java/org/javacs/AutocompleteTest.java
index 1f0a3eb..4640f25 100644
--- a/src/test/java/org/javacs/AutocompleteTest.java
+++ b/src/test/java/org/javacs/AutocompleteTest.java
@@ -1,12 +1,13 @@
package org.javacs;
-import org.eclipse.lsp4j.*;
+import org.eclipse.lsp4j.CompletionItem;
+import org.eclipse.lsp4j.Position;
+import org.eclipse.lsp4j.TextDocumentIdentifier;
+import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
@@ -16,7 +17,7 @@ import java.util.stream.Stream;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
-public class AutocompleteTest extends Fixtures {
+public class AutocompleteTest {
private static final Logger LOG = Logger.getLogger("main");
@Test
@@ -417,6 +418,8 @@ public class AutocompleteTest extends Fixtures {
.collect(Collectors.toSet());
}
+ private static final JavaLanguageServer server = LanguageServerFixture.getJavaLanguageServer();
+
private List<? extends CompletionItem> items(String file, int row, int column) {
TextDocumentPositionParams position = new TextDocumentPositionParams();
@@ -424,18 +427,8 @@ public class AutocompleteTest extends Fixtures {
position.getPosition().setLine(row);
position.getPosition().setCharacter(column);
position.setTextDocument(new TextDocumentIdentifier());
- position.getTextDocument().setUri(uri(file).toString());
-
- JavaLanguageServer server = getJavaLanguageServer();
+ position.getTextDocument().setUri(FindResource.uri(file).toString());
return server.autocomplete(position).getItems();
}
-
- private URI uri(String file) {
- try {
- return AutocompleteTest.class.getResource(file).toURI();
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- }
}
diff --git a/src/test/java/org/javacs/CompilerProfiling.java b/src/test/java/org/javacs/CompilerProfiling.java
index 5056a88..dc2edc4 100644
--- a/src/test/java/org/javacs/CompilerProfiling.java
+++ b/src/test/java/org/javacs/CompilerProfiling.java
@@ -6,26 +6,24 @@ import com.sun.tools.javac.util.Context;
import org.junit.Ignore;
import org.junit.Test;
-import javax.tools.DiagnosticCollector;
-import javax.tools.JavaFileObject;
import java.io.IOException;
+import java.net.URI;
import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Collections;
+import java.util.Optional;
import java.util.logging.Logger;
import static org.junit.Assert.assertNotNull;
@Ignore
-public class CompilerProfiling extends Fixtures {
+public class CompilerProfiling {
private static final Logger LOG = Logger.getLogger("main");
@Test
public void parsingSpeed() throws IOException, URISyntaxException {
- StringFileObject file = fromResource("/org/javacs/example/LargeFile.java");
+ URI file = FindResource.uri("/org/javacs/example/LargeFile.java");
for (int i = 0; i < 10; i++) {
Duration duration = compileLargeFile(file);
@@ -34,19 +32,14 @@ public class CompilerProfiling extends Fixtures {
}
}
- private Duration compileLargeFile(StringFileObject file) {
+ private Duration compileLargeFile(URI file) {
long start = System.nanoTime();
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- JavacHolder compiler = new JavacHolder(Collections.emptySet(), Collections.emptySet(), Paths.get("out"));
+ JavacHolder compiler = new JavacHolder(Collections.emptySet(), Collections.emptySet(), Paths.get("out"), false);
GetCompilationUnit compilationUnit = new GetCompilationUnit(compiler.context);
- compiler.onError(errors);
-
try {
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- tree.accept(compilationUnit);
+ compiler.compile(Collections.singletonMap(file, Optional.empty())).trees.forEach(tree -> tree.accept(compilationUnit));
} catch (RuntimeException e) {
if (e.getCause() instanceof AbortCompilation)
LOG.info("Aborted further stages");
@@ -61,12 +54,6 @@ public class CompilerProfiling extends Fixtures {
return Duration.ofNanos(finish - start);
}
- private StringFileObject fromResource(String file) throws URISyntaxException, IOException {
- Path path = Paths.get(LinterTest.class.getResource(file).toURI());
- String content = new String(Files.readAllBytes(path));
- return new StringFileObject(content, path);
- }
-
private static class GetCompilationUnit extends BaseScanner {
private CompilationUnitTree result;
diff --git a/src/test/java/org/javacs/ContextPrinter.java b/src/test/java/org/javacs/ContextPrinter.java
new file mode 100644
index 0000000..c61827c
--- /dev/null
+++ b/src/test/java/org/javacs/ContextPrinter.java
@@ -0,0 +1,218 @@
+package org.javacs;
+
+import com.sun.tools.javac.util.Context;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+public class ContextPrinter {
+ public static Tree tree(Context context, int depth) throws NoSuchFieldException, IllegalAccessException {
+ Field ht = Context.class.getDeclaredField("ht");
+
+ ht.setAccessible(true);
+
+ Object value = ht.get(context);
+ TreeConverter treeConverter = new TreeConverter();
+
+ treeConverter.seen.add(context);
+
+ return treeConverter.convert(value, depth);
+ }
+}
+
+class TreeConverter {
+ Set<Object> seen = new HashSet<>();
+
+ Tree convert(Object o, int depth) throws IllegalAccessException {
+ if (o == null)
+ return new Leaf("null");
+ else if (seen.contains(o))
+ return new Leaf("<" + o.getClass().getSimpleName() + ">");
+ else {
+ seen.add(o);
+
+ if (o instanceof Map) {
+ Node node = Node.anonymous();
+ Map map = (Map) o;
+
+ for (Object key : map.keySet()) {
+ Object value = map.get(key);
+
+ node.children.put(keyString(key, value, node.children.keySet()), convert(value, depth));
+ }
+
+ return node;
+ } else if (o instanceof Iterable) {
+ Seq seq = new Seq();
+ Iterable it = (Iterable) o;
+
+ for (Object each : it)
+ seq.children.add(convert(each, depth));
+
+ return seq;
+ } else if (depth > 0) {
+ Class<?> klass = o.getClass();
+ Node node = Node.named(klass.getSimpleName());
+
+ for (Field field : klass.getDeclaredFields()) {
+ field.setAccessible(true);
+
+ Object value = field.get(o);
+
+ node.children.put(field.getName(), convert(value, depth - 1));
+ }
+
+ return node;
+ }
+ else return new Leaf("<" + o.getClass().getSimpleName() + ">");
+ }
+ }
+
+ private String keyString(Object key, Object value, Set<String> used) {
+ if (key instanceof Context.Key)
+ return "Context.Key<" + value.getClass().getSimpleName() + ">";
+ else
+ return key.toString();
+ }
+}
+
+class IndentPrinter {
+ private final StringBuilder out = new StringBuilder();
+ private int indent = 0;
+ private boolean startOfLine = true;
+
+ IndentPrinter increaseIndent() {
+ indent++;
+
+ return this;
+ }
+
+ IndentPrinter decreaseIndent() {
+ indent--;
+
+ return this;
+ }
+
+ IndentPrinter append(String content) {
+ if (startOfLine) {
+ for (int i = 0; i < indent; i++)
+ out.append(" ");
+
+ startOfLine = false;
+ }
+
+ out.append(content);
+
+ return this;
+ }
+
+ IndentPrinter newline() {
+ out.append("\n");
+ startOfLine = true;
+
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return out.toString();
+ }
+}
+
+abstract class Tree {
+ protected abstract void print(IndentPrinter out);
+
+ @Override
+ public String toString() {
+ IndentPrinter printer = new IndentPrinter();
+
+ print(printer);
+
+ return printer.toString();
+ }
+}
+
+class Node extends Tree {
+ final Optional<String> name;
+ final Map<String, Tree> children = new HashMap<>();
+
+ private Node(Optional<String> name) {
+ this.name = name;
+ }
+
+ static Node anonymous() {
+ return new Node(Optional.empty());
+ }
+
+ static Node named(String name) {
+ return new Node(Optional.of(name));
+ }
+
+ @Override
+ public void print(IndentPrinter out) {
+ name.ifPresent(out::append);
+
+ out.append("{").newline().increaseIndent();
+
+ children.forEach((key, value) -> {
+ out.append(key).append(": ");
+ value.print(out);
+ out.newline();
+ });
+
+ out.decreaseIndent().append("}");
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Node node = (Node) o;
+ return Objects.equals(name, node.name) &&
+ Objects.equals(children, node.children);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, children);
+ }
+}
+
+class Seq extends Tree {
+ final List<Tree> children = new ArrayList<>();
+
+ @Override
+ public void print(IndentPrinter out) {
+ out.append("[").newline().increaseIndent();
+
+ children.forEach(child -> child.print(out));
+
+ out.decreaseIndent().append("]");
+ }
+}
+
+class Leaf extends Tree {
+ final String value;
+
+ Leaf(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public void print(IndentPrinter out) {
+ out.append(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Leaf leaf = (Leaf) o;
+ return Objects.equals(value, leaf.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+} \ No newline at end of file
diff --git a/src/test/java/org/javacs/FindResource.java b/src/test/java/org/javacs/FindResource.java
new file mode 100644
index 0000000..355223a
--- /dev/null
+++ b/src/test/java/org/javacs/FindResource.java
@@ -0,0 +1,24 @@
+package org.javacs;
+
+import java.io.File;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Represents a java source on the system resource path.
+ */
+public class FindResource {
+ public static URI uri(String resourcePath) {
+ if (resourcePath.startsWith("/"))
+ resourcePath = resourcePath.substring(1);
+
+ Path path = Paths.get("./src/test/resources").resolve(resourcePath).normalize();
+ File file = path.toFile();
+
+ if (!file.exists())
+ throw new RuntimeException(file + " does not exist");
+
+ return file.toURI();
+ }
+}
diff --git a/src/test/java/org/javacs/GotoTest.java b/src/test/java/org/javacs/GotoTest.java
index afda170..66f3820 100644
--- a/src/test/java/org/javacs/GotoTest.java
+++ b/src/test/java/org/javacs/GotoTest.java
@@ -6,20 +6,16 @@ import org.junit.Test;
import java.io.IOException;
import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Paths;
import java.util.List;
import java.util.logging.Logger;
import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.hasItems;
-import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
-public class GotoTest extends Fixtures {
+public class GotoTest {
private static final Logger LOG = Logger.getLogger("main");
private static final String file = "/org/javacs/example/Goto.java";
- private static final URI uri = uri(file);
+ private static final URI uri = FindResource.uri(file);
@Test
public void localVariable() throws IOException {
@@ -68,6 +64,8 @@ public class GotoTest extends Fixtures {
public void staticMethod() throws IOException {
List<? extends Location> suggestions = doGoto(file, 15, 13);
+ System.out.println(suggestions.size());
+
assertThat(suggestions, contains(location(uri, 37, 25, 37, 37)));
}
@@ -124,10 +122,12 @@ public class GotoTest extends Fixtures {
return location;
}
+ private static final JavaLanguageServer server = LanguageServerFixture.getJavaLanguageServer();
+
private List<? extends Location> doGoto(String file, int row, int column) throws IOException {
TextDocumentIdentifier document = new TextDocumentIdentifier();
- document.setUri(uri(file).toString());
+ document.setUri(FindResource.uri(file).toString());
Position position = new Position();
@@ -139,16 +139,7 @@ public class GotoTest extends Fixtures {
p.setTextDocument(document);
p.setPosition(position);
- JavaLanguageServer server = Fixtures.getJavaLanguageServer();
-
return server.gotoDefinition(p);
}
- private static URI uri(String file) {
- try {
- return GotoTest.class.getResource(file).toURI();
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- }
}
diff --git a/src/test/java/org/javacs/JavaCompilerTest.java b/src/test/java/org/javacs/JavaCompilerTest.java
index 4c90cf2..b0dc956 100644
--- a/src/test/java/org/javacs/JavaCompilerTest.java
+++ b/src/test/java/org/javacs/JavaCompilerTest.java
@@ -4,18 +4,21 @@ import com.google.common.collect.ImmutableList;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
-import com.sun.tools.javac.tree.JCTree;
import org.junit.Ignore;
import org.junit.Test;
import javax.lang.model.element.Element;
-import javax.tools.*;
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import java.util.logging.Logger;
// TODO java compiler can fail badly, handle somehow
@@ -41,13 +44,9 @@ public class JavaCompilerTest {
@Test
public void javacHolder() {
- JavacHolder javac = new JavacHolder(Collections.emptySet(), Collections.singleton(Paths.get("src/test/resources")), Paths.get("target"));
+ JavacHolder javac = new JavacHolder(Collections.emptySet(), Collections.singleton(Paths.get("src/test/resources")), Paths.get("target"), false);
File file = Paths.get("src/test/resources/org/javacs/example/Bad.java").toFile();
- JCTree.JCCompilationUnit parsed = javac.parse(javac.fileManager.getRegularFile(file));
-
- javac.compile(Collections.singleton(parsed));
-
- LOG.info(parsed.toString());
+ CompilationResult compile = javac.compile(Collections.singletonMap(file.toURI(), Optional.empty()));
}
private void reportError(Diagnostic<? extends JavaFileObject> error) {
diff --git a/src/test/java/org/javacs/JavacHolderTest.java b/src/test/java/org/javacs/JavacHolderTest.java
new file mode 100644
index 0000000..2f6f5e7
--- /dev/null
+++ b/src/test/java/org/javacs/JavacHolderTest.java
@@ -0,0 +1,30 @@
+package org.javacs;
+
+import org.junit.Test;
+
+import java.net.URI;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Optional;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+public class JavacHolderTest {
+ @Test
+ public void clear() throws NoSuchFieldException, IllegalAccessException {
+ JavacHolder javac = new JavacHolder(Collections.emptySet(), Collections.singleton(Paths.get("src/test/resources")), Paths.get("target"), false);
+ URI file = FindResource.uri("org/javacs/example/FooString.java");
+ CompilationResult compile = javac.compile(Collections.singletonMap(file, Optional.empty()));
+ Tree tree = ContextPrinter.tree(javac.context, 3);
+
+ assertThat(tree.toString(), containsString("FooString"));
+
+ javac.clear(file);
+
+ System.out.println(tree.toString());
+
+ assertThat(tree.toString(), not(containsString("FooString")));
+ }
+}
diff --git a/src/test/java/org/javacs/Fixtures.java b/src/test/java/org/javacs/LanguageServerFixture.java
index f3c6db6..3c24acb 100644
--- a/src/test/java/org/javacs/Fixtures.java
+++ b/src/test/java/org/javacs/LanguageServerFixture.java
@@ -1,23 +1,19 @@
package org.javacs;
import org.eclipse.lsp4j.InitializeParams;
-import org.junit.BeforeClass;
-import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Set;
-public class Fixtures {
+public class LanguageServerFixture {
- public static void init() { }
-
- static JavaLanguageServer getJavaLanguageServer() {
+ public static JavaLanguageServer getJavaLanguageServer() {
Set<Path> classPath = Collections.emptySet();
Set<Path> sourcePath = Collections.singleton(Paths.get("src/test/resources").toAbsolutePath());
Path outputDirectory = Paths.get("out").toAbsolutePath();
- JavacHolder javac = new JavacHolder(classPath, sourcePath, outputDirectory);
+ JavacHolder javac = new JavacHolder(classPath, sourcePath, outputDirectory, true);
JavaLanguageServer server = new JavaLanguageServer(javac);
InitializeParams init = new InitializeParams();
diff --git a/src/test/java/org/javacs/LinterTest.java b/src/test/java/org/javacs/LinterTest.java
index 09d3422..88b0680 100644
--- a/src/test/java/org/javacs/LinterTest.java
+++ b/src/test/java/org/javacs/LinterTest.java
@@ -11,6 +11,7 @@ import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import java.io.IOException;
+import java.net.URI;
import java.nio.file.Paths;
import java.util.*;
import java.util.logging.Logger;
@@ -18,133 +19,90 @@ import java.util.logging.Logger;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
-public class LinterTest extends Fixtures {
+public class LinterTest {
private static final Logger LOG = Logger.getLogger("main");
@Test
public void compile() throws IOException {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/HelloWorld.java");
- JavacHolder compiler = newCompiler();
- compiler.onError(errors);
- compiler.compile(Collections.singleton(compiler.parse(file)));
+ URI file = FindResource.uri("/org/javacs/example/HelloWorld.java");
+ DiagnosticCollector<JavaFileObject> errors = newCompiler().compile(Collections.singletonMap(file, Optional.empty())).errors;
assertThat(errors.getDiagnostics(), empty());
}
@Test
public void inspectTree() throws IOException {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/HelloWorld.java");
+ URI file = FindResource.uri("/org/javacs/example/HelloWorld.java");
JavacHolder compiler = newCompiler();
CollectMethods scanner = new CollectMethods(compiler.context);
- compiler.onError(errors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
-
- tree.accept(scanner);
+ compiler.compile(Collections.singletonMap(file, Optional.empty())).trees.forEach(tree -> tree.accept(scanner));
assertThat(scanner.methodNames, hasItem("main"));
}
@Test
public void missingMethodBody() throws IOException {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/MissingMethodBody.java");
+ URI file = FindResource.uri("/org/javacs/example/MissingMethodBody.java");
JavacHolder compiler = newCompiler();
CollectMethods scanner = new CollectMethods(compiler.context);
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.onError(errors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
-
- tree.accept(scanner);
+ compile.trees.forEach(tree -> tree.accept(scanner));
assertThat(scanner.methodNames, hasItem("test"));
- assertThat(errors.getDiagnostics(), not(empty()));
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
// Lint again
- errors = new DiagnosticCollector<>();
-
- compiler.onError(errors);
-
- tree = compiler.parse(file);
+ compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.compile(Collections.singleton(tree));
-
- assertThat(errors.getDiagnostics(), not(empty()));
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
}
@Test
public void incompleteAssignment() throws IOException {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/IncompleteAssignment.java");
+ URI file = FindResource.uri("/org/javacs/example/IncompleteAssignment.java");
JavacHolder compiler = newCompiler();
- CollectMethods parsed = new CollectMethods(compiler.context);
CollectMethods compiled = new CollectMethods(compiler.context);
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.onError(errors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
+ compile.trees.forEach(tree -> tree.accept(compiled));
- tree.accept(parsed);
-
- compiler.compile(Collections.singleton(tree));
-
- tree.accept(compiled);
-
- assertThat(parsed.methodNames, hasItem("test")); // Error recovery should have worked
assertThat(compiled.methodNames, hasItem("test")); // Type error recovery should have worked
- assertThat(errors.getDiagnostics(), not(empty()));
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
}
@Test
public void undefinedSymbol() throws IOException {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/UndefinedSymbol.java");
+ URI file = FindResource.uri("/org/javacs/example/UndefinedSymbol.java");
JavacHolder compiler = newCompiler();
CollectMethods scanner = new CollectMethods(compiler.context);
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.onError(errors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
-
- tree.accept(scanner);
+ compile.trees.forEach(tree -> tree.accept(scanner));
assertThat(scanner.methodNames, hasItem("test")); // Type error, so parse tree is present
- Diagnostic<? extends JavaFileObject> d = errors.getDiagnostics().get(0);
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
+
+ Diagnostic<? extends JavaFileObject> d = compile.errors.getDiagnostics().get(0);
// Error position should span entire 'foo' symbol
assertThat(d.getLineNumber(), greaterThan(0L));
assertThat(d.getStartPosition(), greaterThan(0L));
assertThat(d.getEndPosition(), greaterThan(d.getStartPosition() + 1));
- assertThat(errors.getDiagnostics(), not(empty()));
}
@Test
public void getType() {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/FooString.java");
+ URI file = FindResource.uri("/org/javacs/example/FooString.java");
JavacHolder compiler = newCompiler();
MethodTypes scanner = new MethodTypes(compiler.context);
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.onError(errors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
+ compile.trees.forEach(tree -> tree.accept(scanner));
- tree.accept(scanner);
-
- assertThat(errors.getDiagnostics(), empty());
+ assertThat(compile.errors.getDiagnostics(), empty());
assertThat(scanner.methodTypes, hasKey("test"));
Type.MethodType type = scanner.methodTypes.get("test");
@@ -156,35 +114,29 @@ public class LinterTest extends Fixtures {
@Test
public void notJava() {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/NotJava.java.txt");
+ URI file = FindResource.uri("/org/javacs/example/NotJava.java.txt");
JavacHolder compiler = newCompiler();
- compiler.onError(errors);
- compiler.compile(Collections.singleton(compiler.parse(file)));
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- assertThat(errors.getDiagnostics(), not(empty()));
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
}
@Test
public void errorInDependency() {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/ErrorInDependency.java");
+ URI file = FindResource.uri("/org/javacs/example/ErrorInDependency.java");
JavacHolder compiler = newCompiler();
- compiler.onError(errors);
- compiler.compile(Collections.singleton(compiler.parse(file)));
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- assertThat(errors.getDiagnostics(), not(empty()));
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
}
@Test
public void deprecationWarning() {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/DeprecationWarning.java");
+ URI file = FindResource.uri("/org/javacs/example/DeprecationWarning.java");
JavacHolder compiler = newCompiler();
- compiler.onError(errors);
- compiler.compile(Collections.singleton(compiler.parse(file)));
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- assertThat(errors.getDiagnostics(), not(empty()));
+ assertThat(compile.errors.getDiagnostics(), not(empty()));
}
public static class MethodTypes extends BaseScanner {
@@ -222,8 +174,11 @@ public class LinterTest extends Fixtures {
}
private static JavacHolder newCompiler() {
- return new JavacHolder(Collections.emptySet(),
- Collections.singleton(Paths.get("src/test/resources")),
- Paths.get("out"));
+ return new JavacHolder(
+ Collections.emptySet(),
+ Collections.singleton(Paths.get("src/test/resources")),
+ Paths.get("out"),
+ false
+ );
}
}
diff --git a/src/test/java/org/javacs/ParserTest.java b/src/test/java/org/javacs/ParserTest.java
index 2a3074d..63a93f6 100644
--- a/src/test/java/org/javacs/ParserTest.java
+++ b/src/test/java/org/javacs/ParserTest.java
@@ -5,39 +5,41 @@ import com.sun.tools.javac.tree.TreeScanner;
import org.junit.Test;
import java.io.IOException;
+import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertThat;
-public class ParserTest extends Fixtures {
+public class ParserTest {
@Test
public void missingSemicolon() throws IOException, URISyntaxException {
JavacHolder compiler = newCompiler();
List<String> methods = new ArrayList<>();
+ URI file = FindResource.uri("/org/javacs/example/MissingSemicolon.java");
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/MissingSemicolon.java");
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- tree.accept(new TreeScanner() {
+ compiler.compile(Collections.singletonMap(file, Optional.empty())).trees.forEach(t -> t.accept(new TreeScanner() {
@Override
public void visitMethodDef(JCTree.JCMethodDecl node) {
methods.add(node.getName().toString());
}
- });
+ }));
assertThat(methods, hasItem("methodWithMissingSemicolon"));
assertThat(methods, hasItem("methodAfterMissingSemicolon"));
}
private JavacHolder newCompiler() {
- return new JavacHolder(Collections.emptySet(),
- Collections.singleton(Paths.get("src/test/resources")),
- Paths.get("out"));
+ return new JavacHolder(
+ Collections.emptySet(),
+ Collections.singleton(Paths.get("src/test/resources")),
+ Paths.get("out"),
+ false
+ );
}
}
diff --git a/src/test/java/org/javacs/RecompileTest.java b/src/test/java/org/javacs/RecompileTest.java
index 15da1b5..bb7d123 100644
--- a/src/test/java/org/javacs/RecompileTest.java
+++ b/src/test/java/org/javacs/RecompileTest.java
@@ -7,135 +7,102 @@ import org.junit.Test;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import java.io.IOException;
-import java.nio.file.Path;
+import java.net.URI;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
-public class RecompileTest extends Fixtures {
- static {
- Fixtures.init();
- }
-
+public class RecompileTest {
@Test
public void compileTwice() {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/CompileTwice.java");
+ URI file = FindResource.uri("/org/javacs/example/CompileTwice.java");
JavacHolder compiler = newCompiler();
List<String> visits = new ArrayList<>();
GetClass getClass = new GetClass(compiler.context, visits);
+ CompilationResult compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.onError(errors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
-
- tree.accept(getClass);
+ compile.trees.forEach(tree -> tree.accept(getClass));
- assertThat(errors.getDiagnostics(), empty());
+ assertThat(compile.errors.getDiagnostics(), empty());
assertThat(visits, hasItems("CompileTwice", "NestedStaticClass", "NestedClass"));
// Compile again
- tree = compiler.parse(file);
+ compile = compiler.compile(Collections.singletonMap(file, Optional.empty()));
- compiler.compile(Collections.singleton(tree));
+ compile.trees.forEach(tree -> tree.accept(getClass));
- tree.accept(getClass);
-
- assertThat(errors.getDiagnostics(), empty());
+ assertThat(compile.errors.getDiagnostics(), empty());
assertThat(visits, hasItems("CompileTwice", "NestedStaticClass", "NestedClass",
"CompileTwice", "NestedStaticClass", "NestedClass"));
}
@Test
public void fixParseError() {
- Path path = Paths.get("org/javacs/example/FixParseError.java");
- StringFileObject bad = new StringFileObject("public class FixParseError { public String foo() { return \"foo\"; }", path);
- StringFileObject good = new StringFileObject("public class FixParseError { public String foo() { return \"foo\"; } }", path);
+ URI bad = FindResource.uri("/org/javacs/example/FixParseErrorBefore.java");
+ URI good = FindResource.uri("/org/javacs/example/FixParseErrorAfter.java");
JavacHolder compiler = newCompiler();
- DiagnosticCollector<JavaFileObject> badErrors = new DiagnosticCollector<>();
-
- compiler.onError(badErrors);
- compiler.parse(bad);
-
- DiagnosticCollector<JavaFileObject> goodErrors = new DiagnosticCollector<>();
+ DiagnosticCollector<JavaFileObject> badErrors = compiler.compile(Collections.singletonMap(bad, Optional.empty())).errors;
assertThat(badErrors.getDiagnostics(), not(empty()));
// Parse again
+ CompilationResult goodCompile = compiler.compile(Collections.singletonMap(good, Optional.empty()));
+ DiagnosticCollector<JavaFileObject> goodErrors = goodCompile.errors;
List<String> parsedClassNames = new ArrayList<>();
GetClass getClass = new GetClass(compiler.context, parsedClassNames);
- compiler.onError(goodErrors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(good);
-
- tree.accept(getClass);
+ goodCompile.trees.forEach(tree -> tree.accept(getClass));
assertThat(goodErrors.getDiagnostics(), empty());
- assertThat(parsedClassNames, contains("FixParseError"));
+ assertThat(parsedClassNames, contains("FixParseErrorAfter"));
}
@Test
public void fixTypeError() {
- Path path = Paths.get("org/javacs/example/FixTypeError.java");
- StringFileObject bad = new StringFileObject("public class FixTypeError { public String foo() { return 1; } }", path);
- StringFileObject good = new StringFileObject("public class FixTypeError { public String foo() { return \"foo\"; } }", path);
+ URI bad = FindResource.uri("/org/javacs/example/FixTypeErrorBefore.java");
+ URI good = FindResource.uri("/org/javacs/example/FixTypeErrorAfter.java");
JavacHolder compiler = newCompiler();
- DiagnosticCollector<JavaFileObject> badErrors = new DiagnosticCollector<>();
-
- compiler.onError(badErrors);
- compiler.compile(Collections.singleton(compiler.parse(bad)));
-
- DiagnosticCollector<JavaFileObject> goodErrors = new DiagnosticCollector<>();
+ DiagnosticCollector<JavaFileObject> badErrors = compiler.compile(Collections.singletonMap(bad, Optional.empty())).errors;
assertThat(badErrors.getDiagnostics(), not(empty()));
// Parse again
+ CompilationResult goodCompile = compiler.compile(Collections.singletonMap(good, Optional.empty()));
+ DiagnosticCollector<JavaFileObject> goodErrors = goodCompile.errors;
List<String> parsedClassNames = new ArrayList<>();
-
GetClass getClass = new GetClass(compiler.context, parsedClassNames);
- compiler.onError(goodErrors);
-
- JCTree.JCCompilationUnit tree = compiler.parse(good);
-
- compiler.compile(Collections.singleton(tree));
-
- tree.accept(getClass);
+ goodCompile.trees.forEach(tree -> tree.accept(getClass));
assertThat(goodErrors.getDiagnostics(), empty());
- assertThat(parsedClassNames, contains("FixTypeError"));
+ assertThat(parsedClassNames, contains("FixTypeErrorAfter"));
}
private static JavacHolder newCompiler() {
- return new JavacHolder(Collections.emptySet(),
- Collections.singleton(Paths.get("src/test/resources")),
- Paths.get("out"));
+ return new JavacHolder(
+ Collections.emptySet(),
+ Collections.singleton(Paths.get("src/test/resources")),
+ Paths.get("out"),
+ false
+ );
}
@Test
public void keepTypeError() throws IOException {
- DiagnosticCollector<JavaFileObject> errors = new DiagnosticCollector<>();
- GetResourceFileObject file = new GetResourceFileObject("/org/javacs/example/UndefinedSymbol.java");
+ URI file = FindResource.uri("/org/javacs/example/UndefinedSymbol.java");
JavacHolder compiler = newCompiler();
// Compile once
- compiler.onError(errors);
- compiler.compile(Collections.singleton(compiler.parse(file)));
-
+ DiagnosticCollector<JavaFileObject> errors = compiler.compile(Collections.singletonMap(file, Optional.empty())).errors;
assertThat(errors.getDiagnostics(), not(empty()));
// Compile twice
- errors = new DiagnosticCollector<>();
- compiler.onError(errors);
-
- compiler.compile(Collections.singleton(compiler.parse(file)));
+ errors = compiler.compile(Collections.singletonMap(file, Optional.empty())).errors;
assertThat(errors.getDiagnostics(), not(empty()));
}
diff --git a/src/test/java/org/javacs/SymbolIndexTest.java b/src/test/java/org/javacs/SymbolIndexTest.java
index cedbc5d..a6f35b7 100644
--- a/src/test/java/org/javacs/SymbolIndexTest.java
+++ b/src/test/java/org/javacs/SymbolIndexTest.java
@@ -1,14 +1,16 @@
package org.javacs;
import com.sun.tools.javac.code.Symbol;
-
-import javax.tools.*;
-import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree;
import org.junit.Test;
+import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -62,7 +64,7 @@ public class SymbolIndexTest {
compile(path);
- List<String> all = index.allInFile(new GetResourceFileObject(path).toUri())
+ List<String> all = index.allInFile(FindResource.uri(path))
.map(s -> s.getName())
.collect(Collectors.toList());
@@ -82,7 +84,7 @@ public class SymbolIndexTest {
compile(path);
- List<String> all = index.allInFile(new GetResourceFileObject(path).toUri())
+ List<String> all = index.allInFile(FindResource.uri(path))
.map(s -> s.getName())
.collect(Collectors.toList());
@@ -90,17 +92,14 @@ public class SymbolIndexTest {
}
private Symbol symbol(String path, int line, int character) {
- return new JavaLanguageServer(compiler).findSymbol(compile(path), line, character).orElse(null);
+ return new JavaLanguageServer(compiler)
+ .findSymbol(FindResource.uri(path), line, character).orElse(null);
}
private JCTree.JCCompilationUnit compile(String path) {
- JavaFileObject file = new GetResourceFileObject(path);
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
- index.update(tree, compiler.context);
+ URI file = FindResource.uri(path);
- return tree;
+ return compiler.compile(Collections.singletonMap(file, Optional.empty())).trees.stream().findFirst().get();
}
private Set<String> search(String query) {
@@ -111,20 +110,19 @@ public class SymbolIndexTest {
private SymbolIndex index = getIndex();
private static SymbolIndex getIndex() {
- Set<Path> sourcePath = Collections.singleton(Paths.get("src/main/java").toAbsolutePath());
- Path outputDirectory = Paths.get("out").toAbsolutePath();
- SymbolIndex index = new SymbolIndex(classPath, sourcePath, outputDirectory);
-
- index.initialIndexComplete.join();
+ compiler.initialIndexComplete.join();
- return index;
+ return compiler.index;
}
private static JavacHolder compiler = newCompiler();
private static JavacHolder newCompiler() {
- return new JavacHolder(Collections.emptySet(),
- Collections.singleton(Paths.get("src/test/resources")),
- Paths.get("out"));
+ return new JavacHolder(
+ Collections.emptySet(),
+ Collections.singleton(Paths.get("src/test/resources")),
+ Paths.get("out"),
+ true
+ );
}
} \ No newline at end of file
diff --git a/src/test/java/org/javacs/SymbolUnderCursorTest.java b/src/test/java/org/javacs/SymbolUnderCursorTest.java
index 0de053b..187372d 100644
--- a/src/test/java/org/javacs/SymbolUnderCursorTest.java
+++ b/src/test/java/org/javacs/SymbolUnderCursorTest.java
@@ -1,18 +1,16 @@
package org.javacs;
import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.tree.JCTree;
import org.junit.Ignore;
import org.junit.Test;
-import javax.tools.JavaFileObject;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
-public class SymbolUnderCursorTest extends Fixtures {
+public class SymbolUnderCursorTest {
@Test
public void classDeclaration() {
@@ -81,25 +79,19 @@ public class SymbolUnderCursorTest extends Fixtures {
}
private String symbolAt(String file, int line, int character) {
- Optional<Symbol> symbol = new JavaLanguageServer(compiler).findSymbol(compile(file), line, character);
+ Optional<Symbol> symbol = new JavaLanguageServer(compiler).findSymbol(FindResource.uri(file), line, character);
return symbol.map(s -> s.getSimpleName().toString()).orElse(null);
}
- private JCTree.JCCompilationUnit compile(String path) {
- JavaFileObject file = new GetResourceFileObject(path);
- JCTree.JCCompilationUnit tree = compiler.parse(file);
-
- compiler.compile(Collections.singleton(tree));
-
- return tree;
- }
-
private static JavacHolder compiler = newCompiler();
private static JavacHolder newCompiler() {
- return new JavacHolder(Collections.emptySet(),
- Collections.singleton(Paths.get("src/test/resources")),
- Paths.get("out"));
+ return new JavacHolder(
+ Collections.emptySet(),
+ Collections.singleton(Paths.get("src/test/resources")),
+ Paths.get("out"),
+ false
+ );
}
}
diff --git a/src/test/resources/org/javacs/example/FixParseErrorAfter.java b/src/test/resources/org/javacs/example/FixParseErrorAfter.java
new file mode 100644
index 0000000..87449fb
--- /dev/null
+++ b/src/test/resources/org/javacs/example/FixParseErrorAfter.java
@@ -0,0 +1 @@
+public class FixParseErrorAfter { public String foo() { return "foo"; } } \ No newline at end of file
diff --git a/src/test/resources/org/javacs/example/FixParseErrorBefore.java b/src/test/resources/org/javacs/example/FixParseErrorBefore.java
new file mode 100644
index 0000000..32f6aae
--- /dev/null
+++ b/src/test/resources/org/javacs/example/FixParseErrorBefore.java
@@ -0,0 +1 @@
+public class FixParseErrorBefore { public String foo() { return "foo"; } \ No newline at end of file
diff --git a/src/test/resources/org/javacs/example/FixTypeErrorAfter.java b/src/test/resources/org/javacs/example/FixTypeErrorAfter.java
new file mode 100644
index 0000000..1b72b04
--- /dev/null
+++ b/src/test/resources/org/javacs/example/FixTypeErrorAfter.java
@@ -0,0 +1 @@
+public class FixTypeErrorAfter { public String foo() { return "foo"; } } \ No newline at end of file
diff --git a/src/test/resources/org/javacs/example/FixTypeErrorBefore.java b/src/test/resources/org/javacs/example/FixTypeErrorBefore.java
new file mode 100644
index 0000000..a644d93
--- /dev/null
+++ b/src/test/resources/org/javacs/example/FixTypeErrorBefore.java
@@ -0,0 +1 @@
+public class FixTypeErrorBefore { public String foo() { return 1; } } \ No newline at end of file