Skip to content
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

Julia LSP workspace configuration #196

Closed
ekmecic opened this issue Dec 28, 2018 · 18 comments
Closed

Julia LSP workspace configuration #196

ekmecic opened this issue Dec 28, 2018 · 18 comments

Comments

@ekmecic
Copy link

ekmecic commented Dec 28, 2018

Hello,

I've been using eglot for C/C++ and it is fantastic, thank you for your hard work João!
I'm trying to get Julia's LSP working, however I'm unable to get the workspace configuration to function.

The Julia LSP requires a workspace/didChangeConfiguration message with a non-null settings field, preferably with "runLinter: true". For reference, VS Code sends the following message:

{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"julia":{"runLinter":true}}}}

I have tried using various incantations of eglot-workspace-configuration in my .dir-locals.el based on #59, however I am unable to reproduce the same message. Here is what I have been using:
((nil (eglot-workspace-configuration . ((julia . ((runLinter . t)))))))

Here is what eglot sends to the LSP:
{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":null}}

From reading eglot.el, it seems that my configuration is incorrectly formatted so the following snippet doesn't read them:

eglot/eglot.el

Lines 1561 to 1565 in 7b0d845

(cl-loop for (k . v) in eglot-workspace-configuration
collect (if (keywordp k)
k
(intern (format ":%s" k)))
collect v))))

However, I am a total elisp noob and probably wrong. I would greatly appreciate if you could point me in the right direction.

@joaotavora
Copy link
Owner

However, I am a total elisp noob and probably wrong. I would greatly appreciate if you could point me in the right direction.

Sure. My magic balls tells me that the variable eglot-workspace-configuration isn't being set at all. Tell me what C-h v RET eglot-workspace-configuration outputs for one of your Julia buffers just before activating M-x eglot.

If it's nil, you first have to make sure that it gets a value. Read this part of the Emacs manual to understand directory-local variables first.

@ekmecic
Copy link
Author

ekmecic commented Dec 30, 2018

I have checked that and it is being set properly. I've used .dir-locals for other plugins without any problems. Here's the test from describe-variable:

eglot-workspace-configuration is a variable defined in ‘eglot.el’.
Its value is ((julia (runLinter . t)))
Local in buffer hex2base64.jl; global value is nil

@joaotavora
Copy link
Owner

I have checked that and it is being set properly. I've used .dir-locals for other plugins without any problems.

Hmm, my crystal ball was wrong.

We can pull out the big guns. Since you have found the function that reads the workspace configuration and potentially sends it to the server, do that in your Emacs and place your point anywhere inside that function. Then type C-u C-M-x: that's normal C-M-x to re-evaluate a definition + C-u to say that you want to edebug rather than normally evaluate. Nothing will happen until you type M-x eglot in your hex2base64.jl buffer, at which time you should be taken to the definition to step through it with SPC. At any time you can use C-M-x to re-evaluate the definition without edebug and then q or c to quit or continue the session.

NEVERMIND: I think I see the problem (though I don't understand why Eglot sends null instead of some non-null thing).

To send what you want your eglot-workspace-configuration has to be.

((julia . (:runLinter t)))

Which is synonymous with

((julia :runLinter t))

(I prefer to write the former but Emacs normally prints out the latter)

Try it out.

I.e. At one level you must use alists but at the deepest level you have to use a plist to represent a JSON object. This is not ideal to say the least, so I might leave this issue open to handle this inconsistency.

Also I have a feeling that if you were using some very recent Emacs 27 it would work since it knows how to distinguish automatically I think.

@ekmecic
Copy link
Author

ekmecic commented Dec 30, 2018

Tried both of the eglot-workspace-configuration definitions you supplied, but both produced the same output as before. The first actually produces a malformed function error, probably because I'm running emacs 26.1 and it can't parse it properly (?).

I used edebug to step through eglot-signal-didChangeConfiguration, and it seems that body of the cl-loop is not being executed at all, leading eglot to send a null field. It also seems that eglot-workspace-configuration remains nil in the edebug execution context.

My gut tells me it's something to do with how I'm defining eglot-workspace-configuration in .dir-locals.

@joaotavora
Copy link
Owner

It also seems that eglot-workspace-configuration remains nil in the edebug execution context.

If so than I revert to my previous "crystal ball" diagnostic. It's not being set correctly in the buffer where eglot is starting. Or maybe, in some bizarre twist, eglot-signal-didChangeConfiguration is not being run from the buffer where I expect it to. Can you evaluate (current-buffer) in the edebug session in that location. You can evaluate expressions in edebug context using e, I think.

@ekmecic
Copy link
Author

ekmecic commented Jan 2, 2019

(current-buffer) returns #<buffer *temp*>, instead of hex2base64.jl, though I think it may be referring to the actual debugging window. Evaluating eglot-workspace-configuration still gives nil in edebug. What about setting a global value for eglot-workspace-configuration to see if that works?

@joaotavora
Copy link
Owner

There is no "actual debugging window". I think I found the bug, so give me some time. Setting the global eglot-workspace-configuration will probably work, but that's not what you want.

joaotavora added a commit that referenced this issue Jan 2, 2019
eglot-connect-hook and eglot-server-initialized-hook, must run in a
buffer with properly setup directory-local variables for the project,
so that things like eglot-signal-didChangeConfiguration can succeed.

I could have chosen any of the buffers where Eglot is activating
itself, but the approach using
hack-dir-local-variables-non-file-buffer seems more correct, despite
the name.

* eglot.el (eglot--connect): Run connection hooks with proper
dir-locals.
@joaotavora
Copy link
Owner

@ekmecic can you try the fix in c9d478a?

@ekmecic
Copy link
Author

ekmecic commented Jan 2, 2019

Pulled down the branch and repeated the steps from before. There is no change in the behaviour. I re-ran the edebug as well; eglot-workspace-configuration remains nil, and (current-buffer)returns #<buffer *temp*>.

I can supply you with instructions to reproduce the bug if it would help you with debugging.

@joaotavora
Copy link
Owner

I can supply you with instructions to reproduce the bug if it would help you with debugging.

I don't think that's necessary (yet) as I have reproduced the bug. It was introduced by 83d7025 (quite some time ago, so I don't think many people are using this feature with dir-locals).

Anyway, the commit I sent earlier should work for your case (but try the most recent one, as it covers another corner case).

You should make sure not only to pull the branch but to delete any stale "eglot.elc" files that you may have in your load path. Alternatively, load the file eglot.el by hand (or byte-compile and load it, if you prefer).

@ekmecic
Copy link
Author

ekmecic commented Jan 2, 2019

Just pulled the latest from the fix branch and recompiled, it hasn't picked up the workspace configuration 😕.

@joaotavora
Copy link
Owner

joaotavora commented Jan 2, 2019

Alright, we'll have to do it by the book then. Can you create a test Julia project dir, zip it, and paste it here? Also point me to the location of the Julia server you are using and possibly instructions on how to get Julia running on Debian buster/sid (though I probably find this out myself).

@ekmecic
Copy link
Author

ekmecic commented Jan 2, 2019

No problem! Here are the instructions to get Julia and the language server going with eglot.

All the files you will need are in this gist.

  1. Install Julia from Debian repos, ensure it's version >=1.0
  2. Install LanguageServer.jl from master by running the Julia repl, pressing ] to enter pkg mode, and running add CSTParser#master DocumentFormat#master LanguageServer#master StaticLint#master SymbolServer#master Tokenize#master URIParser#master
  3. Configure eglot using the lsp.jl and lsp.el files
  4. Create a directory with main.jl and .dir-locals.el; run M-x eglot
  5. Observe LSP crash due to null settings field in workspace/didChangeConfiguration

@joaotavora
Copy link
Owner

@ekmecic
Thanks for the recipe.

  • I could reproduce the problem without my latest fix, but I verified that is indeed fixed by the branch scratch/fix-196-attempt. So I'm going to push that to master.

  • I encountered two new problems. the Julia LSP tries to register an unsupported capability by Eglot and it also sends non-standard field on some responses. We can open separate issues for those.

@ekmecic
Copy link
Author

ekmecic commented Jan 4, 2019

The fix works, thank you for your help! Yes, there are a couple server-side problems which I hope to work on as time permits.

@joaotavora
Copy link
Owner

Yes, there are a couple server-side problems which I hope to work on as time permits.

These problems can be dealt with Eglot-side, too. Open new issues for them, so I don't forget about them.

@ekmecic
Copy link
Author

ekmecic commented Jan 9, 2019

I won't be able to contribute anything for 4 months due to some legal documents I have signed. Once the period is over I'll take a look at it.

@easbarba
Copy link

easbarba commented Jan 9, 2019

LOL

bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 18, 2022
eglot-connect-hook and eglot-server-initialized-hook must run in a
buffer with properly setup directory-local variables for the project.

This is crucial for things like eglot-signal-didChangeConfiguration,
which needs a properly setup value of eglot-workspace-configuration to
succeed.

I could have chosen any of the buffers where Eglot is activating
itself, but the approach using
hack-dir-local-variables-non-file-buffer seems more correct, despite
the name.

* eglot.el (eglot--connect): Run connection hooks with proper
dir-locals.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
eglot-connect-hook and eglot-server-initialized-hook must run in a
buffer with properly setup directory-local variables for the project.

This is crucial for things like eglot-signal-didChangeConfiguration,
which needs a properly setup value of eglot-workspace-configuration to
succeed.

I could have chosen any of the buffers where Eglot is activating
itself, but the approach using
hack-dir-local-variables-non-file-buffer seems more correct, despite
the name.

* eglot.el (eglot--connect): Run connection hooks with proper
dir-locals.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
eglot-connect-hook and eglot-server-initialized-hook must run in a
buffer with properly setup directory-local variables for the project.

This is crucial for things like eglot-signal-didChangeConfiguration,
which needs a properly setup value of eglot-workspace-configuration to
succeed.

I could have chosen any of the buffers where Eglot is activating
itself, but the approach using
hack-dir-local-variables-non-file-buffer seems more correct, despite
the name.

* eglot.el (eglot--connect): Run connection hooks with proper
dir-locals.

#196: joaotavora/eglot#196
jollaitbot pushed a commit to sailfishos-mirror/emacs that referenced this issue Oct 12, 2022
eglot-connect-hook and eglot-server-initialized-hook must run in a
buffer with properly setup directory-local variables for the project.

This is crucial for things like eglot-signal-didChangeConfiguration,
which needs a properly setup value of eglot-workspace-configuration to
succeed.

I could have chosen any of the buffers where Eglot is activating
itself, but the approach using
hack-dir-local-variables-non-file-buffer seems more correct, despite
the name.

* eglot.el (eglot--connect): Run connection hooks with proper
dir-locals.

GitHub-reference: fix joaotavora/eglot#196
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants