Add initial element inspector for Zed development (#31315)

Open inspector with `dev: toggle inspector` from command palette or
`cmd-alt-i` on mac or `ctrl-alt-i` on linux.

https://github.com/user-attachments/assets/54c43034-d40b-414e-ba9b-190bed2e6d2f

* Picking of elements via the mouse, with scroll wheel to inspect
occluded elements.

* Temporary manipulation of the selected element.

* Layout info and JSON-based style manipulation for `Div`.

* Navigation to code that constructed the element.

Big thanks to @as-cii and @maxdeviant for sorting out how to implement
the core of an inspector.

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
Co-authored-by: Federico Dionisi <code@fdionisi.me>
This commit is contained in:
Michael Sloan 2025-05-23 17:08:59 -06:00 committed by GitHub
parent 685933b5c8
commit ab59982bf7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 2631 additions and 406 deletions

View file

@ -59,8 +59,10 @@ project.workspace = true
regex.workspace = true
rope.workspace = true
rust-embed.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_json_lenient.workspace = true
settings.workspace = true
smol.workspace = true
snippet_provider.workspace = true

View file

@ -97,6 +97,65 @@ impl JsonLspAdapter {
let tsconfig_schema = serde_json::Value::from_str(TSCONFIG_SCHEMA).unwrap();
let package_json_schema = serde_json::Value::from_str(PACKAGE_JSON_SCHEMA).unwrap();
#[allow(unused_mut)]
let mut schemas = serde_json::json!([
{
"fileMatch": ["tsconfig.json"],
"schema":tsconfig_schema
},
{
"fileMatch": ["package.json"],
"schema":package_json_schema
},
{
"fileMatch": [
schema_file_match(paths::settings_file()),
paths::local_settings_file_relative_path()
],
"schema": settings_schema,
},
{
"fileMatch": [schema_file_match(paths::keymap_file())],
"schema": keymap_schema,
},
{
"fileMatch": [
schema_file_match(paths::tasks_file()),
paths::local_tasks_file_relative_path()
],
"schema": tasks_schema,
},
{
"fileMatch": [
schema_file_match(
paths::snippets_dir()
.join("*.json")
.as_path()
)
],
"schema": snippets_schema,
},
{
"fileMatch": [
schema_file_match(paths::debug_scenarios_file()),
paths::local_debug_file_relative_path()
],
"schema": debug_schema,
},
]);
#[cfg(debug_assertions)]
{
schemas.as_array_mut().unwrap().push(serde_json::json!(
{
"fileMatch": [
"zed-inspector-style.json"
],
"schema": generate_inspector_style_schema(),
}
))
}
// This can be viewed via `dev: open language server logs` -> `json-language-server` ->
// `Server Info`
serde_json::json!({
@ -108,52 +167,7 @@ impl JsonLspAdapter {
{
"enable": true,
},
"schemas": [
{
"fileMatch": ["tsconfig.json"],
"schema":tsconfig_schema
},
{
"fileMatch": ["package.json"],
"schema":package_json_schema
},
{
"fileMatch": [
schema_file_match(paths::settings_file()),
paths::local_settings_file_relative_path()
],
"schema": settings_schema,
},
{
"fileMatch": [schema_file_match(paths::keymap_file())],
"schema": keymap_schema,
},
{
"fileMatch": [
schema_file_match(paths::tasks_file()),
paths::local_tasks_file_relative_path()
],
"schema": tasks_schema,
},
{
"fileMatch": [
schema_file_match(
paths::snippets_dir()
.join("*.json")
.as_path()
)
],
"schema": snippets_schema,
},
{
"fileMatch": [
schema_file_match(paths::debug_scenarios_file()),
paths::local_debug_file_relative_path()
],
"schema": debug_schema,
},
]
"schemas": schemas
}
})
}
@ -180,6 +194,16 @@ impl JsonLspAdapter {
}
}
#[cfg(debug_assertions)]
fn generate_inspector_style_schema() -> serde_json_lenient::Value {
let schema = schemars::r#gen::SchemaSettings::draft07()
.with(|settings| settings.option_add_null_type = false)
.into_generator()
.into_root_schema_for::<gpui::StyleRefinement>();
serde_json_lenient::to_value(schema).unwrap()
}
#[async_trait(?Send)]
impl LspAdapter for JsonLspAdapter {
fn name(&self) -> LanguageServerName {