Default `#[schemars(deny_unknown_fields)] for json-language-server schemas (#33883)
Followup to #33678, doing the same thing for all JSON Schema files provided to json-language-server Release Notes: * Added warnings for unknown fields when editing `tasks.json` / `snippets.json`.
This commit is contained in:
parent
38544e514a
commit
ed7552d3e3
14 changed files with 136 additions and 149 deletions
|
@ -30,6 +30,7 @@ log.workspace = true
|
|||
rand = { workspace = true, optional = true }
|
||||
regex.workspace = true
|
||||
rust-embed.workspace = true
|
||||
schemars.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
serde_json_lenient.workspace = true
|
||||
|
|
58
crates/util/src/schemars.rs
Normal file
58
crates/util/src/schemars.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use schemars::{JsonSchema, transform::transform_subschemas};
|
||||
|
||||
const DEFS_PATH: &str = "#/$defs/";
|
||||
|
||||
/// 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: impl Fn() -> schemars::Schema,
|
||||
) -> schemars::Schema {
|
||||
// fallback on just using the schema name, which could collide.
|
||||
let schema_name = T::schema_name();
|
||||
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());
|
||||
}
|
||||
schemars::Schema::new_ref(format!("{DEFS_PATH}{schema_name}"))
|
||||
}
|
||||
|
||||
/// Adds a new JSON schema definition and returns a reference to it. **Panics** if the name is
|
||||
/// already in use.
|
||||
pub fn add_new_subschema(
|
||||
generator: &mut schemars::SchemaGenerator,
|
||||
name: &str,
|
||||
schema: serde_json::Value,
|
||||
) -> schemars::Schema {
|
||||
let old_definition = generator.definitions_mut().insert(name.to_string(), schema);
|
||||
assert_eq!(old_definition, None);
|
||||
schemars::Schema::new_ref(format!("{DEFS_PATH}{name}"))
|
||||
}
|
||||
|
||||
/// Defaults `additionalProperties` to `true`, as if `#[schemars(deny_unknown_fields)]` was on every
|
||||
/// struct. Skips structs that have `additionalProperties` set (such as if #[serde(flatten)] is used
|
||||
/// on a map).
|
||||
#[derive(Clone)]
|
||||
pub struct DefaultDenyUnknownFields;
|
||||
|
||||
impl schemars::transform::Transform for DefaultDenyUnknownFields {
|
||||
fn transform(&mut self, schema: &mut schemars::Schema) {
|
||||
if let Some(object) = schema.as_object_mut() {
|
||||
if object.contains_key("properties")
|
||||
&& !object.contains_key("additionalProperties")
|
||||
&& !object.contains_key("unevaluatedProperties")
|
||||
{
|
||||
object.insert("additionalProperties".to_string(), false.into());
|
||||
}
|
||||
}
|
||||
transform_subschemas(self, schema);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ pub mod fs;
|
|||
pub mod markdown;
|
||||
pub mod paths;
|
||||
pub mod redact;
|
||||
pub mod schemars;
|
||||
pub mod serde;
|
||||
pub mod shell_env;
|
||||
pub mod size;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue