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
}
fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> Value {
fn workspace_configuration(&self, _workspace_root: &Path, _cx: &mut AppContext) -> Value {
serde_json::json!({})
}

View file

@ -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::notification::DidChangeConfiguration>(
lsp::DidChangeConfigurationParams {
settings: workspace_config.clone(),
},
lsp::DidChangeConfigurationParams { settings },
)
.ok();
}

View file

@ -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.

View file

@ -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::<Self::FileContent>();
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 {

View file

@ -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 {

View file

@ -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<OsString> {
pub struct JsonLspAdapter {
node: Arc<dyn NodeRuntime>,
languages: Arc<LanguageRegistry>,
workspace_config: OnceLock<Value>,
}
impl JsonLspAdapter {
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(
&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::<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 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<String, String> {