From 8c1b469a839aec8358398edce9c761dc805dabdf Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Fri, 13 Dec 2024 16:21:02 +0100 Subject: [PATCH 1/7] Redirecting source locations of files managed by LSP --- .../java/org/rascalmpl/uri/resolvers.config | 1 + .../vscode/lsp/IBaseTextDocumentService.java | 3 + .../ParametricTextDocumentService.java | 12 +++ .../lsp/rascal/RascalTextDocumentService.java | 12 +++ .../vscode/lsp/rascal/model/FileFacts.java | 4 + .../vscode/lsp/uri/FallbackResolver.java | 64 ++++++++++++++- .../vscode/lsp/uri/LSPOpenFileResolver.java | 80 +++++++++++++++++++ 7 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 rascal-lsp/src/main/java/org/rascalmpl/uri/resolvers.config create mode 100644 rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java diff --git a/rascal-lsp/src/main/java/org/rascalmpl/uri/resolvers.config b/rascal-lsp/src/main/java/org/rascalmpl/uri/resolvers.config new file mode 100644 index 000000000..a7f9a3c3f --- /dev/null +++ b/rascal-lsp/src/main/java/org/rascalmpl/uri/resolvers.config @@ -0,0 +1 @@ +org.rascalmpl.vscode.lsp.uri.LSPOpenFileResolver diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IBaseTextDocumentService.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IBaseTextDocumentService.java index 2615b4a0a..3a7bdda10 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IBaseTextDocumentService.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IBaseTextDocumentService.java @@ -44,5 +44,8 @@ public interface IBaseTextDocumentService extends TextDocumentService { void unregisterLanguage(LanguageParameter lang); CompletableFuture executeCommand(String languageName, String command); LineColumnOffsetMap getColumnMap(ISourceLocation file); + TextDocumentState getDocumentState(ISourceLocation file); + + boolean isManagingFile(ISourceLocation file); } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java index 3c3efa605..b4b131dba 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java @@ -106,6 +106,7 @@ import org.rascalmpl.vscode.lsp.parametric.model.ParametricSummary; import org.rascalmpl.vscode.lsp.parametric.model.ParametricSummary.SummaryLookup; import org.rascalmpl.vscode.lsp.terminal.ITerminalIDEServer.LanguageParameter; +import org.rascalmpl.vscode.lsp.uri.FallbackResolver; import org.rascalmpl.vscode.lsp.util.CodeActions; import org.rascalmpl.vscode.lsp.util.Diagnostics; import org.rascalmpl.vscode.lsp.util.FoldingRanges; @@ -160,6 +161,7 @@ public ParametricTextDocumentService(ExecutorService exec, @Nullable LanguagePar this.dedicatedLanguageName = dedicatedLanguage.getName(); this.dedicatedLanguage = dedicatedLanguage; } + FallbackResolver.getInstance().registerTextDocumentService(this); } @Override @@ -683,4 +685,14 @@ public CompletableFuture executeCommand(String languageName, String comm return CompletableFuture.completedFuture(null); } } + + @Override + public boolean isManagingFile(ISourceLocation file) { + return files.containsKey(file.top()); + } + + @Override + public TextDocumentState getDocumentState(ISourceLocation file) { + return files.get(file.top()); + } } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalTextDocumentService.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalTextDocumentService.java index 14e4eb71a..9caa323d1 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalTextDocumentService.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalTextDocumentService.java @@ -101,6 +101,7 @@ import org.rascalmpl.vscode.lsp.rascal.model.FileFacts; import org.rascalmpl.vscode.lsp.rascal.model.SummaryBridge; import org.rascalmpl.vscode.lsp.terminal.ITerminalIDEServer.LanguageParameter; +import org.rascalmpl.vscode.lsp.uri.FallbackResolver; import org.rascalmpl.vscode.lsp.util.CodeActions; import org.rascalmpl.vscode.lsp.util.Diagnostics; import org.rascalmpl.vscode.lsp.util.DocumentChanges; @@ -135,6 +136,7 @@ public RascalTextDocumentService(ExecutorService exec) { this.ownExecuter = exec; this.documents = new ConcurrentHashMap<>(); this.columns = new ColumnMaps(this::getContents); + FallbackResolver.getInstance().registerTextDocumentService(this); } @Override @@ -488,4 +490,14 @@ private static CompletableFuture recoverExceptions(CompletableFuture f return defaultValue.get(); }); } + + @Override + public boolean isManagingFile(ISourceLocation file) { + return facts.containsFile(file); + } + + @Override + public TextDocumentState getDocumentState(ISourceLocation file) { + return documents.get(file.top()); + } } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java index dafb3fd04..daac94cad 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java @@ -101,6 +101,10 @@ public PathConfig getPathConfig(ISourceLocation file) { return confs.lookupConfig(file); } + public boolean containsFile(ISourceLocation file) { + return files.containsKey(file.top()); + } + private class FileFact { private final ISourceLocation file; private final LazyUpdateableReference> summary; diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java index ee1da2e3e..5b042d248 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java @@ -31,11 +31,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Base64; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; @@ -43,9 +46,13 @@ import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Function; + +import org.rascalmpl.uri.ILogicalSourceLocationResolver; import org.rascalmpl.uri.ISourceLocationInputOutput; import org.rascalmpl.uri.ISourceLocationWatcher; import org.rascalmpl.uri.URIUtil; +import org.rascalmpl.vscode.lsp.IBaseTextDocumentService; +import org.rascalmpl.vscode.lsp.TextDocumentState; import org.rascalmpl.vscode.lsp.uri.jsonrpc.VSCodeUriResolverClient; import org.rascalmpl.vscode.lsp.uri.jsonrpc.VSCodeUriResolverServer; import org.rascalmpl.vscode.lsp.uri.jsonrpc.VSCodeVFS; @@ -53,11 +60,26 @@ import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.ISourceLocationRequest; import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.WriteFileRequest; import org.rascalmpl.vscode.lsp.util.Lazy; + import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; + import io.usethesource.vallang.ISourceLocation; -public class FallbackResolver implements ISourceLocationInputOutput, ISourceLocationWatcher { +public class FallbackResolver implements ISourceLocationInputOutput, ISourceLocationWatcher, ILogicalSourceLocationResolver { + + private static FallbackResolver instance = null; + + public static FallbackResolver getInstance() { + if (instance == null) { + throw new IllegalStateException("FallbackResolver accessed before initialization"); + } + return instance; + } + + public FallbackResolver() { + instance = this; + } private static VSCodeUriResolverServer getServer() throws IOException { var result = VSCodeVFS.INSTANCE.getServer(); @@ -250,5 +272,45 @@ public void unwatch(ISourceLocation root, Consumer watch getClient().removeWatcher(root, watcher, getServer()); } + + public boolean isFileManaged(ISourceLocation file) { + for (final var service : textDocumentServices) { + if (service.isManagingFile(file)) { + return true; + } + } + return false; + } + @Override + public ISourceLocation resolve(ISourceLocation input) throws IOException { + if (isFileManaged(input)) { + try { + return URIUtil.changeScheme(input, "lsp+" + input.getScheme()); + } catch (URISyntaxException e) { + // fall through + } + } + return input; + } + + @Override + public String authority() { + throw new UnsupportedOperationException("'authority' not supported by fallback resolver"); + } + + private Set textDocumentServices = new HashSet<>(); + + public void registerTextDocumentService(IBaseTextDocumentService service) { + textDocumentServices.add(service); + } + + public TextDocumentState getDocumentState(ISourceLocation file) { + for (final var service : textDocumentServices) { + if (service.isManagingFile(file)) { + return service.getDocumentState(file); + } + } + return null; + } } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java new file mode 100644 index 000000000..8a2f47e25 --- /dev/null +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java @@ -0,0 +1,80 @@ +package org.rascalmpl.vscode.lsp.uri; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.rascalmpl.uri.ISourceLocationInput; +import org.rascalmpl.uri.URIUtil; + +import io.usethesource.vallang.ISourceLocation; + +public class LSPOpenFileResolver implements ISourceLocationInput { + + @Override + public InputStream getInputStream(ISourceLocation uri) throws IOException { + var fallbackResolver = FallbackResolver.getInstance(); + uri = stripLspPrefix(uri); + if (fallbackResolver.isFileManaged(uri)) { + return new ByteArrayInputStream(fallbackResolver.getDocumentState(uri).getCurrentContent().get().getBytes(StandardCharsets.UTF_16)); + } + throw new IOException("File does not exist"); + } + + @Override + public Charset getCharset(ISourceLocation uri) throws IOException { + return StandardCharsets.UTF_16; + } + + @Override + public boolean exists(ISourceLocation uri) { + return FallbackResolver.getInstance().isFileManaged(stripLspPrefix(uri)); + } + + @Override + public long lastModified(ISourceLocation uri) throws IOException { + return System.currentTimeMillis(); + } + + @Override + public boolean isDirectory(ISourceLocation uri) { + return false; + } + + @Override + public boolean isFile(ISourceLocation uri) { + return exists(uri); + } + + private static ISourceLocation stripLspPrefix(ISourceLocation uri) { + if (uri.getScheme().startsWith("lsp+")) { + try { + return URIUtil.changeScheme(uri, uri.getScheme().substring("lsp+".length())); + } catch (URISyntaxException e) { + // fall through + } + } + return uri; + } + + @Override + public String[] list(ISourceLocation uri) throws IOException { + throw new UnsupportedOperationException("Unimplemented method 'list'"); + } + + @Override + public String scheme() { + return "lsp"; + } + + @Override + public boolean supportsHost() { + return false; + } + +} From ac5a8602db98ebda90d0942f36727f5c56c4b6a3 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Fri, 13 Dec 2024 16:21:32 +0100 Subject: [PATCH 2/7] Make sure FallbackResolver is used while debugging --- rascal-lsp/.vscode/launch.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rascal-lsp/.vscode/launch.json b/rascal-lsp/.vscode/launch.json index 361401f1e..9dde3567f 100644 --- a/rascal-lsp/.vscode/launch.json +++ b/rascal-lsp/.vscode/launch.json @@ -10,7 +10,8 @@ "console": "internalConsole", "vmArgs": [ "-Dlog4j2.level=TRACE", - "-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar" + "-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar", + "-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver" ] }, { @@ -22,7 +23,8 @@ "console": "internalConsole", "vmArgs": [ "-Dlog4j2.level=TRACE", - "-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar" + "-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar", + "-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver" ] } ] From e873a4a9c52538867c9bb4a615a72ca6b7881593 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Fri, 13 Dec 2024 16:22:56 +0100 Subject: [PATCH 3/7] Made sure source locations with lsp prefix don't leak to the outside --- .../vscode/lsp/IRascalFileSystemServices.java | 9 +++----- .../rascalmpl/vscode/lsp/LSPIDEServices.java | 2 +- .../vscode/lsp/rascal/model/FileFacts.java | 4 +++- .../lsp/terminal/TerminalIDEClient.java | 2 +- .../vscode/lsp/util/Diagnostics.java | 2 +- .../vscode/lsp/util/locations/Locations.java | 23 +++++++++++++++++++ 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IRascalFileSystemServices.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IRascalFileSystemServices.java index 084a4425e..5e0c73273 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IRascalFileSystemServices.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IRascalFileSystemServices.java @@ -51,6 +51,7 @@ import org.rascalmpl.uri.URIResolverRegistry; import org.rascalmpl.uri.URIUtil; import org.rascalmpl.values.IRascalValueFactory; +import org.rascalmpl.vscode.lsp.util.locations.Locations; import io.usethesource.vallang.ISourceLocation; import io.usethesource.vallang.IValueFactory; @@ -65,7 +66,7 @@ default CompletableFuture resolveLocation(SourceLocation loc) { try { ISourceLocation tmp = loc.toRascalLocation(); - ISourceLocation resolved = reg.logicalToPhysical(tmp); + ISourceLocation resolved = Locations.toClientLocation(tmp); if (resolved == null) { return loc; @@ -77,10 +78,6 @@ default CompletableFuture resolveLocation(SourceLocation loc) { IRascalFileSystemServices__logger.warn("Could not resolve location {} due to {}.", loc, e.getMessage()); return loc; } - catch (IOException e) { - // This is normal behavior (when its not a logical scheme) - return loc; - } catch (Throwable e) { IRascalFileSystemServices__logger.warn("Could not resolve location {} due to {}.", loc, e.getMessage()); return loc; @@ -130,7 +127,7 @@ private static boolean readonly(ISourceLocation loc) throws IOException { return false; } if (reg.getRegisteredLogicalSchemes().contains(loc.getScheme())) { - var resolved = reg.logicalToPhysical(loc); + var resolved = Locations.toClientLocation(loc); if (resolved != null && resolved != loc) { return readonly(resolved); } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/LSPIDEServices.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/LSPIDEServices.java index 8d1a2dac1..1d446d6a5 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/LSPIDEServices.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/LSPIDEServices.java @@ -92,7 +92,7 @@ public void browse(URI uri, String title, int viewColumn) { @Override public void edit(ISourceLocation path) { try { - ISourceLocation physical = URIResolverRegistry.getInstance().logicalToPhysical(path); + ISourceLocation physical = Locations.toClientLocation(path); ShowDocumentParams params = new ShowDocumentParams(physical.getURI().toASCIIString()); params.setTakeFocus(true); diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java index daac94cad..61586a071 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/model/FileFacts.java @@ -50,6 +50,8 @@ import org.rascalmpl.vscode.lsp.util.concurrent.LazyUpdateableReference; import org.rascalmpl.vscode.lsp.util.concurrent.ReplaceableFuture; import org.rascalmpl.vscode.lsp.util.locations.ColumnMaps; +import org.rascalmpl.vscode.lsp.util.locations.Locations; + import io.usethesource.vallang.ISourceLocation; public class FileFacts { @@ -87,7 +89,7 @@ public void reportParseErrors(ISourceLocation file, List msgs) { private FileFact getFile(ISourceLocation l) { ISourceLocation resolved = null; try { - resolved = URIResolverRegistry.getInstance().logicalToPhysical(l); + resolved = Locations.toClientLocation(l); if (resolved == null) { resolved = l; } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/terminal/TerminalIDEClient.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/terminal/TerminalIDEClient.java index a9430d9b7..a270dd5f2 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/terminal/TerminalIDEClient.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/terminal/TerminalIDEClient.java @@ -97,7 +97,7 @@ public void browse(URI uri, String title, int viewColumn) { @Override public void edit(ISourceLocation path) { try { - ISourceLocation physical = URIResolverRegistry.getInstance().logicalToPhysical(path); + ISourceLocation physical = Locations.toClientLocation(path); ShowDocumentParams params = new ShowDocumentParams(physical.getURI().toASCIIString()); params.setTakeFocus(true); diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Diagnostics.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Diagnostics.java index f6d9e07a5..a9bf4f887 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Diagnostics.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Diagnostics.java @@ -168,7 +168,7 @@ public static Map> translateMessages(IList mes } private static ISourceLocation getMessageLocation(IConstructor message) { - return Locations.toPhysicalIfPossible(((ISourceLocation) message.get("at"))); + return Locations.toClientLocationIfPossible(((ISourceLocation) message.get("at"))); } private static boolean hasValidLocation(IConstructor d, ISourceLocation file) { diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java index da1a42627..ae10935ca 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java @@ -41,6 +41,29 @@ import io.usethesource.vallang.IValue; public class Locations { + public static ISourceLocation toClientLocation(ISourceLocation loc) throws IOException { + var result = URIResolverRegistry.getInstance().logicalToPhysical(loc); + if (result.getScheme().startsWith("lsp+")) { + try { + result = URIUtil.changeScheme(result, result.getScheme().substring("lsp+".length())); + } catch (URISyntaxException e) { + // fall through + } + } + return result; + } + + public static ISourceLocation toClientLocationIfPossible(ISourceLocation loc) { + var result = toPhysicalIfPossible(loc); + if (result.getScheme().startsWith("lsp+")) { + try { + return URIUtil.changeScheme(result, result.getScheme().substring("lsp+".length())); + } catch (URISyntaxException e) { + // fall through + } + } + return loc; + } public static ISourceLocation toPhysicalIfPossible(ISourceLocation loc) { ISourceLocation physical; try { From ba5330739ddbda6dbe6e7300015f63e171aaf51d Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 16 Dec 2024 14:31:00 +0100 Subject: [PATCH 4/7] Fixed offsets in lsp-redirected source locations --- .../java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java | 2 +- .../java/org/rascalmpl/vscode/lsp/util/locations/Locations.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java index 5b042d248..034292c7f 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/FallbackResolver.java @@ -286,7 +286,7 @@ public boolean isFileManaged(ISourceLocation file) { public ISourceLocation resolve(ISourceLocation input) throws IOException { if (isFileManaged(input)) { try { - return URIUtil.changeScheme(input, "lsp+" + input.getScheme()); + return URIUtil.changeScheme(input, "lsp+" + input.getScheme()).top(); } catch (URISyntaxException e) { // fall through } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java index ae10935ca..eb29190c5 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java @@ -62,7 +62,7 @@ public static ISourceLocation toClientLocationIfPossible(ISourceLocation loc) { // fall through } } - return loc; + return result; } public static ISourceLocation toPhysicalIfPossible(ISourceLocation loc) { ISourceLocation physical; From f4ddf7a0c0db5bf7a045ea62282ffc89fb45a40e Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 16 Dec 2024 14:51:25 +0100 Subject: [PATCH 5/7] Keeping track of last modified timestamp for lsp editor states --- .../java/org/rascalmpl/vscode/lsp/TextDocumentState.java | 4 ++++ .../org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java | 2 +- .../main/java/org/rascalmpl/vscode/lsp/util/Versioned.java | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/TextDocumentState.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/TextDocumentState.java index 73690847b..bc2ce6a1c 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/TextDocumentState.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/TextDocumentState.java @@ -105,4 +105,8 @@ public ISourceLocation getLocation() { public Versioned getCurrentContent() { return currentContent; } + + public long getLastModified() { + return currentContent.getTimestamp(); + } } diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java index 8a2f47e25..7617d9894 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java @@ -38,7 +38,7 @@ public boolean exists(ISourceLocation uri) { @Override public long lastModified(ISourceLocation uri) throws IOException { - return System.currentTimeMillis(); + return FallbackResolver.getInstance().getDocumentState(stripLspPrefix(uri)).getLastModified(); } @Override diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Versioned.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Versioned.java index c9a7b7189..c998991bb 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Versioned.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/Versioned.java @@ -31,10 +31,12 @@ public class Versioned { private final int version; private final T object; + private final long timestamp; public Versioned(int version, T object) { this.version = version; this.object = object; + this.timestamp = System.currentTimeMillis(); } public int version() { @@ -45,6 +47,10 @@ public T get() { return object; } + public long getTimestamp() { + return timestamp; + } + @Override public String toString() { return String.format("%s [version %d]", object, version); From d202427dc6138fffa748b687779972bb1f6b3c4e Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 16 Dec 2024 15:44:22 +0100 Subject: [PATCH 6/7] Added copyright notice --- .../vscode/lsp/uri/LSPOpenFileResolver.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java index 7617d9894..72fa70f98 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/uri/LSPOpenFileResolver.java @@ -1,3 +1,29 @@ +/* + * Copyright (c) 2018-2023, NWO-I CWI and Swat.engineering + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ package org.rascalmpl.vscode.lsp.uri; import java.io.ByteArrayInputStream; @@ -7,8 +33,6 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.rascalmpl.uri.ISourceLocationInput; import org.rascalmpl.uri.URIUtil; From c2da74fda1c940c238a30c9de6293a56f1f95da4 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 16 Dec 2024 16:40:29 +0100 Subject: [PATCH 7/7] Fixed indentation --- .../vscode/lsp/parametric/ParametricTextDocumentService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java index b4b131dba..42b6c4d97 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java @@ -693,6 +693,6 @@ public boolean isManagingFile(ISourceLocation file) { @Override public TextDocumentState getDocumentState(ISourceLocation file) { - return files.get(file.top()); + return files.get(file.top()); } }