summaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/javacs/CompileBatch.java7
-rw-r--r--src/main/java/org/javacs/JavaLanguageServer.java20
-rw-r--r--src/main/java/org/javacs/Profiler.java1
-rw-r--r--src/main/java/org/javacs/Pruner.java103
-rw-r--r--src/main/java/org/javacs/lsp/LSP.java1
5 files changed, 104 insertions, 28 deletions
diff --git a/src/main/java/org/javacs/CompileBatch.java b/src/main/java/org/javacs/CompileBatch.java
index 96ab36e..65e3145 100644
--- a/src/main/java/org/javacs/CompileBatch.java
+++ b/src/main/java/org/javacs/CompileBatch.java
@@ -96,7 +96,12 @@ public class CompileBatch {
return Optional.ofNullable(el);
}
}
- throw new RuntimeException("File " + uri + " isn't in batch " + roots);
+ // Somehow, uri was not in batch
+ var names = new StringJoiner(", ");
+ for (var r : roots) {
+ names.add(Parser.fileName(r.getSourceFile().toUri()));
+ }
+ throw new RuntimeException("File " + uri + " isn't in batch " + names);
}
public Optional<List<TreePath>> definitions(Element el) {
diff --git a/src/main/java/org/javacs/JavaLanguageServer.java b/src/main/java/org/javacs/JavaLanguageServer.java
index 4932cc1..41db831 100644
--- a/src/main/java/org/javacs/JavaLanguageServer.java
+++ b/src/main/java/org/javacs/JavaLanguageServer.java
@@ -775,14 +775,15 @@ class JavaLanguageServer extends LanguageServer {
// Compile all files that *might* contain definitions of fromEl
var toFiles = compiler.potentialDefinitions(toEl.get());
if (toFiles.isEmpty()) return Optional.of(List.of());
- var batch = compiler.compileBatch(latestText(toFiles));
+ var name = toEl.get().getSimpleName().toString();
+ var batch = compiler.compileBatch(pruneWord(toFiles, name));
// Find fromEl again, so that we have an Element from the current batch
var fromElAgain = batch.element(fromUri, fromLine, fromColumn).get();
// Find all definitions of fromElAgain
var toTreePaths = batch.definitions(fromElAgain);
- if (toTreePaths.isEmpty()) return Optional.empty();
+ if (!toTreePaths.isPresent()) return Optional.empty();
var result = new ArrayList<Location>();
for (var path : toTreePaths.get()) {
var toUri = path.getCompilationUnit().getSourceFile().toUri();
@@ -845,7 +846,8 @@ class JavaLanguageServer extends LanguageServer {
// Compile all files that *might* contain references to toEl
var fromFiles = compiler.potentialReferences(toEl.get());
if (fromFiles.isEmpty()) return Optional.of(List.of());
- var batch = compiler.compileBatch(latestText(fromFiles));
+ var name = toEl.get().getSimpleName().toString();
+ var batch = compiler.compileBatch(pruneWord(fromFiles, name));
// Find toEl again, so that we have an Element from the current batch
var toElAgain = batch.element(toUri, toLine, toColumn).get();
@@ -853,7 +855,7 @@ class JavaLanguageServer extends LanguageServer {
// Find all references to toElAgain
// TODO this should references to supers of toEl
var fromTreePaths = batch.references(toElAgain);
- if (fromTreePaths.isEmpty()) return Optional.empty();
+ if (!fromTreePaths.isPresent()) return Optional.empty();
var result = new ArrayList<Location>();
for (var path : fromTreePaths.get()) {
var fromUri = path.getCompilationUnit().getSourceFile().toUri();
@@ -868,6 +870,16 @@ class JavaLanguageServer extends LanguageServer {
return Optional.of(result);
}
+ private List<JavaFileObject> pruneWord(List<URI> files, String word) {
+ var sources = new ArrayList<JavaFileObject>();
+ for (var f : files) {
+ var contents = contents(f).content;
+ var pruned = Pruner.prune(f, contents, word);
+ sources.add(new StringFileObject(pruned, f));
+ }
+ return sources;
+ }
+
private List<JavaFileObject> latestText(List<URI> files) {
var sources = new ArrayList<JavaFileObject>();
for (var f : files) {
diff --git a/src/main/java/org/javacs/Profiler.java b/src/main/java/org/javacs/Profiler.java
index 7285732..742ee35 100644
--- a/src/main/java/org/javacs/Profiler.java
+++ b/src/main/java/org/javacs/Profiler.java
@@ -16,6 +16,7 @@ class Profiler implements TaskListener {
public void started(TaskEvent e) {
started.put(e.getKind(), Instant.now());
files.add(e.getSourceFile().toUri());
+ // TODO log file name when we compile something that wasn't in the batch
}
@Override
diff --git a/src/main/java/org/javacs/Pruner.java b/src/main/java/org/javacs/Pruner.java
index 08f2553..bf7203b 100644
--- a/src/main/java/org/javacs/Pruner.java
+++ b/src/main/java/org/javacs/Pruner.java
@@ -1,32 +1,45 @@
package org.javacs;
import com.sun.source.tree.*;
+import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreeScanner;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
class Pruner {
- static String prune(URI file, String contents, int line, int character) {
- var task = Parser.parseTask(new StringFileObject(contents, file));
- CompilationUnitTree root;
- try {
- root = task.parse().iterator().next();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- var buffer = new StringBuilder(contents);
- var sourcePositions = Trees.instance(task).getSourcePositions();
- var lines = root.getLineMap();
- var cursor = lines.getPosition(line, character);
+ private static String prune(CompilationUnitTree root, SourcePositions pos, StringBuilder buffer, long[] offsets) {
class Scan extends TreeScanner<Void, Void> {
boolean erasedAfterCursor = false;
boolean containsCursor(Tree node) {
- long start = sourcePositions.getStartPosition(root, node),
- end = sourcePositions.getEndPosition(root, node);
- return start <= cursor && cursor <= end;
+ var start = pos.getStartPosition(root, node);
+ var end = pos.getEndPosition(root, node);
+ for (var cursor : offsets) {
+ if (start <= cursor && cursor <= end) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ long lastCursorIn(Tree node) {
+ var start = pos.getStartPosition(root, node);
+ var end = pos.getEndPosition(root, node);
+ long last = -1;
+ for (var cursor : offsets) {
+ if (start <= cursor && cursor <= end) {
+ last = cursor;
+ }
+ }
+ if (last == -1) {
+ throw new RuntimeException(
+ String.format("No cursor in %s is between %d and %d", offsets, start, end));
+ }
+ return last;
}
void erase(long start, long end) {
@@ -42,26 +55,27 @@ class Pruner {
}
@Override
- public Void visitImport(ImportTree node, Void aVoid) {
+ public Void visitImport(ImportTree node, Void __) {
// Erase 'static' keyword so autocomplete works better
if (containsCursor(node) && node.isStatic()) {
- var start = (int) sourcePositions.getStartPosition(root, node);
+ var start = (int) pos.getStartPosition(root, node);
start = buffer.indexOf("static", start);
var end = start + "static".length();
erase(start, end);
}
- return super.visitImport(node, aVoid);
+ return super.visitImport(node, null);
}
@Override
- public Void visitBlock(BlockTree node, Void aVoid) {
+ public Void visitBlock(BlockTree node, Void __) {
if (containsCursor(node)) {
- super.visitBlock(node, aVoid);
+ super.visitBlock(node, null);
// When we find the deepest block that includes the cursor
if (!erasedAfterCursor) {
+ var cursor = lastCursorIn(node);
var start = cursor;
- var end = sourcePositions.getEndPosition(root, node);
+ var end = pos.getEndPosition(root, node);
if (end >= buffer.length()) end = buffer.length() - 1;
// Find the next line
while (start < end && buffer.charAt((int) start) != '\n') start++;
@@ -74,8 +88,8 @@ class Pruner {
} else if (!node.getStatements().isEmpty()) {
var first = node.getStatements().get(0);
var last = node.getStatements().get(node.getStatements().size() - 1);
- var start = sourcePositions.getStartPosition(root, first);
- var end = sourcePositions.getEndPosition(root, last);
+ var start = pos.getStartPosition(root, first);
+ var end = pos.getEndPosition(root, last);
if (end >= buffer.length()) end = buffer.length() - 1;
erase(start, end);
}
@@ -92,4 +106,47 @@ class Pruner {
return buffer.toString();
}
+
+ static String prune(URI file, String contents, int line, int character) {
+ // Parse file
+ var task = Parser.parseTask(new StringFileObject(contents, file));
+ CompilationUnitTree root;
+ try {
+ root = task.parse().iterator().next();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ // Erase all blocks that don't include line:character
+ var lines = root.getLineMap();
+ var cursor = lines.getPosition(line, character);
+ var pos = Trees.instance(task).getSourcePositions();
+ var buffer = new StringBuilder(contents);
+ return prune(root, pos, buffer, new long[] {cursor});
+ }
+
+ static String prune(URI file, String contents, String name) {
+ // Find all occurrences of name in contents
+ var list = new ArrayList<Long>();
+ var pattern = Pattern.compile("\\b" + Pattern.quote(name) + "\\b");
+ var matcher = pattern.matcher(contents);
+ while (matcher.find()) {
+ list.add((long) matcher.start());
+ }
+ var offsets = new long[list.size()];
+ for (var i = 0; i < list.size(); i++) {
+ offsets[i] = list.get(i);
+ }
+ // Parse file
+ var task = Parser.parseTask(new StringFileObject(contents, file));
+ CompilationUnitTree root;
+ try {
+ root = task.parse().iterator().next();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ // Erase all blocks that don't contain name
+ var buffer = new StringBuilder(contents);
+ var pos = Trees.instance(task).getSourcePositions();
+ return prune(root, pos, buffer, offsets);
+ }
}
diff --git a/src/main/java/org/javacs/lsp/LSP.java b/src/main/java/org/javacs/lsp/LSP.java
index 55f1eca..4663e0c 100644
--- a/src/main/java/org/javacs/lsp/LSP.java
+++ b/src/main/java/org/javacs/lsp/LSP.java
@@ -415,6 +415,7 @@ public class LSP {
}
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
+ // TODO send failure response if r was a request
}
}
}