Merge pull request #690 from Efratror/LSP-Feature/Reference_Support

Lsp feature/reference support
This commit is contained in:
Ben Fry
2023-07-16 14:31:42 -04:00
committed by GitHub
5 changed files with 106 additions and 15 deletions
+3 -1
View File
@@ -163,7 +163,9 @@ public class ASTUtils {
}
protected static List<SimpleName> findAllOccurrences(ASTNode root, String bindingKey) {
public static List<SimpleName> findAllOccurrences(ASTNode root,
String bindingKey
) {
List<SimpleName> occurrences = new ArrayList<>();
root.getRoot().accept(new ASTVisitor() {
@Override
@@ -18,6 +18,6 @@ public class SketchInterval {
public final int startTabOffset;
public final int stopTabOffset;
final int startPdeOffset;
final int stopPdeOffset;
public final int startPdeOffset;
public final int stopPdeOffset;
}
@@ -78,6 +78,7 @@ class PdeLanguageServer implements LanguageServer, LanguageClientAware {
capabilities.setCompletionProvider(completionOptions);
capabilities.setDocumentFormattingProvider(true);
capabilities.setDeclarationProvider(true);
capabilities.setReferencesProvider(true);
var result = new InitializeResult(capabilities);
return CompletableFuture.completedFuture(result);
}
@@ -18,8 +18,7 @@ import processing.app.SketchCode;
import processing.mode.java.PreprocSketch;
import processing.mode.java.SketchInterval;
import static processing.mode.java.ASTUtils.getSimpleNameAt;
import static processing.mode.java.ASTUtils.resolveBinding;
import static processing.mode.java.ASTUtils.*;
public class PdeSymbolFinder {
@@ -77,18 +76,74 @@ public class PdeSymbolFinder {
System.out.println("declaration is outside of the sketch");
return Collections.emptyList();
}
List<Location> declarationList = new ArrayList<>();
declarationList.add(findLocation(ps, si));
return declarationList;
}
/**
* searches all reference nodes for a provided character offset
*
* @param ps processed sketch, for AST-nodes and sketch
* @param javaOffset character offset for the node we want to look up
*
* @return Location list of all references found, else an empty list.
*/
static public List<? extends Location> searchReference(PreprocSketch ps,
int javaOffset
) {
ASTNode root = ps.compilationUnit;
//Create a location for the found declaration
SimpleName simpleName = getSimpleNameAt(root, javaOffset, javaOffset);
if (simpleName == null) {
System.out.println("no simple name found at location");
return Collections.emptyList();
}
IBinding binding = resolveBinding(simpleName);
if (binding == null) {
System.out.println("binding not resolved");
return Collections.emptyList();
}
// Find usages
String bindingKey = binding.getKey();
List<SketchInterval> referenceIntervals =
findAllOccurrences(ps.compilationUnit, bindingKey).stream()
.map(ps::mapJavaToSketch)
// remove occurrences which fall into generated header
.filter(ps::inRange)
// remove empty intervals (happens when occurence was inserted)
.filter(in -> in.startPdeOffset < in.stopPdeOffset)
.collect(java.util.stream.Collectors.toList());
List<Location> referenceList = new ArrayList<>();
for (SketchInterval referenceInterval: referenceIntervals) {
referenceList.add(findLocation(ps, referenceInterval));
}
return referenceList;
}
/**
* Looks for a location(range) for a given sketchInterval
*
* @param ps processed sketch, for finding the uri and code
* @param si The interval to find the location for
*
* @return Location(range) inside a file from the workspace
*/
static private Location findLocation(PreprocSketch ps, SketchInterval si) {
SketchCode code = ps.sketch.getCode(si.tabIndex);
String program = code.getProgram();
URI uri = PdeAdapter.pathToUri(code.getFile());
Location location =
PdeAdapter.toLocation(program, si.startTabOffset, si.stopTabOffset, uri);
List<Location> declarationList = new ArrayList<>();
declarationList.add(location);
return declarationList;
return PdeAdapter.toLocation(program, si.startTabOffset, si.stopTabOffset,
uri
);
}
}
@@ -17,6 +17,7 @@ import org.eclipse.lsp4j.DocumentFormattingParams;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.ReferenceParams;
import java.util.Collections;
import java.net.URI;
@@ -105,7 +106,7 @@ class PdeTextDocumentService implements TextDocumentService {
Optional<PdeAdapter> adapterOptional =
pls.getAdapter(uri);
if(adapterOptional.isEmpty()){
if (adapterOptional.isEmpty()) {
System.out.println("pde adapter not found");
return CompletableFutures.computeAsync(_x -> Either
.forLeft(Collections.emptyList()));
@@ -116,7 +117,7 @@ class PdeTextDocumentService implements TextDocumentService {
Optional<Integer> optionalJavaOffset = adapter.findJavaOffset(uri,
lineNumber, colNumber);
if(optionalJavaOffset.isEmpty()){
if (optionalJavaOffset.isEmpty()) {
System.out.println("javaOffset not found");
return CompletableFutures.computeAsync(_x -> Either
.forLeft(Collections.emptyList()));
@@ -137,4 +138,36 @@ class PdeTextDocumentService implements TextDocumentService {
);
}
@Override
public CompletableFuture<List<? extends Location>> references(
ReferenceParams params
) {
System.out.println("searching for references");
URI uri = URI.create(params.getTextDocument().getUri());
int lineNumber = params.getPosition().getLine();
int colNumber = params.getPosition().getCharacter();
Optional<PdeAdapter> adapterOptional = pls.getAdapter(uri);
if (adapterOptional.isEmpty()) {
System.out.println("pde adapter not found");
return CompletableFutures.computeAsync(_x -> Collections.emptyList());
}
PdeAdapter adapter = adapterOptional.get();
PreprocSketch preprocSketch = adapter.ps;
Optional<Integer> optionalJavaOffset =
adapter.findJavaOffset(uri, lineNumber, colNumber);
if (optionalJavaOffset.isEmpty()) {
System.out.println("javaOffset not found");
return CompletableFutures.computeAsync(_x -> (Collections.emptyList()));
}
int javaOffset = optionalJavaOffset.get();
List<? extends Location> locations;
locations = PdeSymbolFinder.searchReference(preprocSketch, javaOffset);
return CompletableFutures.computeAsync(_x -> locations);
}
}