handle params with default values in properties (#1408)

This commit is contained in:
Simon 2020-07-12 08:16:43 +02:00 committed by GitHub
parent 1e609b4af8
commit f7ce3e2c71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 5 deletions

View File

@ -8,7 +8,16 @@ use syn::{
/// Alias for a comma-separated list of `GenericArgument`
pub type GenericArguments = Punctuated<GenericArgument, Token![,]>;
/// Converts `GenericParams` into `GenericArguments` and adds `type_ident` as a type arg
/// Finds the index of the first generic param with a default value.
fn first_default_param_position(generics: &Generics) -> Option<usize> {
generics.params.iter().position(|param| match param {
GenericParam::Type(param) => param.default.is_some(),
_ => false,
})
}
/// Converts `GenericParams` into `GenericArguments` and adds `type_ident` as a type arg.
/// `type_ident` is added at the end of the existing type arguments which don't have a default value.
pub fn to_arguments(generics: &Generics, type_ident: Ident) -> GenericArguments {
let mut args: GenericArguments = Punctuated::new();
args.extend(generics.params.iter().map(|param| match param {
@ -18,16 +27,29 @@ pub fn to_arguments(generics: &Generics, type_ident: Ident) -> GenericArguments
}
_ => unimplemented!("const params are not supported in the derive macro"),
}));
args.push(new_generic_type_arg(type_ident));
let new_arg = new_generic_type_arg(type_ident);
if let Some(index) = first_default_param_position(generics) {
args.insert(index, new_arg);
} else {
args.push(new_arg);
}
args
}
/// Adds a new bounded `GenericParam` to a `Generics`
/// The new param is added after the existing ones without a default value.
pub fn with_param_bounds(generics: &Generics, param_ident: Ident, param_bounds: Ident) -> Generics {
let mut new_generics = generics.clone();
new_generics
.params
.push(new_param_bounds(param_ident, param_bounds));
let params = &mut new_generics.params;
let new_param = new_param_bounds(param_ident, param_bounds);
if let Some(index) = first_default_param_position(generics) {
params.insert(index, new_param);
} else {
params.push(new_param);
}
new_generics
}

View File

@ -169,4 +169,20 @@ mod t9 {
}
}
mod t10 {
use super::*;
// this test makes sure that Yew handles generic params with default values properly.
#[derive(Clone, Properties)]
pub struct Foo<S, M = S>
where
S: Clone,
M: Clone,
{
bar: S,
baz: M,
}
}
fn main() {}