Workspace configuration for elixir-ls LSP (#9330)

Richard Taylor created

This allows the workspace configuration settings to be passed to the
elixir-ls LSP via lsp settings.

This following example settings disable dialyzer in the LSP:

```
"lsp": {
  "elixir-ls": {
    "settings": {
      "dialyzerEnabled": false
    }
  }
}
```

It follows the same pattern used in
[#8568](https://github.com/zed-industries/zed/pull/8568) and resolves
[#4260](https://github.com/zed-industries/zed/issues/4260).

Zed's language server logs show the settings are being sent to the
language server:

```
Received client configuration via workspace/configuration
%{"dialyzerEnabled" => false}
Registering for workspace/didChangeConfiguration notifications
Starting build with MIX_ENV: test MIX_TARGET: host
client/registerCapability succeeded
Registering for workspace/didChangeWatchedFiles notifications
client/registerCapability succeeded
Received workspace/didChangeConfiguration
Received client configuration via workspace/didChangeConfiguration
%{"dialyzerEnabled" => false}
```

Release Notes:

- Added workspace configuration settings support for elixir-ls language
server. Those can now be configured by setting `{"lsp": {"elixir-ls": {
"settings: { "your-settings-here": "here"} } }` in Zed settings.
[#4260](https://github.com/zed-industries/zed/issues/4260).

Change summary

crates/languages/src/elixir.rs | 18 ++++++++++++++++--
docs/src/languages/elixir.md   | 18 ++++++++++++++++++
2 files changed, 34 insertions(+), 2 deletions(-)

Detailed changes

crates/languages/src/elixir.rs 🔗

@@ -1,18 +1,20 @@
 use anyhow::{anyhow, bail, Context, Result};
 use async_trait::async_trait;
 use futures::StreamExt;
-use gpui::{AsyncAppContext, Task};
+use gpui::{AppContext, AsyncAppContext, Task};
 pub use language::*;
 use lsp::{CompletionItemKind, LanguageServerBinary, SymbolKind};
+use project::project_settings::ProjectSettings;
 use schemars::JsonSchema;
 use serde_derive::{Deserialize, Serialize};
+use serde_json::Value;
 use settings::Settings;
 use smol::fs::{self, File};
 use std::{
     any::Any,
     env::consts,
     ops::Deref,
-    path::PathBuf,
+    path::{Path, PathBuf},
     sync::{
         atomic::{AtomicBool, Ordering::SeqCst},
         Arc,
@@ -272,6 +274,18 @@ impl LspAdapter for ElixirLspAdapter {
             filter_range,
         })
     }
+
+    fn workspace_configuration(&self, _workspace_root: &Path, cx: &mut AppContext) -> Value {
+        let settings = ProjectSettings::get_global(cx)
+            .lsp
+            .get("elixir-ls")
+            .and_then(|s| s.settings.clone())
+            .unwrap_or_default();
+
+        serde_json::json!({
+            "elixirLS": settings
+        })
+    }
 }
 
 async fn get_cached_server_binary_elixir_ls(

docs/src/languages/elixir.md 🔗

@@ -39,3 +39,21 @@ If you prefer to format your code with [Mix](https://hexdocs.pm/mix/Mix.html), u
   }
 }
 ```
+
+### Additional workspace configuration options (requires Zed `0.128.0`):
+
+You can pass additional elixir-ls workspace configuration options via lsp settings in `settings.json`.
+
+The following example disables dialyzer:
+
+```json
+"lsp": {
+  "elixir-ls": {
+    "settings": {
+      "dialyzerEnabled": false
+    }
+  }
+}
+```
+
+See [ElixirLS configuration settings](https://github.com/elixir-lsp/elixir-ls#elixirls-configuration-settings) for more options.