MopeSWTP-SS21 / MopeSWTP

MIT License
1 stars 0 forks source link

Create LSPConsoleApplication #33

Closed manuEbg closed 3 years ago

manuEbg commented 3 years ago

We want to use LSP4J to connect a Console App to a LanguageServer. This App will be used for Prototype and Testing

manuEbg commented 3 years ago

Yesterday I tried to get Started with LSP4J in Scala. However I ran into Problems similar to the following. https://github.com/eclipse/lsp4j/issues/321 https://github.com/eclipse/lsp4j/issues/313 https://github.com/eclipse/lsp4j/issues/127

None of the suggested Workaround did work for me. Reverting to scalar 2.11 didn't fix the problem for me to...

manuEbg commented 3 years ago

Today I tried to get strarted with lsp4j in Java.

I couldnt get this working because of the/a socketlauncher. I cant find an existing class and have no Idea how i should implement one by my self...
https://www.eclipse.org/community/eclipse_newsletter/2017/may/article2.php

I started a more LSP-specific implementation, where i can run a serverlauncher or a clientlauncher. Both seem to run, but i dont think they are properly connected. Also i have no idea how to proceed further... :(

However you can find the Code I wrote today in this repo: https://github.com/MopeSWTP-SS21/LspConsole

CSchoel commented 3 years ago

You can find the SocketLauncher here: https://github.com/TypeFox/lsp4j-chat-app/blob/da5d11ad2124ff9bd554916f35b88a76abb20abc/src/main/java/io/typefox/lsp4j/chat/shared/SocketLauncher.java

CSchoel commented 3 years ago

Yesterday I tried to get Started with LSP4J in Scala. However I ran into Problems similar to the following. eclipse/lsp4j#321 eclipse/lsp4j#313 eclipse/lsp4j#127

None of the suggested Workaround did work for me. Reverting to scalar 2.11 didn't fix the problem for me to...

Did you fix this issue or does it still persist? In the latter case, can you post the full error message?

CptKaNe commented 3 years ago

I'd like to help you Manu, so i cloned your repo and tried to run it. It seems you used gradle to build and run the example. I never worked with gradle and cant manage to start the application but according to several internet sources for me it seems that your configuration is not set up right. Nevertheless it seems to work with your setup, as you mentioned above. Maybe we can meetup later or tomorrow and try to figure out, why the processes do not connect.

manuEbg commented 3 years ago

I'd like to help you Manu, so i cloned your repo and tried to run it. It seems you used gradle to build and run the example. I never worked with gradle and cant manage to start the application but according to several internet sources for me it seems that your configuration is not set up right. Nevertheless it seems to work with your setup, as you mentioned above. Maybe we can meetup later or tomorrow and try to figure out, why the processes do not connect.

If you view the build.gradle file and save it, you will see a little refresh button. After Clicking this Button all Dependencies will be downloaded. After that I clicked on the Play-Button next to the main-function in the Launcher-Classes

CptKaNe commented 3 years ago

You can find the SocketLauncher here: https://github.com/TypeFox/lsp4j-chat-app/blob/da5d11ad2124ff9bd554916f35b88a76abb20abc/src/main/java/io/typefox/lsp4j/chat/shared/SocketLauncher.java

I added the File, modified it so it seems that Client and Server are properly Connected. This only concerns the ChatExample and until now i dont know how to let them communicate with each other. I pushed the changes in manus created repo under a new branch.

I also managed to run the ConsoleApplication, thanks for your description. As i compared both examples, several questions exist: I am used to connect Server and Client via sockets, as the ChatExample does. Nevertheless in our ConsoleApplication it seems wheather the implemented LanguageServer provides this feature or i did not understand the connection between Server and Client. In my opinion it should not be possible to start the Client before the Server, as it is in the ChatExample. So I really think in our Prototype, server and client do not connect.

@CSchoel Could you give me feedback, if my commits finally work as proposed, since after restarting the VM, again I had problems to push with my ssh. creating a new one solved it.

manuEbg commented 3 years ago

@CptKaNe your new Commit in Conrad branch in LSPConsole Repo is linked to @CptKaNe so evrything should be fine;)

CptKaNe commented 3 years ago

@CSchoel Maybe you could take a look at our LSPApp and help us to understand how the connection is build. I do not really understand the concept so far, especially the function 'launcher.getRemoteProxy()' is driving me crazy, since the documentation doesnt propose any further help.

manuEbg commented 3 years ago

I added a DualLauncher Class to our ConsoleApp. this DualLauncher starts both Server and Client and connects them through "PipedStreams". I got the inspiration from these dubious examples https://www.programcreek.com/java-api-examples/blog/?class=org.eclipse.lsp4j.jsonrpc.Launcher&method=getRemoteProxy

It seems like the Server and the client are able to communicate.

I put

cListeningFuture.cancel(true);
sListeningFuture.cancel(true);

at the End of the DualLauncher.main because otherwise i would get some broken pipe exceptions.

manuEbg commented 3 years ago

Yesterday I tried to get Started with LSP4J in Scala. However I ran into Problems similar to the following. eclipse/lsp4j#321 eclipse/lsp4j#313 eclipse/lsp4j#127 None of the suggested Workaround did work for me. Reverting to scalar 2.11 didn't fix the problem for me to...

Did you fix this issue or does it still persist? In the latter case, can you post the full error message?

Nope I didnt fix this issue. The Error Message is:

Exception in thread "main" java.lang.IllegalStateException: Duplicate RPC method initialized.
    at org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints.lambda$getSupportedMethods$0(ServiceEndpoints.java:113)
    at org.eclipse.lsp4j.jsonrpc.services.AnnotationUtil.findRpcMethods(AnnotationUtil.java:66)
    at org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints.getSupportedMethods(ServiceEndpoints.java:90)
    at org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints.getSupportedMethods(ServiceEndpoints.java:82)
    at org.eclipse.lsp4j.jsonrpc.Launcher$Builder.getSupportedMethods(Launcher.java:413)
    at org.eclipse.lsp4j.jsonrpc.Launcher$Builder.createJsonHandler(Launcher.java:335)
    at org.eclipse.lsp4j.jsonrpc.Launcher$Builder.create(Launcher.java:319)
    at org.eclipse.lsp4j.launch.LSPLauncher.createServerLauncher(LSPLauncher.java:46)
    at swtpss20.lspconsole.ConsoleClient.ConsoleTestServerLauncher.start(ConsoleTestServerLauncher.scala:18)
    at swtpss20.lspconsole.ConsoleClient.UserInterface$.delayedEndpoint$swtpss20$lspconsole$ConsoleClient$UserInterface$1(UserInterface.scala:15)
    at swtpss20.lspconsole.ConsoleClient.UserInterface$delayedInit$body.apply(UserInterface.scala:10)
    at scala.Function0.apply$mcV$sp(Function0.scala:39)
    at scala.Function0.apply$mcV$sp$(Function0.scala:39)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
    at scala.App.$anonfun$main$1(App.scala:76)
    at scala.App.$anonfun$main$1$adapted(App.scala:76)
    at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:563)
    at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:561)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:919)
    at scala.App.main(App.scala:76)
    at swtpss20.lspconsole.ConsoleClient.UserInterface.main(UserInterface.scala)
CSchoel commented 3 years ago

@manuEbg , @CptKaNe , since you were struggling so much with this issue and @CptKaNe asked for my assistance, I decided to give LSP4J a try myself. The result is this new repository: https://github.com/MopeSWTP-SS21/LSP4J-test-CS

It took me two hours to get to the stage of a simple hello world example, another hour to implement a proper shutdown and an example featuring bidirectional communication with a result value, and a fourth hour for the documentation of my results. The LSP4J documentation is not excellent but I found it actually passable.

I think you might need a more systematic approach and better communication and distribution of work in the future. The task is by far not as impossible as it might seem. I think the Scala issue will also turn out to be solvable with a little more research.

That being said, I will have a quick look in your repo to see if I can find any quick fixes for your current approach.

CSchoel commented 3 years ago

This line needs to be called before startListening(), because otherwise the client might be null when the first messages are sent.

Otherwise, yes, the DualLauncher seems to work properly, although it would be better to issue the test calls not on the local client object, but directly on the remote object using sLauncher.getRemoteProxy() instead of client.

The old implementation was always doomed to failure, because it used System.in and System.out as input/output stream. If you start the client and server launcher as separate processes, there will of course be no connection between System.out of the client process and System.in of the server process or vice versa. You would have to do some piping magic in the operating system to make this setup work. The current DualLauncher implementation uses PipedInputStream, which is fine as long as both client and server live in the same Java process. Once you have different processes (which you will of course need to connect something like a VS code plugin), you need to start using sockets.

You may want to read up on basic Java input/output operations before proceeding.

In the tests for LSP4J I also found something interesting. You may want to consider to write your console client without using any of the LSP4J classes at all, just sending raw JSON strings instead. This is of course much more error prone, but as a development tool it would be extremely flexible and you would have ultimate control over which messages are sent in what sequence.

CSchoel commented 3 years ago

Oh and one other remark about the DualLauncher: Is there anything in the documentation about cancelling the listen futures? If not, you should definitely close the input streams instead. This shows a stack trace in the output, but I still think this is the "correct" way to close a launcher. At least that is what people where saying in this LSP4J issue.

In general: Do not do stuff just because it works. Try to find out why it works and if it really is a good idea. :wink:

manuEbg commented 3 years ago

The Console Application can connect to the server and send/receive lsp commands

manuEbg commented 3 years ago

The Console Application can connect to the server and send/receive lsp commands