diff --git a/semver_tests/Cargo.toml b/semver_tests/Cargo.toml index 591d75da..5ba4042c 100644 --- a/semver_tests/Cargo.toml +++ b/semver_tests/Cargo.toml @@ -17,6 +17,7 @@ enum_repr_int_removed = [] enum_repr_c_removed = [] enum_variant_added = [] enum_variant_missing = [] +enum_struct_variant_field_missing = [] function_missing = [] inherent_method_missing = [] sized_impl_removed = [] diff --git a/semver_tests/src/test_cases/enum_struct_variant_field_missing.rs b/semver_tests/src/test_cases/enum_struct_variant_field_missing.rs new file mode 100644 index 00000000..26aa59c9 --- /dev/null +++ b/semver_tests/src/test_cases/enum_struct_variant_field_missing.rs @@ -0,0 +1,19 @@ +pub enum Enum { + FieldWillBeMissing { + foo: usize, + + /// Testing: + #[cfg(not(feature = "enum_struct_variant_field_missing"))] + bar: usize, + } +} + +/// This struct variant should not be reported by the `enum_struct_variant_field_missing` rule: +/// it will be removed altogether, so the correct rule to catch it is +/// the `enum_variant_missing` rule and not the rule for missing fields. +pub enum IgnoredEnum { + #[cfg(not(feature = "enum_struct_variant_field_missing"))] + StructVariantWillBeMissing { + foo: usize, + } +} diff --git a/semver_tests/src/test_cases/mod.rs b/semver_tests/src/test_cases/mod.rs index 2f562b2c..f90e18da 100644 --- a/semver_tests/src/test_cases/mod.rs +++ b/semver_tests/src/test_cases/mod.rs @@ -5,6 +5,7 @@ pub mod enum_repr_int_changed; pub mod enum_repr_int_removed; pub mod enum_variant_added; pub mod enum_variant_missing; +pub mod enum_struct_variant_field_missing; pub mod item_missing; pub mod non_exhaustive; pub mod sized_impl_removed; diff --git a/src/queries/enum_struct_variant_field_missing.ron b/src/queries/enum_struct_variant_field_missing.ron new file mode 100644 index 00000000..8cf855fa --- /dev/null +++ b/src/queries/enum_struct_variant_field_missing.ron @@ -0,0 +1,66 @@ +SemverQuery( + id: "enum_struct_variant_field_missing", + human_readable_name: "pub enum struct variant's field removed or renamed" , + description: "An enum's struct variant has a field that is no longer available under its prior name.", + required_update: Major, + reference_link: Some("https://doc.rust-lang.org/cargo/reference/semver.html#item-remove"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + enum_name: name @output @tag + + importable_path { + path @output @tag + } + + variant { + ... on StructVariant { + variant_name: name @output @tag + + field { + field_name: name @output @tag + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + } + } + current { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + name @filter(op: "=", value: ["%enum_name"]) + + importable_path { + path @filter(op: "=", value: ["%path"]) + } + + variant { + ... on StructVariant { + name @filter(op: "=", value: ["%variant_name"]) + + field @fold @transform(op: "count") @filter(op: "=", value: ["$zero"]) { + name @filter(op: "=", value: ["%field_name"]) + } + } + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "zero": 0, + }, + error_message: "A publicly-visible enum has a struct variant whose field is no longer available under its prior name. It may have been renamed or removed entirely.", + per_result_error_template: Some("field {{field_name}} of variant {{enum_name}}::{{variant_name}}, previously in file {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index df55d4aa..2d7830d6 100644 --- a/src/query.rs +++ b/src/query.rs @@ -85,6 +85,7 @@ impl SemverQuery { include_str!("./queries/enum_repr_int_removed.ron"), include_str!("./queries/enum_variant_added.ron"), include_str!("./queries/enum_variant_missing.ron"), + include_str!("./queries/enum_struct_variant_field_missing.ron"), include_str!("./queries/function_missing.ron"), include_str!("./queries/inherent_method_missing.ron"), include_str!("./queries/sized_impl_removed.ron"), @@ -280,6 +281,7 @@ mod tests { enum_repr_int_removed, enum_variant_added, enum_variant_missing, + enum_struct_variant_field_missing, function_missing, inherent_method_missing, sized_impl_removed, diff --git a/src/test_data/enum_struct_variant_field_missing.output.ron b/src/test_data/enum_struct_variant_field_missing.output.ron new file mode 100644 index 00000000..02978393 --- /dev/null +++ b/src/test_data/enum_struct_variant_field_missing.output.ron @@ -0,0 +1,15 @@ +[ + { + "enum_name": String("Enum"), + "variant_name": String("FieldWillBeMissing"), + "path": List([ + String("semver_tests"), + String("test_cases"), + String("enum_struct_variant_field_missing"), + String("Enum"), + ]), + "field_name": String("bar"), + "span_filename": String("src/test_cases/enum_struct_variant_field_missing.rs"), + "span_begin_line": Uint64(7), + } +]