Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LSP document synchronization #544

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Fix LSP document synchronization #544

wants to merge 7 commits into from

Conversation

rodinaarssen
Copy link
Member

@rodinaarssen rodinaarssen commented Dec 16, 2024

The LSP server is responsible for the content of files that are open in the editor. This was not (fully/correctly) implemented in rascal-lsp (#355). During resolution of a source location, the fallback resolver now rewrites source locations of open files, and file operations on such a location are handled by the new LSPOpenFileResolver class. This works for both Rascal and DSL files.

This depends on usethesource/rascal#2101 to function correctly.

Copy link
Member

@DavyLandman DavyLandman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good, I have some small concerns that I would like your input on.


@Override
public boolean isManagingFile(ISourceLocation file) {
return facts.containsFile(file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this not looking at documents? (just like the Parametric one, where both look at the same container?)

}

public FallbackResolver() {
instance = this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a small comment on why we're doing this

public ISourceLocation resolve(ISourceLocation input) throws IOException {
if (isFileManaged(input)) {
try {
return URIUtil.changeScheme(input, "lsp+" + input.getScheme()).top();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the .top? that would loose information on the URI that we cannot recover?

throw new UnsupportedOperationException("'authority' not supported by fallback resolver");
}

private Set<IBaseTextDocumentService> textDocumentServices = new HashSet<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should be final

notnit: not a threadsafe container, since we're only iterating over it, never clearing any, or using the key of it, an CopyOnWriteArrayList might be the better option.

return service.getDocumentState(file);
}
}
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there an alternative to null? should we throw an exception at this point? since isFileManaged is true?

what happens to a uri that was generated while the editor was open, but refenced after it is closed? do we unresolve it to the original URI?

var fallbackResolver = FallbackResolver.getInstance();
uri = stripLspPrefix(uri);
if (fallbackResolver.isFileManaged(uri)) {
return new ByteArrayInputStream(fallbackResolver.getDocumentState(uri).getCurrentContent().get().getBytes(StandardCharsets.UTF_16));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a risk of a race between isFileManaged and getDocumentState. Maybe it gets better if we merge them? Would also cut down on the map lookups.


@Override
public long lastModified(ISourceLocation uri) throws IOException {
return FallbackResolver.getInstance().getDocumentState(stripLspPrefix(uri)).getLastModified();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can throw a NPE in case getDocumentState returns a null.


public Versioned(int version, T object) {
this.version = version;
this.object = object;
this.timestamp = System.currentTimeMillis();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have no guarantee that the versions are monotomic in their construction. so version 10 might be constructed on thread A at time 20, while version 9 got scheduled on thread B at time 22.

This gets especially messy when tpl files are around where we depend on the "newer" relationship. What I'm wondering is if we could, register the timestamp as close to the time we receive the didChange message? (it might be close to here, I haven't checked)

@@ -41,6 +41,29 @@
import io.usethesource.vallang.IValue;

public class Locations {
public static ISourceLocation toClientLocation(ISourceLocation loc) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add some notes on these functions to help future developer pick the right one, as to remain compatible with this redirection feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants