Skip to content

Commit fb625b2

Browse files
committed
fix(stackable-versioned): Correctly emit enum fields in From impls
1 parent 48f8aad commit fb625b2

File tree

4 files changed

+169
-38
lines changed

4 files changed

+169
-38
lines changed

crates/stackable-versioned-macros/src/codegen/item/variant.rs

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use darling::{FromVariant, Result, util::IdentString};
44
use k8s_version::Version;
55
use proc_macro2::{Span, TokenStream};
66
use quote::{format_ident, quote};
7-
use syn::{Attribute, Fields, Type, TypeNever, Variant, token::Not};
7+
use syn::{
8+
Attribute, Fields, FieldsNamed, FieldsUnnamed, Ident, Type, TypeNever, Variant, token::Not,
9+
};
810

911
use crate::{
1012
attrs::item::VariantAttributes,
@@ -138,7 +140,8 @@ impl VersionedVariant {
138140
next_version: &VersionDefinition,
139141
enum_ident: &IdentString,
140142
) -> Option<TokenStream> {
141-
let variant_fields = self.fields_as_token_stream();
143+
let from_fields = self.generate_from_fields();
144+
let for_fields = self.generate_for_fields();
142145

143146
match &self.changes {
144147
Some(changes) => {
@@ -154,16 +157,15 @@ impl VersionedVariant {
154157
let next_variant_ident = next.get_ident();
155158
let old_variant_ident = old.get_ident();
156159

157-
let old = quote! {
158-
#old_version_ident::#enum_ident::#old_variant_ident #variant_fields
159-
};
160-
let next = quote! {
161-
#next_version_ident::#enum_ident::#next_variant_ident #variant_fields
162-
};
163-
164160
match direction {
165-
Direction::Upgrade => Some(quote! { #old => #next, }),
166-
Direction::Downgrade => Some(quote! { #next => #old, }),
161+
Direction::Upgrade => Some(quote! {
162+
#old_version_ident::#enum_ident::#old_variant_ident #from_fields
163+
=> #next_version_ident::#enum_ident::#next_variant_ident #for_fields,
164+
}),
165+
Direction::Downgrade => Some(quote! {
166+
#next_version_ident::#enum_ident::#next_variant_ident #from_fields
167+
=> #old_version_ident::#enum_ident::#old_variant_ident #from_fields,
168+
}),
167169
}
168170
}
169171
}
@@ -173,48 +175,67 @@ impl VersionedVariant {
173175
let old_version_ident = &version.idents.module;
174176
let variant_ident = &*self.ident;
175177

176-
let old = quote! {
177-
#old_version_ident::#enum_ident::#variant_ident #variant_fields
178-
};
179-
let next = quote! {
180-
#next_version_ident::#enum_ident::#variant_ident #variant_fields
181-
};
182-
183178
match direction {
184-
Direction::Upgrade => Some(quote! { #old => #next, }),
185-
Direction::Downgrade => Some(quote! { #next => #old, }),
179+
Direction::Upgrade => Some(quote! {
180+
#old_version_ident::#enum_ident::#variant_ident #from_fields
181+
=> #next_version_ident::#enum_ident::#variant_ident #for_fields,
182+
}),
183+
Direction::Downgrade => Some(quote! {
184+
#next_version_ident::#enum_ident::#variant_ident #from_fields
185+
=> #old_version_ident::#enum_ident::#variant_ident #for_fields,
186+
}),
186187
}
187188
}
188189
}
189190
}
190191

191-
fn fields_as_token_stream(&self) -> Option<TokenStream> {
192+
fn generate_for_fields(&self) -> Option<TokenStream> {
192193
match &self.fields {
193194
Fields::Named(fields_named) => {
194-
let fields: Vec<_> = fields_named
195-
.named
196-
.iter()
197-
.map(|field| {
198-
field
199-
.ident
200-
.as_ref()
201-
.expect("named fields always have an ident")
202-
})
203-
.collect();
195+
let fields = Self::named_field_idents(fields_named);
196+
Some(quote! { { #(#fields)*: #(#fields.into()),* } })
197+
}
198+
Fields::Unnamed(fields_unnamed) => {
199+
let fields = Self::unnamed_field_ident(fields_unnamed);
200+
Some(quote! { ( #(#fields.into()),* ) })
201+
}
202+
Fields::Unit => None,
203+
}
204+
}
204205

206+
fn generate_from_fields(&self) -> Option<TokenStream> {
207+
match &self.fields {
208+
Fields::Named(fields_named) => {
209+
let fields = Self::named_field_idents(fields_named);
205210
Some(quote! { { #(#fields),* } })
206211
}
207212
Fields::Unnamed(fields_unnamed) => {
208-
let fields: Vec<_> = fields_unnamed
209-
.unnamed
210-
.iter()
211-
.enumerate()
212-
.map(|(index, _)| format_ident!("__sv_{index}"))
213-
.collect();
214-
213+
let fields = Self::unnamed_field_ident(fields_unnamed);
215214
Some(quote! { ( #(#fields),* ) })
216215
}
217216
Fields::Unit => None,
218217
}
219218
}
219+
220+
fn named_field_idents(fields_named: &FieldsNamed) -> Vec<&Ident> {
221+
fields_named
222+
.named
223+
.iter()
224+
.map(|field| {
225+
field
226+
.ident
227+
.as_ref()
228+
.expect("named fields always have an ident")
229+
})
230+
.collect()
231+
}
232+
233+
fn unnamed_field_ident(fields_unnamed: &FieldsUnnamed) -> Vec<Ident> {
234+
fields_unnamed
235+
.unnamed
236+
.iter()
237+
.enumerate()
238+
.map(|(index, _)| format_ident!("__sv_{index}"))
239+
.collect()
240+
}
220241
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use stackable_versioned::versioned;
2+
// ---
3+
#[versioned(version(name = "v1alpha1"), version(name = "v1alpha2"))]
4+
// ---
5+
pub mod versioned {
6+
enum MyEnum {
7+
A { aa: usize },
8+
B { bb: bool },
9+
}
10+
11+
enum Bla {
12+
A(A),
13+
}
14+
15+
struct A {}
16+
}
17+
// ---
18+
fn main() {}

crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@enum_fields.rs.snap

Lines changed: 91 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/tests/trybuild.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod inputs {
2323
// mod crate_overrides;
2424
// mod docs;
2525
// mod downgrade_with;
26+
// mod enum_fields;
2627
// mod module;
2728
// mod module_preserve;
2829
// mod renamed_field;

0 commit comments

Comments
 (0)