Merge pull request #2336 from zed-industries/respect-languages-alias-in-settings-file

Mikayla Maki created

Add support for writing to the langauge_overrides alias in settings

Change summary

crates/settings/src/settings.rs | 63 +++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 3 deletions(-)

Detailed changes

crates/settings/src/settings.rs 🔗

@@ -848,6 +848,9 @@ pub fn parse_json_with_comments<T: DeserializeOwned>(content: &str) -> Result<T>
 }
 
 fn write_settings_key(settings_content: &mut String, key_path: &[&str], new_value: &Value) {
+    const LANGUAGE_OVERRIDES: &'static str = "language_overrides";
+    const LANGAUGES: &'static str = "languages";
+
     let mut parser = tree_sitter::Parser::new();
     parser.set_language(tree_sitter_json::language()).unwrap();
     let tree = parser.parse(&settings_content, None).unwrap();
@@ -864,6 +867,8 @@ fn write_settings_key(settings_content: &mut String, key_path: &[&str], new_valu
     )
     .unwrap();
 
+    let has_language_overrides = settings_content.contains(LANGUAGE_OVERRIDES);
+
     let mut depth = 0;
     let mut last_value_range = 0..0;
     let mut first_key_start = None;
@@ -893,7 +898,13 @@ fn write_settings_key(settings_content: &mut String, key_path: &[&str], new_valu
 
         let found_key = settings_content
             .get(key_range.clone())
-            .map(|key_text| key_text == format!("\"{}\"", key_path[depth]))
+            .map(|key_text| {
+                if key_path[depth] == LANGAUGES && has_language_overrides {
+                    return key_text == format!("\"{}\"", LANGUAGE_OVERRIDES);
+                } else {
+                    return key_text == format!("\"{}\"", key_path[depth]);
+                }
+            })
             .unwrap_or(false);
 
         if found_key {
@@ -917,12 +928,20 @@ fn write_settings_key(settings_content: &mut String, key_path: &[&str], new_valu
         settings_content.replace_range(existing_value_range, &new_val);
     } else {
         // We have key paths, construct the sub objects
-        let new_key = key_path[depth];
+        let new_key = if has_language_overrides && key_path[depth] == LANGAUGES {
+            LANGUAGE_OVERRIDES
+        } else {
+            key_path[depth]
+        };
 
         // We don't have the key, construct the nested objects
         let mut new_value = serde_json::to_value(new_value).unwrap();
         for key in key_path[(depth + 1)..].iter().rev() {
-            new_value = serde_json::json!({ key.to_string(): new_value });
+            if has_language_overrides && key == &LANGAUGES {
+                new_value = serde_json::json!({ LANGUAGE_OVERRIDES.to_string(): new_value });
+            } else {
+                new_value = serde_json::json!({ key.to_string(): new_value });
+            }
         }
 
         if let Some(first_key_start) = first_key_start {
@@ -1095,6 +1114,44 @@ mod tests {
         pretty_assertions::assert_eq!(new_json, expected_new_json.into());
     }
 
+    #[test]
+    fn test_update_language_overrides_copilot() {
+        assert_new_settings(
+            r#"
+                {
+                    "language_overrides": {
+                        "JSON": {
+                            "copilot": "off"
+                        }
+                    }
+                }
+            "#
+            .unindent(),
+            |settings| {
+                settings.languages.insert(
+                    "Rust".into(),
+                    EditorSettings {
+                        copilot: Some(OnOff::On),
+                        ..Default::default()
+                    },
+                );
+            },
+            r#"
+                {
+                    "language_overrides": {
+                        "Rust": {
+                            "copilot": "on"
+                        },
+                        "JSON": {
+                            "copilot": "off"
+                        }
+                    }
+                }
+            "#
+            .unindent(),
+        );
+    }
+
     #[test]
     fn test_update_copilot() {
         assert_new_settings(