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 <kirill@zed.dev>
This commit is contained in:
Piotr Osiewicz 2024-01-26 19:54:45 +01:00 committed by GitHub
parent 0a124a9908
commit 1761e60362
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 63 additions and 54 deletions

View file

@ -342,7 +342,7 @@ pub trait LspAdapter: 'static + Send + Sync {
None None
} }
fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> Value { fn workspace_configuration(&self, _workspace_root: &Path, _cx: &mut AppContext) -> Value {
serde_json::json!({}) serde_json::json!({})
} }

View file

@ -2714,13 +2714,12 @@ impl Project {
})?; })?;
for (adapter, server) in servers { for (adapter, server) in servers {
let workspace_config = let settings =
cx.update(|cx| adapter.workspace_configuration(server.root_path(), cx))?; cx.update(|cx| adapter.workspace_configuration(server.root_path(), cx))?;
server server
.notify::<lsp::notification::DidChangeConfiguration>( .notify::<lsp::notification::DidChangeConfiguration>(
lsp::DidChangeConfigurationParams { lsp::DidChangeConfigurationParams { settings },
settings: workspace_config.clone(),
},
) )
.ok(); .ok();
} }

View file

@ -114,6 +114,7 @@ pub trait Settings: 'static + Send + Sync {
pub struct SettingsJsonSchemaParams<'a> { pub struct SettingsJsonSchemaParams<'a> {
pub staff_mode: bool, pub staff_mode: bool,
pub language_names: &'a [String], pub language_names: &'a [String],
pub font_names: &'a [String],
} }
/// A set of strongly-typed setting values defined via multiple JSON files. /// A set of strongly-typed setting values defined via multiple JSON files.

View file

@ -161,14 +161,14 @@ impl settings::Settings for TerminalSettings {
} }
fn json_schema( fn json_schema(
generator: &mut SchemaGenerator, generator: &mut SchemaGenerator,
_: &SettingsJsonSchemaParams, params: &SettingsJsonSchemaParams,
cx: &AppContext, _: &AppContext,
) -> RootSchema { ) -> RootSchema {
let mut root_schema = generator.root_schema_for::<Self::FileContent>(); let mut root_schema = generator.root_schema_for::<Self::FileContent>();
let available_fonts = cx let available_fonts = params
.text_system() .font_names
.all_font_names() .iter()
.into_iter() .cloned()
.map(Value::String) .map(Value::String)
.collect(); .collect();
let fonts_schema = SchemaObject { let fonts_schema = SchemaObject {

View file

@ -242,10 +242,10 @@ impl settings::Settings for ThemeSettings {
..Default::default() ..Default::default()
}; };
let available_fonts = cx let available_fonts = params
.text_system() .font_names
.all_font_names() .iter()
.into_iter() .cloned()
.map(Value::String) .map(Value::String)
.collect(); .collect();
let fonts_schema = SchemaObject { let fonts_schema = SchemaObject {

View file

@ -7,14 +7,14 @@ use gpui::AppContext;
use language::{LanguageRegistry, LanguageServerName, LspAdapter, LspAdapterDelegate}; use language::{LanguageRegistry, LanguageServerName, LspAdapter, LspAdapterDelegate};
use lsp::LanguageServerBinary; use lsp::LanguageServerBinary;
use node_runtime::NodeRuntime; use node_runtime::NodeRuntime;
use serde_json::json; use serde_json::{json, Value};
use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore}; use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore};
use smol::fs; use smol::fs;
use std::{ use std::{
any::Any, any::Any,
ffi::OsString, ffi::OsString,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::{Arc, OnceLock},
}; };
use util::{paths, ResultExt}; use util::{paths, ResultExt};
@ -28,11 +28,52 @@ fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
pub struct JsonLspAdapter { pub struct JsonLspAdapter {
node: Arc<dyn NodeRuntime>, node: Arc<dyn NodeRuntime>,
languages: Arc<LanguageRegistry>, languages: Arc<LanguageRegistry>,
workspace_config: OnceLock<Value>,
} }
impl JsonLspAdapter { impl JsonLspAdapter {
pub fn new(node: Arc<dyn NodeRuntime>, languages: Arc<LanguageRegistry>) -> Self { pub fn new(node: Arc<dyn NodeRuntime>, languages: Arc<LanguageRegistry>) -> Self {
JsonLspAdapter { node, languages } Self {
node,
languages,
workspace_config: Default::default(),
}
}
fn get_workspace_config(language_names: Vec<String>, 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::<SettingsStore>().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( fn workspace_configuration(&self, _workspace_root: &Path, cx: &mut AppContext) -> Value {
&self, self.workspace_config
_workspace_root: &Path, .get_or_init(|| Self::get_workspace_config(self.languages.language_names(), cx))
cx: &mut AppContext, .clone()
) -> 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::<SettingsStore>().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 language_ids(&self) -> HashMap<String, String> { fn language_ids(&self) -> HashMap<String, String> {