Open fitzgen opened 1 month ago
Edit: well, no. The below does not work. I can see a didChangeConfiguration message getting logged, and its param JSON is identical to what I see with a known-working eglot-workspace-configuration
, but rust-analyzer is not actually creating a subdirectory as it does with the eglot variant. I don't know enough about lsp-mode or the protocol to guess why, atm.
Based on https://github.com/emacs-lsp/lsp-mode/issues/167, it seems that lsp-mode does support passing/overriding LSP config options generically after initialization, via didChangeConfiguration
LSP protocol messages. Here's my init.el snippet to set that up, including setting targetDir
:
(add-hook 'lsp-after-initialize-hook
(lambda ()
(lsp--set-configuration
'(:rust-analyzer (:check (:ignore ["dead_code"
"unused_variables"
"unused_imports"])
:cargo (:targetDir t
:features "all"))))))
I can see/debug the resulting didChangeConfiguration
message via lsp-workspace-show-log
.
As someone with 0 elisp knowledge, I found discussion of the similar eglot option to be useful for understanding the format of this thing: https://github.com/joaotavora/eglot/issues/363.
It's definitely nice to have prepacked per-LSP-server customize vars for common options, but I do also wish that we had this generic fallback as a first class documented and customizable setting.
I looked at this a bit more, though unfortunately the result is that I'm convinced that there's no way to set "override" options for rust-analyzer without changing lsp-mode
sources.
The issue with lsp--set-configuration
is that apparently the workspace/didChangeConfiguration
protocol (where the LSP client notifies the server of config value changes) is at least "semi" deprecated in favor of workspace/configuration
messages (where the server instead queries the client for config values). Rust analyzer still responds to didChangeConfiguration
, but the response is apparently to ignore the config value payload and simply trigger a workspace/configuration
message in reply to re-query the same values: https://github.com/rust-lang/rust-analyzer/blob/64c538f9fb3d490dd0c987df494d802977a5b9f0/crates/rust-analyzer/src/handlers/notification.rs#L201. I can again see in logs that both eglot
and lsp-mode
send the same didChangeConfiguration
message, but only eglot
actually responds to the resulting workspace/configuration
request. lsp-mode
leaves that message on read.
According to https://github.com/emacs-lsp/lsp-mode/issues/3686, there's an alternate mechanism to generically set options, via lsp-register-custom-settings
. However, I couldn't get it to work, and I think that there's just a bug in the lsp-mode rust-analyzer integration which makes this method impossible. Namely, the issue is that, while the rls
integration queries the "custom settings" via (lsp-configuration-section "rust")
when setting up the language server (https://github.com/emacs-lsp/lsp-mode/blob/c36b95be6625dac5a37d3874a1a738e0c84ac39f/clients/lsp-rust.el#L341), the rust-analyzer
integration skips that and just produces a config object in a more hardcoded way - it looks at pre-registered custom variables, but doesn't seem to integrate at all with the lsp-register-custom-settings
system (https://github.com/emacs-lsp/lsp-mode/blob/c36b95be6625dac5a37d3874a1a738e0c84ac39f/clients/lsp-rust.el#L1655).
Since it seems like post-startup configuration via workspace/configuration
is basically unimplemented, and startup-time configuration respects only a hardcoded set of options, I don't think there's a way to provide "extra" options to rust analyzer. Though the latter seems like it could be a straightforward bugfix (ideally for someone who actually knows elisp...).
The
rust-analyzer.cargo.targetDir
setting allows controlling the directory thatrust-analyzer
will use for build artifacts. It is useful to set this to something other than the default project's target directory because only one ofcargo
andrust-analyzer
can use the directory at a time, they each exclusively lock it. This means that running tests andrust-analyzer
running in the background can contend, which results in a poor user experience. Therefore, it would be nice iflsp-mode
allowed configuring this setting via a custom variable or something.More details: https://rust-analyzer.github.io/manual.html#rust-analyzer.cargo.targetDir
Thanks for all your work on
lsp-mode
!