settings_store.rs

   1use anyhow::{Context as _, Result};
   2use collections::{BTreeMap, HashMap, btree_map, hash_map};
   3use ec4rs::{ConfigParser, PropertiesSource, Section};
   4use fs::Fs;
   5use futures::{
   6    FutureExt, StreamExt,
   7    channel::{mpsc, oneshot},
   8    future::LocalBoxFuture,
   9};
  10use gpui::{App, AsyncApp, BorrowAppContext, Global, SharedString, Task, UpdateGlobal};
  11
  12use paths::{EDITORCONFIG_NAME, local_settings_file_relative_path, task_file_name};
  13use schemars::JsonSchema;
  14use serde::{Serialize, de::DeserializeOwned};
  15use serde_json::{Value, json};
  16use smallvec::SmallVec;
  17use std::{
  18    any::{Any, TypeId, type_name},
  19    env,
  20    fmt::Debug,
  21    ops::Range,
  22    path::{Path, PathBuf},
  23    str::{self, FromStr},
  24    sync::Arc,
  25};
  26use util::{
  27    ResultExt as _, merge_non_null_json_value_into,
  28    schemars::{DefaultDenyUnknownFields, add_new_subschema},
  29};
  30
  31pub type EditorconfigProperties = ec4rs::Properties;
  32
  33use crate::{
  34    ActiveSettingsProfileName, ParameterizedJsonSchema, SettingsJsonSchemaParams, SettingsUiEntry,
  35    VsCodeSettings, WorktreeId, parse_json_with_comments, replace_value_in_json_text,
  36    settings_content::{
  37        ExtensionsSettingsContent, ProjectSettingsContent, ServerSettingsContent, SettingsContent,
  38        UserSettingsContent,
  39    },
  40    update_value_in_json_text,
  41};
  42
  43pub trait SettingsKey: 'static + Send + Sync {
  44    /// The name of a key within the JSON file from which this setting should
  45    /// be deserialized. If this is `None`, then the setting will be deserialized
  46    /// from the root object.
  47    const KEY: Option<&'static str>;
  48
  49    const FALLBACK_KEY: Option<&'static str> = None;
  50}
  51
  52/// A value that can be defined as a user setting.
  53///
  54/// Settings can be loaded from a combination of multiple JSON files.
  55pub trait Settings: 'static + Send + Sync + Sized {
  56    /// The name of the keys in the [`FileContent`](Self::FileContent) that should
  57    /// always be written to a settings file, even if their value matches the default
  58    /// value.
  59    ///
  60    /// This is useful for tagged [`FileContent`](Self::FileContent)s where the tag
  61    /// is a "version" field that should always be persisted, even if the current
  62    /// user settings match the current version of the settings.
  63    const PRESERVED_KEYS: Option<&'static [&'static str]> = None;
  64
  65    fn from_file(content: &SettingsContent) -> Option<Self>;
  66
  67    fn refine(&mut self, content: &SettingsContent);
  68
  69    fn missing_default() -> anyhow::Error {
  70        anyhow::anyhow!("missing default for: {}", std::any::type_name::<Self>())
  71    }
  72
  73    /// Use [the helpers in the vscode_import module](crate::vscode_import) to apply known
  74    /// equivalent settings from a vscode config to our config
  75    fn import_from_vscode(vscode: &VsCodeSettings, current: &mut SettingsContent);
  76
  77    #[track_caller]
  78    fn register(cx: &mut App)
  79    where
  80        Self: Sized,
  81    {
  82        SettingsStore::update_global(cx, |store, cx| {
  83            store.register_setting::<Self>(cx);
  84        });
  85    }
  86
  87    #[track_caller]
  88    fn get<'a>(path: Option<SettingsLocation>, cx: &'a App) -> &'a Self
  89    where
  90        Self: Sized,
  91    {
  92        cx.global::<SettingsStore>().get(path)
  93    }
  94
  95    #[track_caller]
  96    fn get_global(cx: &App) -> &Self
  97    where
  98        Self: Sized,
  99    {
 100        cx.global::<SettingsStore>().get(None)
 101    }
 102
 103    #[track_caller]
 104    fn try_get(cx: &App) -> Option<&Self>
 105    where
 106        Self: Sized,
 107    {
 108        if cx.has_global::<SettingsStore>() {
 109            cx.global::<SettingsStore>().try_get(None)
 110        } else {
 111            None
 112        }
 113    }
 114
 115    #[track_caller]
 116    fn try_read_global<R>(cx: &AsyncApp, f: impl FnOnce(&Self) -> R) -> Option<R>
 117    where
 118        Self: Sized,
 119    {
 120        cx.try_read_global(|s: &SettingsStore, _| f(s.get(None)))
 121    }
 122
 123    #[track_caller]
 124    fn override_global(settings: Self, cx: &mut App)
 125    where
 126        Self: Sized,
 127    {
 128        cx.global_mut::<SettingsStore>().override_global(settings)
 129    }
 130}
 131
 132#[derive(Clone, Copy, Debug)]
 133pub struct SettingsSources<'a, T> {
 134    /// The default Zed settings.
 135    pub default: &'a T,
 136    /// Global settings (loaded before user settings).
 137    pub global: Option<&'a T>,
 138    /// Settings provided by extensions.
 139    pub extensions: Option<&'a T>,
 140    /// The user settings.
 141    pub user: Option<&'a T>,
 142    /// The user settings for the current release channel.
 143    pub release_channel: Option<&'a T>,
 144    /// The user settings for the current operating system.
 145    pub operating_system: Option<&'a T>,
 146    /// The settings associated with an enabled settings profile
 147    pub profile: Option<&'a T>,
 148    /// The server's settings.
 149    pub server: Option<&'a T>,
 150    /// The project settings, ordered from least specific to most specific.
 151    pub project: &'a [&'a T],
 152}
 153
 154impl<'a, T: Serialize> SettingsSources<'a, T> {
 155    /// Returns an iterator over the default settings as well as all settings customizations.
 156    pub fn defaults_and_customizations(&self) -> impl Iterator<Item = &T> {
 157        [self.default].into_iter().chain(self.customizations())
 158    }
 159
 160    /// Returns an iterator over all of the settings customizations.
 161    pub fn customizations(&self) -> impl Iterator<Item = &T> {
 162        self.global
 163            .into_iter()
 164            .chain(self.extensions)
 165            .chain(self.user)
 166            .chain(self.release_channel)
 167            .chain(self.operating_system)
 168            .chain(self.profile)
 169            .chain(self.server)
 170            .chain(self.project.iter().copied())
 171    }
 172
 173    /// Returns the settings after performing a JSON merge of the provided customizations.
 174    ///
 175    /// Customizations later in the iterator win out over the earlier ones.
 176    pub fn json_merge_with<O: DeserializeOwned>(
 177        customizations: impl Iterator<Item = &'a T>,
 178    ) -> Result<O> {
 179        let mut merged = Value::Null;
 180        for value in customizations {
 181            merge_non_null_json_value_into(serde_json::to_value(value).unwrap(), &mut merged);
 182        }
 183        Ok(serde_json::from_value(merged)?)
 184    }
 185
 186    /// Returns the settings after performing a JSON merge of the customizations into the
 187    /// default settings.
 188    ///
 189    /// More-specific customizations win out over the less-specific ones.
 190    pub fn json_merge<O: DeserializeOwned>(&'a self) -> Result<O> {
 191        Self::json_merge_with(self.defaults_and_customizations())
 192    }
 193}
 194
 195#[derive(Clone, Copy, Debug)]
 196pub struct SettingsLocation<'a> {
 197    pub worktree_id: WorktreeId,
 198    pub path: &'a Path,
 199}
 200
 201/// A set of strongly-typed setting values defined via multiple config files.
 202pub struct SettingsStore {
 203    setting_values: HashMap<TypeId, Box<dyn AnySettingValue>>,
 204    default_settings: Option<SettingsContent>,
 205    user_settings: Option<UserSettingsContent>,
 206    global_settings: Option<SettingsContent>,
 207
 208    extension_settings: Option<SettingsContent>,
 209    server_settings: Option<SettingsContent>,
 210    local_settings: BTreeMap<(WorktreeId, Arc<Path>), SettingsContent>,
 211    raw_editorconfig_settings: BTreeMap<(WorktreeId, Arc<Path>), (String, Option<Editorconfig>)>,
 212
 213    _setting_file_updates: Task<()>,
 214    setting_file_updates_tx:
 215        mpsc::UnboundedSender<Box<dyn FnOnce(AsyncApp) -> LocalBoxFuture<'static, Result<()>>>>,
 216}
 217
 218#[derive(Clone)]
 219pub struct Editorconfig {
 220    pub is_root: bool,
 221    pub sections: SmallVec<[Section; 5]>,
 222}
 223
 224impl FromStr for Editorconfig {
 225    type Err = anyhow::Error;
 226
 227    fn from_str(contents: &str) -> Result<Self, Self::Err> {
 228        let parser = ConfigParser::new_buffered(contents.as_bytes())
 229            .context("creating editorconfig parser")?;
 230        let is_root = parser.is_root;
 231        let sections = parser
 232            .collect::<Result<SmallVec<_>, _>>()
 233            .context("parsing editorconfig sections")?;
 234        Ok(Self { is_root, sections })
 235    }
 236}
 237
 238#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 239pub enum LocalSettingsKind {
 240    Settings,
 241    Tasks,
 242    Editorconfig,
 243    Debug,
 244}
 245
 246impl Global for SettingsStore {}
 247
 248#[derive(Debug)]
 249struct SettingValue<T> {
 250    global_value: Option<T>,
 251    local_values: Vec<(WorktreeId, Arc<Path>, T)>,
 252}
 253
 254trait AnySettingValue: 'static + Send + Sync {
 255    fn setting_type_name(&self) -> &'static str;
 256
 257    fn from_file(&self, s: &SettingsContent) -> Option<Box<dyn Any>>;
 258    fn refine(&self, value: &mut dyn Any, s: &[&SettingsContent]);
 259
 260    fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any;
 261    fn all_local_values(&self) -> Vec<(WorktreeId, Arc<Path>, &dyn Any)>;
 262    fn set_global_value(&mut self, value: Box<dyn Any>);
 263    fn set_local_value(&mut self, root_id: WorktreeId, path: Arc<Path>, value: Box<dyn Any>);
 264    fn json_schema(&self, generator: &mut schemars::SchemaGenerator) -> schemars::Schema;
 265    fn edits_for_update(
 266        &self,
 267        raw_settings: &serde_json::Value,
 268        tab_size: usize,
 269        vscode_settings: &VsCodeSettings,
 270        text: &mut String,
 271        edits: &mut Vec<(Range<usize>, String)>,
 272    );
 273    fn settings_ui_item(&self) -> SettingsUiEntry;
 274}
 275
 276struct DeserializedSetting(Box<dyn Any>);
 277
 278impl SettingsStore {
 279    pub fn new(cx: &App) -> Self {
 280        let (setting_file_updates_tx, mut setting_file_updates_rx) = mpsc::unbounded();
 281        Self {
 282            setting_values: Default::default(),
 283            default_settings: Some(Default::default()), // todo!()
 284            global_settings: None,
 285            server_settings: None,
 286            user_settings: Some(Default::default()), // todo!()
 287            extension_settings: None,
 288            local_settings: BTreeMap::default(),
 289            raw_editorconfig_settings: BTreeMap::default(),
 290            setting_file_updates_tx,
 291            _setting_file_updates: cx.spawn(async move |cx| {
 292                while let Some(setting_file_update) = setting_file_updates_rx.next().await {
 293                    (setting_file_update)(cx.clone()).await.log_err();
 294                }
 295            }),
 296        }
 297    }
 298
 299    pub fn observe_active_settings_profile_name(cx: &mut App) -> gpui::Subscription {
 300        cx.observe_global::<ActiveSettingsProfileName>(|cx| {
 301            Self::update_global(cx, |store, cx| {
 302                store.recompute_values(None, cx).log_err();
 303            });
 304        })
 305    }
 306
 307    pub fn update<C, R>(cx: &mut C, f: impl FnOnce(&mut Self, &mut C) -> R) -> R
 308    where
 309        C: BorrowAppContext,
 310    {
 311        cx.update_global(f)
 312    }
 313
 314    /// Add a new type of setting to the store.
 315    pub fn register_setting<T: Settings>(&mut self, cx: &mut App) {
 316        let setting_type_id = TypeId::of::<T>();
 317        let entry = self.setting_values.entry(setting_type_id);
 318
 319        if matches!(entry, hash_map::Entry::Occupied(_)) {
 320            return;
 321        }
 322
 323        let setting_value = entry.or_insert(Box::new(SettingValue::<T> {
 324            global_value: None,
 325            local_values: Vec::new(),
 326        }));
 327
 328        let mut refinements = Vec::default();
 329
 330        if let Some(extension_settings) = self.extension_settings.as_ref() {
 331            refinements.push(extension_settings)
 332        }
 333
 334        if let Some(user_settings) = self.user_settings.as_ref() {
 335            refinements.push(&user_settings.content);
 336            if let Some(release_channel) = user_settings.for_release_channel() {
 337                refinements.push(release_channel)
 338            }
 339            if let Some(os) = user_settings.for_os() {
 340                refinements.push(os)
 341            }
 342            if let Some(profile) = user_settings.for_profile(cx) {
 343                refinements.push(profile)
 344            }
 345        }
 346
 347        if let Some(server_settings) = self.server_settings.as_ref() {
 348            refinements.push(server_settings)
 349        }
 350        let default = self.default_settings.as_ref().unwrap();
 351        // todo!() unwrap...
 352        let mut value = T::from_file(default).unwrap();
 353        for refinement in refinements {
 354            value.refine(refinement)
 355        }
 356
 357        setting_value.set_global_value(Box::new(value));
 358
 359        // todo!() local settings
 360        // (they weren't handled before...)
 361    }
 362
 363    /// Get the value of a setting.
 364    ///
 365    /// Panics if the given setting type has not been registered, or if there is no
 366    /// value for this setting.
 367    pub fn get<T: Settings>(&self, path: Option<SettingsLocation>) -> &T {
 368        self.setting_values
 369            .get(&TypeId::of::<T>())
 370            .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::<T>()))
 371            .value_for_path(path)
 372            .downcast_ref::<T>()
 373            .expect("no default value for setting type")
 374    }
 375
 376    /// Get the value of a setting.
 377    ///
 378    /// Does not panic
 379    pub fn try_get<T: Settings>(&self, path: Option<SettingsLocation>) -> Option<&T> {
 380        self.setting_values
 381            .get(&TypeId::of::<T>())
 382            .map(|value| value.value_for_path(path))
 383            .and_then(|value| value.downcast_ref::<T>())
 384    }
 385
 386    /// Get all values from project specific settings
 387    pub fn get_all_locals<T: Settings>(&self) -> Vec<(WorktreeId, Arc<Path>, &T)> {
 388        self.setting_values
 389            .get(&TypeId::of::<T>())
 390            .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::<T>()))
 391            .all_local_values()
 392            .into_iter()
 393            .map(|(id, path, any)| {
 394                (
 395                    id,
 396                    path,
 397                    any.downcast_ref::<T>()
 398                        .expect("wrong value type for setting"),
 399                )
 400            })
 401            .collect()
 402    }
 403
 404    /// Override the global value for a setting.
 405    ///
 406    /// The given value will be overwritten if the user settings file changes.
 407    pub fn override_global<T: Settings>(&mut self, value: T) {
 408        self.setting_values
 409            .get_mut(&TypeId::of::<T>())
 410            .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::<T>()))
 411            .set_global_value(Box::new(value))
 412    }
 413
 414    /// Get the user's settings as a raw JSON value.
 415    ///
 416    /// For user-facing functionality use the typed setting interface.
 417    /// (e.g. ProjectSettings::get_global(cx))
 418    pub fn raw_user_settings(&self) -> Option<&UserSettingsContent> {
 419        self.user_settings.as_ref()
 420    }
 421
 422    /// Replaces current settings with the values from the given JSON.
 423    pub fn set_raw_user_settings(
 424        &mut self,
 425        new_settings: UserSettingsContent,
 426        cx: &mut App,
 427    ) -> Result<()> {
 428        self.user_settings = Some(new_settings);
 429        self.recompute_values(None, cx)?;
 430        Ok(())
 431    }
 432
 433    /// Get the configured settings profile names.
 434    pub fn configured_settings_profiles(&self) -> impl Iterator<Item = &str> {
 435        self.user_settings
 436            .iter()
 437            .flat_map(|settings| settings.profiles.keys().map(|k| k.as_str()))
 438    }
 439
 440    /// Access the raw JSON value of the default settings.
 441    pub fn raw_default_settings(&self) -> Option<&SettingsContent> {
 442        self.default_settings.as_ref()
 443    }
 444
 445    #[cfg(any(test, feature = "test-support"))]
 446    pub fn test(cx: &mut App) -> Self {
 447        let mut this = Self::new(cx);
 448        this.set_default_settings(&crate::test_settings(), cx)
 449            .unwrap();
 450        this.set_user_settings("{}", cx).unwrap();
 451        this
 452    }
 453
 454    /// Updates the value of a setting in the user's global configuration.
 455    ///
 456    /// This is only for tests. Normally, settings are only loaded from
 457    /// JSON files.
 458    #[cfg(any(test, feature = "test-support"))]
 459    pub fn update_user_settings(
 460        &mut self,
 461        cx: &mut App,
 462        update: impl FnOnce(&mut SettingsContent),
 463    ) {
 464        let mut content = self.user_settings.as_ref().unwrap().content.clone();
 465        update(&mut content);
 466        let new_text = serde_json::to_string(&UserSettingsContent {
 467            content,
 468            ..Default::default()
 469        })
 470        .unwrap();
 471        self.set_user_settings(&new_text, cx).unwrap();
 472    }
 473
 474    pub async fn load_settings(fs: &Arc<dyn Fs>) -> Result<String> {
 475        match fs.load(paths::settings_file()).await {
 476            result @ Ok(_) => result,
 477            Err(err) => {
 478                if let Some(e) = err.downcast_ref::<std::io::Error>()
 479                    && e.kind() == std::io::ErrorKind::NotFound
 480                {
 481                    return Ok(crate::initial_user_settings_content().to_string());
 482                }
 483                Err(err)
 484            }
 485        }
 486    }
 487
 488    fn update_settings_file_inner(
 489        &self,
 490        fs: Arc<dyn Fs>,
 491        update: impl 'static + Send + FnOnce(String, AsyncApp) -> Result<String>,
 492    ) -> oneshot::Receiver<Result<()>> {
 493        let (tx, rx) = oneshot::channel::<Result<()>>();
 494        self.setting_file_updates_tx
 495            .unbounded_send(Box::new(move |cx: AsyncApp| {
 496                async move {
 497                    let res = async move {
 498                        let old_text = Self::load_settings(&fs).await?;
 499                        let new_text = update(old_text, cx)?;
 500                        let settings_path = paths::settings_file().as_path();
 501                        if fs.is_file(settings_path).await {
 502                            let resolved_path =
 503                                fs.canonicalize(settings_path).await.with_context(|| {
 504                                    format!(
 505                                        "Failed to canonicalize settings path {:?}",
 506                                        settings_path
 507                                    )
 508                                })?;
 509
 510                            fs.atomic_write(resolved_path.clone(), new_text)
 511                                .await
 512                                .with_context(|| {
 513                                    format!("Failed to write settings to file {:?}", resolved_path)
 514                                })?;
 515                        } else {
 516                            fs.atomic_write(settings_path.to_path_buf(), new_text)
 517                                .await
 518                                .with_context(|| {
 519                                    format!("Failed to write settings to file {:?}", settings_path)
 520                                })?;
 521                        }
 522                        anyhow::Ok(())
 523                    }
 524                    .await;
 525
 526                    let new_res = match &res {
 527                        Ok(_) => anyhow::Ok(()),
 528                        Err(e) => Err(anyhow::anyhow!("Failed to write settings to file {:?}", e)),
 529                    };
 530
 531                    _ = tx.send(new_res);
 532                    res
 533                }
 534                .boxed_local()
 535            }))
 536            .map_err(|err| anyhow::format_err!("Failed to update settings file: {}", err))
 537            .log_with_level(log::Level::Warn);
 538        return rx;
 539    }
 540
 541    pub fn update_settings_file_at_path(
 542        &self,
 543        fs: Arc<dyn Fs>,
 544        path: &[impl AsRef<str>],
 545        new_value: serde_json::Value,
 546    ) -> oneshot::Receiver<Result<()>> {
 547        let key_path = path
 548            .into_iter()
 549            .map(AsRef::as_ref)
 550            .map(SharedString::new)
 551            .collect::<Vec<_>>();
 552        let update = move |mut old_text: String, cx: AsyncApp| {
 553            cx.read_global(|store: &SettingsStore, _cx| {
 554                // todo(settings_ui) use `update_value_in_json_text` for merging new and old objects with comment preservation, needs old value though...
 555                let (range, replacement) = replace_value_in_json_text(
 556                    &old_text,
 557                    key_path.as_slice(),
 558                    store.json_tab_size(),
 559                    Some(&new_value),
 560                    None,
 561                );
 562                old_text.replace_range(range, &replacement);
 563                old_text
 564            })
 565        };
 566        self.update_settings_file_inner(fs, update)
 567    }
 568
 569    pub fn update_settings_file(
 570        &self,
 571        fs: Arc<dyn Fs>,
 572        update: impl 'static + Send + FnOnce(&mut SettingsContent, &App),
 573    ) {
 574        _ = self.update_settings_file_inner(fs, move |old_text: String, cx: AsyncApp| {
 575            cx.read_global(|store: &SettingsStore, cx| {
 576                store.new_text_for_update(old_text, |content| update(content, cx))
 577            })
 578        });
 579    }
 580
 581    pub fn import_vscode_settings(
 582        &self,
 583        fs: Arc<dyn Fs>,
 584        vscode_settings: VsCodeSettings,
 585    ) -> oneshot::Receiver<Result<()>> {
 586        self.update_settings_file_inner(fs, move |old_text: String, cx: AsyncApp| {
 587            cx.read_global(|store: &SettingsStore, _cx| {
 588                store.get_vscode_edits(old_text, &vscode_settings)
 589            })
 590        })
 591    }
 592
 593    pub fn settings_ui_items(&self) -> impl IntoIterator<Item = SettingsUiEntry> {
 594        self.setting_values
 595            .values()
 596            .map(|item| item.settings_ui_item())
 597    }
 598}
 599
 600impl SettingsStore {
 601    /// Updates the value of a setting in a JSON file, returning the new text
 602    /// for that JSON file.
 603    pub fn new_text_for_update(
 604        &self,
 605        old_text: String,
 606        update: impl FnOnce(&mut SettingsContent),
 607    ) -> String {
 608        let edits = self.edits_for_update(&old_text, update);
 609        let mut new_text = old_text;
 610        for (range, replacement) in edits.into_iter() {
 611            new_text.replace_range(range, &replacement);
 612        }
 613        new_text
 614    }
 615
 616    pub fn get_vscode_edits(&self, mut old_text: String, vscode: &VsCodeSettings) -> String {
 617        let mut new_text = old_text.clone();
 618        let mut edits: Vec<(Range<usize>, String)> = Vec::new();
 619        let raw_settings = parse_json_with_comments::<Value>(&old_text).unwrap_or_default();
 620        let tab_size = self.json_tab_size();
 621        for v in self.setting_values.values() {
 622            v.edits_for_update(&raw_settings, tab_size, vscode, &mut old_text, &mut edits);
 623        }
 624        for (range, replacement) in edits.into_iter() {
 625            new_text.replace_range(range, &replacement);
 626        }
 627        new_text
 628    }
 629
 630    /// Updates the value of a setting in a JSON file, returning a list
 631    /// of edits to apply to the JSON file.
 632    pub fn edits_for_update(
 633        &self,
 634        text: &str,
 635        update: impl FnOnce(&mut SettingsContent),
 636    ) -> Vec<(Range<usize>, String)> {
 637        let old_content: UserSettingsContent = serde_json::from_str(text).unwrap_or_default();
 638        let mut new_content = old_content.clone();
 639        update(&mut new_content.content);
 640
 641        let old_value = serde_json::to_value(&old_content).unwrap();
 642        let new_value = serde_json::to_value(new_content).unwrap();
 643
 644        let mut key_path = Vec::new();
 645        let mut edits = Vec::new();
 646        let tab_size = self.json_tab_size();
 647        let mut text = text.to_string();
 648        update_value_in_json_text(
 649            &mut text,
 650            &mut key_path,
 651            tab_size,
 652            &old_value,
 653            &new_value,
 654            &[], // todo!() is this still needed?
 655            &mut edits,
 656        );
 657        edits
 658    }
 659
 660    pub fn json_tab_size(&self) -> usize {
 661        2
 662    }
 663
 664    /// Sets the default settings via a JSON string.
 665    ///
 666    /// The string should contain a JSON object with a default value for every setting.
 667    pub fn set_default_settings(
 668        &mut self,
 669        default_settings_content: &str,
 670        cx: &mut App,
 671    ) -> Result<()> {
 672        self.default_settings = parse_json_with_comments(default_settings_content)?;
 673        self.recompute_values(None, cx)?;
 674        Ok(())
 675    }
 676
 677    /// Sets the user settings via a JSON string.
 678    pub fn set_user_settings(&mut self, user_settings_content: &str, cx: &mut App) -> Result<()> {
 679        let settings: UserSettingsContent = if user_settings_content.is_empty() {
 680            parse_json_with_comments("{}")?
 681        } else {
 682            parse_json_with_comments(user_settings_content)?
 683        };
 684
 685        self.user_settings = Some(settings);
 686        self.recompute_values(None, cx)?;
 687        Ok(())
 688    }
 689
 690    /// Sets the global settings via a JSON string.
 691    pub fn set_global_settings(
 692        &mut self,
 693        global_settings_content: &str,
 694        cx: &mut App,
 695    ) -> Result<()> {
 696        let settings: SettingsContent = if global_settings_content.is_empty() {
 697            parse_json_with_comments("{}")?
 698        } else {
 699            parse_json_with_comments(global_settings_content)?
 700        };
 701
 702        self.global_settings = Some(settings);
 703        self.recompute_values(None, cx)?;
 704        Ok(())
 705    }
 706
 707    pub fn set_server_settings(
 708        &mut self,
 709        server_settings_content: &str,
 710        cx: &mut App,
 711    ) -> Result<()> {
 712        let settings: Option<ServerSettingsContent> = if server_settings_content.is_empty() {
 713            None
 714        } else {
 715            parse_json_with_comments(server_settings_content)?
 716        };
 717
 718        todo!();
 719        // self.server_settings = Some(settings);
 720        self.recompute_values(None, cx)?;
 721        Ok(())
 722    }
 723
 724    /// Add or remove a set of local settings via a JSON string.
 725    pub fn set_local_settings(
 726        &mut self,
 727        root_id: WorktreeId,
 728        directory_path: Arc<Path>,
 729        kind: LocalSettingsKind,
 730        settings_content: Option<&str>,
 731        cx: &mut App,
 732    ) -> std::result::Result<(), InvalidSettingsError> {
 733        let mut zed_settings_changed = false;
 734        match (
 735            kind,
 736            settings_content
 737                .map(|content| content.trim())
 738                .filter(|content| !content.is_empty()),
 739        ) {
 740            (LocalSettingsKind::Tasks, _) => {
 741                return Err(InvalidSettingsError::Tasks {
 742                    message: "Attempted to submit tasks into the settings store".to_string(),
 743                    path: directory_path.join(task_file_name()),
 744                });
 745            }
 746            (LocalSettingsKind::Debug, _) => {
 747                return Err(InvalidSettingsError::Debug {
 748                    message: "Attempted to submit debugger config into the settings store"
 749                        .to_string(),
 750                    path: directory_path.join(task_file_name()),
 751                });
 752            }
 753            (LocalSettingsKind::Settings, None) => {
 754                zed_settings_changed = self
 755                    .local_settings
 756                    .remove(&(root_id, directory_path.clone()))
 757                    .is_some()
 758            }
 759            (LocalSettingsKind::Editorconfig, None) => {
 760                self.raw_editorconfig_settings
 761                    .remove(&(root_id, directory_path.clone()));
 762            }
 763            (LocalSettingsKind::Settings, Some(settings_contents)) => {
 764                let new_settings = parse_json_with_comments::<ProjectSettingsContent>(
 765                    settings_contents,
 766                )
 767                .map_err(|e| InvalidSettingsError::LocalSettings {
 768                    path: directory_path.join(local_settings_file_relative_path()),
 769                    message: e.to_string(),
 770                })?;
 771                match self.local_settings.entry((root_id, directory_path.clone())) {
 772                    btree_map::Entry::Vacant(v) => {
 773                        v.insert(SettingsContent {
 774                            project: new_settings,
 775                            ..Default::default()
 776                        });
 777                        zed_settings_changed = true;
 778                    }
 779                    btree_map::Entry::Occupied(mut o) => {
 780                        if &o.get().project != &new_settings {
 781                            o.insert(SettingsContent {
 782                                project: new_settings,
 783                                ..Default::default()
 784                            });
 785                            zed_settings_changed = true;
 786                        }
 787                    }
 788                }
 789            }
 790            (LocalSettingsKind::Editorconfig, Some(editorconfig_contents)) => {
 791                match self
 792                    .raw_editorconfig_settings
 793                    .entry((root_id, directory_path.clone()))
 794                {
 795                    btree_map::Entry::Vacant(v) => match editorconfig_contents.parse() {
 796                        Ok(new_contents) => {
 797                            v.insert((editorconfig_contents.to_owned(), Some(new_contents)));
 798                        }
 799                        Err(e) => {
 800                            v.insert((editorconfig_contents.to_owned(), None));
 801                            return Err(InvalidSettingsError::Editorconfig {
 802                                message: e.to_string(),
 803                                path: directory_path.join(EDITORCONFIG_NAME),
 804                            });
 805                        }
 806                    },
 807                    btree_map::Entry::Occupied(mut o) => {
 808                        if o.get().0 != editorconfig_contents {
 809                            match editorconfig_contents.parse() {
 810                                Ok(new_contents) => {
 811                                    o.insert((
 812                                        editorconfig_contents.to_owned(),
 813                                        Some(new_contents),
 814                                    ));
 815                                }
 816                                Err(e) => {
 817                                    o.insert((editorconfig_contents.to_owned(), None));
 818                                    return Err(InvalidSettingsError::Editorconfig {
 819                                        message: e.to_string(),
 820                                        path: directory_path.join(EDITORCONFIG_NAME),
 821                                    });
 822                                }
 823                            }
 824                        }
 825                    }
 826                }
 827            }
 828        };
 829
 830        if zed_settings_changed {
 831            self.recompute_values(Some((root_id, &directory_path)), cx)?;
 832        }
 833        Ok(())
 834    }
 835
 836    pub fn set_extension_settings(
 837        &mut self,
 838        content: ExtensionsSettingsContent,
 839        cx: &mut App,
 840    ) -> Result<()> {
 841        self.extension_settings = Some(SettingsContent {
 842            project: ProjectSettingsContent {
 843                all_languages: content.all_languages,
 844            },
 845            ..Default::default()
 846        });
 847        self.recompute_values(None, cx)?;
 848        Ok(())
 849    }
 850
 851    /// Add or remove a set of local settings via a JSON string.
 852    pub fn clear_local_settings(&mut self, root_id: WorktreeId, cx: &mut App) -> Result<()> {
 853        self.local_settings
 854            .retain(|(worktree_id, _), _| worktree_id != &root_id);
 855        self.recompute_values(Some((root_id, "".as_ref())), cx)?;
 856        Ok(())
 857    }
 858
 859    pub fn local_settings(
 860        &self,
 861        root_id: WorktreeId,
 862    ) -> impl '_ + Iterator<Item = (Arc<Path>, String)> {
 863        self.local_settings
 864            .range(
 865                (root_id, Path::new("").into())
 866                    ..(
 867                        WorktreeId::from_usize(root_id.to_usize() + 1),
 868                        Path::new("").into(),
 869                    ),
 870            )
 871            .map(|((_, path), content)| (path.clone(), serde_json::to_string(content).unwrap()))
 872    }
 873
 874    pub fn local_editorconfig_settings(
 875        &self,
 876        root_id: WorktreeId,
 877    ) -> impl '_ + Iterator<Item = (Arc<Path>, String, Option<Editorconfig>)> {
 878        self.raw_editorconfig_settings
 879            .range(
 880                (root_id, Path::new("").into())
 881                    ..(
 882                        WorktreeId::from_usize(root_id.to_usize() + 1),
 883                        Path::new("").into(),
 884                    ),
 885            )
 886            .map(|((_, path), (content, parsed_content))| {
 887                (path.clone(), content.clone(), parsed_content.clone())
 888            })
 889    }
 890
 891    pub fn json_schema(&self, schema_params: &SettingsJsonSchemaParams, cx: &App) -> Value {
 892        todo!()
 893        // let mut generator = schemars::generate::SchemaSettings::draft2019_09()
 894        //     .with_transform(DefaultDenyUnknownFields)
 895        //     .into_generator();
 896        // let mut combined_schema = json!({
 897        //     "type": "object",
 898        //     "properties": {}
 899        // });
 900
 901        // // Merge together settings schemas, similarly to json schema's "allOf". This merging is
 902        // // recursive, though at time of writing this recursive nature isn't used very much. An
 903        // // example of it is the schema for `jupyter` having contribution from both `EditorSettings`
 904        // // and `JupyterSettings`.
 905        // //
 906        // // This logic could be removed in favor of "allOf", but then there isn't the opportunity to
 907        // // validate and fully control the merge.
 908        // for setting_value in self.setting_values.values() {
 909        //     let mut setting_schema = setting_value.json_schema(&mut generator);
 910
 911        //     if let Some(key) = setting_value.key() {
 912        //         if let Some(properties) = combined_schema.get_mut("properties")
 913        //             && let Some(properties_obj) = properties.as_object_mut()
 914        //         {
 915        //             if let Some(target) = properties_obj.get_mut(key) {
 916        //                 merge_schema(target, setting_schema.to_value());
 917        //             } else {
 918        //                 properties_obj.insert(key.to_string(), setting_schema.to_value());
 919        //             }
 920        //         }
 921        //     } else {
 922        //         setting_schema.remove("description");
 923        //         setting_schema.remove("additionalProperties");
 924        //         merge_schema(&mut combined_schema, setting_schema.to_value());
 925        //     }
 926        // }
 927
 928        // fn merge_schema(target: &mut serde_json::Value, source: serde_json::Value) {
 929        //     let (Some(target_obj), serde_json::Value::Object(source_obj)) =
 930        //         (target.as_object_mut(), source)
 931        //     else {
 932        //         return;
 933        //     };
 934
 935        //     for (source_key, source_value) in source_obj {
 936        //         match source_key.as_str() {
 937        //             "properties" => {
 938        //                 let serde_json::Value::Object(source_properties) = source_value else {
 939        //                     log::error!(
 940        //                         "bug: expected object for `{}` json schema field, but got: {}",
 941        //                         source_key,
 942        //                         source_value
 943        //                     );
 944        //                     continue;
 945        //                 };
 946        //                 let target_properties =
 947        //                     target_obj.entry(source_key.clone()).or_insert(json!({}));
 948        //                 let Some(target_properties) = target_properties.as_object_mut() else {
 949        //                     log::error!(
 950        //                         "bug: expected object for `{}` json schema field, but got: {}",
 951        //                         source_key,
 952        //                         target_properties
 953        //                     );
 954        //                     continue;
 955        //                 };
 956        //                 for (key, value) in source_properties {
 957        //                     if let Some(existing) = target_properties.get_mut(&key) {
 958        //                         merge_schema(existing, value);
 959        //                     } else {
 960        //                         target_properties.insert(key, value);
 961        //                     }
 962        //                 }
 963        //             }
 964        //             "allOf" | "anyOf" | "oneOf" => {
 965        //                 let serde_json::Value::Array(source_array) = source_value else {
 966        //                     log::error!(
 967        //                         "bug: expected array for `{}` json schema field, but got: {}",
 968        //                         source_key,
 969        //                         source_value,
 970        //                     );
 971        //                     continue;
 972        //                 };
 973        //                 let target_array =
 974        //                     target_obj.entry(source_key.clone()).or_insert(json!([]));
 975        //                 let Some(target_array) = target_array.as_array_mut() else {
 976        //                     log::error!(
 977        //                         "bug: expected array for `{}` json schema field, but got: {}",
 978        //                         source_key,
 979        //                         target_array,
 980        //                     );
 981        //                     continue;
 982        //                 };
 983        //                 target_array.extend(source_array);
 984        //             }
 985        //             "type"
 986        //             | "$ref"
 987        //             | "enum"
 988        //             | "minimum"
 989        //             | "maximum"
 990        //             | "pattern"
 991        //             | "description"
 992        //             | "additionalProperties" => {
 993        //                 if let Some(old_value) =
 994        //                     target_obj.insert(source_key.clone(), source_value.clone())
 995        //                     && old_value != source_value
 996        //                 {
 997        //                     log::error!(
 998        //                         "bug: while merging JSON schemas, \
 999        //                             mismatch `\"{}\": {}` (before was `{}`)",
1000        //                         source_key,
1001        //                         old_value,
1002        //                         source_value
1003        //                     );
1004        //                 }
1005        //             }
1006        //             _ => {
1007        //                 log::error!(
1008        //                     "bug: while merging settings JSON schemas, \
1009        //                     encountered unexpected `\"{}\": {}`",
1010        //                     source_key,
1011        //                     source_value
1012        //                 );
1013        //             }
1014        //         }
1015        //     }
1016        // }
1017
1018        // // add schemas which are determined at runtime
1019        // for parameterized_json_schema in inventory::iter::<ParameterizedJsonSchema>() {
1020        //     (parameterized_json_schema.add_and_get_ref)(&mut generator, schema_params, cx);
1021        // }
1022
1023        // // add merged settings schema to the definitions
1024        // const ZED_SETTINGS: &str = "ZedSettings";
1025        // let zed_settings_ref = add_new_subschema(&mut generator, ZED_SETTINGS, combined_schema);
1026
1027        // // add `ZedSettingsOverride` which is the same as `ZedSettings` except that unknown
1028        // // fields are rejected. This is used for release stage settings and profiles.
1029        // let mut zed_settings_override = zed_settings_ref.clone();
1030        // zed_settings_override.insert("unevaluatedProperties".to_string(), false.into());
1031        // let zed_settings_override_ref = add_new_subschema(
1032        //     &mut generator,
1033        //     "ZedSettingsOverride",
1034        //     zed_settings_override.to_value(),
1035        // );
1036
1037        // // Remove `"additionalProperties": false` added by `DefaultDenyUnknownFields` so that
1038        // // unknown fields can be handled by the root schema and `ZedSettingsOverride`.
1039        // let mut definitions = generator.take_definitions(true);
1040        // definitions
1041        //     .get_mut(ZED_SETTINGS)
1042        //     .unwrap()
1043        //     .as_object_mut()
1044        //     .unwrap()
1045        //     .remove("additionalProperties");
1046
1047        // let meta_schema = generator
1048        //     .settings()
1049        //     .meta_schema
1050        //     .as_ref()
1051        //     .expect("meta_schema should be present in schemars settings")
1052        //     .to_string();
1053
1054        // json!({
1055        //     "$schema": meta_schema,
1056        //     "title": "Zed Settings",
1057        //     "unevaluatedProperties": false,
1058        //     // ZedSettings + settings overrides for each release stage / OS / profiles
1059        //     "allOf": [
1060        //         zed_settings_ref,
1061        //         {
1062        //             "properties": {
1063        //                 "dev": zed_settings_override_ref,
1064        //                 "nightly": zed_settings_override_ref,
1065        //                 "stable": zed_settings_override_ref,
1066        //                 "preview": zed_settings_override_ref,
1067        //                 "linux": zed_settings_override_ref,
1068        //                 "macos": zed_settings_override_ref,
1069        //                 "windows": zed_settings_override_ref,
1070        //                 "profiles": {
1071        //                     "type": "object",
1072        //                     "description": "Configures any number of settings profiles.",
1073        //                     "additionalProperties": zed_settings_override_ref
1074        //                 }
1075        //             }
1076        //         }
1077        //     ],
1078        //     "$defs": definitions,
1079        // })
1080    }
1081
1082    fn recompute_values(
1083        &mut self,
1084        changed_local_path: Option<(WorktreeId, &Path)>,
1085        cx: &mut App,
1086    ) -> std::result::Result<(), InvalidSettingsError> {
1087        // Reload the global and local values for every setting.
1088        let mut project_settings_stack = Vec::<&SettingsContent>::new();
1089        let mut paths_stack = Vec::<Option<(WorktreeId, &Path)>>::new();
1090
1091        let mut refinements = Vec::default();
1092
1093        if let Some(extension_settings) = self.extension_settings.as_ref() {
1094            refinements.push(extension_settings)
1095        }
1096
1097        if let Some(user_settings) = self.user_settings.as_ref() {
1098            refinements.push(&user_settings.content);
1099            if let Some(release_channel) = user_settings.for_release_channel() {
1100                refinements.push(release_channel)
1101            }
1102            if let Some(os) = user_settings.for_os() {
1103                refinements.push(os)
1104            }
1105            if let Some(profile) = user_settings.for_profile(cx) {
1106                refinements.push(profile)
1107            }
1108        }
1109
1110        if let Some(server_settings) = self.server_settings.as_ref() {
1111            refinements.push(server_settings)
1112        }
1113        let default = self.default_settings.as_ref().unwrap();
1114
1115        for setting_value in self.setting_values.values_mut() {
1116            // If the global settings file changed, reload the global value for the field.
1117            if changed_local_path.is_none() {
1118                let mut value = setting_value.from_file(&default).unwrap();
1119                setting_value.refine(&mut value, &refinements);
1120                setting_value.set_global_value(value);
1121            }
1122
1123            // Reload the local values for the setting.
1124            paths_stack.clear();
1125            project_settings_stack.clear();
1126            for ((root_id, directory_path), local_settings) in &self.local_settings {
1127                // Build a stack of all of the local values for that setting.
1128                while let Some(prev_entry) = paths_stack.last() {
1129                    if let Some((prev_root_id, prev_path)) = prev_entry
1130                        && (root_id != prev_root_id || !directory_path.starts_with(prev_path))
1131                    {
1132                        paths_stack.pop();
1133                        project_settings_stack.pop();
1134                        continue;
1135                    }
1136                    break;
1137                }
1138
1139                // NOTE: this kind of condition existing in the old code too,
1140                // but is there a problem when a setting is removed from a file?
1141                if setting_value.from_file(local_settings).is_some() {
1142                    paths_stack.push(Some((*root_id, directory_path.as_ref())));
1143                    project_settings_stack.push(local_settings);
1144
1145                    // If a local settings file changed, then avoid recomputing local
1146                    // settings for any path outside of that directory.
1147                    if changed_local_path.is_some_and(|(changed_root_id, changed_local_path)| {
1148                        *root_id != changed_root_id
1149                            || !directory_path.starts_with(changed_local_path)
1150                    }) {
1151                        continue;
1152                    }
1153
1154                    let mut value = setting_value.from_file(&default).unwrap();
1155                    setting_value.refine(&mut value, &refinements);
1156                    setting_value.refine(&mut value, &project_settings_stack);
1157                    setting_value.set_local_value(*root_id, directory_path.clone(), value);
1158                }
1159            }
1160        }
1161        Ok(())
1162    }
1163
1164    pub fn editorconfig_properties(
1165        &self,
1166        for_worktree: WorktreeId,
1167        for_path: &Path,
1168    ) -> Option<EditorconfigProperties> {
1169        let mut properties = EditorconfigProperties::new();
1170
1171        for (directory_with_config, _, parsed_editorconfig) in
1172            self.local_editorconfig_settings(for_worktree)
1173        {
1174            if !for_path.starts_with(&directory_with_config) {
1175                properties.use_fallbacks();
1176                return Some(properties);
1177            }
1178            let parsed_editorconfig = parsed_editorconfig?;
1179            if parsed_editorconfig.is_root {
1180                properties = EditorconfigProperties::new();
1181            }
1182            for section in parsed_editorconfig.sections {
1183                section.apply_to(&mut properties, for_path).log_err()?;
1184            }
1185        }
1186
1187        properties.use_fallbacks();
1188        Some(properties)
1189    }
1190}
1191
1192#[derive(Debug, Clone, PartialEq)]
1193pub enum InvalidSettingsError {
1194    LocalSettings { path: PathBuf, message: String },
1195    UserSettings { message: String },
1196    ServerSettings { message: String },
1197    DefaultSettings { message: String },
1198    Editorconfig { path: PathBuf, message: String },
1199    Tasks { path: PathBuf, message: String },
1200    Debug { path: PathBuf, message: String },
1201}
1202
1203impl std::fmt::Display for InvalidSettingsError {
1204    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1205        match self {
1206            InvalidSettingsError::LocalSettings { message, .. }
1207            | InvalidSettingsError::UserSettings { message }
1208            | InvalidSettingsError::ServerSettings { message }
1209            | InvalidSettingsError::DefaultSettings { message }
1210            | InvalidSettingsError::Tasks { message, .. }
1211            | InvalidSettingsError::Editorconfig { message, .. }
1212            | InvalidSettingsError::Debug { message, .. } => {
1213                write!(f, "{message}")
1214            }
1215        }
1216    }
1217}
1218impl std::error::Error for InvalidSettingsError {}
1219
1220impl Debug for SettingsStore {
1221    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1222        f.debug_struct("SettingsStore")
1223            .field(
1224                "types",
1225                &self
1226                    .setting_values
1227                    .values()
1228                    .map(|value| value.setting_type_name())
1229                    .collect::<Vec<_>>(),
1230            )
1231            .field("default_settings", &self.default_settings)
1232            .field("user_settings", &self.user_settings)
1233            .field("local_settings", &self.local_settings)
1234            .finish_non_exhaustive()
1235    }
1236}
1237
1238impl<T: Settings> AnySettingValue for SettingValue<T> {
1239    fn from_file(&self, s: &SettingsContent) -> Option<Box<dyn Any>> {
1240        T::from_file(s).map(|result| Box::new(result) as _)
1241    }
1242
1243    fn refine(&self, value: &mut dyn Any, refinements: &[&SettingsContent]) {
1244        let value = value.downcast_mut::<T>().unwrap();
1245        for refinement in refinements {
1246            value.refine(refinement)
1247        }
1248    }
1249
1250    fn setting_type_name(&self) -> &'static str {
1251        type_name::<T>()
1252    }
1253
1254    fn all_local_values(&self) -> Vec<(WorktreeId, Arc<Path>, &dyn Any)> {
1255        self.local_values
1256            .iter()
1257            .map(|(id, path, value)| (*id, path.clone(), value as _))
1258            .collect()
1259    }
1260
1261    fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any {
1262        if let Some(SettingsLocation { worktree_id, path }) = path {
1263            for (settings_root_id, settings_path, value) in self.local_values.iter().rev() {
1264                if worktree_id == *settings_root_id && path.starts_with(settings_path) {
1265                    return value;
1266                }
1267            }
1268        }
1269
1270        self.global_value
1271            .as_ref()
1272            .unwrap_or_else(|| panic!("no default value for setting {}", self.setting_type_name()))
1273    }
1274
1275    fn set_global_value(&mut self, value: Box<dyn Any>) {
1276        self.global_value = Some(*value.downcast().unwrap());
1277    }
1278
1279    fn set_local_value(&mut self, root_id: WorktreeId, path: Arc<Path>, value: Box<dyn Any>) {
1280        let value = *value.downcast().unwrap();
1281        match self
1282            .local_values
1283            .binary_search_by_key(&(root_id, &path), |e| (e.0, &e.1))
1284        {
1285            Ok(ix) => self.local_values[ix].2 = value,
1286            Err(ix) => self.local_values.insert(ix, (root_id, path, value)),
1287        }
1288    }
1289
1290    fn json_schema(&self, generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
1291        todo!()
1292        // T::FileContent::json_schema(generator)
1293    }
1294
1295    fn edits_for_update(
1296        &self,
1297        raw_settings: &serde_json::Value,
1298        tab_size: usize,
1299        vscode_settings: &VsCodeSettings,
1300        text: &mut String,
1301        edits: &mut Vec<(Range<usize>, String)>,
1302    ) {
1303        todo!()
1304        // let (key, deserialized_setting) = self.deserialize_setting_with_key(raw_settings);
1305        // let old_content = match deserialized_setting {
1306        //     Ok(content) => content.0.downcast::<T::FileContent>().unwrap(),
1307        //     Err(_) => Box::<<T as Settings>::FileContent>::default(),
1308        // };
1309        // let mut new_content = old_content.clone();
1310        // T::import_from_vscode(vscode_settings, &mut new_content);
1311
1312        // let old_value = serde_json::to_value(&old_content).unwrap();
1313        // let new_value = serde_json::to_value(new_content).unwrap();
1314
1315        // let mut key_path = Vec::new();
1316        // if let Some(key) = key {
1317        //     key_path.push(key);
1318        // }
1319
1320        // update_value_in_json_text(
1321        //     text,
1322        //     &mut key_path,
1323        //     tab_size,
1324        //     &old_value,
1325        //     &new_value,
1326        //     T::PRESERVED_KEYS.unwrap_or_default(),
1327        //     edits,
1328        // );
1329    }
1330
1331    fn settings_ui_item(&self) -> SettingsUiEntry {
1332        todo!()
1333        // <<T as Settings>::FileContent as SettingsUi>::settings_ui_entry()
1334    }
1335}
1336
1337#[cfg(test)]
1338mod tests {
1339    use crate::{VsCodeSettingsSource, settings_content::LanguageSettingsContent};
1340
1341    use super::*;
1342    // This is so the SettingsUi macro can still work properly
1343    use crate as settings;
1344    use serde::Deserialize;
1345    use settings_ui_macros::{SettingsKey, SettingsUi};
1346    use unindent::Unindent;
1347
1348    // #[gpui::test]
1349    // fn test_settings_store_basic(cx: &mut App) {
1350    //     let mut store = SettingsStore::new(cx);
1351    //     store.register_setting::<UserSettings>(cx);
1352    //     store.register_setting::<TurboSetting>(cx);
1353    //     store.register_setting::<MultiKeySettings>(cx);
1354    //     store
1355    //         .set_default_settings(
1356    //             r#"{
1357    //                 "turbo": false,
1358    //                 "user": {
1359    //                     "name": "John Doe",
1360    //                     "age": 30,
1361    //                     "staff": false
1362    //                 }
1363    //             }"#,
1364    //             cx,
1365    //         )
1366    //         .unwrap();
1367
1368    //     assert_eq!(store.get::<TurboSetting>(None), &TurboSetting(false));
1369    //     assert_eq!(
1370    //         store.get::<UserSettings>(None),
1371    //         &UserSettings {
1372    //             name: "John Doe".to_string(),
1373    //             age: 30,
1374    //             staff: false,
1375    //         }
1376    //     );
1377    //     assert_eq!(
1378    //         store.get::<MultiKeySettings>(None),
1379    //         &MultiKeySettings {
1380    //             key1: String::new(),
1381    //             key2: String::new(),
1382    //         }
1383    //     );
1384
1385    //     store
1386    //         .set_user_settings(
1387    //             r#"{
1388    //                 "turbo": true,
1389    //                 "user": { "age": 31 },
1390    //                 "key1": "a"
1391    //             }"#,
1392    //             cx,
1393    //         )
1394    //         .unwrap();
1395
1396    //     assert_eq!(store.get::<TurboSetting>(None), &TurboSetting(true));
1397    //     assert_eq!(
1398    //         store.get::<UserSettings>(None),
1399    //         &UserSettings {
1400    //             name: "John Doe".to_string(),
1401    //             age: 31,
1402    //             staff: false
1403    //         }
1404    //     );
1405
1406    //     store
1407    //         .set_local_settings(
1408    //             WorktreeId::from_usize(1),
1409    //             Path::new("/root1").into(),
1410    //             LocalSettingsKind::Settings,
1411    //             Some(r#"{ "user": { "staff": true } }"#),
1412    //             cx,
1413    //         )
1414    //         .unwrap();
1415    //     store
1416    //         .set_local_settings(
1417    //             WorktreeId::from_usize(1),
1418    //             Path::new("/root1/subdir").into(),
1419    //             LocalSettingsKind::Settings,
1420    //             Some(r#"{ "user": { "name": "Jane Doe" } }"#),
1421    //             cx,
1422    //         )
1423    //         .unwrap();
1424
1425    //     store
1426    //         .set_local_settings(
1427    //             WorktreeId::from_usize(1),
1428    //             Path::new("/root2").into(),
1429    //             LocalSettingsKind::Settings,
1430    //             Some(r#"{ "user": { "age": 42 }, "key2": "b" }"#),
1431    //             cx,
1432    //         )
1433    //         .unwrap();
1434
1435    //     assert_eq!(
1436    //         store.get::<UserSettings>(Some(SettingsLocation {
1437    //             worktree_id: WorktreeId::from_usize(1),
1438    //             path: Path::new("/root1/something"),
1439    //         })),
1440    //         &UserSettings {
1441    //             name: "John Doe".to_string(),
1442    //             age: 31,
1443    //             staff: true
1444    //         }
1445    //     );
1446    //     assert_eq!(
1447    //         store.get::<UserSettings>(Some(SettingsLocation {
1448    //             worktree_id: WorktreeId::from_usize(1),
1449    //             path: Path::new("/root1/subdir/something")
1450    //         })),
1451    //         &UserSettings {
1452    //             name: "Jane Doe".to_string(),
1453    //             age: 31,
1454    //             staff: true
1455    //         }
1456    //     );
1457    //     assert_eq!(
1458    //         store.get::<UserSettings>(Some(SettingsLocation {
1459    //             worktree_id: WorktreeId::from_usize(1),
1460    //             path: Path::new("/root2/something")
1461    //         })),
1462    //         &UserSettings {
1463    //             name: "John Doe".to_string(),
1464    //             age: 42,
1465    //             staff: false
1466    //         }
1467    //     );
1468    //     assert_eq!(
1469    //         store.get::<MultiKeySettings>(Some(SettingsLocation {
1470    //             worktree_id: WorktreeId::from_usize(1),
1471    //             path: Path::new("/root2/something")
1472    //         })),
1473    //         &MultiKeySettings {
1474    //             key1: "a".to_string(),
1475    //             key2: "b".to_string(),
1476    //         }
1477    //     );
1478    // }
1479
1480    // #[gpui::test]
1481    // fn test_setting_store_assign_json_before_register(cx: &mut App) {
1482    //     let mut store = SettingsStore::new(cx);
1483    //     store
1484    //         .set_default_settings(
1485    //             r#"{
1486    //                 "turbo": true,
1487    //                 "user": {
1488    //                     "name": "John Doe",
1489    //                     "age": 30,
1490    //                     "staff": false
1491    //                 },
1492    //                 "key1": "x"
1493    //             }"#,
1494    //             cx,
1495    //         )
1496    //         .unwrap();
1497    //     store
1498    //         .set_user_settings(r#"{ "turbo": false }"#, cx)
1499    //         .unwrap();
1500    //     store.register_setting::<UserSettings>(cx);
1501    //     store.register_setting::<TurboSetting>(cx);
1502
1503    //     assert_eq!(store.get::<TurboSetting>(None), &TurboSetting(false));
1504    //     assert_eq!(
1505    //         store.get::<UserSettings>(None),
1506    //         &UserSettings {
1507    //             name: "John Doe".to_string(),
1508    //             age: 30,
1509    //             staff: false,
1510    //         }
1511    //     );
1512
1513    //     store.register_setting::<MultiKeySettings>(cx);
1514    //     assert_eq!(
1515    //         store.get::<MultiKeySettings>(None),
1516    //         &MultiKeySettings {
1517    //             key1: "x".into(),
1518    //             key2: String::new(),
1519    //         }
1520    //     );
1521    // }
1522
1523    fn check_settings_update(
1524        store: &mut SettingsStore,
1525        old_json: String,
1526        update: fn(&mut SettingsContent),
1527        expected_new_json: String,
1528        cx: &mut App,
1529    ) {
1530        store.set_user_settings(&old_json, cx).ok();
1531        let edits = store.edits_for_update(&old_json, update);
1532        let mut new_json = old_json;
1533        for (range, replacement) in edits.into_iter() {
1534            new_json.replace_range(range, &replacement);
1535        }
1536        pretty_assertions::assert_eq!(new_json, expected_new_json);
1537    }
1538
1539    #[gpui::test]
1540    fn test_setting_store_update(cx: &mut App) {
1541        let mut store = SettingsStore::new(cx);
1542        // store.register_setting::<MultiKeySettings>(cx);
1543        // store.register_setting::<UserSettings>(cx);
1544        // store.register_setting::<LanguageSettings>(cx);
1545
1546        // entries added and updated
1547        check_settings_update(
1548            &mut store,
1549            r#"{
1550                "languages": {
1551                    "JSON": {
1552                        "auto_indent": true
1553                    }
1554                }
1555            }"#
1556            .unindent(),
1557            |settings| {
1558                settings
1559                    .languages_mut()
1560                    .get_mut("JSON")
1561                    .unwrap()
1562                    .auto_indent = Some(false);
1563
1564                settings.languages_mut().insert(
1565                    "Rust".into(),
1566                    LanguageSettingsContent {
1567                        auto_indent: Some(true),
1568                        ..Default::default()
1569                    },
1570                );
1571            },
1572            r#"{
1573                "languages": {
1574                    "Rust": {
1575                        "auto_indent": true
1576                    },
1577                    "JSON": {
1578                        "auto_indent": false
1579                    }
1580                }
1581            }"#
1582            .unindent(),
1583            cx,
1584        );
1585
1586        // entries removed
1587        check_settings_update(
1588            &mut store,
1589            r#"{
1590                "languages": {
1591                    "Rust": {
1592                        "language_setting_2": true
1593                    },
1594                    "JSON": {
1595                        "language_setting_1": false
1596                    }
1597                }
1598            }"#
1599            .unindent(),
1600            |settings| {
1601                settings.languages_mut().remove("JSON").unwrap();
1602            },
1603            r#"{
1604                "languages": {
1605                    "Rust": {
1606                        "language_setting_2": true
1607                    }
1608                }
1609            }"#
1610            .unindent(),
1611            cx,
1612        );
1613
1614        check_settings_update(
1615            &mut store,
1616            r#"{
1617                "languages": {
1618                    "Rust": {
1619                        "language_setting_2": true
1620                    },
1621                    "JSON": {
1622                        "language_setting_1": false
1623                    }
1624                }
1625            }"#
1626            .unindent(),
1627            |settings| {
1628                settings.languages_mut().remove("Rust").unwrap();
1629            },
1630            r#"{
1631                "languages": {
1632                    "JSON": {
1633                        "language_setting_1": false
1634                    }
1635                }
1636            }"#
1637            .unindent(),
1638            cx,
1639        );
1640
1641        // // weird formatting
1642        // check_settings_update(
1643        //     &mut store,
1644        //     r#"{
1645        //         "user":   { "age": 36, "name": "Max", "staff": true }
1646        //         }"#
1647        //     .unindent(),
1648        //     |settings| settings.age = Some(37),
1649        //     r#"{
1650        //         "user":   { "age": 37, "name": "Max", "staff": true }
1651        //         }"#
1652        //     .unindent(),
1653        //     cx,
1654        // );
1655
1656        // // single-line formatting, other keys
1657        // check_settings_update::<MultiKeySettings>(
1658        //     &mut store,
1659        //     r#"{ "one": 1, "two": 2 }"#.unindent(),
1660        //     |settings| settings.key1 = Some("x".into()),
1661        //     r#"{ "key1": "x", "one": 1, "two": 2 }"#.unindent(),
1662        //     cx,
1663        // );
1664
1665        // // empty object
1666        // check_settings_update::<UserSettings>(
1667        //     &mut store,
1668        //     r#"{
1669        //         "user": {}
1670        //     }"#
1671        //     .unindent(),
1672        //     |settings| settings.age = Some(37),
1673        //     r#"{
1674        //         "user": {
1675        //             "age": 37
1676        //         }
1677        //     }"#
1678        //     .unindent(),
1679        //     cx,
1680        // );
1681
1682        // // no content
1683        // check_settings_update::<UserSettings>(
1684        //     &mut store,
1685        //     r#""#.unindent(),
1686        //     |settings| settings.age = Some(37),
1687        //     r#"{
1688        //         "user": {
1689        //             "age": 37
1690        //         }
1691        //     }
1692        //     "#
1693        //     .unindent(),
1694        //     cx,
1695        // );
1696
1697        // check_settings_update::<UserSettings>(
1698        //     &mut store,
1699        //     r#"{
1700        //     }
1701        //     "#
1702        //     .unindent(),
1703        //     |settings| settings.age = Some(37),
1704        //     r#"{
1705        //         "user": {
1706        //             "age": 37
1707        //         }
1708        //     }
1709        //     "#
1710        //     .unindent(),
1711        //     cx,
1712        // );
1713    }
1714
1715    // #[gpui::test]
1716    // fn test_vscode_import(cx: &mut App) {
1717    //     let mut store = SettingsStore::new(cx);
1718    //     store.register_setting::<UserSettings>(cx);
1719    //     store.register_setting::<JournalSettings>(cx);
1720    //     store.register_setting::<LanguageSettings>(cx);
1721    //     store.register_setting::<MultiKeySettings>(cx);
1722
1723    //     // create settings that werent present
1724    //     check_vscode_import(
1725    //         &mut store,
1726    //         r#"{
1727    //         }
1728    //         "#
1729    //         .unindent(),
1730    //         r#" { "user.age": 37 } "#.to_owned(),
1731    //         r#"{
1732    //             "user": {
1733    //                 "age": 37
1734    //             }
1735    //         }
1736    //         "#
1737    //         .unindent(),
1738    //         cx,
1739    //     );
1740
1741    //     // persist settings that were present
1742    //     check_vscode_import(
1743    //         &mut store,
1744    //         r#"{
1745    //             "user": {
1746    //                 "staff": true,
1747    //                 "age": 37
1748    //             }
1749    //         }
1750    //         "#
1751    //         .unindent(),
1752    //         r#"{ "user.age": 42 }"#.to_owned(),
1753    //         r#"{
1754    //             "user": {
1755    //                 "staff": true,
1756    //                 "age": 42
1757    //             }
1758    //         }
1759    //         "#
1760    //         .unindent(),
1761    //         cx,
1762    //     );
1763
1764    //     // don't clobber settings that aren't present in vscode
1765    //     check_vscode_import(
1766    //         &mut store,
1767    //         r#"{
1768    //             "user": {
1769    //                 "staff": true,
1770    //                 "age": 37
1771    //             }
1772    //         }
1773    //         "#
1774    //         .unindent(),
1775    //         r#"{}"#.to_owned(),
1776    //         r#"{
1777    //             "user": {
1778    //                 "staff": true,
1779    //                 "age": 37
1780    //             }
1781    //         }
1782    //         "#
1783    //         .unindent(),
1784    //         cx,
1785    //     );
1786
1787    //     // custom enum
1788    //     check_vscode_import(
1789    //         &mut store,
1790    //         r#"{
1791    //             "journal": {
1792    //             "hour_format": "hour12"
1793    //             }
1794    //         }
1795    //         "#
1796    //         .unindent(),
1797    //         r#"{ "time_format": "24" }"#.to_owned(),
1798    //         r#"{
1799    //             "journal": {
1800    //             "hour_format": "hour24"
1801    //             }
1802    //         }
1803    //         "#
1804    //         .unindent(),
1805    //         cx,
1806    //     );
1807
1808    //     // Multiple keys for one setting
1809    //     check_vscode_import(
1810    //         &mut store,
1811    //         r#"{
1812    //             "key1": "value"
1813    //         }
1814    //         "#
1815    //         .unindent(),
1816    //         r#"{
1817    //             "key_1_first": "hello",
1818    //             "key_1_second": "world"
1819    //         }"#
1820    //         .to_owned(),
1821    //         r#"{
1822    //             "key1": "hello world"
1823    //         }
1824    //         "#
1825    //         .unindent(),
1826    //         cx,
1827    //     );
1828
1829    //     // Merging lists together entries added and updated
1830    //     check_vscode_import(
1831    //         &mut store,
1832    //         r#"{
1833    //             "languages": {
1834    //                 "JSON": {
1835    //                     "language_setting_1": true
1836    //                 },
1837    //                 "Rust": {
1838    //                     "language_setting_2": true
1839    //                 }
1840    //             }
1841    //         }"#
1842    //         .unindent(),
1843    //         r#"{
1844    //             "vscode_languages": [
1845    //                 {
1846    //                     "name": "JavaScript",
1847    //                     "language_setting_1": true
1848    //                 },
1849    //                 {
1850    //                     "name": "Rust",
1851    //                     "language_setting_2": false
1852    //                 }
1853    //             ]
1854    //         }"#
1855    //         .to_owned(),
1856    //         r#"{
1857    //             "languages": {
1858    //                 "JavaScript": {
1859    //                     "language_setting_1": true
1860    //                 },
1861    //                 "JSON": {
1862    //                     "language_setting_1": true
1863    //                 },
1864    //                 "Rust": {
1865    //                     "language_setting_2": false
1866    //                 }
1867    //             }
1868    //         }"#
1869    //         .unindent(),
1870    //         cx,
1871    //     );
1872    // }
1873
1874    // fn check_vscode_import(
1875    //     store: &mut SettingsStore,
1876    //     old: String,
1877    //     vscode: String,
1878    //     expected: String,
1879    //     cx: &mut App,
1880    // ) {
1881    //     store.set_user_settings(&old, cx).ok();
1882    //     let new = store.get_vscode_edits(
1883    //         old,
1884    //         &VsCodeSettings::from_str(&vscode, VsCodeSettingsSource::VsCode).unwrap(),
1885    //     );
1886    //     pretty_assertions::assert_eq!(new, expected);
1887    // }
1888
1889    // #[derive(Debug, PartialEq, Deserialize, SettingsUi)]
1890    // struct UserSettings {
1891    //     name: String,
1892    //     age: u32,
1893    //     staff: bool,
1894    // }
1895
1896    // #[derive(Default, Clone, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)]
1897    // #[settings_key(key = "user")]
1898    // struct UserSettingsContent {
1899    //     name: Option<String>,
1900    //     age: Option<u32>,
1901    //     staff: Option<bool>,
1902    // }
1903
1904    // impl Settings for UserSettings {
1905    //     type FileContent = UserSettingsContent;
1906
1907    //     fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
1908    //         sources.json_merge()
1909    //     }
1910
1911    //     fn import_from_vscode(vscode: &VsCodeSettings, current: &mut Self::FileContent) {
1912    //         vscode.u32_setting("user.age", &mut current.age);
1913    //     }
1914    // }
1915
1916    // #[derive(Debug, Deserialize, PartialEq)]
1917    // struct TurboSetting(bool);
1918
1919    // #[derive(
1920    //     Copy,
1921    //     Clone,
1922    //     PartialEq,
1923    //     Eq,
1924    //     Debug,
1925    //     Default,
1926    //     serde::Serialize,
1927    //     serde::Deserialize,
1928    //     SettingsUi,
1929    //     SettingsKey,
1930    //     JsonSchema,
1931    // )]
1932    // #[serde(default)]
1933    // #[settings_key(None)]
1934    // pub struct TurboSettingContent {
1935    //     turbo: Option<bool>,
1936    // }
1937
1938    // impl Settings for TurboSetting {
1939    //     type FileContent = TurboSettingContent;
1940
1941    //     fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
1942    //         Ok(Self(
1943    //             sources
1944    //                 .user
1945    //                 .or(sources.server)
1946    //                 .unwrap_or(sources.default)
1947    //                 .turbo
1948    //                 .unwrap_or_default(),
1949    //         ))
1950    //     }
1951
1952    //     fn import_from_vscode(_vscode: &VsCodeSettings, _current: &mut Self::FileContent) {}
1953    // }
1954
1955    // #[derive(Clone, Debug, PartialEq, Deserialize)]
1956    // struct MultiKeySettings {
1957    //     #[serde(default)]
1958    //     key1: String,
1959    //     #[serde(default)]
1960    //     key2: String,
1961    // }
1962
1963    // #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)]
1964    // #[settings_key(None)]
1965    // struct MultiKeySettingsJson {
1966    //     key1: Option<String>,
1967    //     key2: Option<String>,
1968    // }
1969
1970    // impl Settings for MultiKeySettings {
1971    //     type FileContent = MultiKeySettingsJson;
1972
1973    //     fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
1974    //         sources.json_merge()
1975    //     }
1976
1977    //     fn import_from_vscode(vscode: &VsCodeSettings, current: &mut Self::FileContent) {
1978    //         let first_value = vscode.read_string("key_1_first");
1979    //         let second_value = vscode.read_string("key_1_second");
1980
1981    //         if let Some((first, second)) = first_value.zip(second_value) {
1982    //             current.key1 = Some(format!("{} {}", first, second));
1983    //         }
1984    //     }
1985    // }
1986
1987    // #[derive(Debug, Deserialize)]
1988    // struct JournalSettings {
1989    //     #[expect(unused)]
1990    //     pub path: String,
1991    //     #[expect(unused)]
1992    //     pub hour_format: HourFormat,
1993    // }
1994
1995    // #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1996    // #[serde(rename_all = "snake_case")]
1997    // enum HourFormat {
1998    //     Hour12,
1999    //     Hour24,
2000    // }
2001
2002    // #[derive(
2003    //     Clone, Default, Debug, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey,
2004    // )]
2005    // #[settings_key(key = "journal")]
2006    // struct JournalSettingsJson {
2007    //     pub path: Option<String>,
2008    //     pub hour_format: Option<HourFormat>,
2009    // }
2010
2011    // impl Settings for JournalSettings {
2012    //     type FileContent = JournalSettingsJson;
2013
2014    //     fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
2015    //         sources.json_merge()
2016    //     }
2017
2018    //     fn import_from_vscode(vscode: &VsCodeSettings, current: &mut Self::FileContent) {
2019    //         vscode.enum_setting("time_format", &mut current.hour_format, |s| match s {
2020    //             "12" => Some(HourFormat::Hour12),
2021    //             "24" => Some(HourFormat::Hour24),
2022    //             _ => None,
2023    //         });
2024    //     }
2025    // }
2026
2027    // #[gpui::test]
2028    // fn test_global_settings(cx: &mut App) {
2029    //     let mut store = SettingsStore::new(cx);
2030    //     store.register_setting::<UserSettings>(cx);
2031    //     store
2032    //         .set_default_settings(
2033    //             r#"{
2034    //                 "user": {
2035    //                     "name": "John Doe",
2036    //                     "age": 30,
2037    //                     "staff": false
2038    //                 }
2039    //             }"#,
2040    //             cx,
2041    //         )
2042    //         .unwrap();
2043
2044    //     // Set global settings - these should override defaults but not user settings
2045    //     store
2046    //         .set_global_settings(
2047    //             r#"{
2048    //                 "user": {
2049    //                     "name": "Global User",
2050    //                     "age": 35,
2051    //                     "staff": true
2052    //                 }
2053    //             }"#,
2054    //             cx,
2055    //         )
2056    //         .unwrap();
2057
2058    //     // Before user settings, global settings should apply
2059    //     assert_eq!(
2060    //         store.get::<UserSettings>(None),
2061    //         &UserSettings {
2062    //             name: "Global User".to_string(),
2063    //             age: 35,
2064    //             staff: true,
2065    //         }
2066    //     );
2067
2068    //     // Set user settings - these should override both defaults and global
2069    //     store
2070    //         .set_user_settings(
2071    //             r#"{
2072    //                 "user": {
2073    //                     "age": 40
2074    //                 }
2075    //             }"#,
2076    //             cx,
2077    //         )
2078    //         .unwrap();
2079
2080    //     // User settings should override global settings
2081    //     assert_eq!(
2082    //         store.get::<UserSettings>(None),
2083    //         &UserSettings {
2084    //             name: "Global User".to_string(), // Name from global settings
2085    //             age: 40,                         // Age from user settings
2086    //             staff: true,                     // Staff from global settings
2087    //         }
2088    //     );
2089    // }
2090
2091    // #[derive(
2092    //     Clone, Debug, Default, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey,
2093    // )]
2094    // #[settings_key(None)]
2095    // struct LanguageSettings {
2096    //     #[serde(default)]
2097    //     languages: HashMap<String, LanguageSettingEntry>,
2098    // }
2099
2100    // #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
2101    // struct LanguageSettingEntry {
2102    //     language_setting_1: Option<bool>,
2103    //     language_setting_2: Option<bool>,
2104    // }
2105
2106    // impl Settings for LanguageSettings {
2107    //     type FileContent = Self;
2108
2109    //     fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
2110    //         sources.json_merge()
2111    //     }
2112
2113    //     fn import_from_vscode(vscode: &VsCodeSettings, current: &mut Self::FileContent) {
2114    //         current.languages.extend(
2115    //             vscode
2116    //                 .read_value("vscode_languages")
2117    //                 .and_then(|value| value.as_array())
2118    //                 .map(|languages| {
2119    //                     languages
2120    //                         .iter()
2121    //                         .filter_map(|value| value.as_object())
2122    //                         .filter_map(|item| {
2123    //                             let mut rest = item.clone();
2124    //                             let name = rest.remove("name")?.as_str()?.to_string();
2125    //                             let entry = serde_json::from_value::<LanguageSettingEntry>(
2126    //                                 serde_json::Value::Object(rest),
2127    //                             )
2128    //                             .ok()?;
2129
2130    //                             Some((name, entry))
2131    //                         })
2132    //                 })
2133    //                 .into_iter()
2134    //                 .flatten(),
2135    //         );
2136    //     }
2137    // }
2138}