diff --git a/src/lints/trait_now_doc_hidden.ron b/src/lints/trait_now_doc_hidden.ron new file mode 100644 index 00000000..8a146477 --- /dev/null +++ b/src/lints/trait_now_doc_hidden.ron @@ -0,0 +1,48 @@ +SemverQuery( + id: "trait_now_doc_hidden", + human_readable_name: "pub trait is now #[doc(hidden)]", + description: "A pub trait is now marked #[doc(hidden)] and is thus no longer part of the public API.", + required_update: Major, + reference_link: Some("https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html#hidden"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on Trait { + visibility_limit @filter(op: "=", value: ["$public"]) + + importable_path { + path @output @tag + public_api @filter(op: "=", value: ["$true"]) + } + } + } + } + current { + item { + ... on Trait { + visibility_limit @filter(op: "=", value: ["$public"]) + trait_name: name @output + + importable_path { + path @filter(op: "=", value: ["%path"]) + public_api @filter(op: "!=", value: ["$true"]) + } + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "true": true, + }, + error_message: "A pub trait is now #[doc(hidden)], removing it from the crate's public API.", + per_result_error_template: Some("trait {{trait_name}} in file {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index 6760410b..c97aaf04 100644 --- a/src/query.rs +++ b/src/query.rs @@ -505,6 +505,7 @@ add_lints!( trait_method_missing, trait_missing, trait_must_use_added, + trait_now_doc_hidden, trait_unsafe_added, trait_unsafe_removed, tuple_struct_to_plain_struct, diff --git a/test_crates/enum_now_doc_hidden/new/src/lib.rs b/test_crates/enum_now_doc_hidden/new/src/lib.rs index e4fb5f9a..8d4c2657 100644 --- a/test_crates/enum_now_doc_hidden/new/src/lib.rs +++ b/test_crates/enum_now_doc_hidden/new/src/lib.rs @@ -63,7 +63,7 @@ pub enum Example { pub enum PublicEnumHiddenVariant { // shouldn't flag `enum_now_doc_hidden` rule // as this is a field that's hidden, - // not the entire struct + // not the entire enum #[doc(hidden)] A, B, @@ -71,7 +71,7 @@ pub enum PublicEnumHiddenVariant { pub enum PublicEnumHiddenStructFieldOnVariant { // shouldn't flag `enum_now_doc_hidden` rule - // as this is a field that's hidden on a struct variant, + // as this is a field that's hidden on a enum variant, // not the entire enum A { #[doc(hidden)] diff --git a/test_crates/trait_now_doc_hidden/new/Cargo.toml b/test_crates/trait_now_doc_hidden/new/Cargo.toml new file mode 100644 index 00000000..cc1fa995 --- /dev/null +++ b/test_crates/trait_now_doc_hidden/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "trait_now_doc_hidden" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/trait_now_doc_hidden/new/src/lib.rs b/test_crates/trait_now_doc_hidden/new/src/lib.rs new file mode 100644 index 00000000..2babbfd1 --- /dev/null +++ b/test_crates/trait_now_doc_hidden/new/src/lib.rs @@ -0,0 +1,62 @@ +mod MyNonPublicMod { + // despite adding #[doc(hidden)], this trait is in a + // private mod, so it isn't part of the crate's public + // api + #[doc(hidden)] + pub trait MyTrait {} +} + +pub mod MyPublicMod { + // added #[doc(hidden)], however this trait is in a + // public mod, so it previously was part of the crate's public api + #[doc(hidden)] + pub trait MyTrait {} +} + +#[doc(hidden)] +pub mod MyTopLevelDocHiddenMod { + #[doc(hidden)] // this shouldn't flag, as it's a top level mod + // was never part of the public api of the crate + pub trait MyTraitThatIsNowDocHidden {} +} + +mod MyNestedNonPublicMod { + pub mod PublicInnerMod { + // despite adding #[doc(hidden)], this trait is in a + // private outer mod, so it isn't part of the crate's public + // api + #[doc(hidden)] + pub trait MyTrait {} + } +} + +pub mod MyNestedPublicMod { + pub mod PublicInnerMod { + // added #[doc(hidden)], however this trait is in a + // public mod, so it previously was part of the crate's public api + #[doc(hidden)] + pub trait MyTrait {} + } +} + +#[doc(alias = "hidden")] // shouldn't flag, this is just aliased as hidden, + // but it should be #[doc(hidden)] +pub trait AliasedAsDocHidden {} + +#[doc(hidden)] // should flag, this is the simplest case of adding #[doc(hidden)] to a pub trait. +pub trait Example {} + +pub trait PublicTraitHiddenVariant { + // shouldn't flag `trait_now_doc_hidden` rule + // as this is a trait-fn that's hidden, + // not the entire trait + #[doc(hidden)] + fn my_trait_fn(&self); +} + +#[doc(hidden)] +trait PublicTraitThatGoesPrivate {} + +#[doc = "hidden"] // shouldn't flag, this is just documented with the string "hidden", + // it's not actually #[doc(hidden)] +pub trait PublicTraitDocumentedWithStringHidden {} diff --git a/test_crates/trait_now_doc_hidden/old/Cargo.toml b/test_crates/trait_now_doc_hidden/old/Cargo.toml new file mode 100644 index 00000000..cc1fa995 --- /dev/null +++ b/test_crates/trait_now_doc_hidden/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "trait_now_doc_hidden" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/trait_now_doc_hidden/old/src/lib.rs b/test_crates/trait_now_doc_hidden/old/src/lib.rs new file mode 100644 index 00000000..147d07d1 --- /dev/null +++ b/test_crates/trait_now_doc_hidden/old/src/lib.rs @@ -0,0 +1,36 @@ +mod MyNonPublicMod { + pub trait MyTrait {} +} + +pub mod MyPublicMod { + pub trait MyTrait {} +} + +#[doc(hidden)] +pub mod MyTopLevelDocHiddenMod { + pub trait MyTraitThatIsNowDocHidden {} +} + +mod MyNestedNonPublicMod { + pub mod PublicInnerMod { + pub trait MyTrait {} + } +} + +pub mod MyNestedPublicMod { + pub mod PublicInnerMod { + pub trait MyTrait {} + } +} + +pub trait AliasedAsDocHidden {} + +pub trait Example {} + +pub trait PublicTraitHiddenVariant { + fn my_trait_fn(&self); +} + +trait PublicTraitThatGoesPrivate {} + +pub trait PublicTraitDocumentedWithStringHidden {} diff --git a/test_outputs/trait_now_doc_hidden.output.ron b/test_outputs/trait_now_doc_hidden.output.ron new file mode 100644 index 00000000..0d27431f --- /dev/null +++ b/test_outputs/trait_now_doc_hidden.output.ron @@ -0,0 +1,34 @@ +{ + "./test_crates/trait_now_doc_hidden/": [ + { + "path": List([ + String("trait_now_doc_hidden"), + String("MyPublicMod"), + String("MyTrait"), + ]), + "span_begin_line": Uint64(13), + "span_filename": String("src/lib.rs"), + "trait_name": String("MyTrait"), + }, + { + "path": List([ + String("trait_now_doc_hidden"), + String("MyNestedPublicMod"), + String("PublicInnerMod"), + String("MyTrait"), + ]), + "span_begin_line": Uint64(38), + "span_filename": String("src/lib.rs"), + "trait_name": String("MyTrait"), + }, + { + "path": List([ + String("trait_now_doc_hidden"), + String("Example"), + ]), + "span_begin_line": Uint64(47), + "span_filename": String("src/lib.rs"), + "trait_name": String("Example"), + }, + ], +}