-
Notifications
You must be signed in to change notification settings - Fork 13
Parametric completion #706
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
base: main
Are you sure you want to change the base?
Conversation
toinehartman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am excited to see this in action! Since we already discussed this design together, my comments mostly consider documentation and naming.
rascal-lsp/src/main/rascal/library/demo/lang/pico/LanguageServer.rsc
Outdated
Show resolved
Hide resolved
rascal-lsp/src/main/rascal/library/demo/lang/pico/LanguageServer.rsc
Outdated
Show resolved
Hide resolved
DavyLandman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's looking good, it's not a small API, but it's looking good.
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
…al-language-servers into completions/parametric
rascal-lsp/src/main/rascal/library/demo/lang/pico/LanguageServer.rsc
Outdated
Show resolved
Hide resolved
…er.rsc Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
…al-language-servers into completions/parametric
|
It would perhaps be good to test drive this contribution with a generic function that takes a reified grammar and produces a simplified syntax directed completion contribution function (based on error trees or normal trees). To be used as That way we can see if the LSP side fits on the Rascal side with what we have in mind. Or if we still need to think more about the Rascal side. |
|
I've discussed the design choice of merging the 2 LSP enums into one ADT with @jurgenvinju and he agrees that in the end it's the cleanest solution. It's not 100% ideal, but the alternatives are worse for the end users. He indicated he would take a final look at the rest of the API today, as he had some concerns and wanted to verify how they were addressed. |
Co-authored-by: Toine Hartman <toinehartman@users.noreply.github.com>
…al-language-servers into completions/parametric
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/Locations.java
Show resolved
Hide resolved
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <Configuration xmlns="https://logging.apache.org/xml/ns" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation=" | ||
| https://logging.apache.org/xml/ns | ||
| https://logging.apache.org/xml/ns/log4j-config-2.xsd"> | ||
| <Appenders> | ||
| <Console name="CONSOLE"> | ||
| <PatternLayout pattern="%d [%t] %p - %c %m%n"/> | ||
| </Console> | ||
| </Appenders> | ||
| <Loggers> | ||
| <Root level="DEBUG"> | ||
| <AppenderRef ref="CONSOLE"/> | ||
| </Root> | ||
| </Loggers> | ||
| </Configuration> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently we don't have any logging from LSP, since log4j is disabled. We do have a lot of logs coming from the Rascal monitor though.
DavyLandman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks a lot better, but I have some remaining concerns about the merging of capabilities.
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
| public CompletableFuture<Void> updateCapabilities(Collection<ILanguageContributions> contribs) { | ||
| // Copy the contributions so we know we are looking at a stable set of elements. | ||
| // If the contributions change, we expect our caller to call again. | ||
| var stableContribs = new LinkedHashSet<>(contribs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good protection against modifying contribs.
Is there a specific reason we're using LinkedHashSet here? and not List.copyOf for example? or ArrayList for that matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My rationale was that this should conceptually be a set (unique, unordered). But if we want that, we should enforce that higher up and shift responsibility to our caller.
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
DavyLandman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a lot more readable, I have some small concerns about the timing of updates on the map, especially if there is a window where the map might run ahead of registered reality. I don't know what the trade-off is, but at least that is not documented in the code right now.
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
...-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/DynamicCapabilities.java
Outdated
Show resolved
Hide resolved
| // If our administration contains exactly this registration, remove it and inform the client | ||
| if (!currentRegistrations.remove(reg.getMethod(), reg)) { | ||
| return falsy.get(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should only be done after the unregisterCapability has been completed succesfully?
(else this happens 3/4 statements after the .get)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the answer here #706 (comment)
| // If our administration contains no registration, inform the client | ||
| if (currentRegistrations.putIfAbsent(reg.getMethod(), reg) != null) { | ||
| return falsy.get(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if we should do this here, or after a succesfull register.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea here (and similarly for unregister) is the following:
Initial assumption: the client and server have the same administration of registrations.
- Atomically verify-and-update the state of the map with the new registration. If someone raced us and we lost, verification fails, no update will happen, and the next steps will be skipped.
- Send
registerCapabilityrequest.- If this succeeds: done.
- If this fails: the capability is not registered on the client. Remove it from our map (verifying the exact value being removed again). Done.
- The client and server (
currentRegistrations) now have the same administration of registrations.
| if (!b.booleanValue()) { | ||
| return falsy.get(); | ||
| } | ||
| return register(newRegistration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this reads better, but what if the unregister fails, shouldn't we at least try to register? as in, what is the state we're leaving ourselves in. I don't know the right answer, but since there is no comment in the code wrt this trade-off, I'm confused about the guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment. At lest in VS Code, registration only explicitly fails when registering a capability that is not supported:
https://github.com/microsoft/vscode-languageserver-node/blob/00392bf903f6b6de92ae6f722408d41c8b921637/client/src/common/client.ts#L2187-L2199
In our case, that means programmer error, since AbstractDynamicCapability::isProvidedBy should check this.
Since we are talking about unregister specifically, this should never happen; we only unregister after a previous register succeeded (which requires the capability to be supported).
rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java
Outdated
Show resolved
Hide resolved
|



Design & implementation of completion support for the parametric language server.
This PR also includes support for dynamically registering capabilities.