-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
[ZEPPELIN-3645] Add LSP Protocol completion support #3090
Conversation
Is there any document of how to use this ? Like how to configure and start the LSP server |
Now this feature is enabled only in python interpreter. So you can specify |
Could you add instruction in |
@zjffdu Sound like good idea) |
server.getTextDocumentService().completion(getCompletionParams(buf, cursor)); | ||
|
||
Either<List<CompletionItem>, CompletionList> either = | ||
(Either<List<CompletionItem>, CompletionList>) future.get(3, TimeUnit.SECONDS); |
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.
BTW, if not set LSP, it waits for 3 seconds every time, doesn't 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.
In my opinion, how about adding one more option to enable/disable 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.
Right, agree wth @jongyoul Interpreter should know whether LSP is enabled or not.
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.
what if the user try to auto complete before the LSP connects? "hanging" for 3 seconds when the user press tab seems pretty bad
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 "hanging" for 3 seconds only exists only if the connection to the server is successful. But i think it's good idea to add property for enable/disable this whole feature.
try (ServerSocket serverSocket = new ServerSocket(0)) { | ||
final int port = serverSocket.getLocalPort(); | ||
|
||
Thread t = new Thread(() -> { |
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.
Making thread has timing issue sometimes. How about using @Mock
?
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.
@Mock
does not work with static methods. For this, powermock
library is needed which will be additional dependency.
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.
Even if we should powermock
, it looks better than making tests fragile, in my opinion.
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.
You are right, fragile test is bad practice. I changed it to PowerMock.
@@ -51,6 +52,21 @@ | |||
|
|||
<dependencies> | |||
|
|||
<!-- https://mvnrepository.com/artifact/org.eclipse.lsp4j/org.eclipse.lsp4j --> | |||
<dependency> | |||
<groupId>org.eclipse.lsp4j</groupId> |
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.
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.
We should not put lsp4j in zeppelin-interpreter. It is better to put it into python module
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 agree to move it under python. Even if LSP supports most of the languages, zeppelin-interpreter
influences many of interpreters. We should be careful when we add code in zeppelin-interpreter
.
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 right of course.
But this code seems reusable in other interpreters. And it would be strange to add it in python module and use it in other interpreters like method from python module.
<dependency> | ||
<groupId>org.eclipse.lsp4j</groupId> | ||
<artifactId>org.eclipse.lsp4j</artifactId> | ||
<version>${lsp4j.version}</version> |
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.
What's the licence of this dependency ?
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.
LSP4J is published under two licenses:
Logger.info("Trying to complete on {} with cursor {}", buf, cursor); | ||
|
||
List<InterpreterCompletion> list = Collections.emptyList(); | ||
try (Socket socket = new Socket(host, port)) { |
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 doesn't seems efficient to create new connection for each getCompletion call. getCompletion will be a very frequent call sometimes.
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.
Yes, but we can't keep this connection because we can connect to server from different JVMs. And if one JVM process occupies connection, other JVMs will not be able to connect to server.
final String beforeCursor = buf.substring(0, actualCursor); | ||
final int line = countLines(beforeCursor) - 1; | ||
final int character = beforeCursor.length() - beforeCursor.lastIndexOf("\n") - 1; | ||
Logger.info("Line: {}, character: {} from actual cursor: ", line, character, cursor); |
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.
change it to debug level
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.
Ok
@oxygen311 I can not install it. Let me know if there any other dependency I need to install
|
1 similar comment
@oxygen311 I can not install it. Let me know if there any other dependency I need to install
|
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.
maybe change the PR title to say python?
btw, why is it LSP
?
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.
how is connecting to LSP secured? connecting to a port on localhost without any authentication and then send all content from the paragraph to it sounds very dangerous?
@@ -464,12 +467,23 @@ public int getProgress(InterpreterContext context) throws InterpreterException { | |||
public List<InterpreterCompletion> completion(String buf, int cursor, | |||
InterpreterContext interpreterContext) | |||
throws InterpreterException { | |||
|
|||
final List <InterpreterCompletion> completions = LSPUtils. | |||
getLspServerComplitions(buf, cursor, |
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 doesn;t seem like the style for multi - line code
LSPUtils.
getLspServerComplitions
other places have .
in the 2nd line
also Complitions
?
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.
Fixed
@@ -37,6 +37,7 @@ | |||
|
|||
<properties> | |||
<!--library versions--> | |||
<lsp4j.version>0.4.1</lsp4j.version> |
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.
need to add to LICENSE?
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
server.initialize(new InitializeParams()); | ||
|
||
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams( | ||
new TextDocumentItem(ANY_URI, langId, ANY_VERSION, buf) |
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.
what is version = ANY_VERSION for?
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 described in the const definition.
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.
hm, it just says it is not used Zeppelin don't support file versions, so we can pass any version
- but doesn't say if it does support version what it will do. Actually zeppelin does have notebook git support etc, and could have iteration or revision support.
server.getTextDocumentService().completion(getCompletionParams(buf, cursor)); | ||
|
||
Either<List<CompletionItem>, CompletionList> either = | ||
(Either<List<CompletionItem>, CompletionList>) future.get(3, TimeUnit.SECONDS); |
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.
what if the user try to auto complete before the LSP connects? "hanging" for 3 seconds when the user press tab seems pretty bad
@zjffdu |
@felixcheung |
|
2-3. Now every paragraph is isolated, so |
Then it looks like LSP can only work in paragraph level. This seems not workable for users. Let's assume we also want to make PySpark support LSP. Then I guess if I type |
Is there any session concept in LSP ? so that multiple LSP request could belong to the same session |
@zjffdu |
Very interesting improvements. Thanks for working on this. |
@oxygen311 This is what I concern about the behavior consistency. Let's assume user use PySpark (ipython is disabled). User may find code completion works pretty well in p1, but works badly in p2 because LSP only works in paragraph level. BTW, it is weird to me that LSP don't support concept of session. That would mean If I am writing a long code (1000 lines of code), I need to send all these code to LSP for code completion each time, this seems very inefficient. But I may be wrong. I am so familiar with LSP. Just want to confirm whether there's more efficient way to use LSP |
open ip and port to connect to has become a huge problem recently, so unless LSP has some sort of authentication story, my vote would be "no" even if this is disabled by default, because this can become a support issue when users do have it enable. |
@felixcheung I agree that support of LSP in Zeppelin is unmature idea. Share please undesired cases with open ip and port. |
Solution must be improved to use by real users. |
What is this PR for?
Add support of request autocomplete with LSP Protocol through TCP.
What type of PR is it?
Feature
What is the Jira issue?
ZEPPELIN-3645
Demo
Questions: