diff --git a/crates/stackable-versioned-macros/src/attrs/item/mod.rs b/crates/stackable-versioned-macros/src/attrs/item/mod.rs index f33fc07e1..568f318d7 100644 --- a/crates/stackable-versioned-macros/src/attrs/item/mod.rs +++ b/crates/stackable-versioned-macros/src/attrs/item/mod.rs @@ -310,6 +310,10 @@ impl CommonItemAttributes { let docs = change.previous_docs.as_deref()?; Some((*change.version, docs.into_doc_comments())) }) + .chain(self.deprecated.iter().filter_map(|deprecation| { + let docs = deprecation.previous_docs.as_deref()?; + Some((*deprecation.version, docs.into_doc_comments())) + })) .collect() } @@ -501,9 +505,11 @@ pub struct ChangedAttributes { /// Example usage: /// - `deprecated(in = "...")` /// - `deprecated(in = "...", note = "...")` +/// - `deprecated(in = "...", note = "..."), previous_docs = "..."` #[derive(Clone, Debug, FromMeta)] pub struct DeprecatedAttributes { #[darling(rename = "in")] pub version: SpannedValue, pub note: Option>, + pub previous_docs: Option>, } diff --git a/crates/stackable-versioned-macros/src/lib.rs b/crates/stackable-versioned-macros/src/lib.rs index f34dfb5e1..0dec72c5e 100644 --- a/crates/stackable-versioned-macros/src/lib.rs +++ b/crates/stackable-versioned-macros/src/lib.rs @@ -567,22 +567,22 @@ mod utils; /// ``` /// /// -/// #### Changed Docs +/// ### Deprecated Action /// -/// The doc comments of an item can be changed using the `previous_docs` argument. -/// The doc comments attached to the item are used after the version of the -/// last relevant change. All earlier versions use the doc comments provided via -/// `previous_docs` instead. This is especially useful to adjust the description of -/// a field in the generated CRD schema without changing it for older versions. +/// This action indicates that an item is deprecated in a particular version. +/// Deprecated items are not removed. Available arguments are: +/// +/// - `in` to indicate in which version the item is deprecated. +/// - `note` to specify an optional deprecation note. +/// - `previous_docs` to provide the previous doc comments of the item. /// /// ``` /// # use stackable_versioned_macros::versioned; /// #[versioned(version(name = "v1alpha1"), version(name = "v1beta1"))] /// mod versioned { /// pub struct Foo { -/// /// The number of bars. -/// #[versioned(changed(in = "v1beta1", previous_docs = "The bar."))] -/// bar: usize, +/// #[versioned(deprecated(in = "v1beta1"))] +/// deprecated_bar: usize, /// baz: bool, /// } /// } @@ -591,49 +591,61 @@ mod utils; ///
/// Expand Generated Code /// -/// 1. In version `v1alpha1` the field uses the doc comments provided via -/// `previous_docs`. -/// 2. In the next version, `v1beta1`, the field uses the doc comments attached -/// to the field. +/// 1. In version `v1alpha1` the field `bar` is not yet deprecated and thus uses +/// the name without the `deprecated_` prefix. +/// 2. In version `v1beta1` the field is deprecated and now includes the +/// `deprecated_` prefix. It also uses the `#[deprecated]` attribute to +/// indicate to Clippy this part of Rust code is deprecated. Therefore, the +/// conversion implementations include `#[allow(deprecated)]` to allow the +/// usage of deprecated items in automatically generated code. /// /// ```ignore /// pub mod v1alpha1 { /// use super::*; /// pub struct Foo { -/// /// The bar. // 1 -/// pub bar: usize, +/// pub bar: usize, // 1 /// pub baz: bool, /// } /// } /// -/// // Snip +/// #[allow(deprecated)] // 2 +/// impl From for v1beta1::Foo { +/// fn from(foo: v1alpha1::Foo) -> Self { +/// Self { +/// deprecated_bar: foo.bar, // 2 +/// baz: foo.baz, +/// } +/// } +/// } /// /// pub mod v1beta1 { /// use super::*; /// pub struct Foo { -/// /// The number of bars. // 2 -/// pub bar: usize, +/// #[deprecated] // 2 +/// pub deprecated_bar: usize, /// pub baz: bool, /// } /// } /// ``` ///
/// -/// ### Deprecated Action +/// ### Changed Docs /// -/// This action indicates that an item was deprecated in a particular version. -/// Deprecated items are not removed. Available arguments are: -/// -/// - `in` to indicate in which version the item was deprecated. -/// - `note` to specify an optional deprecation note. +/// The doc comments of an item can be changed using the `previous_docs` argument +/// in the `changed` and `deprecated` actions. The doc comments attached to the +/// item are used after the version of the last relevant change. All earlier +/// versions use the doc comments provided via `previous_docs` instead. This is +/// especially useful to adjust the description of a field in the generated CRD +/// schema without changing it for older versions. /// /// ``` /// # use stackable_versioned_macros::versioned; /// #[versioned(version(name = "v1alpha1"), version(name = "v1beta1"))] /// mod versioned { /// pub struct Foo { -/// #[versioned(deprecated(in = "v1beta1"))] -/// deprecated_bar: usize, +/// /// The number of bars. +/// #[versioned(changed(in = "v1beta1", previous_docs = "The bar."))] +/// bar: usize, /// baz: bool, /// } /// } @@ -642,38 +654,28 @@ mod utils; ///
/// Expand Generated Code /// -/// 1. In version `v1alpha1` the field `bar` is not yet deprecated and thus uses -/// the name without the `deprecated_` prefix. -/// 2. In version `v1beta1` the field is deprecated and now includes the -/// `deprecated_` prefix. It also uses the `#[deprecated]` attribute to -/// indicate to Clippy this part of Rust code is deprecated. Therefore, the -/// conversion implementations include `#[allow(deprecated)]` to allow the -/// usage of deprecated items in automatically generated code. +/// 1. In version `v1alpha1` the field uses the doc comments provided via +/// `previous_docs`. +/// 2. In the next version, `v1beta1`, the field uses the doc comments attached +/// to the field. /// /// ```ignore /// pub mod v1alpha1 { /// use super::*; /// pub struct Foo { -/// pub bar: usize, // 1 +/// /// The bar. // 1 +/// pub bar: usize, /// pub baz: bool, /// } /// } /// -/// #[allow(deprecated)] // 2 -/// impl From for v1beta1::Foo { -/// fn from(foo: v1alpha1::Foo) -> Self { -/// Self { -/// deprecated_bar: foo.bar, // 2 -/// baz: foo.baz, -/// } -/// } -/// } +/// // Snip /// /// pub mod v1beta1 { /// use super::*; /// pub struct Foo { -/// #[deprecated] // 2 -/// pub deprecated_bar: usize, +/// /// The number of bars. // 2 +/// pub bar: usize, /// pub baz: bool, /// } /// } diff --git a/crates/stackable-versioned-macros/tests/inputs/pass/docs.rs b/crates/stackable-versioned-macros/tests/inputs/pass/docs.rs index f428d1b58..30d339b4f 100644 --- a/crates/stackable-versioned-macros/tests/inputs/pass/docs.rs +++ b/crates/stackable-versioned-macros/tests/inputs/pass/docs.rs @@ -53,12 +53,18 @@ mod versioned { #[serde(rename = "corge")] corge: String, - /// The docs of this field changed in v1, while it was renamed in v1beta1. + /// This field is now deprecated. + /// + /// Previously, the docs of this field changed in v1, while it was renamed in v1beta1. #[versioned( changed(in = "v1beta1", previous_name = "waldo"), - changed(in = "v1", previous_docs = "These are the docs before v1.") + changed(in = "v1", previous_docs = "These are the docs before v1."), + deprecated( + in = "v2", + previous_docs = "The docs of this field changed in v1, while it was renamed in v1beta1." + ) )] - fred: String, + deprecated_fred: String, } /// Test diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap index 49d2ef516..4abcebe55 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap @@ -408,7 +408,7 @@ where baz: __sv_foo.baz.into(), quux: __sv_foo.quux.into(), corge: __sv_foo.corge.into(), - fred: __sv_foo.fred.into(), + deprecated_fred: __sv_foo.fred.into(), }; spec } @@ -427,7 +427,7 @@ where baz: __sv_foo.baz.into(), quux: __sv_foo.quux.into(), corge: __sv_foo.corge.into(), - fred: __sv_foo.fred.into(), + fred: __sv_foo.deprecated_fred.into(), }; spec } @@ -475,8 +475,11 @@ mod v2 { #[doc(alias = "grault")] #[serde(rename = "corge")] pub corge: String, - /// The docs of this field changed in v1, while it was renamed in v1beta1. - pub fred: String, + /// This field is now deprecated. + /// + /// Previously, the docs of this field changed in v1, while it was renamed in v1beta1. + #[deprecated] + pub deprecated_fred: String, } /// Test #[derive(Default)] diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 21892ae2a..be02eda22 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ### Added +- Add support to provide the `previous_docs` argument in the `deprecated` action ([#1314]). - Add public `ExtractIfExt` trait ([#1306]). - Re-add support for generics in tracking impls ([#1304]). - Add support to provide `#[versioned(crd(selectable = "..."))]` arguments to configure selectable fields ([#1312]). @@ -33,6 +34,7 @@ All notable changes to this project will be documented in this file. [#1311]: https://github.com/stackabletech/operator-rs/pull/1311 [#1312]: https://github.com/stackabletech/operator-rs/pull/1312 [#1313]: https://github.com/stackabletech/operator-rs/pull/1313 +[#1314]: https://github.com/stackabletech/operator-rs/pull/1314 ## [0.13.0] - 2026-10-14