From 1761e603629b5b98ff5636f69fa18357f47f6dcd Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 26 Jan 2024 19:54:45 +0100 Subject: [PATCH] Improve performance of JSON schema creation (#6770) JSON LSP adapter now caches the schema. `workspace_configuration` is back to being async, and we are also no longer asking for font names twice while constructing the schema. Release Notes: - Improved performance when opening the .json files. --------- Co-authored-by: Kirill --- crates/language/src/language.rs | 2 +- crates/project/src/project.rs | 7 +- crates/settings/src/settings_store.rs | 1 + crates/terminal/src/terminal_settings.rs | 12 ++-- crates/theme/src/settings.rs | 8 +-- crates/zed/src/languages/json.rs | 87 +++++++++++++----------- 6 files changed, 63 insertions(+), 54 deletions(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index ca4a559617..5b860a9de6 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -342,7 +342,7 @@ pub trait LspAdapter: 'static + Send + Sync { None } - fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> Value { + fn workspace_configuration(&self, _workspace_root: &Path, _cx: &mut AppContext) -> Value { serde_json::json!({}) } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 9476463e33..4f7fe8302a 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2714,13 +2714,12 @@ impl Project { })?; for (adapter, server) in servers { - let workspace_config = + let settings = cx.update(|cx| adapter.workspace_configuration(server.root_path(), cx))?; + server .notify::( - lsp::DidChangeConfigurationParams { - settings: workspace_config.clone(), - }, + lsp::DidChangeConfigurationParams { settings }, ) .ok(); } diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index c55ec5a686..78bfefd4fa 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -114,6 +114,7 @@ pub trait Settings: 'static + Send + Sync { pub struct SettingsJsonSchemaParams<'a> { pub staff_mode: bool, pub language_names: &'a [String], + pub font_names: &'a [String], } /// A set of strongly-typed setting values defined via multiple JSON files. diff --git a/crates/terminal/src/terminal_settings.rs b/crates/terminal/src/terminal_settings.rs index 7fcbcf9541..4ea0f3afcb 100644 --- a/crates/terminal/src/terminal_settings.rs +++ b/crates/terminal/src/terminal_settings.rs @@ -161,14 +161,14 @@ impl settings::Settings for TerminalSettings { } fn json_schema( generator: &mut SchemaGenerator, - _: &SettingsJsonSchemaParams, - cx: &AppContext, + params: &SettingsJsonSchemaParams, + _: &AppContext, ) -> RootSchema { let mut root_schema = generator.root_schema_for::(); - let available_fonts = cx - .text_system() - .all_font_names() - .into_iter() + let available_fonts = params + .font_names + .iter() + .cloned() .map(Value::String) .collect(); let fonts_schema = SchemaObject { diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index 0a3c3fd168..39e24daaa2 100644 --- a/crates/theme/src/settings.rs +++ b/crates/theme/src/settings.rs @@ -242,10 +242,10 @@ impl settings::Settings for ThemeSettings { ..Default::default() }; - let available_fonts = cx - .text_system() - .all_font_names() - .into_iter() + let available_fonts = params + .font_names + .iter() + .cloned() .map(Value::String) .collect(); let fonts_schema = SchemaObject { diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index b90459cc25..1b3667fca4 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -7,14 +7,14 @@ use gpui::AppContext; use language::{LanguageRegistry, LanguageServerName, LspAdapter, LspAdapterDelegate}; use lsp::LanguageServerBinary; use node_runtime::NodeRuntime; -use serde_json::json; +use serde_json::{json, Value}; use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore}; use smol::fs; use std::{ any::Any, ffi::OsString, path::{Path, PathBuf}, - sync::Arc, + sync::{Arc, OnceLock}, }; use util::{paths, ResultExt}; @@ -28,11 +28,52 @@ fn server_binary_arguments(server_path: &Path) -> Vec { pub struct JsonLspAdapter { node: Arc, languages: Arc, + workspace_config: OnceLock, } impl JsonLspAdapter { pub fn new(node: Arc, languages: Arc) -> Self { - JsonLspAdapter { node, languages } + Self { + node, + languages, + workspace_config: Default::default(), + } + } + + fn get_workspace_config(language_names: Vec, cx: &mut AppContext) -> Value { + let action_names = cx.all_action_names(); + let staff_mode = cx.is_staff(); + + let font_names = &cx.text_system().all_font_names(); + let settings_schema = cx.global::().json_schema( + &SettingsJsonSchemaParams { + language_names: &language_names, + staff_mode, + font_names, + }, + cx, + ); + + serde_json::json!({ + "json": { + "format": { + "enable": true, + }, + "schemas": [ + { + "fileMatch": [ + schema_file_match(&paths::SETTINGS), + &*paths::LOCAL_SETTINGS_RELATIVE_PATH, + ], + "schema": settings_schema, + }, + { + "fileMatch": [schema_file_match(&paths::KEYMAP)], + "schema": KeymapFile::generate_json_schema(&action_names), + } + ] + } + }) } } @@ -102,42 +143,10 @@ impl LspAdapter for JsonLspAdapter { })) } - fn workspace_configuration( - &self, - _workspace_root: &Path, - cx: &mut AppContext, - ) -> serde_json::Value { - let action_names = cx.all_action_names(); - let staff_mode = cx.is_staff(); - let language_names = &self.languages.language_names(); - let settings_schema = cx.global::().json_schema( - &SettingsJsonSchemaParams { - language_names, - staff_mode, - }, - cx, - ); - - serde_json::json!({ - "json": { - "format": { - "enable": true, - }, - "schemas": [ - { - "fileMatch": [ - schema_file_match(&paths::SETTINGS), - &*paths::LOCAL_SETTINGS_RELATIVE_PATH, - ], - "schema": settings_schema, - }, - { - "fileMatch": [schema_file_match(&paths::KEYMAP)], - "schema": KeymapFile::generate_json_schema(&action_names), - } - ] - } - }) + fn workspace_configuration(&self, _workspace_root: &Path, cx: &mut AppContext) -> Value { + self.workspace_config + .get_or_init(|| Self::get_workspace_config(self.languages.language_names(), cx)) + .clone() } fn language_ids(&self) -> HashMap {