diff --git a/Cargo.toml b/Cargo.toml index 59f8e265694f060c9f65b30143b79e324de1f08c..38bca7089ea1cb73b18541351279180c8d4f6517 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -906,6 +906,7 @@ wasmtime = { opt-level = 3 } cranelift-codegen = { opt-level = 3 } wasmtime-environ = { opt-level = 3 } wasmtime-internal-cranelift = { opt-level = 3 } +serde_json = { opt-level = 3 } # Build single-source-file crates with cg=1 as it helps make `cargo build` of a whole workspace a bit faster activity_indicator = { codegen-units = 1 } assets = { codegen-units = 1 } diff --git a/crates/collab/tests/integration/test_server.rs b/crates/collab/tests/integration/test_server.rs index f077f5f35cb6110b4cf4ec927f2cf572bea27b06..2e24115b21c9e068aa4219542d87634a8c30c709 100644 --- a/crates/collab/tests/integration/test_server.rs +++ b/crates/collab/tests/integration/test_server.rs @@ -173,7 +173,6 @@ impl TestServer { } let settings = SettingsStore::test(cx); cx.set_global(settings); - theme_settings::init(theme::LoadThemes::JustBase, cx); release_channel::init(semver::Version::new(0, 0, 0), cx); }); @@ -352,9 +351,7 @@ impl TestServer { collab_ui::init(&app_state, cx); file_finder::init(cx); menu::init(); - cx.bind_keys( - settings::KeymapFile::load_asset_allow_partial_failure(os_keymap, cx).unwrap(), - ); + cx.bind_keys(settings::KeymapFile::load_asset_cached(os_keymap, cx).unwrap()); language_model::LanguageModelRegistry::test(cx); }); diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index f4529e305a4428b1ab9ead8671542108b963216b..cc750e00ed19be8c178c3fba40d3f3748067f944 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -220,6 +220,27 @@ impl KeymapFile { } } + #[cfg(any(test, feature = "test-support"))] + pub fn load_asset_cached(asset_path: &str, cx: &App) -> anyhow::Result> { + static CACHED: std::sync::OnceLock = std::sync::OnceLock::new(); + let keymap = CACHED + .get_or_init(|| Self::parse(asset_str::(asset_path).as_ref()).unwrap()); + match keymap.load_keymap(cx) { + KeymapFileLoadResult::SomeFailedToLoad { + key_bindings, + error_message, + .. + } if key_bindings.is_empty() => { + anyhow::bail!("Error loading built-in keymap \"{asset_path}\": {error_message}") + } + KeymapFileLoadResult::Success { key_bindings, .. } + | KeymapFileLoadResult::SomeFailedToLoad { key_bindings, .. } => Ok(key_bindings), + KeymapFileLoadResult::JsonParseFailure { error } => { + anyhow::bail!("JSON parse error in built-in keymap \"{asset_path}\": {error}") + } + } + } + #[cfg(feature = "test-support")] pub fn load_panic_on_failure(content: &str, cx: &App) -> Vec { match Self::load(content, cx) { @@ -240,7 +261,10 @@ impl KeymapFile { return KeymapFileLoadResult::JsonParseFailure { error }; } }; + keymap_file.load_keymap(cx) + } + pub fn load_keymap(&self, cx: &App) -> KeymapFileLoadResult { // Accumulate errors in order to support partial load of user keymap in the presence of // errors in context and binding parsing. let mut errors = Vec::new(); @@ -252,7 +276,7 @@ impl KeymapFile { unbind, bindings, unrecognized_fields, - } in keymap_file.0.iter() + } in self.0.iter() { let context_predicate: Option> = if context.is_empty() { None diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index 87ab85aae595faf9a69c45b77d98ea1230ea5162..20fa4381d4ec27d857d69ad52c1b3763f9700c8c 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -89,42 +89,46 @@ pub fn visual_test_settings() -> String { } #[cfg(any(test, feature = "test-support"))] -pub fn test_settings() -> String { - let mut value = - crate::parse_json_with_comments::(crate::default_settings().as_ref()) - .unwrap(); - #[cfg(not(target_os = "windows"))] - util::merge_non_null_json_value_into( - serde_json::json!({ - "ui_font_family": "Courier", - "ui_font_features": {}, - "ui_font_size": 14, - "ui_font_fallback": [], - "buffer_font_family": "Courier", - "buffer_font_features": {}, - "buffer_font_size": 14, - "buffer_font_fallbacks": [], - "theme": EMPTY_THEME_NAME, - }), - &mut value, - ); - #[cfg(target_os = "windows")] - util::merge_non_null_json_value_into( - serde_json::json!({ - "ui_font_family": "Courier New", - "ui_font_features": {}, - "ui_font_size": 14, - "ui_font_fallback": [], - "buffer_font_family": "Courier New", - "buffer_font_features": {}, - "buffer_font_size": 14, - "buffer_font_fallbacks": [], - "theme": EMPTY_THEME_NAME, - }), - &mut value, - ); - value.as_object_mut().unwrap().remove("languages"); - serde_json::to_string(&value).unwrap() +pub fn test_settings() -> &'static str { + static CACHED: std::sync::LazyLock = std::sync::LazyLock::new(|| { + let mut value = crate::parse_json_with_comments::( + crate::default_settings().as_ref(), + ) + .unwrap(); + #[cfg(not(target_os = "windows"))] + util::merge_non_null_json_value_into( + serde_json::json!({ + "ui_font_family": "Courier", + "ui_font_features": {}, + "ui_font_size": 14, + "ui_font_fallback": [], + "buffer_font_family": "Courier", + "buffer_font_features": {}, + "buffer_font_size": 14, + "buffer_font_fallbacks": [], + "theme": EMPTY_THEME_NAME, + }), + &mut value, + ); + #[cfg(target_os = "windows")] + util::merge_non_null_json_value_into( + serde_json::json!({ + "ui_font_family": "Courier New", + "ui_font_features": {}, + "ui_font_size": 14, + "ui_font_fallback": [], + "buffer_font_family": "Courier New", + "buffer_font_features": {}, + "buffer_font_size": 14, + "buffer_font_fallbacks": [], + "theme": EMPTY_THEME_NAME, + }), + &mut value, + ); + value.as_object_mut().unwrap().remove("languages"); + serde_json::to_string(&value).unwrap() + }); + &CACHED } pub fn watch_config_file( diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 6e37c22afe0087c54c5574e17275218d8468ae05..558f13366323da71054289edd733682f1529dac6 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -284,9 +284,13 @@ impl SettingsStore { } pub fn new_with_semantic_tokens(cx: &mut App, default_settings: &str) -> Self { - let (setting_file_updates_tx, mut setting_file_updates_rx) = mpsc::unbounded(); let default_settings: SettingsContent = SettingsContent::parse_json_with_comments(default_settings).unwrap(); + Self::from_settings_content(cx, default_settings) + } + + fn from_settings_content(cx: &mut App, default_settings: SettingsContent) -> Self { + let (setting_file_updates_tx, mut setting_file_updates_rx) = mpsc::unbounded(); if !cx.has_global::() { cx.set_global::( crate::parse_json_with_comments::( @@ -447,7 +451,11 @@ impl SettingsStore { #[cfg(any(test, feature = "test-support"))] pub fn test(cx: &mut App) -> Self { - Self::new(cx, &crate::test_settings()) + static CACHED_SETTINGS_CONTENT: std::sync::LazyLock = + std::sync::LazyLock::new(|| { + SettingsContent::parse_json_with_comments(crate::test_settings()).unwrap() + }); + Self::from_settings_content(cx, CACHED_SETTINGS_CONTENT.clone()) } /// Updates the value of a setting in the user's global configuration.