-
Notifications
You must be signed in to change notification settings - Fork 80
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
Add signatureHelp and hover to Python autocomplete #3607
Conversation
proto/proto-backplane-grpc/src/main/proto/deephaven/proto/console.proto
Outdated
Show resolved
Hide resolved
server/src/main/java/io/deephaven/server/console/completer/JavaAutoCompleteObserver.java
Outdated
Show resolved
Hide resolved
server/src/main/java/io/deephaven/server/console/completer/JavaAutoCompleteObserver.java
Outdated
Show resolved
Hide resolved
server/src/main/java/io/deephaven/server/console/completer/PythonAutoCompleteObserver.java
Outdated
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/client/ide/IdeSession.java
Outdated
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/shared/ide/lsp/ParameterInformation.java
Outdated
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/shared/ide/lsp/SignatureInformation.java
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/shared/ide/lsp/SignatureInformation.java
Outdated
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/shared/ide/lsp/SignatureInformation.java
Outdated
Show resolved
Hide resolved
Corresponds with deephaven/deephaven-core#3607 This adds signatureHelp and hover providers if the JS API supports the corresponding requests SignatureHelp is provided when you type a method and then type the `(` character. There's also probably a keybinding in monaco to trigger it, but I'm not sure what it is. Hover provided when you hover anything Needs to use [my core branch](https://github.com/mattrunyon/deephaven-core/tree/lsp-improvements) to test. After pulling that branch, will need to build/install the Python server using the following commands ``` ./gradlew :py-server:assemble :py-embedded-server:assemble pip install --force-reinstall py/server/build/wheel/deephaven_core-0.23.0-py3-none-any.whl py/embedded-server/build/wheel/deephaven_server-0.23.0-py3-none-any.whl ``` Then start using one of these commands. Groovy provided just to show it doesn't break anything in Groovy. There is no autocomplete in Python notebooks if you are using a Groovy worker. ``` ./gradlew server-jetty-app:run # Python START_OPTS="-Ddeephaven.console.type=groovy" ./gradlew server-jetty-app:run # Groovy ```
web/client-api/src/main/java/io/deephaven/web/client/ide/LspTranslate.java
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/shared/ide/lsp/Hover.java
Outdated
Show resolved
Hide resolved
web/client-api/src/main/java/io/deephaven/web/shared/ide/lsp/MarkupContent.java
Outdated
Show resolved
Hide resolved
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.
Small quibbles
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 Python changes LGTM
I could have swore we didn't throw any huge errors when |
Follow up #3640 |
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 did not get deep into the LSP side of things. My main concerns are about server/client semantics.
switch (request.getRequestCase()) { | ||
case GET_COMPLETION_ITEMS: { | ||
response.setCompletionItems(getCompletionItems(request.getGetCompletionItems(), exportedConsole, | ||
parser, responseObserver)); | ||
break; | ||
} | ||
case GET_SIGNATURE_HELP: { | ||
// Not implemented. Return empty signature list | ||
response.setSignatures(GetSignatureHelpResponse.getDefaultInstance()); | ||
break; | ||
} | ||
case GET_HOVER: { | ||
// Not implemented. Return empty hover help | ||
response.setHover( | ||
GetHoverResponse.newBuilder().setContents(MarkupContent.getDefaultInstance()).build()); | ||
break; | ||
} | ||
case GET_DIAGNOSTIC: { | ||
// Not implemented. Return empty diagnostics | ||
response.setDiagnostic(GetPullDiagnosticResponse.getDefaultInstance()); | ||
break; |
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 looks like the pattern here is to return success if the server knows about the type, but doesn't implement it. That said, I wonder if it's better to not set any response on the GET_SIGNATURE_HELP / GET_HOVER / GET_DIAGNOSTIC cases.
The way the implementation works now, for example, on a GET_DIAGNOSTIC request, the client needs to know that an empty kind
field means it's not implemented?
message GetPullDiagnosticResponse {
string kind = 1;
optional string result_id = 2;
repeated Diagnostic items = 3;
}
Note: as the server is previously implemented, and implemented now, a newer client won't be able to talk to an older server (REQUEST_NOT_SET will throw an exception, which seems acceptable as long as the client knows how to properly handle it).
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 if we ever see the default
case (in the way the code is currently structured), we should throw an illegal argument exception.
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 LSP spec is to first negotiate what the client and server support. Then the client should not send requests or expect results if the server does not support the request type in that negotiation. The client can also tell the server what it supports (like markdown or plaintext only). For now we are just assuming the web IDE which supports markdown
We could instead add a NOT_SUPPORTED
response type to be more explicit in these cases. In that case we probably wouldn't throw in the default
and instead just return a NOT_SUPPORTED
response
On the web client I'm checking if the JS API has either of the new requests before registering the provider, so the web IDE won't try to send requests unless the JS API has the method we expect.
// Maintain compatibility with older clients | ||
// The only autocomplete type supported before the consoleId was moved to the parent request was | ||
// GetCompletionItems | ||
final io.deephaven.proto.backplane.grpc.Ticket consoleId = | ||
value.hasConsoleId() ? value.getConsoleId() : value.getGetCompletionItems().getConsoleId(); |
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.
Should we have a safer version of this? If console_id
is not set, ensure that request type is get_completion_items
? (Could extract code and use on the java side too)
.append("\tbuild_response_time=").append(toMillis(totalResponseBuildNanos)) | ||
.append("\ttotal_complete_time=").append(toMillis(totalCompletionNanos)) | ||
.endl(); | ||
switch (request.getRequestCase()) { |
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 if we ever see the default
case (in the way the code is currently structured), we should throw an illegal argument exception.
} | ||
} | ||
|
||
message BrowserNextResponse { | ||
} | ||
|
||
message OpenDocumentRequest { | ||
io.deephaven.proto.backplane.grpc.Ticket console_id = 1; | ||
io.deephaven.proto.backplane.grpc.Ticket console_id = 1 [deprecated=true]; |
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.
Should we have a server safety layer that ensures if the deprecated fields and new fields are set, they are equal; otherwise blowup? Alternatively, we could say either the new fields must be set, or the deprecated fields must be set, but not both.
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 the only reason for deprecation here (as opposed to just ripping out these fields) is if a user had an older web client but newer engine version. Realistically I think the only place that may happen right now is with web developers, so I would be fine just removing these fields instead of deprecating, but I know @niloc132 had other thoughts on that
Although one main reason to not rip this out would be in DnD where at the moment we might have the enterprise JS API talking to the community engine still
Corresponds with deephaven/web-client-ui#1178
This addresses the first 3 items in #3453 except deprecation tags.
Adds
signatureHelp
andhover
requests to the Python autocomplete serverRequires you build and force reinstall the Python server locally unless you are using
pip -e
flag for your local Python server.Put the plumbing in place for autocomplete cancellation and diagnostic requests
You can either use the web-client-ui main branch dev server or change
web/client-ui/Dockerfile
toWEB_VERSION=0.32.1-lsp.3
locally to test the web UI.