Enable formatting feature of JSON language server

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>
This commit is contained in:
Max Brunsfeld 2022-03-03 14:16:56 -08:00
parent 81627a0f14
commit 9999862016
3 changed files with 32 additions and 6 deletions

View file

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

View file

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

View file

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