Respect user preference for JS/TS on_type formatting (#14536)

Mathias created

Release Notes:

- Fix user preferences for JS/TS on_type formatting not being respected by VTSLS.
([#13733](https://github.com/zed-industries/zed/issues/13733),
[#14499](https://github.com/zed-industries/zed/issues/14499))

Change summary

crates/languages/src/vtsls.rs     | 55 ++++++---------------------------
crates/project/src/lsp_command.rs | 34 +++++++-------------
crates/project/src/project.rs     | 23 +++++++------
3 files changed, 35 insertions(+), 77 deletions(-)

Detailed changes

crates/languages/src/vtsls.rs 🔗

@@ -180,8 +180,8 @@ impl LspAdapter for VtslsLspAdapter {
         Ok(Some(json!({
             "typescript": {
                 "tsdk": tsdk_path,
-                "format": {
-                    "enable": true
+                "suggest": {
+                    "completeFunctionCalls": true
                 },
                 "inlayHints": {
                     "parameterNames": {
@@ -206,6 +206,11 @@ impl LspAdapter for VtslsLspAdapter {
                     }
                 }
             },
+            "javascript": {
+                "suggest": {
+                    "completeFunctionCalls": true
+                }
+            },
             "vtsls": {
                 "experimental": {
                     "completion": {
@@ -232,49 +237,9 @@ impl LspAdapter for VtslsLspAdapter {
         if let Some(options) = override_options {
             return Ok(options);
         }
-        let tsdk_path = Self::tsdk_path(&adapter).await;
-        Ok(json!({
-            "typescript": {
-                "suggest": {
-                    "completeFunctionCalls": true
-                },
-                "tsdk": tsdk_path,
-                "format": {
-                    "enable": true
-                },
-                "inlayHints": {
-                    "parameterNames": {
-                        "enabled": "all",
-                        "suppressWhenArgumentMatchesName": false,
-                    },
-                    "parameterTypes": {
-                        "enabled": true
-                    },
-                    "variableTypes": {
-                        "enabled": true,
-                        "suppressWhenTypeMatchesName": false,
-                    },
-                    "propertyDeclarationTypes": {
-                        "enabled": true,
-                    },
-                    "functionLikeReturnTypes": {
-                        "enabled": true,
-                    },
-                    "enumMemberValues": {
-                        "enabled": true,
-                    }
-                }
-            },
-            "vtsls": {
-                "experimental": {
-                    "completion": {
-                        "enableServerSideFuzzyMatch": true,
-                        "entriesLimit": 5000,
-                    }
-                },
-                "autoUseWorkspaceTsdk": true
-            }
-        }))
+        self.initialization_options(adapter)
+            .await
+            .map(|o| o.unwrap())
     }
 
     fn language_ids(&self) -> HashMap<String, String> {

crates/project/src/lsp_command.rs 🔗

@@ -12,7 +12,7 @@ use clock::Global;
 use futures::future;
 use gpui::{AppContext, AsyncAppContext, Model};
 use language::{
-    language_settings::{language_settings, InlayHintKind},
+    language_settings::{language_settings, InlayHintKind, LanguageSettings},
     point_from_lsp, point_to_lsp,
     proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
     range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CharKind,
@@ -31,11 +31,13 @@ pub use signature_help::{
     SignatureHelp, SIGNATURE_HELP_HIGHLIGHT_CURRENT, SIGNATURE_HELP_HIGHLIGHT_OVERLOAD,
 };
 
-pub fn lsp_formatting_options(tab_size: u32) -> lsp::FormattingOptions {
+pub fn lsp_formatting_options(settings: &LanguageSettings) -> lsp::FormattingOptions {
     lsp::FormattingOptions {
-        tab_size,
-        insert_spaces: true,
-        insert_final_newline: Some(true),
+        tab_size: settings.tab_size.into(),
+        insert_spaces: !settings.hard_tabs,
+        trim_trailing_whitespace: Some(settings.remove_trailing_whitespace_on_save),
+        trim_final_newlines: Some(settings.ensure_final_newline_on_save),
+        insert_final_newline: Some(settings.ensure_final_newline_on_save),
         ..lsp::FormattingOptions::default()
     }
 }
@@ -153,7 +155,7 @@ pub(crate) struct GetCodeActions {
 pub(crate) struct OnTypeFormatting {
     pub position: PointUtf16,
     pub trigger: String,
-    pub options: FormattingOptions,
+    pub options: lsp::FormattingOptions,
     pub push_to_history: bool,
 }
 
@@ -161,18 +163,6 @@ pub(crate) struct InlayHints {
     pub range: Range<Anchor>,
 }
 
-pub(crate) struct FormattingOptions {
-    tab_size: u32,
-}
-
-impl From<lsp::FormattingOptions> for FormattingOptions {
-    fn from(value: lsp::FormattingOptions) -> Self {
-        Self {
-            tab_size: value.tab_size,
-        }
-    }
-}
-
 pub(crate) struct LinkedEditingRange {
     pub position: Anchor,
 }
@@ -2069,7 +2059,7 @@ impl LspCommand for OnTypeFormatting {
                 point_to_lsp(self.position),
             ),
             ch: self.trigger.clone(),
-            options: lsp_formatting_options(self.options.tab_size),
+            options: self.options.clone(),
         }
     }
 
@@ -2127,14 +2117,14 @@ impl LspCommand for OnTypeFormatting {
             })?
             .await?;
 
-        let tab_size = buffer.update(&mut cx, |buffer, cx| {
-            language_settings(buffer.language(), buffer.file(), cx).tab_size
+        let options = buffer.update(&mut cx, |buffer, cx| {
+            lsp_formatting_options(language_settings(buffer.language(), buffer.file(), cx))
         })?;
 
         Ok(Self {
             position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
             trigger: message.trigger.clone(),
-            options: lsp_formatting_options(tab_size.get()).into(),
+            options,
             push_to_history: false,
         })
     }

crates/project/src/project.rs 🔗

@@ -43,6 +43,7 @@ use itertools::Itertools;
 use language::{
     language_settings::{
         language_settings, AllLanguageSettings, FormatOnSave, Formatter, InlayHintKind,
+        LanguageSettings,
     },
     markdown, point_to_lsp, prepare_completion_documentation,
     proto::{
@@ -93,7 +94,6 @@ use std::{
     ffi::OsStr,
     hash::Hash,
     iter, mem,
-    num::NonZeroU32,
     ops::Range,
     path::{self, Component, Path, PathBuf},
     process::Stdio,
@@ -4967,7 +4967,6 @@ impl Project {
 
             let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save;
             let ensure_final_newline = settings.ensure_final_newline_on_save;
-            let tab_size = settings.tab_size;
 
             // First, format buffer's whitespace according to the settings.
             let trailing_whitespace_diff = if remove_trailing_whitespace {
@@ -5052,7 +5051,7 @@ impl Project {
                                 buffer,
                                 buffer_abs_path,
                                 language_server,
-                                tab_size,
+                                &settings,
                                 &mut cx,
                             )
                             .await
@@ -5101,7 +5100,7 @@ impl Project {
                                 buffer,
                                 buffer_abs_path,
                                 language_server,
-                                tab_size,
+                                &settings,
                                 &mut cx,
                             )
                             .await
@@ -5171,7 +5170,7 @@ impl Project {
         buffer: &Model<Buffer>,
         abs_path: &Path,
         language_server: &Arc<LanguageServer>,
-        tab_size: NonZeroU32,
+        settings: &LanguageSettings,
         cx: &mut AsyncAppContext,
     ) -> Result<Vec<(Range<Anchor>, String)>> {
         let uri = lsp::Url::from_file_path(abs_path)
@@ -5186,7 +5185,7 @@ impl Project {
             language_server
                 .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
                     text_document,
-                    options: lsp_command::lsp_formatting_options(tab_size.get()),
+                    options: lsp_command::lsp_formatting_options(settings),
                     work_done_progress_params: Default::default(),
                 })
                 .await?
@@ -5198,7 +5197,7 @@ impl Project {
                 .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
                     text_document,
                     range: lsp::Range::new(buffer_start, buffer_end),
-                    options: lsp_command::lsp_formatting_options(tab_size.get()),
+                    options: lsp_command::lsp_formatting_options(settings),
                     work_done_progress_params: Default::default(),
                 })
                 .await?
@@ -6829,8 +6828,12 @@ impl Project {
         push_to_history: bool,
         cx: &mut ModelContext<Self>,
     ) -> Task<Result<Option<Transaction>>> {
-        let tab_size = buffer.update(cx, |buffer, cx| {
-            language_settings(buffer.language_at(position).as_ref(), buffer.file(), cx).tab_size
+        let options = buffer.update(cx, |buffer, cx| {
+            lsp_command::lsp_formatting_options(language_settings(
+                buffer.language_at(position).as_ref(),
+                buffer.file(),
+                cx,
+            ))
         });
         self.request_lsp(
             buffer.clone(),
@@ -6838,7 +6841,7 @@ impl Project {
             OnTypeFormatting {
                 position,
                 trigger,
-                options: lsp_command::lsp_formatting_options(tab_size.get()).into(),
+                options,
                 push_to_history,
             },
             cx,