Fix remote server (ssh) crash when editing json (#33818)

Closes #33807

Release Notes:

- (Preview Only) Fixes a remote server (ssh) crash when editing json
files

---------

Co-authored-by: Cole <cole@zed.dev>
This commit is contained in:
Michael Sloan 2025-07-02 18:21:39 -06:00 committed by GitHub
parent 77c4530e12
commit 32d058d95e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 38 deletions

View file

@ -23,35 +23,26 @@ inventory::collect!(ParameterizedJsonSchema);
const DEFS_PATH: &str = "#/$defs/";
/// Replaces the JSON schema definition for some type, and returns a reference to it.
/// Replaces the JSON schema definition for some type if it is in use (in the definitions list), and
/// returns a reference to it.
///
/// This asserts that JsonSchema::schema_name() + "2" does not exist because this indicates that
/// there are multiple types that use this name, and unfortunately schemars APIs do not support
/// resolving this ambiguity - see https://github.com/GREsau/schemars/issues/449
///
/// This takes a closure for `schema` because some settings types are not available on the remote
/// server, and so will crash when attempting to access e.g. GlobalThemeRegistry.
pub fn replace_subschema<T: JsonSchema>(
generator: &mut schemars::SchemaGenerator,
schema: schemars::Schema,
schema: impl Fn() -> schemars::Schema,
) -> schemars::Schema {
// The key in definitions may not match T::schema_name() if multiple types have the same name.
// This is a workaround for there being no straightforward way to get the key used for a type -
// see https://github.com/GREsau/schemars/issues/449
let ref_schema = generator.subschema_for::<T>();
if let Some(serde_json::Value::String(definition_pointer)) = ref_schema.get("$ref") {
if let Some(definition_name) = definition_pointer.strip_prefix(DEFS_PATH) {
generator
.definitions_mut()
.insert(definition_name.to_string(), schema.to_value());
return ref_schema;
} else {
log::error!(
"bug: expected `$ref` field to start with {DEFS_PATH}, \
got {definition_pointer}"
);
}
} else {
log::error!("bug: expected `$ref` field in result of `subschema_for`");
}
// fallback on just using the schema name, which could collide.
let schema_name = T::schema_name();
generator
.definitions_mut()
.insert(schema_name.to_string(), schema.to_value());
let definitions = generator.definitions_mut();
assert!(!definitions.contains_key(&format!("{schema_name}2")));
if definitions.contains_key(schema_name.as_ref()) {
definitions.insert(schema_name.to_string(), schema().to_value());
}
Schema::new_ref(format!("{DEFS_PATH}{schema_name}"))
}