Skip to content

Commit 46acd20

Browse files
committed
refactor(stackable-versioned): Simplify and improve From code generation
1 parent 4f550c3 commit 46acd20

File tree

6 files changed

+197
-389
lines changed

6 files changed

+197
-389
lines changed

crates/stackable-versioned-macros/src/codegen/container/enum.rs

Lines changed: 61 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
codegen::{
1111
ItemStatus, StandaloneContainerAttributes, VersionDefinition,
1212
changes::Neighbors,
13-
container::{CommonContainerData, Container, ContainerIdents, ContainerOptions},
13+
container::{CommonContainerData, Container, ContainerIdents, ContainerOptions, Direction},
1414
item::VersionedVariant,
1515
},
1616
};
@@ -122,9 +122,10 @@ impl Enum {
122122
}
123123
}
124124

125-
/// Generates code for the `From<Version> for NextVersion` implementation.
126-
pub fn generate_upgrade_from_impl(
125+
// TODO (@Techassi): Add doc comments
126+
pub fn generate_from_impl(
127127
&self,
128+
direction: Direction,
128129
version: &VersionDefinition,
129130
next_version: Option<&VersionDefinition>,
130131
add_attributes: bool,
@@ -133,119 +134,69 @@ impl Enum {
133134
return None;
134135
}
135136

136-
match next_version {
137-
Some(next_version) => {
138-
// TODO (@Techassi): Support generic types which have been removed in newer versions,
139-
// but need to exist for older versions How do we represent that? Because the
140-
// defined struct always represents the latest version. I guess we could generally
141-
// advise against using generic types, but if you have to, avoid removing it in
142-
// later versions.
143-
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
144-
let from_enum_ident = &self.common.idents.parameter;
145-
let enum_ident = &self.common.idents.original;
146-
147-
let for_module_ident = &next_version.idents.module;
148-
let from_module_ident = &version.idents.module;
149-
150-
let variants: TokenStream = self
151-
.variants
152-
.iter()
153-
.filter_map(|v| {
154-
v.generate_for_upgrade_from_impl(version, next_version, enum_ident)
155-
})
156-
.collect();
157-
158-
// Include allow(deprecated) only when this or the next version is
159-
// deprecated. Also include it, when a variant in this or the next
160-
// version is deprecated.
161-
let allow_attribute = (version.deprecated.is_some()
162-
|| next_version.deprecated.is_some()
163-
|| self.is_any_variant_deprecated(version)
164-
|| self.is_any_variant_deprecated(next_version))
165-
.then_some(quote! { #[allow(deprecated)] });
166-
167-
// Only add the #[automatically_derived] attribute only if this impl is used
168-
// outside of a module (in standalone mode).
169-
let automatically_derived = add_attributes
170-
.not()
171-
.then(|| quote! {#[automatically_derived]});
172-
173-
Some(quote! {
174-
#automatically_derived
175-
#allow_attribute
176-
impl #impl_generics ::std::convert::From<#from_module_ident::#enum_ident #type_generics> for #for_module_ident::#enum_ident #type_generics
177-
#where_clause
178-
{
179-
fn from(#from_enum_ident: #from_module_ident::#enum_ident #type_generics) -> Self {
180-
match #from_enum_ident {
181-
#variants
182-
}
183-
}
184-
}
185-
})
186-
}
187-
None => None,
188-
}
189-
}
190-
191-
pub fn generate_downgrade_from_impl(
192-
&self,
193-
version: &VersionDefinition,
194-
next_version: Option<&VersionDefinition>,
195-
add_attributes: bool,
196-
) -> Option<TokenStream> {
197-
if version.skip_from || self.common.options.skip_from {
198-
return None;
199-
}
200-
201-
match next_version {
202-
Some(next_version) => {
203-
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
204-
let from_enum_ident = &self.common.idents.parameter;
205-
let enum_ident = &self.common.idents.original;
206-
207-
let from_module_ident = &next_version.idents.module;
208-
let for_module_ident = &version.idents.module;
209-
210-
let variants: TokenStream = self
211-
.variants
137+
next_version.map(|next_version| {
138+
// TODO (@Techassi): Support generic types which have been removed in newer versions,
139+
// but need to exist for older versions How do we represent that? Because the
140+
// defined struct always represents the latest version. I guess we could generally
141+
// advise against using generic types, but if you have to, avoid removing it in
142+
// later versions.
143+
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
144+
let from_enum_ident = &self.common.idents.parameter;
145+
let enum_ident = &self.common.idents.original;
146+
147+
// Include allow(deprecated) only when this or the next version is
148+
// deprecated. Also include it, when a variant in this or the next
149+
// version is deprecated.
150+
let allow_attribute = (version.deprecated.is_some()
151+
|| next_version.deprecated.is_some()
152+
|| self.is_any_variant_deprecated(version)
153+
|| self.is_any_variant_deprecated(next_version))
154+
.then_some(quote! { #[allow(deprecated)] });
155+
156+
// Only add the #[automatically_derived] attribute only if this impl is used
157+
// outside of a module (in standalone mode).
158+
let automatically_derived = add_attributes
159+
.not()
160+
.then(|| quote! {#[automatically_derived]});
161+
162+
let variants = |direction: Direction| -> TokenStream {
163+
self.variants
212164
.iter()
213165
.filter_map(|v| {
214-
v.generate_for_downgrade_from_impl(version, next_version, enum_ident)
166+
v.generate_for_from_impl(direction, version, next_version, enum_ident)
215167
})
216-
.collect();
217-
218-
// Include allow(deprecated) only when this or the next version is
219-
// deprecated. Also include it, when a variant in this or the next
220-
// version is deprecated.
221-
let allow_attribute = (version.deprecated.is_some()
222-
|| next_version.deprecated.is_some()
223-
|| self.is_any_variant_deprecated(version)
224-
|| self.is_any_variant_deprecated(next_version))
225-
.then_some(quote! { #[allow(deprecated)] });
226-
227-
// Only add the #[automatically_derived] attribute only if this impl is used
228-
// outside of a module (in standalone mode).
229-
let automatically_derived = add_attributes
230-
.not()
231-
.then(|| quote! {#[automatically_derived]});
232-
233-
Some(quote! {
234-
#automatically_derived
235-
#allow_attribute
236-
impl #impl_generics ::std::convert::From<#from_module_ident::#enum_ident #type_generics> for #for_module_ident::#enum_ident #type_generics
237-
#where_clause
238-
{
239-
fn from(#from_enum_ident: #from_module_ident::#enum_ident #type_generics) -> Self {
240-
match #from_enum_ident {
241-
#variants
242-
}
168+
.collect()
169+
};
170+
171+
let (variants, for_module_ident, from_module_ident) = match direction {
172+
Direction::Upgrade => {
173+
let for_module_ident = &next_version.idents.module;
174+
let from_module_ident = &version.idents.module;
175+
176+
(variants(Direction::Upgrade), for_module_ident, from_module_ident)
177+
},
178+
Direction::Downgrade => {
179+
let for_module_ident = &version.idents.module;
180+
let from_module_ident = &next_version.idents.module;
181+
182+
(variants(Direction::Downgrade), for_module_ident, from_module_ident)
183+
},
184+
};
185+
186+
quote! {
187+
#automatically_derived
188+
#allow_attribute
189+
impl #impl_generics ::std::convert::From<#from_module_ident::#enum_ident #type_generics> for #for_module_ident::#enum_ident #type_generics
190+
#where_clause
191+
{
192+
fn from(#from_enum_ident: #from_module_ident::#enum_ident #type_generics) -> Self {
193+
match #from_enum_ident {
194+
#variants
243195
}
244196
}
245-
})
197+
}
246198
}
247-
None => None,
248-
}
199+
})
249200
}
250201

251202
/// Returns whether any variant is deprecated in the provided `version`.

crates/stackable-versioned-macros/src/codegen/container/mod.rs

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,36 +46,20 @@ impl Container {
4646
}
4747
}
4848

49-
/// Generates the `From<Version> for NextVersion` implementation for the container.
50-
pub fn generate_upgrade_from_impl(
49+
pub fn generate_from_impl(
5150
&self,
51+
direction: Direction,
5252
version: &VersionDefinition,
5353
next_version: Option<&VersionDefinition>,
5454
add_attributes: bool,
5555
) -> Option<TokenStream> {
5656
match self {
5757
Container::Struct(s) => {
58-
s.generate_upgrade_from_impl(version, next_version, add_attributes)
58+
// TODO (@Techassi): Decide here (based on K8s args) what we want to generate
59+
s.generate_from_impl(direction, version, next_version, add_attributes)
5960
}
6061
Container::Enum(e) => {
61-
e.generate_upgrade_from_impl(version, next_version, add_attributes)
62-
}
63-
}
64-
}
65-
66-
/// Generates the `From<NextVersion> for Version` implementation for the container.
67-
pub fn generate_downgrade_from_impl(
68-
&self,
69-
version: &VersionDefinition,
70-
next_version: Option<&VersionDefinition>,
71-
add_attributes: bool,
72-
) -> Option<TokenStream> {
73-
match self {
74-
Container::Struct(s) => {
75-
s.generate_downgrade_from_impl(version, next_version, add_attributes)
76-
}
77-
Container::Enum(e) => {
78-
e.generate_downgrade_from_impl(version, next_version, add_attributes)
62+
e.generate_from_impl(direction, version, next_version, add_attributes)
7963
}
8064
}
8165
}
@@ -183,12 +167,15 @@ impl StandaloneContainer {
183167
// Generate the From impl for upgrading the CRD.
184168
let upgrade_from_impl =
185169
self.container
186-
.generate_upgrade_from_impl(version, next_version, false);
170+
.generate_from_impl(Direction::Upgrade, version, next_version, false);
187171

188172
// Generate the From impl for downgrading the CRD.
189-
let downgrade_from_impl =
190-
self.container
191-
.generate_downgrade_from_impl(version, next_version, false);
173+
let downgrade_from_impl = self.container.generate_from_impl(
174+
Direction::Downgrade,
175+
version,
176+
next_version,
177+
false,
178+
);
192179

193180
// Add the #[deprecated] attribute when the version is marked as deprecated.
194181
let deprecated_attribute = version
@@ -287,3 +274,9 @@ pub struct ContainerOptions {
287274
pub kubernetes_arguments: Option<KubernetesArguments>,
288275
pub skip_from: bool,
289276
}
277+
278+
#[derive(Copy, Clone, Debug)]
279+
pub enum Direction {
280+
Upgrade,
281+
Downgrade,
282+
}

0 commit comments

Comments
 (0)