diff --git a/crates/stackable-versioned-macros/src/codegen/common/container.rs b/crates/stackable-versioned-macros/src/codegen/common/container.rs index 22e8fcdae..1ab77e7c4 100644 --- a/crates/stackable-versioned-macros/src/codegen/common/container.rs +++ b/crates/stackable-versioned-macros/src/codegen/common/container.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use proc_macro2::TokenStream; -use syn::{Attribute, Ident}; +use syn::{Attribute, Ident, Visibility}; use crate::{attrs::common::ContainerAttributes, codegen::common::ContainerVersion}; @@ -21,12 +21,7 @@ where Self: Sized + Deref>, { /// Creates a new versioned container. - fn new( - ident: Ident, - data: D, - attributes: ContainerAttributes, - original_attributes: Vec, - ) -> syn::Result; + fn new(input: ContainerInput, data: D, attributes: ContainerAttributes) -> syn::Result; /// This generates the complete code for a single versioned container. /// @@ -37,6 +32,21 @@ where fn generate_tokens(&self) -> TokenStream; } +/// This struct bundles values from [`DeriveInput`][1]. +/// +/// [`DeriveInput`][1] cannot be used directly when constructing a +/// [`VersionedStruct`][2] or [`VersionedEnum`][3] because we run into borrow +/// issues caused by the match statement which extracts the data. +/// +/// [1]: syn::DeriveInput +/// [2]: crate::codegen::vstruct::VersionedStruct +/// [3]: crate::codegen::venum::VersionedEnum +pub(crate) struct ContainerInput { + pub(crate) original_attributes: Vec, + pub(crate) visibility: Visibility, + pub(crate) ident: Ident, +} + /// Stores individual versions of a single container. /// /// Each version tracks item actions, which describe if the item was added, @@ -55,13 +65,17 @@ pub(crate) struct VersionedContainer { /// The ident, or name, of the versioned container. pub(crate) ident: Ident, + /// The visibility of the versioned container. Used to forward the + /// visibility during code generation. + pub(crate) visibility: Visibility, + + /// The original attributes that were added to the container. + pub(crate) original_attributes: Vec, + /// The name of the container used in `From` implementations. pub(crate) from_ident: Ident, /// Whether the [`From`] implementation generation should be skipped for all /// versions of this container. pub(crate) skip_from: bool, - - /// The original attributes that were added to the container. - pub(crate) original_attributes: Vec, } diff --git a/crates/stackable-versioned-macros/src/codegen/mod.rs b/crates/stackable-versioned-macros/src/codegen/mod.rs index ba2eefa9f..f1b1bab79 100644 --- a/crates/stackable-versioned-macros/src/codegen/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/mod.rs @@ -3,7 +3,11 @@ use syn::{spanned::Spanned, Data, DeriveInput, Error, Result}; use crate::{ attrs::common::ContainerAttributes, - codegen::{common::Container, venum::VersionedEnum, vstruct::VersionedStruct}, + codegen::{ + common::{Container, ContainerInput}, + venum::VersionedEnum, + vstruct::VersionedStruct, + }, }; pub(crate) mod chain; @@ -26,10 +30,22 @@ pub(crate) mod vstruct; pub(crate) fn expand(attributes: ContainerAttributes, input: DeriveInput) -> Result { let expanded = match input.data { Data::Struct(data) => { - VersionedStruct::new(input.ident, data, attributes, input.attrs)?.generate_tokens() + let input = ContainerInput { + original_attributes: input.attrs, + visibility: input.vis, + ident: input.ident, + }; + + VersionedStruct::new(input, data, attributes)?.generate_tokens() } Data::Enum(data) => { - VersionedEnum::new(input.ident, data, attributes, input.attrs)?.generate_tokens() + let input = ContainerInput { + original_attributes: input.attrs, + visibility: input.vis, + ident: input.ident, + }; + + VersionedEnum::new(input, data, attributes)?.generate_tokens() } _ => { return Err(Error::new( diff --git a/crates/stackable-versioned-macros/src/codegen/venum/mod.rs b/crates/stackable-versioned-macros/src/codegen/venum/mod.rs index bf4f52642..47744e330 100644 --- a/crates/stackable-versioned-macros/src/codegen/venum/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/venum/mod.rs @@ -3,13 +3,14 @@ use std::ops::Deref; use itertools::Itertools; use proc_macro2::TokenStream; use quote::quote; -use syn::{Attribute, DataEnum, Error, Ident}; +use syn::{DataEnum, Error}; use crate::{ attrs::common::ContainerAttributes, codegen::{ common::{ - format_container_from_ident, Container, ContainerVersion, Item, VersionedContainer, + format_container_from_ident, Container, ContainerInput, ContainerVersion, Item, + VersionedContainer, }, venum::variant::VersionedVariant, }, @@ -34,11 +35,16 @@ impl Deref for VersionedEnum { impl Container for VersionedEnum { fn new( - ident: Ident, + input: ContainerInput, data: DataEnum, attributes: ContainerAttributes, - original_attributes: Vec, ) -> syn::Result { + let ContainerInput { + original_attributes, + visibility, + ident, + } = input; + // Convert the raw version attributes into a container version. let versions: Vec<_> = (&attributes).into(); @@ -78,11 +84,12 @@ impl Container for VersionedEnum { .options .skip .map_or(false, |s| s.from.is_present()), + original_attributes, + visibility, from_ident, versions, items, ident, - original_attributes, })) } @@ -105,8 +112,10 @@ impl VersionedEnum { next_version: Option<&ContainerVersion>, ) -> TokenStream { let mut token_stream = TokenStream::new(); - let enum_name = &self.ident; + let original_attributes = &self.original_attributes; + let visibility = &self.visibility; + let enum_name = &self.ident; // Generate variants of the enum for `version`. let variants = self.generate_enum_variants(version); @@ -140,7 +149,7 @@ impl VersionedEnum { token_stream.extend(quote! { #[automatically_derived] #deprecated_attr - pub mod #version_ident { + #visibility mod #version_ident { #(#original_attributes)* #version_specific_docs pub enum #enum_name { diff --git a/crates/stackable-versioned-macros/src/codegen/vstruct/mod.rs b/crates/stackable-versioned-macros/src/codegen/vstruct/mod.rs index cebe66765..7f5aa4e70 100644 --- a/crates/stackable-versioned-macros/src/codegen/vstruct/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/vstruct/mod.rs @@ -3,13 +3,14 @@ use std::ops::Deref; use itertools::Itertools; use proc_macro2::TokenStream; use quote::quote; -use syn::{Attribute, DataStruct, Error, Ident}; +use syn::{DataStruct, Error, Ident}; use crate::{ attrs::common::ContainerAttributes, codegen::{ common::{ - format_container_from_ident, Container, ContainerVersion, Item, VersionedContainer, + format_container_from_ident, Container, ContainerInput, ContainerVersion, Item, + VersionedContainer, }, vstruct::field::VersionedField, }, @@ -34,11 +35,16 @@ impl Deref for VersionedStruct { impl Container for VersionedStruct { fn new( - ident: Ident, + input: ContainerInput, data: DataStruct, attributes: ContainerAttributes, - original_attributes: Vec, ) -> syn::Result { + let ContainerInput { + original_attributes, + visibility, + ident, + } = input; + // Convert the raw version attributes into a container version. let versions: Vec<_> = (&attributes).into(); @@ -78,11 +84,12 @@ impl Container for VersionedStruct { .options .skip .map_or(false, |s| s.from.is_present()), + original_attributes, + visibility, from_ident, versions, items, ident, - original_attributes, })) } @@ -105,8 +112,10 @@ impl VersionedStruct { next_version: Option<&ContainerVersion>, ) -> TokenStream { let mut token_stream = TokenStream::new(); - let struct_name = &self.ident; + let original_attributes = &self.original_attributes; + let visibility = &self.visibility; + let struct_name = &self.ident; // Generate fields of the struct for `version`. let fields = self.generate_struct_fields(version); @@ -140,7 +149,7 @@ impl VersionedStruct { token_stream.extend(quote! { #[automatically_derived] #deprecated_attr - pub mod #version_ident { + #visibility mod #version_ident { #(#original_attributes)* #version_specific_docs pub struct #struct_name { diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index e7bdd819c..352960457 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -7,7 +7,8 @@ All notable changes to this project will be documented in this file. ### Added - Pass through container and item attributes (including doc-comments). Add - attribute for version specific docs. ([#847]) + attribute for version specific docs ([#847]). +- Forward container visibility to generated modules ([#850]). ### Fixed @@ -16,6 +17,7 @@ All notable changes to this project will be documented in this file. [#842]: https://github.com/stackabletech/operator-rs/pull/842 [#847]: https://github.com/stackabletech/operator-rs/pull/847 +[#850]: https://github.com/stackabletech/operator-rs/pull/850 ## [0.1.1] - 2024-07-10