diff --git a/crates/stackable-versioned-macros/src/attrs/common.rs b/crates/stackable-versioned-macros/src/attrs/common.rs index 0d2768fe6..24ee40e87 100644 --- a/crates/stackable-versioned-macros/src/attrs/common.rs +++ b/crates/stackable-versioned-macros/src/attrs/common.rs @@ -1,6 +1,8 @@ +use std::ops::Deref; + use darling::{ Error, FromMeta, Result, - util::{Flag, Override, SpannedValue}, + util::{Flag, Override as FlagOrOverride, SpannedValue}, }; use itertools::Itertools; use k8s_version::Version; @@ -11,15 +13,15 @@ pub trait CommonOptions { #[derive(Debug, FromMeta)] #[darling(and_then = CommonRootArguments::validate)] -pub(crate) struct CommonRootArguments +pub struct CommonRootArguments where T: CommonOptions + Default, { #[darling(default)] - pub(crate) options: T, + pub options: T, #[darling(multiple, rename = "version")] - pub(crate) versions: SpannedValue>, + pub versions: SpannedValue>, } impl CommonRootArguments @@ -78,11 +80,11 @@ where /// - `skip` option to skip generating various pieces of code. /// - `doc` option to add version-specific documentation. #[derive(Clone, Debug, FromMeta)] -pub(crate) struct VersionArguments { - pub(crate) deprecated: Option>, - pub(crate) name: Version, - pub(crate) skip: Option, - pub(crate) doc: Option, +pub struct VersionArguments { + pub deprecated: Option>, + pub skip: Option, + pub doc: Option, + pub name: Version, } /// This struct contains supported common skip arguments. @@ -91,8 +93,35 @@ pub(crate) struct VersionArguments { /// /// - `from` flag, which skips generating [`From`] implementations when provided. #[derive(Clone, Debug, Default, FromMeta)] -pub(crate) struct SkipArguments { +pub struct SkipArguments { /// Whether the [`From`] implementation generation should be skipped for all versions of this /// container. - pub(crate) from: Flag, + pub from: Flag, +} + +/// Wraps a value to indicate whether it is original or has been overridden. +#[derive(Clone, Debug)] +pub enum Override { + Default(T), + Explicit(T), +} + +impl FromMeta for Override +where + T: FromMeta, +{ + fn from_meta(item: &syn::Meta) -> Result { + FromMeta::from_meta(item).map(Override::Explicit) + } +} + +impl Deref for Override { + type Target = T; + + fn deref(&self) -> &Self::Target { + match &self { + Override::Default(inner) => inner, + Override::Explicit(inner) => inner, + } + } } diff --git a/crates/stackable-versioned-macros/src/attrs/container/k8s.rs b/crates/stackable-versioned-macros/src/attrs/container/k8s.rs new file mode 100644 index 000000000..a9c17b476 --- /dev/null +++ b/crates/stackable-versioned-macros/src/attrs/container/k8s.rs @@ -0,0 +1,179 @@ +use darling::{FromMeta, util::Flag}; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; +use syn::{Path, parse_quote}; + +use crate::attrs::common::Override; + +/// This struct contains supported Kubernetes arguments. +/// +/// The arguments are passed through to the `#[kube]` attribute. More details can be found in the +/// official docs: . +/// +/// Supported arguments are: +/// +/// - `group`: Set the group of the CR object, usually the domain of the company. +/// This argument is Required. +/// - `kind`: Override the kind field of the CR object. This defaults to the struct +/// name (without the 'Spec' suffix). +/// - `singular`: Set the singular name of the CR object. +/// - `plural`: Set the plural name of the CR object. +/// - `namespaced`: Indicate that this is a namespaced scoped resource rather than a +/// cluster scoped resource. +/// - `crates`: Override specific crates. +/// - `status`: Set the specified struct as the status subresource. +/// - `shortname`: Set a shortname for the CR object. This can be specified multiple +/// times. +/// - `skip`: Controls skipping parts of the generation. +#[derive(Clone, Debug, FromMeta)] +pub struct KubernetesArguments { + pub group: String, + pub kind: Option, + pub singular: Option, + pub plural: Option, + pub namespaced: Flag, + // root + #[darling(default)] + pub crates: KubernetesCrateArguments, + pub status: Option, + // derive + // schema + // scale + // printcolumn + #[darling(multiple, rename = "shortname")] + pub shortnames: Vec, + // category + // selectable + // doc + // annotation + // label + pub skip: Option, + + #[darling(default)] + pub options: KubernetesConfigOptions, +} + +/// This struct contains supported kubernetes skip arguments. +/// +/// Supported arguments are: +/// +/// - `merged_crd` flag, which skips generating the `crd()` and `merged_crd()` functions are +/// generated. +#[derive(Clone, Debug, FromMeta)] +pub struct KubernetesSkipArguments { + /// Whether the `crd()` and `merged_crd()` generation should be skipped for + /// this container. + pub merged_crd: Flag, +} + +/// This struct contains crate overrides to be passed to `#[kube]`. +#[derive(Clone, Debug, FromMeta)] +pub struct KubernetesCrateArguments { + #[darling(default = default_kube_core)] + pub kube_core: Override, + + #[darling(default = default_kube_client)] + pub kube_client: Override, + + #[darling(default = default_k8s_openapi)] + pub k8s_openapi: Override, + + #[darling(default = default_schemars)] + pub schemars: Override, + + #[darling(default = default_serde)] + pub serde: Override, + + #[darling(default = default_serde_json)] + pub serde_json: Override, + + #[darling(default = default_versioned)] + pub versioned: Override, +} + +impl Default for KubernetesCrateArguments { + fn default() -> Self { + Self { + kube_core: default_kube_core(), + kube_client: default_kube_client(), + k8s_openapi: default_k8s_openapi(), + schemars: default_schemars(), + serde: default_serde(), + serde_json: default_serde_json(), + versioned: default_versioned(), + } + } +} + +fn default_kube_core() -> Override { + Override::Default(parse_quote! { ::kube::core }) +} + +fn default_kube_client() -> Override { + Override::Default(parse_quote! { ::kube::client }) +} + +fn default_k8s_openapi() -> Override { + Override::Default(parse_quote! { ::k8s_openapi }) +} + +fn default_schemars() -> Override { + Override::Default(parse_quote! { ::schemars }) +} + +fn default_serde() -> Override { + Override::Default(parse_quote! { ::serde }) +} + +fn default_serde_json() -> Override { + Override::Default(parse_quote! { ::serde_json }) +} + +fn default_versioned() -> Override { + Override::Default(parse_quote! { ::stackable_versioned }) +} + +impl ToTokens for KubernetesCrateArguments { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let mut crate_overrides = TokenStream::new(); + + let KubernetesCrateArguments { + kube_client: _, + k8s_openapi, + serde_json, + kube_core, + schemars, + serde, + .. + } = self; + + if let Override::Explicit(k8s_openapi) = k8s_openapi { + crate_overrides.extend(quote! { k8s_openapi = #k8s_openapi, }); + } + + if let Override::Explicit(serde_json) = serde_json { + crate_overrides.extend(quote! { serde_json = #serde_json, }); + } + + if let Override::Explicit(kube_core) = kube_core { + crate_overrides.extend(quote! { kube_core = #kube_core, }); + } + + if let Override::Explicit(schemars) = schemars { + crate_overrides.extend(quote! { schemars = #schemars, }); + } + + if let Override::Explicit(serde) = serde { + crate_overrides.extend(quote! { serde = #serde, }); + } + + if !crate_overrides.is_empty() { + tokens.extend(quote! { , crates(#crate_overrides) }); + } + } +} + +#[derive(Clone, Default, Debug, FromMeta)] +pub struct KubernetesConfigOptions { + pub experimental_conversion_tracking: Flag, +} diff --git a/crates/stackable-versioned-macros/src/attrs/container.rs b/crates/stackable-versioned-macros/src/attrs/container/mod.rs similarity index 69% rename from crates/stackable-versioned-macros/src/attrs/container.rs rename to crates/stackable-versioned-macros/src/attrs/container/mod.rs index 25e934801..f43a06866 100644 --- a/crates/stackable-versioned-macros/src/attrs/container.rs +++ b/crates/stackable-versioned-macros/src/attrs/container/mod.rs @@ -2,17 +2,19 @@ use darling::{Error, FromAttributes, FromMeta, Result, util::Flag}; use crate::attrs::{ common::{CommonOptions, CommonRootArguments, SkipArguments}, - k8s::KubernetesArguments, + container::k8s::KubernetesArguments, }; +pub mod k8s; + #[derive(Debug, FromMeta)] #[darling(and_then = StandaloneContainerAttributes::validate)] -pub(crate) struct StandaloneContainerAttributes { +pub struct StandaloneContainerAttributes { #[darling(rename = "k8s")] - pub(crate) kubernetes_arguments: Option, + pub kubernetes_arguments: Option, #[darling(flatten)] - pub(crate) common: CommonRootArguments, + pub common: CommonRootArguments, } impl StandaloneContainerAttributes { @@ -28,9 +30,9 @@ impl StandaloneContainerAttributes { } #[derive(Debug, FromMeta, Default)] -pub(crate) struct StandaloneContainerOptions { - pub(crate) allow_unsorted: Flag, - pub(crate) skip: Option, +pub struct StandaloneContainerOptions { + pub allow_unsorted: Flag, + pub skip: Option, } impl CommonOptions for StandaloneContainerOptions { @@ -44,12 +46,12 @@ impl CommonOptions for StandaloneContainerOptions { attributes(versioned), and_then = NestedContainerAttributes::validate )] -pub(crate) struct NestedContainerAttributes { +pub struct NestedContainerAttributes { #[darling(rename = "k8s")] - pub(crate) kubernetes_arguments: Option, + pub kubernetes_arguments: Option, #[darling(default)] - pub(crate) options: NestedContainerOptionArguments, + pub options: NestedContainerOptionArguments, } impl NestedContainerAttributes { @@ -65,6 +67,6 @@ impl NestedContainerAttributes { } #[derive(Debug, Default, FromMeta)] -pub(crate) struct NestedContainerOptionArguments { - pub(crate) skip: Option, +pub struct NestedContainerOptionArguments { + pub skip: Option, } diff --git a/crates/stackable-versioned-macros/src/attrs/item/field.rs b/crates/stackable-versioned-macros/src/attrs/item/field.rs index bee008fd2..b8b5ad0dc 100644 --- a/crates/stackable-versioned-macros/src/attrs/item/field.rs +++ b/crates/stackable-versioned-macros/src/attrs/item/field.rs @@ -22,20 +22,20 @@ use crate::{attrs::item::CommonItemAttributes, codegen::VersionDefinition, utils forward_attrs, and_then = FieldAttributes::validate )] -pub(crate) struct FieldAttributes { +pub struct FieldAttributes { #[darling(flatten)] - pub(crate) common: CommonItemAttributes, + pub common: CommonItemAttributes, // The ident (automatically extracted by darling) cannot be moved into the // shared item attributes because for struct fields, the type is // `Option`, while for enum variants, the type is `Ident`. - pub(crate) ident: Option, + pub ident: Option, // This must be named `attrs` for darling to populate it accordingly, and // cannot live in common because Vec is not implemented for // FromMeta. /// The original attributes for the field. - pub(crate) attrs: Vec, + pub attrs: Vec, } impl FieldAttributes { @@ -56,7 +56,7 @@ impl FieldAttributes { Ok(self) } - pub(crate) fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> { + pub fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> { self.common.validate_versions(versions) } } diff --git a/crates/stackable-versioned-macros/src/attrs/item/mod.rs b/crates/stackable-versioned-macros/src/attrs/item/mod.rs index e2cb041b3..415a514cb 100644 --- a/crates/stackable-versioned-macros/src/attrs/item/mod.rs +++ b/crates/stackable-versioned-macros/src/attrs/item/mod.rs @@ -12,10 +12,10 @@ use crate::{ }; mod field; -pub(crate) use field::*; +pub use field::*; mod variant; -pub(crate) use variant::*; +pub use variant::*; /// These attributes are meant to be used in super structs, which add /// [`Field`](syn::Field) or [`Variant`](syn::Variant) specific attributes via @@ -30,19 +30,19 @@ pub(crate) use variant::*; /// - An item can only be deprecated once. A field or variant not marked as /// 'deprecated' will be included up until the latest version. #[derive(Debug, FromMeta)] -pub(crate) struct CommonItemAttributes { +pub struct CommonItemAttributes { /// This parses the `added` attribute on items (fields or variants). It can /// only be present at most once. - pub(crate) added: Option, + pub added: Option, /// This parses the `changed` attribute on items (fields or variants). It /// can be present 0..n times. #[darling(multiple, rename = "changed")] - pub(crate) changes: Vec, + pub changes: Vec, /// This parses the `deprecated` attribute on items (fields or variants). It /// can only be present at most once. - pub(crate) deprecated: Option, + pub deprecated: Option, } // This impl block ONLY contains validation. The main entrypoint is the associated 'validate' @@ -50,11 +50,7 @@ pub(crate) struct CommonItemAttributes { // it contains functions which can only be called after the initial parsing and validation because // they need additional context, namely the list of versions defined on the container or module. impl CommonItemAttributes { - pub(crate) fn validate( - &self, - item_ident: impl ItemIdentExt, - item_attrs: &[Attribute], - ) -> Result<()> { + pub fn validate(&self, item_ident: impl ItemIdentExt, item_attrs: &[Attribute]) -> Result<()> { let mut errors = Error::accumulator(); errors.handle(self.validate_action_combinations(&item_ident)); @@ -67,7 +63,7 @@ impl CommonItemAttributes { errors.finish() } - pub(crate) fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> { + pub fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> { let mut errors = Error::accumulator(); if let Some(added) = &self.added { @@ -225,8 +221,14 @@ impl CommonItemAttributes { fn validate_changed_action(&self, item_ident: &impl ItemIdentExt) -> Result<()> { let mut errors = Error::accumulator(); - // This ensures that `from_name` doesn't include the deprecation prefix. for change in &self.changes { + if change.from_name.is_none() && change.from_type.is_none() { + errors.push(Error::custom( + "both `from_name` and `from_type` are unset. Is this `changed()` action needed?" + ).with_span(&change.since.span())); + } + + // This ensures that `from_name` doesn't include the deprecation prefix. if let Some(from_name) = change.from_name.as_ref() { if from_name.starts_with(item_ident.deprecated_prefix()) { errors.push( @@ -287,7 +289,7 @@ impl CommonItemAttributes { } impl CommonItemAttributes { - pub(crate) fn into_changeset( + pub fn into_changeset( self, ident: &impl ItemIdentExt, ty: Type, @@ -436,11 +438,11 @@ impl CommonItemAttributes { /// - `added(since = "...")` /// - `added(since = "...", default_fn = "custom_fn")` #[derive(Clone, Debug, FromMeta)] -pub(crate) struct AddedAttributes { - pub(crate) since: SpannedValue, +pub struct AddedAttributes { + pub since: SpannedValue, #[darling(rename = "default", default = "default_default_fn")] - pub(crate) default_fn: SpannedValue, + pub default_fn: SpannedValue, } fn default_default_fn() -> SpannedValue { @@ -451,10 +453,6 @@ fn default_default_fn() -> SpannedValue { ) } -// TODO (@Techassi): Add validation for when from_name AND from_type are both -// none => is this action needed in the first place? -// TODO (@Techassi): Add validation that the from_name mustn't include the -// deprecated prefix. /// For the changed() action /// /// Example usage: @@ -477,7 +475,7 @@ pub struct ChangedAttributes { /// - `deprecated(since = "...")` /// - `deprecated(since = "...", note = "...")` #[derive(Clone, Debug, FromMeta)] -pub(crate) struct DeprecatedAttributes { - pub(crate) since: SpannedValue, - pub(crate) note: Option>, +pub struct DeprecatedAttributes { + pub since: SpannedValue, + pub note: Option>, } diff --git a/crates/stackable-versioned-macros/src/attrs/item/variant.rs b/crates/stackable-versioned-macros/src/attrs/item/variant.rs index 42dc58149..afaec94a0 100644 --- a/crates/stackable-versioned-macros/src/attrs/item/variant.rs +++ b/crates/stackable-versioned-macros/src/attrs/item/variant.rs @@ -23,20 +23,20 @@ use crate::{attrs::item::CommonItemAttributes, codegen::VersionDefinition, utils forward_attrs, and_then = VariantAttributes::validate )] -pub(crate) struct VariantAttributes { +pub struct VariantAttributes { #[darling(flatten)] - pub(crate) common: CommonItemAttributes, + pub common: CommonItemAttributes, // The ident (automatically extracted by darling) cannot be moved into the // shared item attributes because for struct fields, the type is // `Option`, while for enum variants, the type is `Ident`. - pub(crate) ident: Ident, + pub ident: Ident, // This must be named `attrs` for darling to populate it accordingly, and // cannot live in common because Vec is not implemented for // FromMeta. /// The original attributes for the field. - pub(crate) attrs: Vec, + pub attrs: Vec, } impl VariantAttributes { @@ -69,7 +69,7 @@ impl VariantAttributes { errors.finish_with(self) } - pub(crate) fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> { + pub fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> { self.common.validate_versions(versions) } } diff --git a/crates/stackable-versioned-macros/src/attrs/k8s.rs b/crates/stackable-versioned-macros/src/attrs/k8s.rs deleted file mode 100644 index 06fcbbcb3..000000000 --- a/crates/stackable-versioned-macros/src/attrs/k8s.rs +++ /dev/null @@ -1,79 +0,0 @@ -use darling::{FromMeta, util::Flag}; -use syn::Path; - -/// This struct contains supported Kubernetes arguments. -/// -/// The arguments are passed through to the `#[kube]` attribute. More details can be found in the -/// official docs: . -/// -/// Supported arguments are: -/// -/// - `group`: Set the group of the CR object, usually the domain of the company. -/// This argument is Required. -/// - `kind`: Override the kind field of the CR object. This defaults to the struct -/// name (without the 'Spec' suffix). -/// - `singular`: Set the singular name of the CR object. -/// - `plural`: Set the plural name of the CR object. -/// - `namespaced`: Indicate that this is a namespaced scoped resource rather than a -/// cluster scoped resource. -/// - `crates`: Override specific crates. -/// - `status`: Set the specified struct as the status subresource. -/// - `shortname`: Set a shortname for the CR object. This can be specified multiple -/// times. -/// - `skip`: Controls skipping parts of the generation. -#[derive(Clone, Debug, FromMeta)] -pub struct KubernetesArguments { - pub group: String, - pub kind: Option, - pub singular: Option, - pub plural: Option, - pub namespaced: Flag, - // root - pub crates: Option, - pub status: Option, - // derive - // schema - // scale - // printcolumn - #[darling(multiple, rename = "shortname")] - pub shortnames: Vec, - // category - // selectable - // doc - // annotation - // label - pub skip: Option, - - #[darling(default)] - pub options: RawKubernetesOptions, -} - -/// This struct contains supported kubernetes skip arguments. -/// -/// Supported arguments are: -/// -/// - `merged_crd` flag, which skips generating the `crd()` and `merged_crd()` functions are -/// generated. -#[derive(Clone, Debug, FromMeta)] -pub struct KubernetesSkipArguments { - /// Whether the `crd()` and `merged_crd()` generation should be skipped for - /// this container. - pub merged_crd: Flag, -} - -/// This struct contains crate overrides to be passed to `#[kube]`. -#[derive(Clone, Debug, FromMeta)] -pub struct KubernetesCrateArguments { - pub kube_core: Option, - pub kube_client: Option, - pub k8s_openapi: Option, - pub schemars: Option, - pub serde: Option, - pub serde_json: Option, - pub versioned: Option, -} - -#[derive(Clone, Default, Debug, FromMeta)] -pub struct RawKubernetesOptions { - pub experimental_conversion_tracking: Flag, -} diff --git a/crates/stackable-versioned-macros/src/attrs/mod.rs b/crates/stackable-versioned-macros/src/attrs/mod.rs index e7c06ef8d..4442ca4f6 100644 --- a/crates/stackable-versioned-macros/src/attrs/mod.rs +++ b/crates/stackable-versioned-macros/src/attrs/mod.rs @@ -1,5 +1,4 @@ -pub(crate) mod common; -pub(crate) mod container; -pub(crate) mod item; -pub(crate) mod k8s; -pub(crate) mod module; +pub mod common; +pub mod container; +pub mod item; +pub mod module; diff --git a/crates/stackable-versioned-macros/src/attrs/module.rs b/crates/stackable-versioned-macros/src/attrs/module.rs index 869d24a13..addc1a93c 100644 --- a/crates/stackable-versioned-macros/src/attrs/module.rs +++ b/crates/stackable-versioned-macros/src/attrs/module.rs @@ -3,16 +3,16 @@ use darling::{FromMeta, util::Flag}; use crate::attrs::common::{CommonOptions, CommonRootArguments, SkipArguments}; #[derive(Debug, FromMeta)] -pub(crate) struct ModuleAttributes { +pub struct ModuleAttributes { #[darling(flatten)] - pub(crate) common: CommonRootArguments, + pub common: CommonRootArguments, } #[derive(Debug, FromMeta, Default)] -pub(crate) struct ModuleOptions { - pub(crate) allow_unsorted: Flag, - pub(crate) skip: Option, - pub(crate) preserve_module: Flag, +pub struct ModuleOptions { + pub allow_unsorted: Flag, + pub skip: Option, + pub preserve_module: Flag, } impl CommonOptions for ModuleOptions { diff --git a/crates/stackable-versioned-macros/src/codegen/changes.rs b/crates/stackable-versioned-macros/src/codegen/changes.rs index 90709c688..31e9a6dab 100644 --- a/crates/stackable-versioned-macros/src/codegen/changes.rs +++ b/crates/stackable-versioned-macros/src/codegen/changes.rs @@ -5,7 +5,7 @@ use syn::Type; use crate::codegen::{ItemStatus, VersionDefinition}; -pub(crate) trait Neighbors +pub trait Neighbors where K: Ord + Eq, { @@ -78,7 +78,7 @@ where } } -pub(crate) trait BTreeMapExt +pub trait BTreeMapExt where K: Ord, { @@ -95,7 +95,7 @@ impl BTreeMapExt for BTreeMap { } } -pub(crate) trait ChangesetExt { +pub trait ChangesetExt { fn insert_container_versions(&mut self, versions: &[VersionDefinition], ty: &Type); } diff --git a/crates/stackable-versioned-macros/src/codegen/container/enum.rs b/crates/stackable-versioned-macros/src/codegen/container/enum.rs index d8ee3d668..c9c7d8937 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/enum.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/enum.rs @@ -16,7 +16,7 @@ use crate::{ }; impl Container { - pub(crate) fn new_standalone_enum( + pub fn new_standalone_enum( item_enum: ItemEnum, attributes: StandaloneContainerAttributes, versions: &[VersionDefinition], @@ -29,7 +29,7 @@ impl Container { } let options = ContainerOptions { - kubernetes_options: None, + kubernetes_arguments: None, skip_from: attributes .common .options @@ -53,10 +53,7 @@ impl Container { } // TODO (@Techassi): See what can be unified into a single 'new' function - pub(crate) fn new_enum_nested( - item_enum: ItemEnum, - versions: &[VersionDefinition], - ) -> Result { + pub fn new_enum_nested(item_enum: ItemEnum, versions: &[VersionDefinition]) -> Result { let attributes = NestedContainerAttributes::from_attributes(&item_enum.attrs)?; let mut versioned_variants = Vec::new(); @@ -67,7 +64,7 @@ impl Container { } let options = ContainerOptions { - kubernetes_options: None, + kubernetes_arguments: None, skip_from: attributes.options.skip.is_some_and(|s| s.from.is_present()), }; @@ -88,13 +85,13 @@ impl Container { } /// A versioned enum. -pub(crate) struct Enum { +pub struct Enum { /// List of variants defined in the original enum. How, and if, an item /// should generate code, is decided by the currently generated version. - pub(crate) variants: Vec, + pub variants: Vec, /// Common container data which is shared between enums and structs. - pub(crate) common: CommonContainerData, + pub common: CommonContainerData, /// Generic types of the enum pub generics: Generics, @@ -103,7 +100,7 @@ pub(crate) struct Enum { // Common token generation impl Enum { /// Generates code for the enum definition. - pub(crate) fn generate_definition(&self, version: &VersionDefinition) -> TokenStream { + pub fn generate_definition(&self, version: &VersionDefinition) -> TokenStream { let where_clause = self.generics.where_clause.as_ref(); let type_generics = &self.generics; diff --git a/crates/stackable-versioned-macros/src/codegen/container/mod.rs b/crates/stackable-versioned-macros/src/codegen/container/mod.rs index 7ac654ade..9d4b73b17 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/mod.rs @@ -1,15 +1,10 @@ -use std::ops::Deref; - use darling::{Result, util::IdentString}; use proc_macro2::{Span, TokenStream}; -use quote::{ToTokens, quote}; -use syn::{Attribute, Ident, ItemEnum, ItemStruct, Path, Visibility, parse_quote}; +use quote::quote; +use syn::{Attribute, Ident, ItemEnum, ItemStruct, Visibility}; use crate::{ - attrs::{ - container::StandaloneContainerAttributes, - k8s::{KubernetesArguments, KubernetesCrateArguments, RawKubernetesOptions}, - }, + attrs::container::{StandaloneContainerAttributes, k8s::KubernetesArguments}, codegen::{ VersionDefinition, container::{r#enum::Enum, r#struct::Struct}, @@ -23,13 +18,13 @@ mod r#struct; /// Contains common container data shared between structs and enums. pub struct CommonContainerData { /// Original attributes placed on the container, like `#[derive()]` or `#[cfg()]`. - pub(crate) original_attributes: Vec, + pub original_attributes: Vec, /// Different options which influence code generation. - pub(crate) options: ContainerOptions, + pub options: ContainerOptions, /// A collection of container idents used for different purposes. - pub(crate) idents: ContainerIdents, + pub idents: ContainerIdents, } /// Supported types of containers, structs and enums. @@ -44,7 +39,7 @@ pub enum Container { impl Container { /// Generates the container definition for the specified `version`. - pub(crate) fn generate_definition(&self, version: &VersionDefinition) -> TokenStream { + pub fn generate_definition(&self, version: &VersionDefinition) -> TokenStream { match self { Container::Struct(s) => s.generate_definition(version), Container::Enum(e) => e.generate_definition(version), @@ -150,7 +145,7 @@ impl Container { /// for more information about versioned modules. /// /// [1]: crate::codegen::module::Module -pub(crate) struct StandaloneContainer { +pub struct StandaloneContainer { versions: Vec, container: Container, vis: Visibility, @@ -158,7 +153,7 @@ pub(crate) struct StandaloneContainer { impl StandaloneContainer { /// Creates a new versioned standalone struct. - pub(crate) fn new_struct( + pub fn new_struct( item_struct: ItemStruct, attributes: StandaloneContainerAttributes, ) -> Result { @@ -175,7 +170,7 @@ impl StandaloneContainer { } /// Creates a new versioned standalone enum. - pub(crate) fn new_enum( + pub fn new_enum( item_enum: ItemEnum, attributes: StandaloneContainerAttributes, ) -> Result { @@ -192,7 +187,7 @@ impl StandaloneContainer { } /// Generate tokens containing every piece of code required for a standalone container. - pub(crate) fn generate_tokens(&self) -> TokenStream { + pub fn generate_tokens(&self) -> TokenStream { let vis = &self.vis; let mut tokens = TokenStream::new(); @@ -267,7 +262,7 @@ impl StandaloneContainer { /// A collection of container idents used for different purposes. #[derive(Debug)] -pub(crate) struct ContainerIdents { +pub struct ContainerIdents { /// The ident used in the context of Kubernetes specific code. This ident /// removes the 'Spec' suffix present in the definition container. pub kubernetes: IdentString, @@ -280,8 +275,8 @@ pub(crate) struct ContainerIdents { } impl ContainerIdents { - pub(crate) fn from(ident: Ident, kubernetes_options: Option<&KubernetesOptions>) -> Self { - let kubernetes = kubernetes_options.map_or_else( + pub fn from(ident: Ident, kubernetes_arguments: Option<&KubernetesArguments>) -> Self { + let kubernetes = kubernetes_arguments.map_or_else( || ident.as_cleaned_kubernetes_ident(), |options| { options.kind.as_ref().map_or_else( @@ -301,183 +296,6 @@ impl ContainerIdents { #[derive(Debug)] pub struct ContainerOptions { - pub kubernetes_options: Option, + pub kubernetes_arguments: Option, pub skip_from: bool, } - -// TODO (@Techassi): Get rid of this whole mess. There should be an elegant way of using the -// attributes directly (with all defaults set and validation done). -#[derive(Debug)] -pub struct KubernetesOptions { - pub group: String, - pub kind: Option, - pub singular: Option, - pub plural: Option, - pub namespaced: bool, - // root - pub crates: KubernetesCrateOptions, - pub status: Option, - // derive - // schema - // scale - // printcolumn - pub shortnames: Vec, - // category - // selectable - // doc - // annotation - // label - pub skip_merged_crd: bool, - pub config_options: KubernetesConfigOptions, -} - -impl From for KubernetesOptions { - fn from(args: KubernetesArguments) -> Self { - KubernetesOptions { - group: args.group, - kind: args.kind, - singular: args.singular, - plural: args.plural, - namespaced: args.namespaced.is_present(), - crates: args - .crates - .map_or_else(KubernetesCrateOptions::default, |crates| crates.into()), - status: args.status, - shortnames: args.shortnames, - skip_merged_crd: args.skip.is_some_and(|s| s.merged_crd.is_present()), - config_options: args.options.into(), - } - } -} - -#[derive(Debug)] -pub struct KubernetesCrateOptions { - pub kube_client: Override, - pub kube_core: Override, - pub k8s_openapi: Override, - pub schemars: Override, - pub serde: Override, - pub serde_json: Override, - pub versioned: Override, -} - -impl Default for KubernetesCrateOptions { - fn default() -> Self { - Self { - versioned: Override::Default(parse_quote! { ::stackable_versioned }), - kube_client: Override::Default(parse_quote! { ::kube::client }), - k8s_openapi: Override::Default(parse_quote! { ::k8s_openapi }), - serde_json: Override::Default(parse_quote! { ::serde_json }), - kube_core: Override::Default(parse_quote! { ::kube::core }), - schemars: Override::Default(parse_quote! { ::schemars }), - serde: Override::Default(parse_quote! { ::serde }), - } - } -} - -impl From for KubernetesCrateOptions { - fn from(args: KubernetesCrateArguments) -> Self { - let mut crate_options = Self::default(); - - if let Some(k8s_openapi) = args.k8s_openapi { - crate_options.k8s_openapi = Override::Overridden(k8s_openapi); - } - - if let Some(serde_json) = args.serde_json { - crate_options.serde_json = Override::Overridden(serde_json); - } - - if let Some(kube_core) = args.kube_core { - crate_options.kube_core = Override::Overridden(kube_core); - } - - if let Some(kube_client) = args.kube_client { - crate_options.kube_client = Override::Overridden(kube_client); - } - - if let Some(schemars) = args.schemars { - crate_options.schemars = Override::Overridden(schemars); - } - - if let Some(serde) = args.serde { - crate_options.serde = Override::Overridden(serde); - } - - if let Some(versioned) = args.versioned { - crate_options.versioned = Override::Overridden(versioned); - } - - crate_options - } -} - -impl ToTokens for KubernetesCrateOptions { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - let mut crate_overrides = TokenStream::new(); - - let KubernetesCrateOptions { - kube_client: _, - k8s_openapi, - serde_json, - kube_core, - schemars, - serde, - .. - } = self; - - if let Override::Overridden(k8s_openapi) = k8s_openapi { - crate_overrides.extend(quote! { k8s_openapi = #k8s_openapi, }); - } - - if let Override::Overridden(serde_json) = serde_json { - crate_overrides.extend(quote! { serde_json = #serde_json, }); - } - - if let Override::Overridden(kube_core) = kube_core { - crate_overrides.extend(quote! { kube_core = #kube_core, }); - } - - if let Override::Overridden(schemars) = schemars { - crate_overrides.extend(quote! { schemars = #schemars, }); - } - - if let Override::Overridden(serde) = serde { - crate_overrides.extend(quote! { serde = #serde, }); - } - - if !crate_overrides.is_empty() { - tokens.extend(quote! { , crates(#crate_overrides) }); - } - } -} - -/// Wraps a value to indicate whether it is original or has been overridden. -#[derive(Debug)] -pub enum Override { - Default(T), - Overridden(T), -} - -impl Deref for Override { - type Target = T; - - fn deref(&self) -> &Self::Target { - match &self { - Override::Default(inner) => inner, - Override::Overridden(inner) => inner, - } - } -} - -#[derive(Debug)] -pub struct KubernetesConfigOptions { - experimental_conversion_tracking: bool, -} - -impl From for KubernetesConfigOptions { - fn from(options: RawKubernetesOptions) -> Self { - Self { - experimental_conversion_tracking: options.experimental_conversion_tracking.is_present(), - } - } -} diff --git a/crates/stackable-versioned-macros/src/codegen/container/struct.rs b/crates/stackable-versioned-macros/src/codegen/container/struct.rs index cbb428c91..c6aaf8873 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct.rs @@ -17,7 +17,7 @@ use crate::{ }; impl Container { - pub(crate) fn new_standalone_struct( + pub fn new_standalone_struct( item_struct: ItemStruct, attributes: StandaloneContainerAttributes, versions: &[VersionDefinition], @@ -31,12 +31,12 @@ impl Container { versioned_fields.push(versioned_field); } - let kubernetes_options = attributes.kubernetes_arguments.map(Into::into); - let idents = ContainerIdents::from(item_struct.ident, kubernetes_options.as_ref()); + let kubernetes_arguments = attributes.kubernetes_arguments; + let idents = ContainerIdents::from(item_struct.ident, kubernetes_arguments.as_ref()); // Validate K8s specific requirements // Ensure that the struct name includes the 'Spec' suffix. - if kubernetes_options.is_some() && !idents.original.as_str().ends_with("Spec") { + if kubernetes_arguments.is_some() && !idents.original.as_str().ends_with("Spec") { return Err(Error::custom( "struct name needs to include the `Spec` suffix if Kubernetes features are enabled via `#[versioned(k8s())]`" ).with_span(&idents.original.span())); @@ -48,7 +48,7 @@ impl Container { .options .skip .is_some_and(|s| s.from.is_present()), - kubernetes_options, + kubernetes_arguments, }; let common = CommonContainerData { @@ -65,7 +65,7 @@ impl Container { } // TODO (@Techassi): See what can be unified into a single 'new' function - pub(crate) fn new_struct_nested( + pub fn new_struct_nested( item_struct: ItemStruct, versions: &[VersionDefinition], ) -> Result { @@ -78,12 +78,12 @@ impl Container { versioned_fields.push(versioned_field); } - let kubernetes_options = attributes.kubernetes_arguments.map(Into::into); - let idents = ContainerIdents::from(item_struct.ident, kubernetes_options.as_ref()); + let kubernetes_arguments = attributes.kubernetes_arguments; + let idents = ContainerIdents::from(item_struct.ident, kubernetes_arguments.as_ref()); // Validate K8s specific requirements // Ensure that the struct name includes the 'Spec' suffix. - if kubernetes_options.is_some() && !idents.original.as_str().ends_with("Spec") { + if kubernetes_arguments.is_some() && !idents.original.as_str().ends_with("Spec") { return Err(Error::custom( "struct name needs to include the `Spec` suffix if Kubernetes features are enabled via `#[versioned(k8s())]`" ).with_span(&idents.original.span())); @@ -91,7 +91,7 @@ impl Container { let options = ContainerOptions { skip_from: attributes.options.skip.is_some_and(|s| s.from.is_present()), - kubernetes_options, + kubernetes_arguments, }; // Nested structs @@ -320,12 +320,12 @@ impl Struct { // Kubernetes-specific token generation impl Struct { pub fn generate_kube_attribute(&self, version: &VersionDefinition) -> Option { - let kubernetes_options = self.common.options.kubernetes_options.as_ref()?; + let kubernetes_arguments = self.common.options.kubernetes_arguments.as_ref()?; // Required arguments - let group = &kubernetes_options.group; + let group = &kubernetes_arguments.group; let version = version.inner.to_string(); - let kind = kubernetes_options + let kind = kubernetes_arguments .kind .as_ref() .map_or(self.common.idents.kubernetes.to_string(), |kind| { @@ -333,26 +333,28 @@ impl Struct { }); // Optional arguments - let singular = kubernetes_options + let singular = kubernetes_arguments .singular .as_ref() .map(|s| quote! { , singular = #s }); - let plural = kubernetes_options + let plural = kubernetes_arguments .plural .as_ref() .map(|p| quote! { , plural = #p }); - let namespaced = kubernetes_options + let namespaced = kubernetes_arguments .namespaced + .is_present() .then_some(quote! { , namespaced }); - let crates = kubernetes_options.crates.to_token_stream(); + let crates = kubernetes_arguments.crates.to_token_stream(); let status = match ( - kubernetes_options - .config_options - .experimental_conversion_tracking, - &kubernetes_options.status, + kubernetes_arguments + .options + .experimental_conversion_tracking + .is_present(), + &kubernetes_arguments.status, ) { (true, _) => { // TODO (@Techassi): This struct name should be defined once in a single place instead @@ -367,7 +369,7 @@ impl Struct { (_, _) => None, }; - let shortnames: TokenStream = kubernetes_options + let shortnames: TokenStream = kubernetes_arguments .shortnames .iter() .map(|s| quote! { , shortname = #s }) @@ -389,10 +391,14 @@ impl Struct { &self, version: &VersionDefinition, ) -> Option<(IdentString, String, TokenStream)> { - let kubernetes_options = self.common.options.kubernetes_options.as_ref()?; + let kubernetes_arguments = self.common.options.kubernetes_arguments.as_ref()?; - if !kubernetes_options.skip_merged_crd { - let kube_core_crate = &*kubernetes_options.crates.kube_core; + if !kubernetes_arguments + .skip + .as_ref() + .is_some_and(|s| s.merged_crd.is_present()) + { + let kube_core_crate = &*kubernetes_arguments.crates.kube_core; let enum_variant_ident = version.inner.as_variant_ident(); let enum_variant_string = version.inner.to_string(); @@ -419,9 +425,13 @@ impl Struct { vis: &Visibility, is_nested: bool, ) -> Option { - let kubernetes_options = self.common.options.kubernetes_options.as_ref()?; + let kubernetes_arguments = self.common.options.kubernetes_arguments.as_ref()?; - if !kubernetes_options.skip_merged_crd { + if !kubernetes_arguments + .skip + .as_ref() + .is_some_and(|s| s.merged_crd.is_present()) + { let enum_ident = &self.common.idents.kubernetes; // Only add the #[automatically_derived] attribute if this impl is used outside of a @@ -429,8 +439,8 @@ impl Struct { let automatically_derived = is_nested.not().then(|| quote! {#[automatically_derived]}); // Get the crate paths - let k8s_openapi_path = &*kubernetes_options.crates.k8s_openapi; - let kube_core_path = &*kubernetes_options.crates.kube_core; + let k8s_openapi_path = &*kubernetes_arguments.crates.k8s_openapi; + let kube_core_path = &*kubernetes_arguments.crates.kube_core; Some(quote! { #automatically_derived @@ -463,23 +473,24 @@ impl Struct { } pub fn generate_kubernetes_status_struct(&self) -> Option { - let kubernetes_options = self.common.options.kubernetes_options.as_ref()?; + let kubernetes_arguments = self.common.options.kubernetes_arguments.as_ref()?; - kubernetes_options - .config_options + kubernetes_arguments + .options .experimental_conversion_tracking + .is_present() .then(|| { let status_ident = format_ident!( "{struct_ident}StatusWithChangedValues", struct_ident = self.common.idents.kubernetes.as_ident() ); - let versioned_crate = &*kubernetes_options.crates.versioned; - let schemars_crate = &*kubernetes_options.crates.schemars; - let serde_crate = &*kubernetes_options.crates.serde; + let versioned_crate = &*kubernetes_arguments.crates.versioned; + let schemars_crate = &*kubernetes_arguments.crates.schemars; + let serde_crate = &*kubernetes_arguments.crates.serde; // TODO (@Techassi): Validate that users don't specify the status we generate - let status = kubernetes_options.status.as_ref().map(|status| { + let status = kubernetes_arguments.status.as_ref().map(|status| { quote! { #[serde(flatten)] pub status: #status, diff --git a/crates/stackable-versioned-macros/src/codegen/item/field.rs b/crates/stackable-versioned-macros/src/codegen/item/field.rs index c039e9873..358a94000 100644 --- a/crates/stackable-versioned-macros/src/codegen/item/field.rs +++ b/crates/stackable-versioned-macros/src/codegen/item/field.rs @@ -15,15 +15,15 @@ use crate::{ utils::FieldIdent, }; -pub(crate) struct VersionedField { - pub(crate) original_attributes: Vec, - pub(crate) changes: Option>, - pub(crate) ident: FieldIdent, - pub(crate) ty: Type, +pub struct VersionedField { + pub original_attributes: Vec, + pub changes: Option>, + pub ident: FieldIdent, + pub ty: Type, } impl VersionedField { - pub(crate) fn new(field: Field, versions: &[VersionDefinition]) -> Result { + pub fn new(field: Field, versions: &[VersionDefinition]) -> Result { let field_attributes = FieldAttributes::from_field(&field)?; field_attributes.validate_versions(versions)?; @@ -44,16 +44,13 @@ impl VersionedField { }) } - pub(crate) fn insert_container_versions(&mut self, versions: &[VersionDefinition]) { + pub fn insert_container_versions(&mut self, versions: &[VersionDefinition]) { if let Some(changes) = &mut self.changes { changes.insert_container_versions(versions, &self.ty); } } - pub(crate) fn generate_for_container( - &self, - version: &VersionDefinition, - ) -> Option { + pub fn generate_for_container(&self, version: &VersionDefinition) -> Option { let original_attributes = &self.original_attributes; match &self.changes { diff --git a/crates/stackable-versioned-macros/src/codegen/item/mod.rs b/crates/stackable-versioned-macros/src/codegen/item/mod.rs index 2c1d5f151..8c7ce2b66 100644 --- a/crates/stackable-versioned-macros/src/codegen/item/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/item/mod.rs @@ -1,5 +1,5 @@ mod field; -pub(crate) use field::*; +pub use field::*; mod variant; -pub(crate) use variant::*; +pub use variant::*; diff --git a/crates/stackable-versioned-macros/src/codegen/item/variant.rs b/crates/stackable-versioned-macros/src/codegen/item/variant.rs index 24c62f76b..54bf34c37 100644 --- a/crates/stackable-versioned-macros/src/codegen/item/variant.rs +++ b/crates/stackable-versioned-macros/src/codegen/item/variant.rs @@ -15,15 +15,15 @@ use crate::{ utils::VariantIdent, }; -pub(crate) struct VersionedVariant { - pub(crate) original_attributes: Vec, - pub(crate) changes: Option>, - pub(crate) ident: VariantIdent, - pub(crate) fields: Fields, +pub struct VersionedVariant { + pub original_attributes: Vec, + pub changes: Option>, + pub ident: VariantIdent, + pub fields: Fields, } impl VersionedVariant { - pub(crate) fn new(variant: Variant, versions: &[VersionDefinition]) -> Result { + pub fn new(variant: Variant, versions: &[VersionDefinition]) -> Result { let variant_attributes = VariantAttributes::from_variant(&variant)?; variant_attributes.validate_versions(versions)?; @@ -45,7 +45,7 @@ impl VersionedVariant { }) } - pub(crate) fn insert_container_versions(&mut self, versions: &[VersionDefinition]) { + pub fn insert_container_versions(&mut self, versions: &[VersionDefinition]) { if let Some(changes) = &mut self.changes { // FIXME (@Techassi): Support enum variants with data let ty = Type::Never(TypeNever { @@ -57,10 +57,7 @@ impl VersionedVariant { } /// Generates tokens to be used in a container definition. - pub(crate) fn generate_for_container( - &self, - version: &VersionDefinition, - ) -> Option { + pub fn generate_for_container(&self, version: &VersionDefinition) -> Option { let original_attributes = &self.original_attributes; let fields = &self.fields; diff --git a/crates/stackable-versioned-macros/src/codegen/mod.rs b/crates/stackable-versioned-macros/src/codegen/mod.rs index 88bf340c6..73f5d5c5c 100644 --- a/crates/stackable-versioned-macros/src/codegen/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/mod.rs @@ -5,27 +5,27 @@ use syn::{Path, Type}; use crate::attrs::{container::StandaloneContainerAttributes, module::ModuleAttributes}; -pub(crate) mod changes; -pub(crate) mod container; -pub(crate) mod item; -pub(crate) mod module; +pub mod changes; +pub mod container; +pub mod item; +pub mod module; #[derive(Debug)] -pub(crate) struct VersionDefinition { +pub struct VersionDefinition { /// Indicates that the container version is deprecated. - pub(crate) deprecated: Option, + pub deprecated: Option, /// Indicates that the generation of `From for NEW` should be skipped. - pub(crate) skip_from: bool, + pub skip_from: bool, /// A validated Kubernetes API version. - pub(crate) inner: Version, + pub inner: Version, /// The ident of the container. - pub(crate) ident: IdentString, + pub ident: IdentString, /// Store additional doc-comment lines for this version. - pub(crate) docs: Vec, + pub docs: Vec, } // NOTE (@Techassi): Can we maybe unify these two impls? @@ -102,7 +102,7 @@ pub enum ItemStatus { } impl ItemStatus { - pub(crate) fn get_ident(&self) -> &IdentString { + pub fn get_ident(&self) -> &IdentString { match &self { ItemStatus::Addition { ident, .. } => ident, ItemStatus::Change { to_ident, .. } => to_ident, diff --git a/crates/stackable-versioned-macros/src/codegen/module.rs b/crates/stackable-versioned-macros/src/codegen/module.rs index 11e84e47c..96c650fba 100644 --- a/crates/stackable-versioned-macros/src/codegen/module.rs +++ b/crates/stackable-versioned-macros/src/codegen/module.rs @@ -10,7 +10,7 @@ use crate::{ codegen::{VersionDefinition, container::Container}, }; -pub(crate) type KubernetesItems = (Vec, Vec, Vec); +pub type KubernetesItems = (Vec, Vec, Vec); /// A versioned module. /// diff --git a/crates/stackable-versioned-macros/src/test_utils.rs b/crates/stackable-versioned-macros/src/test_utils.rs index d3f14cbb8..95598eafa 100644 --- a/crates/stackable-versioned-macros/src/test_utils.rs +++ b/crates/stackable-versioned-macros/src/test_utils.rs @@ -20,7 +20,7 @@ static REGEX: LazyLock = LazyLock::new(|| { }); #[derive(Debug, Snafu)] -pub(crate) enum Error { +pub enum Error { #[snafu(display("failed to read input file"))] ReadFile { source: std::io::Error }, @@ -40,7 +40,7 @@ pub(crate) enum Error { ParseOutputFile { source: syn::Error }, } -pub(crate) fn expand_from_file(path: &Path) -> Result { +pub fn expand_from_file(path: &Path) -> Result { let input = std::fs::read_to_string(path).context(ReadFileSnafu)?; let (attrs, input) = prepare_from_string(input)?; @@ -73,7 +73,7 @@ fn prepare_from_string(input: String) -> Result<(TokenStream, Item), Error> { Ok((attrs, input)) } -pub(crate) fn set_snapshot_path() -> Settings { +pub fn set_snapshot_path() -> Settings { let dir = std::env::var("CARGO_MANIFEST_DIR").expect("env var CARGO_MANIFEST_DIR must be set"); let mut settings = Settings::clone_current(); settings.set_snapshot_path(PathBuf::from(dir).join("tests/snapshots")); diff --git a/crates/stackable-versioned-macros/src/utils.rs b/crates/stackable-versioned-macros/src/utils.rs index 1109884cd..a682f581b 100644 --- a/crates/stackable-versioned-macros/src/utils.rs +++ b/crates/stackable-versioned-macros/src/utils.rs @@ -6,7 +6,7 @@ use k8s_version::Version; use quote::{ToTokens, format_ident}; use syn::{Ident, spanned::Spanned}; -pub(crate) trait VersionExt { +pub trait VersionExt { fn as_variant_ident(&self) -> IdentString; } @@ -17,7 +17,7 @@ impl VersionExt for Version { } /// Provides extra functionality on top of [`IdentString`]s used to name containers. -pub(crate) trait ContainerIdentExt { +pub trait ContainerIdentExt { /// Removes the 'Spec' suffix from the [`IdentString`]. fn as_cleaned_kubernetes_ident(&self) -> IdentString; @@ -37,7 +37,7 @@ impl ContainerIdentExt for Ident { } } -pub(crate) trait ItemIdentExt: Deref + From + Spanned { +pub trait ItemIdentExt: Deref + From + Spanned { const DEPRECATED_PREFIX: &'static str; fn deprecated_prefix(&self) -> &'static str { @@ -52,7 +52,7 @@ pub(crate) trait ItemIdentExt: Deref + From + Spann fn as_cleaned_ident(&self) -> IdentString; } -pub(crate) struct FieldIdent(IdentString); +pub struct FieldIdent(IdentString); impl ItemIdentExt for FieldIdent { const DEPRECATED_PREFIX: &'static str = "deprecated_"; @@ -84,7 +84,7 @@ impl ToTokens for FieldIdent { } } -pub(crate) struct VariantIdent(IdentString); +pub struct VariantIdent(IdentString); impl ItemIdentExt for VariantIdent { const DEPRECATED_PREFIX: &'static str = "Deprecated"; diff --git a/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.rs b/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.rs index 2d17aa768..1ca047717 100644 --- a/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.rs +++ b/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.rs @@ -4,12 +4,14 @@ fn main() { #[versioned( version(name = "v1alpha1"), version(name = "v1beta1"), - version(name = "v1") + version(name = "v1"), + version(name = "v2") )] struct Foo { #[versioned( changed(since = "v1beta1", from_name = "deprecated_bar"), - changed(since = "v1", from_name = "deprecated_baz") + changed(since = "v1", from_name = "deprecated_baz"), + changed(since = "v2") )] bar: usize, } diff --git a/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.stderr b/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.stderr index 5290e5db3..da1a7063b 100644 --- a/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.stderr +++ b/crates/stackable-versioned-macros/tests/inputs/default/fail/changed.stderr @@ -1,11 +1,17 @@ error: the previous name must not start with the deprecation prefix - --> tests/inputs/default/fail/changed.rs:11:52 + --> tests/inputs/default/fail/changed.rs:12:52 | -11 | changed(since = "v1beta1", from_name = "deprecated_bar"), +12 | changed(since = "v1beta1", from_name = "deprecated_bar"), | ^^^^^^^^^^^^^^^^ error: the previous name must not start with the deprecation prefix - --> tests/inputs/default/fail/changed.rs:12:47 + --> tests/inputs/default/fail/changed.rs:13:47 | -12 | changed(since = "v1", from_name = "deprecated_baz") +13 | changed(since = "v1", from_name = "deprecated_baz"), | ^^^^^^^^^^^^^^^^ + +error: both `from_name` and `from_type` are unset. Is this `changed()` action needed? + --> tests/inputs/default/fail/changed.rs:14:29 + | +14 | changed(since = "v2") + | ^^^^