Skip to content

feat(stackable-versioned): Add basic handling for enum variants with data #892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/stackable-versioned-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ all-features = true
# are, however, used in K8s specific test cases. This is a false-positive and an
# apparent limitation of cargo-udeps. These entries can be removed once
# cargo-udeps supports detecting usage of such dependencies.
development = ["schemars", "serde_yaml", "stackable-versioned"]
development = ["k8s-openapi", "schemars", "serde_yaml", "stackable-versioned"]

# cargo-udeps throws an error stating that these dependencies are unused. They are all marked as
# optional, which trips up cargo-udeps for whatever reason...
Expand Down Expand Up @@ -45,6 +45,7 @@ quote.workspace = true
[dev-dependencies]
# Only needed for doc tests / examples
stackable-versioned = { path = "../stackable-versioned", features = ["k8s"] }
k8s-openapi = { workspace = true }

insta.workspace = true
prettyplease.workspace = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#[versioned(version(name = "v1alpha1"), version(name = "v1alpha2"))]
// ---
enum Foo {
Foo,
Bar(u32, String),

#[versioned(added(since = "v1alpha2"))]
Baz {
id: u32,
name: String,
},
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 42 additions & 9 deletions crates/stackable-versioned-macros/src/codegen/venum/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ops::{Deref, DerefMut};

use darling::FromVariant;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use quote::{format_ident, quote};
use syn::{token::Not, Ident, Type, TypeNever, Variant};

use crate::{
Expand Down Expand Up @@ -104,6 +104,7 @@ impl VersionedVariant {
container_version: &ContainerVersion,
) -> Option<TokenStream> {
let original_attributes = &self.original_attributes;
let fields = &self.inner.fields;

match &self.chain {
// NOTE (@Techassi): https://rust-lang.github.io/rust-clippy/master/index.html#/expect_fun_call
Expand All @@ -115,11 +116,11 @@ impl VersionedVariant {
}) {
ItemStatus::Addition { ident, .. } => Some(quote! {
#(#original_attributes)*
#ident,
#ident #fields,
}),
ItemStatus::Change { to_ident, .. } => Some(quote! {
#(#original_attributes)*
#to_ident,
#to_ident #fields,
}),
ItemStatus::Deprecation { ident, note, .. } => {
// FIXME (@Techassi): Emitting the deprecated attribute
Expand All @@ -139,7 +140,7 @@ impl VersionedVariant {
Some(quote! {
#(#original_attributes)*
#deprecated_attr
#ident,
#ident #fields,
})
}
ItemStatus::NoChange {
Expand All @@ -154,7 +155,7 @@ impl VersionedVariant {
Some(quote! {
#(#original_attributes)*
#deprecated_attr
#ident,
#ident #fields,
})
}
ItemStatus::NotPresent => None,
Expand All @@ -163,11 +164,11 @@ impl VersionedVariant {
// If there is no chain of variant actions, the variant is not
// versioned and code generation is straight forward.
// Unversioned variants are always included in versioned enums.
let variant_ident = &self.inner.ident;
let ident = &self.inner.ident;

Some(quote! {
#(#original_attributes)*
#variant_ident,
#ident #fields,
})
}
}
Expand All @@ -182,6 +183,38 @@ impl VersionedVariant {
next_version: &ContainerVersion,
enum_ident: &Ident,
) -> TokenStream {
let variant_data = match &self.inner.fields {
syn::Fields::Named(fields_named) => {
let field_names = fields_named
.named
.iter()
.map(|field| {
field
.ident
.as_ref()
.expect("named fields always have an ident")
.clone()
})
.collect::<Vec<_>>();

let tokens = quote! { { #(#field_names),* } };
tokens
}
syn::Fields::Unnamed(fields_unnamed) => {
let field_names = fields_unnamed
.unnamed
.iter()
.enumerate()
.map(|(index, _)| format_ident!("__sv_{index}"))
.collect::<Vec<_>>();

let tokens = quote! { ( #(#field_names),* ) };
tokens
}

syn::Fields::Unit => TokenStream::new(),
};

match &self.chain {
Some(chain) => match (
chain.get_expect(&version.inner),
Expand All @@ -197,15 +230,15 @@ impl VersionedVariant {
.expect("internal error: next variant must have a name");

quote! {
#module_name::#enum_ident::#old_variant_ident => #next_module_name::#enum_ident::#next_variant_ident,
#module_name::#enum_ident::#old_variant_ident #variant_data => #next_module_name::#enum_ident::#next_variant_ident #variant_data,
}
}
},
None => {
let variant_ident = &self.inner.ident;

quote! {
#module_name::#enum_ident::#variant_ident => #next_module_name::#enum_ident::#variant_ident,
#module_name::#enum_ident::#variant_ident #variant_data => #next_module_name::#enum_ident::#variant_ident #variant_data,
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/stackable-versioned-macros/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::versioned_impl;
const DELIMITER: &str = "// ---\n";

static REGEX: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"#\[versioned\(\n(?P<args>[[:ascii:]]+)\n\)\]")
Regex::new(r"#\[versioned\(\s*(?P<args>[[:ascii:]]+)\s*\)\]")
.expect("failed to compile versioned regex")
});

Expand Down Expand Up @@ -55,7 +55,7 @@ fn prepare_from_string(input: String) -> Result<(TokenStream, DeriveInput), Erro

let attrs = REGEX
.captures(attrs)
.unwrap()
.expect("the regex did not match")
.name("args")
.context(MissingRegexMatchGroupSnafu)?
.as_str();
Expand Down
10 changes: 10 additions & 0 deletions crates/stackable-versioned/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- Add basic handling for enum variants with data ([#892]).

### Fixed

- Accept a wider variety of formatting styles in the macro testing regex ([#892]).

[#892]: https://github.com/stackabletech/operator-rs/pull/892

## [0.4.0] - 2024-10-14

### Added
Expand Down
Loading