Enable formatting feature of JSON language server

Max Brunsfeld and Nathan Sobo created

The feature doesn't work yet because the JSON language server
only supports *range* formatting, not document formatting.
We need to adjust our code to inspect the server's capabilities
and send range formatting requests instead when needed.

We're going to hold off on doing this right now, because it
will create merge conflicts with the `preserve-worktrees`
branch (#525)

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/language/src/language.rs | 16 ++++++++++++++--
crates/lsp/src/lsp.rs           | 15 +++++++++++----
crates/zed/src/language.rs      |  7 +++++++
3 files changed, 32 insertions(+), 6 deletions(-)

Detailed changes

crates/language/src/language.rs 🔗

@@ -18,6 +18,7 @@ use highlight_map::HighlightMap;
 use lazy_static::lazy_static;
 use parking_lot::{Mutex, RwLock};
 use serde::Deserialize;
+use serde_json::Value;
 use std::{
     cell::RefCell,
     ops::Range,
@@ -78,9 +79,11 @@ pub trait LspAdapter: 'static + Send + Sync {
     ) -> BoxFuture<'static, Result<PathBuf>>;
     fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option<PathBuf>>;
     fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams);
+
     fn label_for_completion(&self, _: &lsp::CompletionItem, _: &Language) -> Option<CodeLabel> {
         None
     }
+
     fn label_for_symbol(&self, _: &str, _: lsp::SymbolKind, _: &Language) -> Option<CodeLabel> {
         None
     }
@@ -88,6 +91,10 @@ pub trait LspAdapter: 'static + Send + Sync {
     fn server_args(&self) -> &[&str] {
         &[]
     }
+
+    fn initialization_options(&self) -> Option<Value> {
+        None
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -291,8 +298,13 @@ impl LanguageRegistry {
         Some(cx.background().spawn(async move {
             let server_binary_path = server_binary_path.await?;
             let server_args = adapter.server_args();
-            let server =
-                lsp::LanguageServer::new(&server_binary_path, server_args, &root_path, background)?;
+            let server = lsp::LanguageServer::new(
+                &server_binary_path,
+                server_args,
+                adapter.initialization_options(),
+                &root_path,
+                background,
+            )?;
             Ok(server)
         }))
     }

crates/lsp/src/lsp.rs 🔗

@@ -103,6 +103,7 @@ impl LanguageServer {
     pub fn new(
         binary_path: &Path,
         args: &[&str],
+        options: Option<Value>,
         root_path: &Path,
         background: Arc<executor::Background>,
     ) -> Result<Arc<Self>> {
@@ -115,13 +116,14 @@ impl LanguageServer {
             .spawn()?;
         let stdin = server.stdin.take().unwrap();
         let stdout = server.stdout.take().unwrap();
-        Self::new_internal(stdin, stdout, root_path, background)
+        Self::new_internal(stdin, stdout, root_path, options, background)
     }
 
     fn new_internal<Stdin, Stdout>(
         stdin: Stdin,
         stdout: Stdout,
         root_path: &Path,
+        options: Option<Value>,
         executor: Arc<executor::Background>,
     ) -> Result<Arc<Self>>
     where
@@ -232,7 +234,7 @@ impl LanguageServer {
             .spawn({
                 let this = this.clone();
                 async move {
-                    if let Some(capabilities) = this.init(root_uri).log_err().await {
+                    if let Some(capabilities) = this.init(root_uri, options).log_err().await {
                         *capabilities_tx.borrow_mut() = Some(capabilities);
                     }
 
@@ -244,13 +246,17 @@ impl LanguageServer {
         Ok(this)
     }
 
-    async fn init(self: Arc<Self>, root_uri: Url) -> Result<ServerCapabilities> {
+    async fn init(
+        self: Arc<Self>,
+        root_uri: Url,
+        options: Option<Value>,
+    ) -> Result<ServerCapabilities> {
         #[allow(deprecated)]
         let params = InitializeParams {
             process_id: Default::default(),
             root_path: Default::default(),
             root_uri: Some(root_uri),
-            initialization_options: Default::default(),
+            initialization_options: options,
             capabilities: ClientCapabilities {
                 text_document: Some(TextDocumentClientCapabilities {
                     definition: Some(GotoCapability {
@@ -530,6 +536,7 @@ impl LanguageServer {
             stdin_writer,
             stdout_reader,
             Path::new("/"),
+            None,
             cx.background().clone(),
         )
         .unwrap();

crates/zed/src/language.rs 🔗

@@ -7,6 +7,7 @@ use lazy_static::lazy_static;
 use regex::Regex;
 use rust_embed::RustEmbed;
 use serde::Deserialize;
+use serde_json::json;
 use smol::fs::{self, File};
 use std::{borrow::Cow, env::consts, path::PathBuf, str, sync::Arc};
 use util::{ResultExt, TryFutureExt};
@@ -522,6 +523,12 @@ impl LspAdapter for JsonLspAdapter {
     }
 
     fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
+
+    fn initialization_options(&self) -> Option<serde_json::Value> {
+        Some(json!({
+            "provideFormatter": true
+        }))
+    }
 }
 
 pub fn build_language_registry() -> LanguageRegistry {