Preserve order for grouped params, fix persist
...for nested but not grouped parameters. This was a regression in
4affa40244
.
This commit is contained in:
parent
cc313fcc2c
commit
a69526c758
|
@ -27,13 +27,12 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
// parameters. For the `persist` function we'll create functions that serialize and deserialize
|
// parameters. For the `persist` function we'll create functions that serialize and deserialize
|
||||||
// those fields individually (so they can be added and removed independently of eachother) using
|
// those fields individually (so they can be added and removed independently of eachother) using
|
||||||
// JSON. The `nested` fields should also implement the `Params` trait and their fields will be
|
// JSON. The `nested` fields should also implement the `Params` trait and their fields will be
|
||||||
// inherited and added to this field's lists. We'll also enforce that there are no duplicate
|
// inherited and added to this field's param mapping list. The order follows the declaration
|
||||||
// keys at compile time.
|
// order We'll also enforce that there are no duplicate keys for `id` fields at compile time.
|
||||||
// TODO: This duplication check doesn't work for nested fields since we don't know anything
|
// TODO: This duplication check doesn't work for nested fields since we don't know anything
|
||||||
// about the fields on the nested structs
|
// about the fields on the nested structs
|
||||||
let mut params: Vec<Param> = Vec::new();
|
let mut params: Vec<Param> = Vec::new();
|
||||||
let mut persistent_fields: Vec<PersistentField> = Vec::new();
|
let mut persistent_fields: Vec<PersistentField> = Vec::new();
|
||||||
let mut group_params: Vec<NestedParams> = Vec::new();
|
|
||||||
for field in fields.named {
|
for field in fields.named {
|
||||||
let field_name = match &field.ident {
|
let field_name = match &field.ident {
|
||||||
Some(ident) => ident,
|
Some(ident) => ident,
|
||||||
|
@ -133,7 +132,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if attr.path.is_ident("nested") {
|
} else if attr.path.is_ident("nested") {
|
||||||
// This one is more complicated. Support an `array` attribute, an `id_prefix =
|
// This one is more complicated. Supports an `array` attribute, an `id_prefix =
|
||||||
// "foo"` attribute, and a `group = "group name"` attribute. All are optional, and
|
// "foo"` attribute, and a `group = "group name"` attribute. All are optional, and
|
||||||
// the first two are mutually exclusive.
|
// the first two are mutually exclusive.
|
||||||
let mut nested_array = false;
|
let mut nested_array = false;
|
||||||
|
@ -207,7 +206,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let param = match (nested_array, nested_id_prefix) {
|
params.push(Param::Nested(match (nested_array, nested_id_prefix) {
|
||||||
(true, None) => NestedParams::Array {
|
(true, None) => NestedParams::Array {
|
||||||
field: field_name.clone(),
|
field: field_name.clone(),
|
||||||
group: nested_group,
|
group: nested_group,
|
||||||
|
@ -229,20 +228,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
.to_compile_error()
|
.to_compile_error()
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
};
|
}));
|
||||||
|
|
||||||
// Grouped parameters are handled differently than nested parameters:
|
|
||||||
// DAWs that support grouped parameters usually display parameter groups below "regular" ones
|
|
||||||
// in a tree view. To keep the order consistent with those, group parameters are collected
|
|
||||||
// separately, so they can be inserted at the end of the parameter list.
|
|
||||||
// Nested parameters without a group on the other hand are merely an implementation detail of
|
|
||||||
// the plugin and thus should not behave different than regular parameters to the user. Because
|
|
||||||
// of this, they are inserted alongside the "regular" ones.
|
|
||||||
if param.is_group() {
|
|
||||||
group_params.push(param);
|
|
||||||
} else {
|
|
||||||
params.push(Param::Nested(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
processed_attribute = true;
|
processed_attribute = true;
|
||||||
}
|
}
|
||||||
|
@ -263,8 +249,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
// The next step is build the gathered information into tokens that can be spliced into a
|
// The next step is build the gathered information into tokens that can be spliced into a
|
||||||
// `Params` implementation
|
// `Params` implementation
|
||||||
let param_map_tokens = {
|
let param_map_tokens = {
|
||||||
let param_mapping_self_tokens = params.into_iter().map(|p| p.to_token());
|
let param_mapping_tokens = params.iter().map(|p| p.param_map_tokens());
|
||||||
let param_mapping_group_tokens = group_params.iter().map(|p| p.to_token());
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
// This may not be in scope otherwise, used to call .as_ptr()
|
// This may not be in scope otherwise, used to call .as_ptr()
|
||||||
|
@ -272,8 +257,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut param_map = Vec::new();
|
let mut param_map = Vec::new();
|
||||||
#(param_map.extend(#param_mapping_self_tokens); )*
|
#(param_map.extend(#param_mapping_tokens); )*
|
||||||
#(param_map.extend(#param_mapping_group_tokens); )*
|
|
||||||
|
|
||||||
param_map
|
param_map
|
||||||
}
|
}
|
||||||
|
@ -330,8 +314,12 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
||||||
.unzip();
|
.unzip();
|
||||||
|
|
||||||
let (serialize_fields_nested_tokens, deserialize_fields_nested_tokens): (Vec<_>, Vec<_>) =
|
let (serialize_fields_nested_tokens, deserialize_fields_nested_tokens): (Vec<_>, Vec<_>) =
|
||||||
group_params
|
params
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter_map(|p| match p {
|
||||||
|
Param::Single { .. } => None,
|
||||||
|
Param::Nested(nested) => Some(nested),
|
||||||
|
})
|
||||||
.map(|nested| match nested {
|
.map(|nested| match nested {
|
||||||
NestedParams::Inline { field, .. } | NestedParams::Prefixed { field, .. } => (
|
NestedParams::Inline { field, .. } | NestedParams::Prefixed { field, .. } => (
|
||||||
// TODO: For some reason the macro won't parse correctly if you inline this
|
// TODO: For some reason the macro won't parse correctly if you inline this
|
||||||
|
@ -419,12 +407,14 @@ enum Param {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Param {
|
impl Param {
|
||||||
fn to_token(&self) -> proc_macro2::TokenStream {
|
/// Generate the tokens needed for a field (or nested parameter struct) to add itself to the
|
||||||
|
/// parameter map.
|
||||||
|
fn param_map_tokens(&self) -> proc_macro2::TokenStream {
|
||||||
match self {
|
match self {
|
||||||
Param::Single { field, id } => {
|
Param::Single { field, id } => {
|
||||||
quote! { [(String::from(#id), self.#field.as_ptr(), String::new())] }
|
quote! { [(String::from(#id), self.#field.as_ptr(), String::new())] }
|
||||||
}
|
}
|
||||||
Param::Nested(params) => params.to_token(),
|
Param::Nested(params) => params.param_map_tokens(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,27 +454,15 @@ enum NestedParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedParams {
|
impl NestedParams {
|
||||||
fn is_group(&self) -> bool {
|
/// Constrruct an iterator that iterates over all parmaeters of a nested parameter object. This
|
||||||
let group = match self {
|
/// takes ID prefixes and suffixes into account, and prefixes the group to the parameter's
|
||||||
NestedParams::Inline { field: _, group } => group,
|
/// existing groups if the `group` attribute on the `#[nested]` macro was specified.
|
||||||
NestedParams::Prefixed {
|
fn param_map_tokens(&self) -> proc_macro2::TokenStream {
|
||||||
field: _,
|
|
||||||
id_prefix: _,
|
|
||||||
group,
|
|
||||||
} => group,
|
|
||||||
NestedParams::Array { field: _, group } => group,
|
|
||||||
};
|
|
||||||
|
|
||||||
group.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_token(&self) -> proc_macro2::TokenStream {
|
|
||||||
// How nested parameters are handled depends on the `NestedParams` variant.
|
// How nested parameters are handled depends on the `NestedParams` variant.
|
||||||
// These are pairs of `(parameter_id, param_ptr, param_group)`. The specific
|
// These are pairs of `(parameter_id, param_ptr, param_group)`. The specific
|
||||||
// parameter types know how to convert themselves into the correct ParamPtr variant.
|
// parameter types know how to convert themselves into the correct ParamPtr variant.
|
||||||
// Top-level parameters have no group, and we'll prefix the group name specified in
|
// Top-level parameters have no group, and we'll prefix the group name specified in
|
||||||
// the `#[nested(...)]` attribute to fields coming from nested groups
|
// the `#[nested(...)]` attribute to fields coming from nested groups.
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
// TODO: No idea how to splice this as an `Option<&str>`, so this involves some
|
// TODO: No idea how to splice this as an `Option<&str>`, so this involves some
|
||||||
// copy-pasting
|
// copy-pasting
|
||||||
|
|
Loading…
Reference in a new issue