diff --git a/Cargo.lock b/Cargo.lock index 3576302d..729f02a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -874,6 +874,12 @@ version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "libyaml-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e126dda6f34391ab7b444f9922055facc83c07a910da3eb16f1e4d9c45dc777" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -1505,19 +1511,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - [[package]] name = "sha2" version = "0.10.9" @@ -1848,12 +1841,6 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "untrusted" version = "0.9.0" @@ -2110,8 +2097,8 @@ version = "0.2.30" dependencies = [ "serde", "serde_json", - "serde_yaml", "workshop-rs", + "yaml_serde", ] [[package]] @@ -2224,6 +2211,19 @@ dependencies = [ "rustix", ] +[[package]] +name = "yaml_serde" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b729a08a9a6be689bbad3e2bf8015926db54b6622cc89c3a5f7dc174b9e918" +dependencies = [ + "indexmap", + "itoa", + "libyaml-rs", + "ryu", + "serde", +] + [[package]] name = "yoke" version = "0.8.3" diff --git a/Cargo.toml b/Cargo.toml index d1c397a3..5f9bb375 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ workshop-rs = "=0.3.11" libc = "0.2" serde = "1" serde_json = "1" -serde_yaml = "0.9" +yaml_serde = "0.10" sha2 = "0.10" flate2 = "1" tar = "0.4" diff --git a/crates/wright-analyzer/Cargo.toml b/crates/wright-analyzer/Cargo.toml index 23c153be..36ebf858 100644 --- a/crates/wright-analyzer/Cargo.toml +++ b/crates/wright-analyzer/Cargo.toml @@ -13,6 +13,6 @@ workspace = true [dependencies] serde = { workspace = true, features = ["derive"] } serde_json.workspace = true -serde_yaml.workspace = true +yaml_serde.workspace = true # Single pinned reference: `[workspace.dependencies]` in the root Cargo.toml. workshop-rs.workspace = true diff --git a/crates/wright-analyzer/src/declarative.rs b/crates/wright-analyzer/src/declarative.rs index 41b1e4ed..d0029643 100644 --- a/crates/wright-analyzer/src/declarative.rs +++ b/crates/wright-analyzer/src/declarative.rs @@ -205,7 +205,7 @@ enum CanonicalValuePattern { impl RuleDefinition { pub fn from_yaml_str(input: &str) -> Result { - serde_yaml::from_str(input).map_err(RuleError::Yaml) + yaml_serde::from_str(input).map_err(RuleError::Yaml) } } @@ -959,7 +959,7 @@ fn default_true() -> bool { #[derive(Debug)] pub enum RuleError { - Yaml(serde_yaml::Error), + Yaml(yaml_serde::Error), InvalidIdentity(String), UnsupportedLocale(String), UnknownSpelling { diff --git a/crates/wright-analyzer/src/registry.rs b/crates/wright-analyzer/src/registry.rs index 1b09a89b..acbac558 100644 --- a/crates/wright-analyzer/src/registry.rs +++ b/crates/wright-analyzer/src/registry.rs @@ -161,14 +161,14 @@ pub struct LintConfig { impl LintConfig { /// Parse a project lint configuration from the stable YAML surface. - pub fn from_yaml_str(input: &str) -> Result { - serde_yaml::from_str(input) + pub fn from_yaml_str(input: &str) -> Result { + yaml_serde::from_str(input) } /// Read and parse a project lint configuration from YAML. pub fn from_yaml_path(path: &Path) -> Result { let input = std::fs::read_to_string(path)?; - serde_yaml::from_str(&input).map_err(std::io::Error::other) + yaml_serde::from_str(&input).map_err(std::io::Error::other) } /// Disable a rule by its stable ID. diff --git a/crates/wright-analyzer/tests/yaml_contract.rs b/crates/wright-analyzer/tests/yaml_contract.rs new file mode 100644 index 00000000..b918491e --- /dev/null +++ b/crates/wright-analyzer/tests/yaml_contract.rs @@ -0,0 +1,35 @@ +use wright_analyzer::declarative::RuleDefinition; +use wright_analyzer::registry::LintConfig; + +#[test] +fn lint_config_yaml_round_trips_through_yaml_serialization() { + let config = LintConfig::from_yaml_str( + r#" +rules: + community/minimum-wait: + enabled: false + severity: warn + options: + max-matches: 2 +"#, + ) + .expect("lint config YAML parses"); + + let serialized = yaml_serde::to_string(&config).expect("lint config serializes"); + let round_tripped = + LintConfig::from_yaml_str(&serialized).expect("serialized lint config parses"); + + assert!(!round_tripped.is_enabled("community/minimum-wait")); + assert_eq!( + round_tripped.options("community/minimum-wait").max_matches, + Some(2) + ); +} + +#[test] +fn invalid_rule_yaml_remains_an_explicit_error() { + let error = RuleDefinition::from_yaml_str("id: community/broken\nmetadata: []\nmatcher: {}\n") + .expect_err("invalid rule YAML must be rejected"); + + assert!(error.to_string().starts_with("invalid rule YAML:")); +}