Add test that JSON schema generation works + actions build from no input (#23049)

Release Notes:

- N/A
This commit is contained in:
Michael Sloan 2025-01-13 13:42:08 -07:00 committed by GitHub
parent 85b727c1a2
commit b633f62aa6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 81 additions and 16 deletions

1
Cargo.lock generated
View file

@ -6819,7 +6819,6 @@ dependencies = [
"regex", "regex",
"rope", "rope",
"rust-embed", "rust-embed",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
"settings", "settings",

View file

@ -56,7 +56,6 @@ project.workspace = true
regex.workspace = true regex.workspace = true
rope.workspace = true rope.workspace = true
rust-embed.workspace = true rust-embed.workspace = true
schemars.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
settings.workspace = true settings.workspace = true

View file

@ -10,7 +10,6 @@ use language::{LanguageRegistry, LanguageToolchainStore, LspAdapter, LspAdapterD
use lsp::{LanguageServerBinary, LanguageServerName}; use lsp::{LanguageServerBinary, LanguageServerName};
use node_runtime::NodeRuntime; use node_runtime::NodeRuntime;
use project::{lsp_store::language_server_settings, ContextProviderWithTasks}; use project::{lsp_store::language_server_settings, ContextProviderWithTasks};
use schemars::gen::SchemaSettings;
use serde_json::{json, Value}; use serde_json::{json, Value};
use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore}; use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore};
use smol::{ use smol::{
@ -76,6 +75,7 @@ impl JsonLspAdapter {
} }
fn get_workspace_config(language_names: Vec<String>, cx: &mut AppContext) -> Value { fn get_workspace_config(language_names: Vec<String>, cx: &mut AppContext) -> Value {
let keymap_schema = KeymapFile::generate_json_schema_for_registered_actions(cx);
let font_names = &cx.text_system().all_font_names(); let font_names = &cx.text_system().all_font_names();
let settings_schema = cx.global::<SettingsStore>().json_schema( let settings_schema = cx.global::<SettingsStore>().json_schema(
&SettingsJsonSchemaParams { &SettingsJsonSchemaParams {
@ -115,7 +115,7 @@ impl JsonLspAdapter {
}, },
{ {
"fileMatch": [schema_file_match(paths::keymap_file())], "fileMatch": [schema_file_match(paths::keymap_file())],
"schema": Self::generate_keymap_schema(cx), "schema": keymap_schema,
}, },
{ {
"fileMatch": [ "fileMatch": [
@ -129,16 +129,6 @@ impl JsonLspAdapter {
} }
}) })
} }
fn generate_keymap_schema(cx: &mut AppContext) -> Value {
let mut generator = SchemaSettings::draft07()
.with(|settings| settings.option_add_null_type = false)
.into_generator();
let action_schemas = cx.action_schemas(&mut generator);
let deprecations = cx.action_deprecations();
KeymapFile::generate_json_schema(generator, action_schemas, deprecations)
}
} }
#[async_trait(?Send)] #[async_trait(?Send)]

View file

@ -3,7 +3,7 @@ use anyhow::{anyhow, Context, Result};
use collections::{BTreeMap, HashMap}; use collections::{BTreeMap, HashMap};
use gpui::{Action, AppContext, KeyBinding, SharedString}; use gpui::{Action, AppContext, KeyBinding, SharedString};
use schemars::{ use schemars::{
gen::SchemaGenerator, gen::{SchemaGenerator, SchemaSettings},
schema::{ArrayValidation, InstanceType, Metadata, Schema, SchemaObject, SubschemaValidation}, schema::{ArrayValidation, InstanceType, Metadata, Schema, SchemaObject, SubschemaValidation},
JsonSchema, JsonSchema,
}; };
@ -139,7 +139,17 @@ impl KeymapFile {
Ok(()) Ok(())
} }
pub fn generate_json_schema( pub fn generate_json_schema_for_registered_actions(cx: &mut AppContext) -> Value {
let mut generator = SchemaSettings::draft07()
.with(|settings| settings.option_add_null_type = false)
.into_generator();
let action_schemas = cx.action_schemas(&mut generator);
let deprecations = cx.action_deprecations();
KeymapFile::generate_json_schema(generator, action_schemas, deprecations)
}
fn generate_json_schema(
generator: SchemaGenerator, generator: SchemaGenerator,
action_schemas: Vec<(SharedString, Option<Schema>)>, action_schemas: Vec<(SharedString, Option<Schema>)>,
deprecations: &HashMap<SharedString, SharedString>, deprecations: &HashMap<SharedString, SharedString>,

View file

@ -3502,6 +3502,73 @@ mod tests {
assert_key_bindings_for(workspace.into(), cx, vec![("6", &Deploy)], line!()); assert_key_bindings_for(workspace.into(), cx, vec![("6", &Deploy)], line!());
} }
#[gpui::test]
async fn test_generate_keymap_json_schema_for_registered_actions(
cx: &mut gpui::TestAppContext,
) {
init_keymap_test(cx);
cx.update(|cx| {
// Make sure it doesn't panic.
KeymapFile::generate_json_schema_for_registered_actions(cx);
});
}
/// Actions that don't build from empty input won't work from command palette invocation.
#[gpui::test]
async fn test_actions_build_with_empty_input(cx: &mut gpui::TestAppContext) {
init_keymap_test(cx);
cx.update(|cx| {
let all_actions = cx.all_action_names();
let mut failing_names = Vec::new();
let mut errors = Vec::new();
for action in all_actions {
match action.to_string().as_str() {
"vim::FindCommand"
| "vim::Literal"
| "vim::ResizePane"
| "vim::SwitchMode"
| "vim::PushOperator"
| "vim::Number"
| "vim::SelectRegister"
| "terminal::SendText"
| "terminal::SendKeystroke"
| "app_menu::OpenApplicationMenu"
| "app_menu::NavigateApplicationMenuInDirection"
| "picker::ConfirmInput"
| "editor::HandleInput"
| "editor::FoldAtLevel"
| "pane::ActivateItem"
| "workspace::ActivatePane"
| "workspace::ActivatePaneInDirection"
| "workspace::MoveItemToPane"
| "workspace::MoveItemToPaneInDirection"
| "workspace::OpenTerminal"
| "workspace::SwapPaneInDirection"
| "workspace::SendKeystrokes"
| "zed::OpenBrowser"
| "zed::OpenZedUrl" => {}
_ => {
let result = cx.build_action(action, None);
match &result {
Ok(_) => {}
Err(err) => {
failing_names.push(action);
errors.push(format!("{action} failed to build: {err:?}"));
}
}
}
}
}
if errors.len() > 0 {
panic!(
"Failed to build actions using {{}} as input: {:?}. Errors:\n{}",
failing_names,
errors.join("\n")
);
}
});
}
#[gpui::test] #[gpui::test]
fn test_bundled_settings_and_themes(cx: &mut AppContext) { fn test_bundled_settings_and_themes(cx: &mut AppContext) {
cx.text_system() cx.text_system()