use super::TypeParameter;
use quote::{format_ident, quote};
use scale_info::form::PortableForm;
use std::collections::BTreeSet;
#[derive(Clone, Debug, Default)]
pub struct TypeParameters {
params: Vec<TypeParameter>,
unused: BTreeSet<TypeParameter>,
}
impl TypeParameters {
pub fn from_scale_info(params: &[scale_info::TypeParameter<PortableForm>]) -> Self {
let params = params
.iter()
.enumerate()
.filter_map(|(i, tp)| {
tp.ty.as_ref().map(|ty| {
let tp_name = format_ident!("_{}", i);
TypeParameter {
concrete_type_id: ty.id,
original_name: tp.name.clone(),
name: tp_name,
}
})
})
.collect::<Vec<_>>();
let unused = params.iter().cloned().collect();
Self { params, unused }
}
pub fn unused_params_phantom_data(&self) -> Option<syn::TypePath> {
if self.unused.is_empty() {
return None;
}
let params = if self.unused.len() == 1 {
let param = self
.unused
.iter()
.next()
.expect("Checked for exactly one unused param");
quote! { #param }
} else {
let params = self.unused.iter();
quote! { ( #( #params ), * ) }
};
Some(syn::parse_quote! {::core::marker::PhantomData<#params> })
}
pub fn params(&self) -> &[TypeParameter] {
&self.params
}
pub fn has_unused_type_params(&self) -> bool {
!self.unused.is_empty()
}
pub(super) fn mark_used(&mut self, param: &TypeParameter) {
self.unused.remove(param);
}
}
impl quote::ToTokens for TypeParameters {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if !self.params.is_empty() {
let params = &self.params;
tokens.extend(quote! { < #( #params ),* > })
}
}
}