diff --git a/src/lints/type_marked_deprecated.ron b/src/lints/type_marked_deprecated.ron new file mode 100644 index 00000000..d66234ac --- /dev/null +++ b/src/lints/type_marked_deprecated.ron @@ -0,0 +1,62 @@ +SemverQuery( + id: "type_marked_deprecated", + human_readable_name: "#[deprecated] added on type", + description: "A type has been newly marked with #[deprecated].", + required_update: Minor, + reference_link: Some("https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute"), + query: r#" + { + CrateDiff { + current { + item { + ... on ImplOwner { + visibility_limit @filter(op: "=", value: ["$public"]) + name @output + owner_type: __typename @tag @output + + importable_path { + path @tag @output + } + + attribute { + new_attr: raw_attribute @output + content { + base @filter(op: "=", value: ["$deprecated"]) + } + } + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + baseline { + item { + ... on ImplOwner { + visibility_limit @filter(op: "=", value: ["$public"]) @output + __typename @filter(op: "=", value: ["%owner_type"]) + + importable_path { + path @filter(op: "=", value: ["%path"]) + } + + attribute @fold @transform(op: "count") @filter(op: "=", value: ["$zero"]) { + content { + base @filter(op: "=", value: ["$deprecated"]) + } + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "deprecated": "deprecated", + "zero": 0, + }, + error_message: "A type is now #[deprecated]. Downstream crates will get a compiler warning when using this type.", + per_result_error_template: Some("{{owner_type}} {{name}} in {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index f7aa5b70..d02e9a61 100644 --- a/src/query.rs +++ b/src/query.rs @@ -474,6 +474,7 @@ add_lints!( trait_unsafe_added, trait_unsafe_removed, tuple_struct_to_plain_struct, + type_marked_deprecated, unit_struct_changed_kind, variant_marked_non_exhaustive, ); diff --git a/test_crates/type_marked_deprecated/new/Cargo.toml b/test_crates/type_marked_deprecated/new/Cargo.toml new file mode 100644 index 00000000..bdcf17f0 --- /dev/null +++ b/test_crates/type_marked_deprecated/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "type_marked_deprecated" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/type_marked_deprecated/new/src/enums.rs b/test_crates/type_marked_deprecated/new/src/enums.rs new file mode 100644 index 00000000..2261b89c --- /dev/null +++ b/test_crates/type_marked_deprecated/new/src/enums.rs @@ -0,0 +1,57 @@ +// These enums did not have the #[deprecated] attribute in the old version. +// Addition of the attribute should be reported. + +#[deprecated] +pub enum EnumToDeprecatedEnum { + First, +} + +#[deprecated = "This attribute was added"] +pub enum EnumToDeprecatedMessageEnum { + First, +} + +// These structs had the #[deprecated] attribute in the old version. +// They also included the user-defined warning message. Changes of +// the attribute, including deletion, should NOT be reported by this rule. + +pub enum DeprecatedEnumToEnum { + First, +} + +#[deprecated = "This message was added"] +pub enum DeprecatedEnumToDeprecatedMessageEnum { + First, +} + +pub enum DeprecatedMessageEnumToEnum { + First, +} + +#[deprecated] +pub enum DeprecatedMessageEnumToDeprecatedEnum { + First, +} + +#[deprecated = "This message was changed"] +pub enum DeprecatedMessageEnumToDeprecatedMessageEnum { + First, +} + +// This enum is private and should NOT be reported. + +#[deprecated] +enum DeprecatedPrivateEnum { + First, +} + +// This enum was added in the new version of the crate with its attribute. +// It should NOT be reported by this rule to avoid duplicate lints. +// It should be reported as a new pub type that is part of the crate's API. +// This might seem like a nonsensical test but is a valid edge case. + +#[deprecated] +pub enum DeprecatedNewEnum { + First, +} + diff --git a/test_crates/type_marked_deprecated/new/src/lib.rs b/test_crates/type_marked_deprecated/new/src/lib.rs new file mode 100644 index 00000000..8a40ae7e --- /dev/null +++ b/test_crates/type_marked_deprecated/new/src/lib.rs @@ -0,0 +1,3 @@ +pub mod enums; +pub mod structs; +pub mod unions; diff --git a/test_crates/type_marked_deprecated/new/src/structs.rs b/test_crates/type_marked_deprecated/new/src/structs.rs new file mode 100644 index 00000000..1c3f4231 --- /dev/null +++ b/test_crates/type_marked_deprecated/new/src/structs.rs @@ -0,0 +1,59 @@ +// These structs did not have the #[deprecated] attribute in the old version. +// Addition of the attribute should be reported by this rule. + +#[deprecated] +pub struct StructToDeprecatedStruct { + bar: u64, +} + +#[deprecated = "This attribute was added"] +pub struct StructToDeprecatedMessageStruct { + bar: u64, +} + +// These structs had the #[deprecated] attribute in the old version. Changes of +// the attribute, including deletion, should NOT be reported by this rule. + +pub struct DeprecatedStructToStruct { + bar: u64, +} + +#[deprecated = "This message was added"] +pub struct DeprecatedStructToDeprecatedMessageStruct { + bar: u64, +} + +// These structs had the #[deprecated] attribute in the old version. +// They also included the user-defined warning message. Changes of +// the attribute, including deletion, should NOT be reported by this rule. + +pub struct DeprecatedMessageStructToStruct { + bar: u64, +} + +#[deprecated] +pub struct DeprecatedMessageStructToDeprecatedStruct { + bar: u64, +} + +#[deprecated = "This message was changed"] +pub struct DeprecatedMessageStructToDeprecatedMessageStruct { + bar: u64, +} + +// This struct is private and should NOT be reported by this rule. + +#[deprecated] +struct DeprecatedPrivateStruct { + bar: u64, +} + +// This struct was added in the new version of the crate with its attribute. +// It should NOT be reported by this rule to avoid duplicate lints. +// It should be reported as a new pub type that is part of the crate's API. +// This might seem like a nonsensical test but is a valid edge case. + +#[deprecated] +pub struct DeprecatedNewStruct { + bar: u64, +} diff --git a/test_crates/type_marked_deprecated/new/src/unions.rs b/test_crates/type_marked_deprecated/new/src/unions.rs new file mode 100644 index 00000000..7adc62e8 --- /dev/null +++ b/test_crates/type_marked_deprecated/new/src/unions.rs @@ -0,0 +1,56 @@ +// These unions did not have the #[deprecated] attribute in the old version. +// Addition of the attribute should be reported. + +#[deprecated] +pub union UnionToDeprecatedUnion { + bar: u64, +} + +#[deprecated = "This attribute was added"] +pub union UnionToDeprecatedMessageUnion { + bar: u64, +} + +// These structs had the #[deprecated] attribute in the old version. +// They also included the user-defined warning message. Changes of +// the attribute, including deletion, should NOT be reported by this rule. + +pub union DeprecatedUnionToUnion { + bar: u64, +} + +#[deprecated = "This message was added"] +pub union DeprecatedUnionToDeprecatedMessageUnion { + bar: u64, +} + +pub union DeprecatedMessageUnionToUnion { + bar: u64, +} + +#[deprecated] +pub union DeprecatedMessageUnionToDeprecatedUnion { + bar: u64, +} + +#[deprecated = "This message was changed"] +pub union DeprecatedMessageUnionToDeprecatedMessageUnion { + bar: u64, +} + +// This union is private and should NOT be reported. + +#[deprecated] +union DeprecatedPrivateUnion { + bar: u64, +} + +// This union was added in the new version of the crate with its attribute. +// It should NOT be reported by this rule to avoid duplicate lints. +// It should be reported as a new pub type that is part of the crate's API. +// This might seem like a nonsensical test but is a valid edge case. + +#[deprecated] +pub union DeprecatedNewUnion { + bar: u64, +} diff --git a/test_crates/type_marked_deprecated/old/Cargo.toml b/test_crates/type_marked_deprecated/old/Cargo.toml new file mode 100644 index 00000000..bdcf17f0 --- /dev/null +++ b/test_crates/type_marked_deprecated/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "type_marked_deprecated" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/type_marked_deprecated/old/src/enums.rs b/test_crates/type_marked_deprecated/old/src/enums.rs new file mode 100644 index 00000000..cc9297cd --- /dev/null +++ b/test_crates/type_marked_deprecated/old/src/enums.rs @@ -0,0 +1,43 @@ +// Adding #[deprecated] to these enums should be reported. + +pub enum EnumToDeprecatedEnum { + First, +} + +pub enum EnumToDeprecatedMessageEnum { + First, +} + +// These enums already have the attribute and changes to the attribute should not be reported. + +#[deprecated] +pub enum DeprecatedEnumToEnum { + First, +} + +#[deprecated] +pub enum DeprecatedEnumToDeprecatedMessageEnum { + First, +} + +#[deprecated = "This attribute will be deleted"] +pub enum DeprecatedMessageEnumToEnum { + First, +} + +#[deprecated = "This message will be deleted"] +pub enum DeprecatedMessageEnumToDeprecatedEnum { + First, +} + +#[deprecated = "This message will change"] +pub enum DeprecatedMessageEnumToDeprecatedMessageEnum { + First, +} + +// This enum is private and should NOT be reported. + +enum DeprecatedPrivateEnum { + First, +} + diff --git a/test_crates/type_marked_deprecated/old/src/lib.rs b/test_crates/type_marked_deprecated/old/src/lib.rs new file mode 100644 index 00000000..8a40ae7e --- /dev/null +++ b/test_crates/type_marked_deprecated/old/src/lib.rs @@ -0,0 +1,3 @@ +pub mod enums; +pub mod structs; +pub mod unions; diff --git a/test_crates/type_marked_deprecated/old/src/structs.rs b/test_crates/type_marked_deprecated/old/src/structs.rs new file mode 100644 index 00000000..4a8a5cd9 --- /dev/null +++ b/test_crates/type_marked_deprecated/old/src/structs.rs @@ -0,0 +1,43 @@ +// Adding #[deprecated] to these structs should be reported. + +pub struct StructToDeprecatedStruct { + bar: u64, +} + +pub struct StructToDeprecatedMessageStruct { + bar: u64, +} + +// These structs already have the attribute and changes to the attribute should not be reported. + +#[deprecated] +pub struct DeprecatedStructToStruct { + bar: u64, +} + +#[deprecated] +pub struct DeprecatedStructToDeprecatedMessageStruct { + bar: u64, +} + +#[deprecated = "This attribute will be deleted"] +pub struct DeprecatedMessageStructToStruct { + bar: u64, +} + +#[deprecated = "This message will be deleted"] +pub struct DeprecatedMessageStructToDeprecatedStruct { + bar: u64, +} + +#[deprecated = "This message will change"] +pub struct DeprecatedMessageStructToDeprecatedMessageStruct { + bar: u64, +} + +// This struct is private and should NOT be reported. + +struct DeprecatedPrivateStruct { + bar: u64, +} + diff --git a/test_crates/type_marked_deprecated/old/src/unions.rs b/test_crates/type_marked_deprecated/old/src/unions.rs new file mode 100644 index 00000000..74fc5432 --- /dev/null +++ b/test_crates/type_marked_deprecated/old/src/unions.rs @@ -0,0 +1,42 @@ +// Adding #[deprecated] to these unions should be reported. + +pub union UnionToDeprecatedUnion { + bar: u64, +} + +pub union UnionToDeprecatedMessageUnion { + bar: u64, +} + +// These unions already have the attribute and changes to the attribute should not be reported. + +#[deprecated] +pub union DeprecatedUnionToUnion { + bar: u64, +} + +#[deprecated] +pub union DeprecatedUnionToDeprecatedMessageUnion { + bar: u64, +} + +#[deprecated = "This attribute will be deleted"] +pub union DeprecatedMessageUnionToUnion { + bar: u64, +} + +#[deprecated = "This message will be deleted"] +pub union DeprecatedMessageUnionToDeprecatedUnion { + bar: u64, +} + +#[deprecated = "This message will change"] +pub union DeprecatedMessageUnionToDeprecatedMessageUnion { + bar: u64, +} + +// This union is private and should NOT be reported. + +union DeprecatedPrivateUnion { + bar: u64, +} diff --git a/test_outputs/type_marked_deprecated.output.ron b/test_outputs/type_marked_deprecated.output.ron new file mode 100644 index 00000000..db574343 --- /dev/null +++ b/test_outputs/type_marked_deprecated.output.ron @@ -0,0 +1,56 @@ +{ + "./test_crates/type_marked_deprecated/": [ + { + "name": String("EnumToDeprecatedEnum"), + "new_attr": String("#[deprecated]"), + "owner_type": String("Enum"), + "path": List([ + String("type_marked_deprecated"), + String("enums"), + String("EnumToDeprecatedEnum"), + ]), + "span_begin_line": Uint64(5), + "span_filename": String("src/enums.rs"), + "visibility_limit": String("public"), + }, + { + "name": String("EnumToDeprecatedMessageEnum"), + "new_attr": String("#[deprecated = \"This attribute was added\"]"), + "owner_type": String("Enum"), + "path": List([ + String("type_marked_deprecated"), + String("enums"), + String("EnumToDeprecatedMessageEnum"), + ]), + "span_begin_line": Uint64(10), + "span_filename": String("src/enums.rs"), + "visibility_limit": String("public"), + }, + { + "name": String("StructToDeprecatedStruct"), + "new_attr": String("#[deprecated]"), + "owner_type": String("Struct"), + "path": List([ + String("type_marked_deprecated"), + String("structs"), + String("StructToDeprecatedStruct"), + ]), + "span_begin_line": Uint64(5), + "span_filename": String("src/structs.rs"), + "visibility_limit": String("public"), + }, + { + "name": String("StructToDeprecatedMessageStruct"), + "new_attr": String("#[deprecated = \"This attribute was added\"]"), + "owner_type": String("Struct"), + "path": List([ + String("type_marked_deprecated"), + String("structs"), + String("StructToDeprecatedMessageStruct"), + ]), + "span_begin_line": Uint64(10), + "span_filename": String("src/structs.rs"), + "visibility_limit": String("public"), + }, + ] +}