Skip to content

Commit

Permalink
feat(stackable-versioned): Add basic handling for enum variants with …
Browse files Browse the repository at this point in the history
…data (#892)

* fix(stackable-versioned): allow various formatting styles for macro in testing regex

* fix(stackable-versioned): add k8s-openapi as a dev-dependency

* feat(stackable-versioned): basic handling for enum variants with data

* chore(stackable-versioned): Update changelog

* chore(stackable-versioned): Make udeps happy with k8s-openapi
  • Loading branch information
NickLarsenNZ authored Oct 15, 2024
1 parent cb4218b commit 244eda7
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 12 deletions.
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

0 comments on commit 244eda7

Please sign in to comment.