sourcer icon indicating copy to clipboard operation
sourcer copied to clipboard

Erlang LSP errs without message.

Open shoorlyne opened this issue 6 years ago • 15 comments

I am connecting with sourcer via --transport stdio, from Microsoft's Monaco editor. After the client sends the initialize request, the language server never sends a response, causing the client to fail.

Here are the args passed to the language server when starting up: --transport stdio -v

The request sent from the client looks like:

{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"rootPath":null,"rootUri":"file:///home","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true},"didChangeConfiguration":{"dynamicRegistration":false},"didChangeWatchedFiles":{"dynamicRegistration":false},"symbol":{"dynamicRegistration":true},"executeCommand":{"dynamicRegistration":true}},"textDocument":{"synchronization":{"dynamicRegistration":true},"completion":{"completionItem":{"snippetSupport":true},"dynamicRegistration":true},"hover":{"dynamicRegistration":true},"signatureHelp":{"dynamicRegistration":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"definition":{"dynamicRegistration":true},"codeAction":{"dynamicRegistration":true},"codeLens":{"dynamicRegistration":true},"documentLink":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true}}},"trace":"off"}}

And the error I am seeing from the language server's output when it processes the request is: Erlang Server: Logger - error: And that's all it prints -- not telling what the actually error is.

Could you kindly let me know how I can print the actual error message, so that I can dig further?

Or maybe let me know why it fails, if it's possible to tell from the above info.

Thanks!

shoorlyne avatar Sep 18 '18 01:09 shoorlyne

I will look at that. The stdio transport is not tested as well. My guess is that something gets stuck in decoding the messages (some silly detail like not having a newline at the very end, or something like that).

I hope I will be able to reproduce it - what client are you using in the editor?

vladdu avatar Sep 18 '18 05:09 vladdu

I use this client.

shoorlyne avatar Sep 18 '18 08:09 shoorlyne

The client might not be the easiest to set up. Did you run into any issue while trying so?

Also, how do I print the error message, so that I have more insight into this issue, in case you might not have time to take on this issue at the moment?

Thanks!

shoorlyne avatar Sep 30 '18 08:09 shoorlyne

Sorry for the delay, I had answered but shut down the PC before sending, then I forgot.

Yes, I have trouble setting up the client.

I haven't checked the code for a while, will have to look myself.

Please feel free to persist asking how it goes, I am a little too thinly spread between different projects.

vladdu avatar Oct 03 '18 18:10 vladdu

Thanks @vladdu! Really looking forward to getting this up and going.

shoorlyne avatar Oct 04 '18 04:10 shoorlyne

Ping :) Did you have some opportunity to revisit this issue?

Thanks!

shoorlyne avatar Nov 16 '18 06:11 shoorlyne

Sorry, no, I didn't. It's in the top three on my to-do list, though.

vladdu avatar Nov 16 '18 09:11 vladdu

Hi,

I took a look at this and it looks like there are a few things at play. I tested this with the lsp-mode for emacs.

  1. jsonrpc.erl returns strings, not binaries, which fails here.
  2. lsp-mode sends data with a content-length that ends directly after the trailing "}" in the json structure, which means that io:get_line won't get that last "}" and try_decode never finds a complete message.
  3. jsonrpc, lsp_server etc. log (DEBUG/TRACE) to standard out, which is what the lsp-mode reads in my case. lsp-mode prints this to the Messages buffer: error in process filter: progn: Error parsing language server output: (error No Content-Length header)
  4. I got a case when try_decode was called with an Buf=<<>>, and try_decode_1 with N=0, which meant that was interpreted as a complete message and the jsx decoder choked. Not sure if this is a side-effect of my quick hacks -- haven't dug into that one yet.

I've tried with some hacks to see how far I'd get:

  1. Used this to switch standard input to binary: io:setopts(standard_io, [binary]),
  2. Added a trailing "\n" (running macos) to the lsp-mode's requests (for get_line to "work"). Have also been using io:get_chars('', 1) instead to read one character at a time (very crudely for now). Would be nicer to read bigger chunks.
  3. I commented out the -define(DEBUG, true). etc.
@@ -153,7 +161,7 @@ try_decode_1(Buf, N) ->
                {ok, {http_header, _, _, _, _}, R} ->
                        try_decode_1(R, N);
                {ok, http_eoh, R} ->
-                       if size(R) < N ->
+                       if size(R) < N; N == 0  ->
                                    more;
                            true ->
                                    <<D:N/binary, Rest/binary>> = R,

With that in place erlang_ls starts OK but I then get some errors in the Messages buffer, like this one: eldoc error: (void-variable capability). That's where I'm at right now... Will see when I get to dig more.

(FYI: I noticed some problems with the lsp-mode for TCP -- looks like it tries to connect to the TCP server before it's been successfully started and therefore gets a connection refused)

Cheers, Klas

klajo avatar Dec 08 '18 13:12 klajo

Klas, thanks for sharing your findings here. Would really like to get this up to a point where it's sort of usable in this regard.

shoorlyne avatar Dec 08 '18 14:12 shoorlyne

Thank you very much, Klas. I will try to get this fixed this year :-) and your detailed info helps a lot!

vladdu avatar Dec 08 '18 19:12 vladdu

@vladdu Thanks! I made a fix for bullet 3 (DEBUG/TRACE) in #22. Please have a look at let me know if you think it's a reasonable approach.

klajo avatar Dec 08 '18 22:12 klajo

Hi again!

I've pushed yet another change to #22 which I hope fixes the stdio reader: bullet 1 (binaries instead of strings) and bullet 2 (accepts non-newline terminated jsonrpc text). I didn't see any problems with bullet 4 (<<>>) this time so I left that out.

With this change I'm at eldoc error: (void-variable capability) again, although with less hacky code. This is the my first attempt at using both lsp-mode and sourcer so I'm guessing it's something with my emacs/elisp setup this time. Will look into that.

Cheers, Klas

klajo avatar Dec 09 '18 00:12 klajo

FYI: with an upgraded lsp-mode I don't get the capability errors anymore.

klajo avatar Dec 10 '18 22:12 klajo

@klajo, this sounds great -- how can I test your changes?

shoorlyne avatar Dec 13 '18 10:12 shoorlyne

@shoorlyne The easiest is probably to clone my fork of the repo:

git clone https://github.com/klajo/sourcer.git

check out the emacs-lsp-mode-stdio-fixes branch and build that version of sourcer.

You can also add my fork as a remote and go from there if you want.

klajo avatar Dec 13 '18 21:12 klajo