Remove some more sketchy defaults

Conrad Irwin created

Change summary

assets/settings/default.json                                  |   3 
crates/collab/src/tests/integration_tests.rs                  |   4 
crates/collab/src/tests/remote_editing_collaboration_tests.rs |   6 
crates/copilot/src/copilot_completion_provider.rs             |  24 
crates/editor/src/editor_tests.rs                             | 107 +-
crates/editor/src/jsx_tag_auto_close.rs                       |   8 
crates/language/src/language_settings.rs                      | 153 +++-
crates/settings/src/settings_content/language.rs              |  47 -
8 files changed, 183 insertions(+), 169 deletions(-)

Detailed changes

assets/settings/default.json πŸ”—

@@ -953,6 +953,7 @@
   //
   // This is typically customized on a per-language basis.
   "language_servers": ["..."],
+
   // When to automatically save edited buffers. This setting can
   // take four values.
   //
@@ -1838,7 +1839,7 @@
   // and configure default Prettier, used when no project-level Prettier installation is found.
   "prettier": {
     // // Whether to consider prettier formatter or not when attempting to format a file.
-    // "allowed": false,
+    "allowed": false
     //
     // // Use regular Prettier json configuration.
     // // If Prettier is allowed, Zed will use this for its Prettier instance for any applicable file, if

crates/collab/src/tests/integration_tests.rs πŸ”—

@@ -4695,7 +4695,7 @@ async fn test_prettier_formatting_buffer(
             store.update_user_settings(cx, |file| {
                 file.project.all_languages.defaults.formatter = Some(SelectedFormatter::Auto);
                 file.project.all_languages.defaults.prettier = Some(PrettierSettingsContent {
-                    allowed: true,
+                    allowed: Some(true),
                     ..Default::default()
                 });
             });
@@ -4708,7 +4708,7 @@ async fn test_prettier_formatting_buffer(
                     FormatterList::Single(Formatter::LanguageServer { name: None }),
                 ));
                 file.project.all_languages.defaults.prettier = Some(PrettierSettingsContent {
-                    allowed: true,
+                    allowed: Some(true),
                     ..Default::default()
                 });
             });

crates/collab/src/tests/remote_editing_collaboration_tests.rs πŸ”—

@@ -499,7 +499,7 @@ async fn test_ssh_collaboration_formatting_with_prettier(
             store.update_user_settings(cx, |file| {
                 file.project.all_languages.defaults.formatter = Some(SelectedFormatter::Auto);
                 file.project.all_languages.defaults.prettier = Some(PrettierSettingsContent {
-                    allowed: true,
+                    allowed: Some(true),
                     ..Default::default()
                 });
             });
@@ -512,7 +512,7 @@ async fn test_ssh_collaboration_formatting_with_prettier(
                     FormatterList::Single(Formatter::LanguageServer { name: None }),
                 ));
                 file.project.all_languages.defaults.prettier = Some(PrettierSettingsContent {
-                    allowed: true,
+                    allowed: Some(true),
                     ..Default::default()
                 });
             });
@@ -556,7 +556,7 @@ async fn test_ssh_collaboration_formatting_with_prettier(
             store.update_user_settings(cx, |file| {
                 file.project.all_languages.defaults.formatter = Some(SelectedFormatter::Auto);
                 file.project.all_languages.defaults.prettier = Some(PrettierSettingsContent {
-                    allowed: true,
+                    allowed: Some(true),
                     ..Default::default()
                 });
             });

crates/copilot/src/copilot_completion_provider.rs πŸ”—

@@ -281,7 +281,7 @@ mod tests {
     use indoc::indoc;
     use language::{
         Point,
-        language_settings::{CompletionSettings, LspInsertMode, WordsCompletionMode},
+        language_settings::{CompletionSettingsContent, LspInsertMode, WordsCompletionMode},
     };
     use project::Project;
     use serde_json::json;
@@ -296,12 +296,11 @@ mod tests {
     async fn test_copilot(executor: BackgroundExecutor, cx: &mut TestAppContext) {
         // flaky
         init_test(cx, |settings| {
-            settings.defaults.completions = Some(CompletionSettings {
-                words: WordsCompletionMode::Disabled,
-                words_min_length: 0,
-                lsp: true,
-                lsp_fetch_timeout_ms: 0,
-                lsp_insert_mode: LspInsertMode::Insert,
+            settings.defaults.completions = Some(CompletionSettingsContent {
+                words: Some(WordsCompletionMode::Disabled),
+                words_min_length: Some(0),
+                lsp_insert_mode: Some(LspInsertMode::Insert),
+                ..Default::default()
             });
         });
 
@@ -529,12 +528,11 @@ mod tests {
     ) {
         // flaky
         init_test(cx, |settings| {
-            settings.defaults.completions = Some(CompletionSettings {
-                words: WordsCompletionMode::Disabled,
-                words_min_length: 0,
-                lsp: true,
-                lsp_fetch_timeout_ms: 0,
-                lsp_insert_mode: LspInsertMode::Insert,
+            settings.defaults.completions = Some(CompletionSettingsContent {
+                words: Some(WordsCompletionMode::Disabled),
+                words_min_length: Some(0),
+                lsp_insert_mode: Some(LspInsertMode::Insert),
+                ..Default::default()
             });
         });
 

crates/editor/src/editor_tests.rs πŸ”—

@@ -25,7 +25,7 @@ use language::{
     DiagnosticSourceKind, FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageMatcher,
     LanguageName, Override, Point,
     language_settings::{
-        CompletionSettings, FormatterList, LanguageSettingsContent, LspInsertMode,
+        CompletionSettingsContent, FormatterList, LanguageSettingsContent, LspInsertMode,
         SelectedFormatter,
     },
     tree_sitter_python,
@@ -11700,7 +11700,7 @@ async fn test_document_format_manual_trigger(cx: &mut TestAppContext) {
     update_test_language_settings(cx, |settings| {
         // Enable Prettier formatting for the same buffer, and ensure
         // LSP is called instead of Prettier.
-        settings.defaults.prettier.get_or_insert_default().allowed = true;
+        settings.defaults.prettier.get_or_insert_default().allowed = Some(true);
     });
     let mut fake_servers = language_registry.register_fake_lsp(
         "Rust",
@@ -12086,7 +12086,7 @@ async fn test_organize_imports_manual_trigger(cx: &mut TestAppContext) {
         Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
     )));
     update_test_language_settings(cx, |settings| {
-        settings.defaults.prettier.get_or_insert_default().allowed = true;
+        settings.defaults.prettier.get_or_insert_default().allowed = Some(true);
     });
     let mut fake_servers = language_registry.register_fake_lsp(
         "TypeScript",
@@ -13341,12 +13341,11 @@ async fn test_completion_mode(cx: &mut TestAppContext) {
             );
 
             update_test_language_settings(&mut cx, |settings| {
-                settings.defaults.completions = Some(CompletionSettings {
-                    lsp_insert_mode,
-                    words: WordsCompletionMode::Disabled,
-                    words_min_length: 0,
-                    lsp: true,
-                    lsp_fetch_timeout_ms: 0,
+                settings.defaults.completions = Some(CompletionSettingsContent {
+                    lsp_insert_mode: Some(lsp_insert_mode),
+                    words: Some(WordsCompletionMode::Disabled),
+                    words_min_length: Some(0),
+                    ..Default::default()
                 });
             });
 
@@ -13401,13 +13400,12 @@ async fn test_completion_with_mode_specified_by_action(cx: &mut TestAppContext)
     let expected_with_replace_mode = "SubscriptionErrorˇ";
 
     update_test_language_settings(&mut cx, |settings| {
-        settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Disabled,
-            words_min_length: 0,
+        settings.defaults.completions = Some(CompletionSettingsContent {
+            words: Some(WordsCompletionMode::Disabled),
+            words_min_length: Some(0),
             // set the opposite here to ensure that the action is overriding the default behavior
-            lsp_insert_mode: LspInsertMode::Insert,
-            lsp: true,
-            lsp_fetch_timeout_ms: 0,
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -13438,13 +13436,12 @@ async fn test_completion_with_mode_specified_by_action(cx: &mut TestAppContext)
     apply_additional_edits.await.unwrap();
 
     update_test_language_settings(&mut cx, |settings| {
-        settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Disabled,
-            words_min_length: 0,
+        settings.defaults.completions = Some(CompletionSettingsContent {
+            words: Some(WordsCompletionMode::Disabled),
+            words_min_length: Some(0),
             // set the opposite here to ensure that the action is overriding the default behavior
-            lsp_insert_mode: LspInsertMode::Replace,
-            lsp: true,
-            lsp_fetch_timeout_ms: 0,
+            lsp_insert_mode: Some(LspInsertMode::Replace),
+            ..Default::default()
         });
     });
 
@@ -14180,12 +14177,11 @@ async fn test_completion_reuse(cx: &mut TestAppContext) {
 async fn test_word_completion(cx: &mut TestAppContext) {
     let lsp_fetch_timeout_ms = 10;
     init_test(cx, |language_settings| {
-        language_settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Fallback,
-            words_min_length: 0,
-            lsp: true,
-            lsp_fetch_timeout_ms: 10,
-            lsp_insert_mode: LspInsertMode::Insert,
+        language_settings.defaults.completions = Some(CompletionSettingsContent {
+            words_min_length: Some(0),
+            lsp_fetch_timeout_ms: Some(10),
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -14277,12 +14273,11 @@ async fn test_word_completion(cx: &mut TestAppContext) {
 #[gpui::test]
 async fn test_word_completions_do_not_duplicate_lsp_ones(cx: &mut TestAppContext) {
     init_test(cx, |language_settings| {
-        language_settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Enabled,
-            words_min_length: 0,
-            lsp: true,
-            lsp_fetch_timeout_ms: 0,
-            lsp_insert_mode: LspInsertMode::Insert,
+        language_settings.defaults.completions = Some(CompletionSettingsContent {
+            words: Some(WordsCompletionMode::Enabled),
+            words_min_length: Some(0),
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -14341,12 +14336,11 @@ async fn test_word_completions_do_not_duplicate_lsp_ones(cx: &mut TestAppContext
 #[gpui::test]
 async fn test_word_completions_continue_on_typing(cx: &mut TestAppContext) {
     init_test(cx, |language_settings| {
-        language_settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Disabled,
-            words_min_length: 0,
-            lsp: true,
-            lsp_fetch_timeout_ms: 0,
-            lsp_insert_mode: LspInsertMode::Insert,
+        language_settings.defaults.completions = Some(CompletionSettingsContent {
+            words: Some(WordsCompletionMode::Disabled),
+            words_min_length: Some(0),
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -14415,12 +14409,11 @@ async fn test_word_completions_continue_on_typing(cx: &mut TestAppContext) {
 #[gpui::test]
 async fn test_word_completions_usually_skip_digits(cx: &mut TestAppContext) {
     init_test(cx, |language_settings| {
-        language_settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Fallback,
-            words_min_length: 0,
-            lsp: false,
-            lsp_fetch_timeout_ms: 0,
-            lsp_insert_mode: LspInsertMode::Insert,
+        language_settings.defaults.completions = Some(CompletionSettingsContent {
+            words_min_length: Some(0),
+            lsp: Some(false),
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -14478,12 +14471,11 @@ async fn test_word_completions_usually_skip_digits(cx: &mut TestAppContext) {
 #[gpui::test]
 async fn test_word_completions_do_not_show_before_threshold(cx: &mut TestAppContext) {
     init_test(cx, |language_settings| {
-        language_settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Enabled,
-            words_min_length: 3,
-            lsp: true,
-            lsp_fetch_timeout_ms: 0,
-            lsp_insert_mode: LspInsertMode::Insert,
+        language_settings.defaults.completions = Some(CompletionSettingsContent {
+            words: Some(WordsCompletionMode::Enabled),
+            words_min_length: Some(3),
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -14548,12 +14540,11 @@ async fn test_word_completions_do_not_show_before_threshold(cx: &mut TestAppCont
 #[gpui::test]
 async fn test_word_completions_disabled(cx: &mut TestAppContext) {
     init_test(cx, |language_settings| {
-        language_settings.defaults.completions = Some(CompletionSettings {
-            words: WordsCompletionMode::Enabled,
-            words_min_length: 0,
-            lsp: true,
-            lsp_fetch_timeout_ms: 0,
-            lsp_insert_mode: LspInsertMode::Insert,
+        language_settings.defaults.completions = Some(CompletionSettingsContent {
+            words: Some(WordsCompletionMode::Enabled),
+            words_min_length: Some(0),
+            lsp_insert_mode: Some(LspInsertMode::Insert),
+            ..Default::default()
         });
     });
 
@@ -17986,7 +17977,7 @@ async fn test_document_format_with_prettier(cx: &mut TestAppContext) {
         Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
     )));
     update_test_language_settings(cx, |settings| {
-        settings.defaults.prettier.get_or_insert_default().allowed = true;
+        settings.defaults.prettier.get_or_insert_default().allowed = Some(true);
     });
 
     let test_plugin = "test_plugin";

crates/editor/src/jsx_tag_auto_close.rs πŸ”—

@@ -328,7 +328,7 @@ pub(crate) fn refresh_enabled_in_any_buffer(
                     snapshot.file(),
                     cx,
                 );
-                if language_settings.jsx_tag_auto_close.enabled {
+                if language_settings.jsx_tag_auto_close {
                     found_enabled = true;
                 }
             }
@@ -406,7 +406,7 @@ pub(crate) fn handle_from(
             };
 
             let language_settings = snapshot.settings_at(edit.new.end, cx);
-            if !language_settings.jsx_tag_auto_close.enabled {
+            if !language_settings.jsx_tag_auto_close {
                 continue;
             }
 
@@ -630,7 +630,7 @@ mod jsx_tag_autoclose_tests {
                 .defaults
                 .jsx_tag_auto_close
                 .get_or_insert_default()
-                .enabled = true;
+                .enabled = Some(true);
         });
 
         let mut cx = EditorTestContext::new(cx).await;
@@ -796,7 +796,7 @@ mod jsx_tag_autoclose_tests {
                 .defaults
                 .jsx_tag_auto_close
                 .get_or_insert_default()
-                .enabled = true;
+                .enabled = Some(true);
         });
 
         let buffer_a = cx.new(|cx| {

crates/language/src/language_settings.rs πŸ”—

@@ -9,16 +9,17 @@ use ec4rs::{
 use globset::{Glob, GlobMatcher, GlobSet, GlobSetBuilder};
 use gpui::{App, Modifiers};
 use itertools::{Either, Itertools};
-use schemars::{JsonSchema, json_schema};
-use serde::{Deserialize, Serialize};
+use schemars::json_schema;
 
 pub use settings::{
-    CompletionSettings, EditPredictionProvider, EditPredictionsMode, FormatOnSave, Formatter,
-    FormatterList, IndentGuideSettings, InlayHintKind, LanguageSettingsContent, LspInsertMode,
-    RewrapBehavior, SelectedFormatter, ShowWhitespaceSetting, SoftWrap, WordsCompletionMode,
+    CompletionSettingsContent, EditPredictionProvider, EditPredictionsMode, FormatOnSave,
+    Formatter, FormatterList, IndentGuideSettings, InlayHintKind, LanguageSettingsContent,
+    LspInsertMode, RewrapBehavior, SelectedFormatter, ShowWhitespaceSetting, SoftWrap,
+    WordsCompletionMode,
 };
 use settings::{
-    ParameterizedJsonSchema, Settings, SettingsContent, SettingsLocation, SettingsStore, SettingsUi,
+    ParameterizedJsonSchema, PrettierSettingsContent, Settings, SettingsContent, SettingsLocation,
+    SettingsStore, SettingsUi,
 };
 use shellexpand;
 use std::{borrow::Cow, num::NonZeroU32, path::Path, sync::Arc};
@@ -100,9 +101,9 @@ pub struct LanguageSettings {
     /// How to perform a buffer format.
     pub formatter: settings::SelectedFormatter,
     /// Zed's Prettier integration settings.
-    pub prettier: settings::PrettierSettingsContent,
+    pub prettier: PrettierSettings,
     /// Whether to automatically close JSX tags.
-    pub jsx_tag_auto_close: settings::JsxTagAutoCloseSettings,
+    pub jsx_tag_auto_close: bool,
     /// Whether to use language servers to provide code intelligence.
     pub enable_language_server: bool,
     /// The list of language servers to use (or disable) for this language.
@@ -157,11 +158,80 @@ pub struct LanguageSettings {
     /// completions menu.
     pub show_completion_documentation: bool,
     /// Completion settings for this language.
-    pub completions: settings::CompletionSettings,
+    pub completions: CompletionSettings,
     /// Preferred debuggers for this language.
     pub debuggers: Vec<String>,
 }
 
+#[derive(Debug, Clone)]
+pub struct CompletionSettings {
+    /// Controls how words are completed.
+    /// For large documents, not all words may be fetched for completion.
+    ///
+    /// Default: `fallback`
+    pub words: WordsCompletionMode,
+    /// How many characters has to be in the completions query to automatically show the words-based completions.
+    /// Before that value, it's still possible to trigger the words-based completion manually with the corresponding editor command.
+    ///
+    /// Default: 3
+    pub words_min_length: usize,
+    /// Whether to fetch LSP completions or not.
+    ///
+    /// Default: true
+    pub lsp: bool,
+    /// When fetching LSP completions, determines how long to wait for a response of a particular server.
+    /// When set to 0, waits indefinitely.
+    ///
+    /// Default: 0
+    pub lsp_fetch_timeout_ms: u64,
+    /// Controls how LSP completions are inserted.
+    ///
+    /// Default: "replace_suffix"
+    pub lsp_insert_mode: LspInsertMode,
+}
+
+impl CompletionSettings {
+    pub fn merge_from(&mut self, src: &Option<CompletionSettingsContent>) {
+        let Some(src) = src else { return };
+        self.words.merge_from(&src.words);
+        self.words_min_length.merge_from(&src.words_min_length);
+        self.lsp.merge_from(&src.lsp);
+        self.lsp_fetch_timeout_ms
+            .merge_from(&src.lsp_fetch_timeout_ms);
+        self.lsp_insert_mode.merge_from(&src.lsp_insert_mode);
+    }
+}
+
+/// Allows to enable/disable formatting with Prettier
+/// and configure default Prettier, used when no project-level Prettier installation is found.
+/// Prettier formatting is disabled by default.
+#[derive(Debug, Clone)]
+pub struct PrettierSettings {
+    /// Enables or disables formatting with Prettier for a given language.
+    pub allowed: bool,
+
+    /// Forces Prettier integration to use a specific parser name when formatting files with the language.
+    pub parser: Option<String>,
+
+    /// Forces Prettier integration to use specific plugins when formatting files with the language.
+    /// The default Prettier will be installed with these plugins.
+    pub plugins: HashSet<String>,
+
+    /// Default Prettier options, in the format as in package.json section for Prettier.
+    /// If project installs Prettier via its package.json, these options will be ignored.
+    pub options: HashMap<String, serde_json::Value>,
+}
+
+impl PrettierSettings {
+    pub fn merge_from(&mut self, src: &Option<PrettierSettingsContent>) {
+        let Some(src) = src.clone() else { return };
+        self.allowed.merge_from(&src.allowed);
+        self.parser = src.parser.clone();
+        self.plugins.extend(src.plugins);
+        self.options.extend(src.options);
+    }
+}
+
 impl LanguageSettings {
     /// A token representing the rest of the available language servers.
     const REST_OF_LANGUAGE_SERVERS: &'static str = "...";
@@ -445,6 +515,9 @@ impl settings::Settings for AllLanguageSettings {
         let all_languages = &content.project.all_languages;
         let defaults = all_languages.defaults.clone();
         let inlay_hints = defaults.inlay_hints.unwrap();
+        let completions = defaults.completions.unwrap();
+        let prettier = defaults.prettier.unwrap();
+
         let default_language_settings = LanguageSettings {
             tab_size: defaults.tab_size.unwrap(),
             hard_tabs: defaults.hard_tabs.unwrap(),
@@ -459,8 +532,13 @@ impl settings::Settings for AllLanguageSettings {
                 .unwrap(),
             ensure_final_newline_on_save: defaults.ensure_final_newline_on_save.unwrap(),
             formatter: defaults.formatter.unwrap(),
-            prettier: defaults.prettier.unwrap(),
-            jsx_tag_auto_close: defaults.jsx_tag_auto_close.unwrap(),
+            prettier: PrettierSettings {
+                allowed: prettier.allowed.unwrap(),
+                parser: prettier.parser,
+                plugins: prettier.plugins,
+                options: prettier.options,
+            },
+            jsx_tag_auto_close: defaults.jsx_tag_auto_close.unwrap().enabled.unwrap(),
             enable_language_server: defaults.enable_language_server.unwrap(),
             language_servers: defaults.language_servers.unwrap(),
             allow_rewrap: defaults.allow_rewrap.unwrap(),
@@ -493,7 +571,13 @@ impl settings::Settings for AllLanguageSettings {
             tasks: defaults.tasks.unwrap(),
             show_completions_on_input: defaults.show_completions_on_input.unwrap(),
             show_completion_documentation: defaults.show_completion_documentation.unwrap(),
-            completions: defaults.completions.unwrap(),
+            completions: CompletionSettings {
+                words: completions.words.unwrap(),
+                words_min_length: completions.words_min_length.unwrap(),
+                lsp: completions.lsp.unwrap(),
+                lsp_fetch_timeout_ms: completions.lsp_fetch_timeout_ms.unwrap(),
+                lsp_insert_mode: completions.lsp_insert_mode.unwrap(),
+            },
             debuggers: defaults.debuggers.unwrap(),
         };
 
@@ -760,17 +844,7 @@ impl settings::Settings for AllLanguageSettings {
             } else {
                 WordsCompletionMode::Disabled
             };
-            if let Some(completion_settings) = d.completions.as_mut() {
-                completion_settings.words = mode;
-            } else {
-                d.completions = Some(CompletionSettings {
-                    words: mode,
-                    words_min_length: 3,
-                    lsp: true,
-                    lsp_fetch_timeout_ms: 0,
-                    lsp_insert_mode: LspInsertMode::ReplaceSuffix,
-                });
-            }
+            d.completions.get_or_insert_default().words = Some(mode);
         }
         // TODO: pull ^ out into helper and reuse for per-language settings
 
@@ -853,7 +927,7 @@ fn merge_settings(settings: &mut LanguageSettings, src: &LanguageSettingsContent
     settings.prettier.merge_from(&src.prettier.clone());
     settings
         .jsx_tag_auto_close
-        .merge_from(&src.jsx_tag_auto_close.clone());
+        .merge_from(&src.jsx_tag_auto_close.as_ref().and_then(|v| v.enabled));
     settings
         .format_on_save
         .merge_from(&src.format_on_save.clone());
@@ -926,39 +1000,12 @@ fn merge_settings(settings: &mut LanguageSettings, src: &LanguageSettingsContent
     settings
         .show_completion_documentation
         .merge_from(&src.show_completion_documentation);
-    settings.completions.merge_from(&src.completions.clone());
-}
-
-/// Allows to enable/disable formatting with Prettier
-/// and configure default Prettier, used when no project-level Prettier installation is found.
-/// Prettier formatting is disabled by default.
-#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, SettingsUi)]
-pub struct PrettierSettings {
-    /// Enables or disables formatting with Prettier for a given language.
-    #[serde(default)]
-    pub allowed: bool,
-
-    /// Forces Prettier integration to use a specific parser name when formatting files with the language.
-    #[serde(default)]
-    pub parser: Option<String>,
-
-    /// Forces Prettier integration to use specific plugins when formatting files with the language.
-    /// The default Prettier will be installed with these plugins.
-    #[serde(default)]
-    #[settings_ui(skip)]
-    pub plugins: HashSet<String>,
-
-    /// Default Prettier options, in the format as in package.json section for Prettier.
-    /// If project installs Prettier via its package.json, these options will be ignored.
-    #[serde(flatten)]
-    #[settings_ui(skip)]
-    pub options: HashMap<String, serde_json::Value>,
+    settings.completions.merge_from(&src.completions);
 }
 
-#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, SettingsUi)]
+#[derive(Default, Debug, Clone, PartialEq, Eq, SettingsUi)]
 pub struct JsxTagAutoCloseSettings {
     /// Enables or disables auto-closing of JSX tags.
-    #[serde(default)]
     pub enabled: bool,
 }
 

crates/settings/src/settings_content/language.rs πŸ”—

@@ -180,7 +180,7 @@ pub struct LanguageSettingsContent {
     /// Default: off
     pub prettier: Option<PrettierSettingsContent>,
     /// Whether to automatically close JSX tags.
-    pub jsx_tag_auto_close: Option<JsxTagAutoCloseSettings>,
+    pub jsx_tag_auto_close: Option<JsxTagAutoCloseSettingsContent>,
     /// Whether to use language servers to provide code intelligence.
     ///
     /// Default: true
@@ -281,7 +281,7 @@ pub struct LanguageSettingsContent {
     /// Default: true
     pub show_completion_documentation: Option<bool>,
     /// Controls how completions are processed for this language.
-    pub completions: Option<CompletionSettings>,
+    pub completions: Option<CompletionSettingsContent>,
     /// Preferred debuggers for this language.
     ///
     /// Default: []
@@ -312,9 +312,7 @@ pub enum ShowWhitespaceSetting {
 #[skip_serializing_none]
 #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
 pub struct WhitespaceMap {
-    #[serde(default)]
     pub space: Option<String>,
-    #[serde(default)]
     pub tab: Option<String>,
 }
 
@@ -347,11 +345,9 @@ pub enum RewrapBehavior {
 
 #[skip_serializing_none]
 #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
-pub struct JsxTagAutoCloseSettings {
+pub struct JsxTagAutoCloseSettingsContent {
     /// Enables or disables auto-closing of JSX tags.
-    // todo! option
-    #[serde(default)]
-    pub enabled: bool,
+    pub enabled: Option<bool>,
 }
 
 /// The settings for inlay hints.
@@ -440,37 +436,32 @@ impl InlayHintKind {
 
 /// Controls how completions are processedfor this anguage.
 #[skip_serializing_none]
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)]
 #[serde(rename_all = "snake_case")]
-pub struct CompletionSettings {
+pub struct CompletionSettingsContent {
     /// Controls how words are completed.
     /// For large documents, not all words may be fetched for completion.
     ///
     /// Default: `fallback`
-    #[serde(default = "default_words_completion_mode")]
-    pub words: WordsCompletionMode,
+    pub words: Option<WordsCompletionMode>,
     /// How many characters has to be in the completions query to automatically show the words-based completions.
     /// Before that value, it's still possible to trigger the words-based completion manually with the corresponding editor command.
     ///
     /// Default: 3
-    #[serde(default = "default_3")]
-    pub words_min_length: usize,
+    pub words_min_length: Option<usize>,
     /// Whether to fetch LSP completions or not.
     ///
     /// Default: true
-    #[serde(default = "default_true")]
-    pub lsp: bool,
+    pub lsp: Option<bool>,
     /// When fetching LSP completions, determines how long to wait for a response of a particular server.
     /// When set to 0, waits indefinitely.
     ///
     /// Default: 0
-    #[serde(default)]
-    pub lsp_fetch_timeout_ms: u64,
+    pub lsp_fetch_timeout_ms: Option<u64>,
     /// Controls how LSP completions are inserted.
     ///
     /// Default: "replace_suffix"
-    #[serde(default = "default_lsp_insert_mode")]
-    pub lsp_insert_mode: LspInsertMode,
+    pub lsp_insert_mode: Option<LspInsertMode>,
 }
 
 #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
@@ -502,18 +493,6 @@ pub enum WordsCompletionMode {
     Disabled,
 }
 
-fn default_words_completion_mode() -> WordsCompletionMode {
-    WordsCompletionMode::Fallback
-}
-
-fn default_lsp_insert_mode() -> LspInsertMode {
-    LspInsertMode::ReplaceSuffix
-}
-
-fn default_3() -> usize {
-    3
-}
-
 /// Allows to enable/disable formatting with Prettier
 /// and configure default Prettier, used when no project-level Prettier installation is found.
 /// Prettier formatting is disabled by default.
@@ -521,11 +500,9 @@ fn default_3() -> usize {
 #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 pub struct PrettierSettingsContent {
     /// Enables or disables formatting with Prettier for a given language.
-    #[serde(default)]
-    pub allowed: bool,
+    pub allowed: Option<bool>,
 
     /// Forces Prettier integration to use a specific parser name when formatting files with the language.
-    #[serde(default)]
     pub parser: Option<String>,
 
     /// Forces Prettier integration to use specific plugins when formatting files with the language.