Add custom derives for specific generated types (#520)

* WIP implement custom derives per type

* WIP wiring up specific type derives

* Fmt

* Rename GeneratedTypeDerives to Derives

* Fmt

* Fix errors

* Fix test runtime

* Make derives appear in alphabetic order

* Clippy

* Add derive_for_type attribute to example

* Add docs to example

* Rename GeneratedTypeDerive

* Rename ty to type in attribute

* Update darling

* Update codegen/src/types/derives.rs

Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>

* Update codegen/src/types/mod.rs

Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>

* Update codegen/src/types/mod.rs

Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>

* review: update method name

* Add unit tests for combined derives

* Remove out of date docs

* Add macro usage docs

Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
This commit is contained in:
Andrew Jones
2022-04-28 14:26:34 +03:00
committed by GitHub
parent 1fd1eee72a
commit 24317b4311
13 changed files with 374 additions and 120 deletions
+7 -4
View File
@@ -15,8 +15,8 @@
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
use super::{
Derives,
Field,
GeneratedTypeDerives,
TypeDefParameters,
TypeGenerator,
TypeParameter,
@@ -29,6 +29,8 @@ use quote::{
quote,
};
use scale_info::{
form::PortableForm,
Type,
TypeDef,
TypeDefPrimitive,
};
@@ -52,6 +54,7 @@ pub struct CompositeDef {
impl CompositeDef {
/// Construct a definition which will generate code for a standalone `struct`.
pub fn struct_def(
ty: &Type<PortableForm>,
ident: &str,
type_params: TypeDefParameters,
fields_def: CompositeDefFields,
@@ -59,7 +62,7 @@ impl CompositeDef {
type_gen: &TypeGenerator,
docs: &[String],
) -> Self {
let mut derives = type_gen.derives().clone();
let mut derives = type_gen.type_derives(ty);
let fields: Vec<_> = fields_def.field_types().collect();
if fields.len() == 1 {
@@ -82,7 +85,7 @@ impl CompositeDef {
| TypeDefPrimitive::U128
)
) {
derives.push_codec_compact_as()
derives.insert_codec_compact_as()
}
}
}
@@ -165,7 +168,7 @@ impl quote::ToTokens for CompositeDef {
pub enum CompositeDefKind {
/// Composite type comprising a Rust `struct`.
Struct {
derives: GeneratedTypeDerives,
derives: Derives,
type_params: TypeDefParameters,
field_visibility: Option<syn::Visibility>,
},
+78 -19
View File
@@ -17,48 +17,107 @@
use syn::{
parse_quote,
punctuated::Punctuated,
Path,
};
#[derive(Debug, Clone)]
pub struct GeneratedTypeDerives {
derives: Punctuated<syn::Path, syn::Token![,]>,
use std::collections::{
HashMap,
HashSet,
};
#[derive(Debug, Default, Clone)]
pub struct DerivesRegistry {
default_derives: Derives,
specific_type_derives: HashMap<syn::TypePath, Derives>,
}
impl GeneratedTypeDerives {
pub fn new(derives: Punctuated<syn::Path, syn::Token!(,)>) -> Self {
Self { derives }
impl DerivesRegistry {
/// Insert derives to be applied to all generated types.
pub fn extend_for_all(&mut self, derives: impl IntoIterator<Item = syn::Path>) {
self.default_derives.derives.extend(derives)
}
/// Insert derives to be applied to a specific generated type.
pub fn extend_for_type(
&mut self,
ty: syn::TypePath,
derives: impl IntoIterator<Item = syn::Path>,
) {
let type_derives = self
.specific_type_derives
.entry(ty)
.or_insert_with(Derives::default);
type_derives.derives.extend(derives)
}
/// Returns the derives to be applied to all generated types.
pub fn default_derives(&self) -> &Derives {
&self.default_derives
}
/// Resolve the derives for a generated type. Includes:
/// - The default derives for all types e.g. `scale::Encode, scale::Decode`
/// - Any user-defined derives for all types via `generated_type_derives`
/// - Any user-defined derives for this specific type
pub fn resolve(&self, ty: &syn::TypePath) -> Derives {
let mut defaults = self.default_derives.derives.clone();
if let Some(specific) = self.specific_type_derives.get(ty) {
defaults.extend(specific.derives.iter().cloned());
}
Derives { derives: defaults }
}
}
#[derive(Debug, Clone)]
pub struct Derives {
derives: HashSet<syn::Path>,
}
impl FromIterator<syn::Path> for Derives {
fn from_iter<T: IntoIterator<Item = Path>>(iter: T) -> Self {
let derives = iter.into_iter().collect();
Self { derives }
}
}
impl Derives {
/// Add `::subxt::codec::CompactAs` to the derives.
pub fn push_codec_compact_as(&mut self) {
self.derives.push(parse_quote!(::subxt::codec::CompactAs));
pub fn insert_codec_compact_as(&mut self) {
self.insert(parse_quote!(::subxt::codec::CompactAs));
}
pub fn append(&mut self, derives: impl Iterator<Item = syn::Path>) {
for derive in derives {
self.derives.push(derive)
self.insert(derive)
}
}
pub fn push(&mut self, derive: syn::Path) {
self.derives.push(derive);
pub fn insert(&mut self, derive: syn::Path) {
self.derives.insert(derive);
}
}
impl Default for GeneratedTypeDerives {
impl Default for Derives {
fn default() -> Self {
let mut derives = Punctuated::new();
derives.push(syn::parse_quote!(::subxt::codec::Encode));
derives.push(syn::parse_quote!(::subxt::codec::Decode));
derives.push(syn::parse_quote!(Debug));
Self::new(derives)
let mut derives = HashSet::new();
derives.insert(syn::parse_quote!(::subxt::codec::Encode));
derives.insert(syn::parse_quote!(::subxt::codec::Decode));
derives.insert(syn::parse_quote!(Debug));
Self { derives }
}
}
impl quote::ToTokens for GeneratedTypeDerives {
impl quote::ToTokens for Derives {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if !self.derives.is_empty() {
let derives = &self.derives;
let mut sorted = self.derives.iter().cloned().collect::<Vec<_>>();
sorted.sort_by(|a, b| {
quote::quote!(#a)
.to_string()
.cmp(&quote::quote!(#b).to_string())
});
let derives: Punctuated<syn::Path, syn::Token![,]> =
sorted.iter().cloned().collect();
tokens.extend(quote::quote! {
#[derive(#derives)]
})
+26 -13
View File
@@ -27,6 +27,7 @@ use proc_macro2::{
Span,
TokenStream,
};
use proc_macro_error::abort_call_site;
use quote::{
quote,
ToTokens,
@@ -48,7 +49,10 @@ pub use self::{
CompositeDefFieldType,
CompositeDefFields,
},
derives::GeneratedTypeDerives,
derives::{
Derives,
DerivesRegistry,
},
type_def::TypeDefGen,
type_def_params::TypeDefParameters,
type_path::{
@@ -71,7 +75,7 @@ pub struct TypeGenerator<'a> {
/// User defined overrides for generated types.
type_substitutes: HashMap<String, syn::TypePath>,
/// Set of derives with which to annotate generated types.
derives: GeneratedTypeDerives,
derives: DerivesRegistry,
}
impl<'a> TypeGenerator<'a> {
@@ -80,7 +84,7 @@ impl<'a> TypeGenerator<'a> {
type_registry: &'a PortableRegistry,
root_mod: &'static str,
type_substitutes: HashMap<String, syn::TypePath>,
derives: GeneratedTypeDerives,
derives: DerivesRegistry,
) -> Self {
let root_mod_ident = Ident::new(root_mod, Span::call_site());
Self {
@@ -92,7 +96,7 @@ impl<'a> TypeGenerator<'a> {
}
/// Generate a module containing all types defined in the supplied type registry.
pub fn generate_types_mod(&'a self) -> Module<'a> {
pub fn generate_types_mod(&self) -> Module {
let mut root_mod =
Module::new(self.types_mod_ident.clone(), self.types_mod_ident.clone());
@@ -119,7 +123,7 @@ impl<'a> TypeGenerator<'a> {
id: u32,
path: Vec<String>,
root_mod_ident: &Ident,
module: &mut Module<'a>,
module: &mut Module,
) {
let joined_path = path.join("::");
if self.type_substitutes.contains_key(&joined_path) {
@@ -215,22 +219,31 @@ impl<'a> TypeGenerator<'a> {
}
}
/// Returns the derives with which all generated type will be decorated.
pub fn derives(&self) -> &GeneratedTypeDerives {
&self.derives
/// Returns the derives to be applied to all generated types.
pub fn default_derives(&self) -> &Derives {
self.derives.default_derives()
}
/// Returns the derives to be applied to a generated type.
pub fn type_derives(&self, ty: &Type<PortableForm>) -> Derives {
let joined_path = ty.path().segments().join("::");
let ty_path: syn::TypePath = syn::parse_str(&joined_path).unwrap_or_else(|e| {
abort_call_site!("'{}' is an invalid type path: {:?}", joined_path, e,)
});
self.derives.resolve(&ty_path)
}
}
/// Represents a Rust `mod`, containing generated types and child `mod`s.
#[derive(Debug)]
pub struct Module<'a> {
pub struct Module {
name: Ident,
root_mod: Ident,
children: BTreeMap<Ident, Module<'a>>,
types: BTreeMap<scale_info::Path<scale_info::form::PortableForm>, TypeDefGen<'a>>,
children: BTreeMap<Ident, Module>,
types: BTreeMap<scale_info::Path<scale_info::form::PortableForm>, TypeDefGen>,
}
impl<'a> ToTokens for Module<'a> {
impl ToTokens for Module {
fn to_tokens(&self, tokens: &mut TokenStream) {
let name = &self.name;
let root_mod = &self.root_mod;
@@ -248,7 +261,7 @@ impl<'a> ToTokens for Module<'a> {
}
}
impl<'a> Module<'a> {
impl Module {
/// Create a new [`Module`], with a reference to the root `mod` for resolving type paths.
pub(crate) fn new(name: Ident, root_mod: Ident) -> Self {
Self {
+139 -36
View File
@@ -21,10 +21,11 @@ use scale_info::{
Registry,
TypeInfo,
};
use syn::parse_quote;
const MOD_PATH: &[&str] = &["subxt_codegen", "types", "tests"];
fn get_mod<'a>(module: &'a Module, path_segs: &[&'static str]) -> Option<&'a Module<'a>> {
fn get_mod<'a>(module: &'a Module, path_segs: &[&'static str]) -> Option<&'a Module> {
let (mod_name, rest) = path_segs.split_first()?;
let mod_ident = Ident::new(mod_name, Span::call_site());
let module = module.children.get(&mod_ident)?;
@@ -64,7 +65,7 @@ fn generate_struct_with_primitives() {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
pub a: ::core::primitive::bool,
pub b: ::core::primitive::u32,
@@ -110,12 +111,12 @@ fn generate_struct_with_a_struct_field() {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Child {
pub a: ::core::primitive::i32,
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Parent {
pub a: ::core::primitive::bool,
pub b: root::subxt_codegen::types::tests::Child,
@@ -155,10 +156,10 @@ fn generate_tuple_struct() {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Child(pub ::core::primitive::i32,);
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Parent(pub ::core::primitive::bool, pub root::subxt_codegen::types::tests::Child,);
}
}
@@ -237,34 +238,34 @@ fn derive_compact_as_for_uint_wrapper_structs() {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Su128 { pub a: ::core::primitive::u128, }
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Su16 { pub a: ::core::primitive::u16, }
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Su32 { pub a: ::core::primitive::u32, }
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Su64 { pub a: ::core::primitive::u64, }
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Su8 { pub a: ::core::primitive::u8, }
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct TSu128(pub ::core::primitive::u128,);
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct TSu16(pub ::core::primitive::u16,);
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct TSu32(pub ::core::primitive::u32,);
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct TSu64(pub ::core::primitive::u64,);
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct TSu8(pub ::core::primitive::u8,);
}
}
@@ -300,7 +301,7 @@ fn generate_enum() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub enum E {
# [codec (index = 0)]
A,
@@ -358,7 +359,7 @@ fn compact_fields() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub enum E {
# [codec (index = 0)]
A {
@@ -369,12 +370,12 @@ fn compact_fields() {
B( #[codec(compact)] ::core::primitive::u32,),
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
#[codec(compact)] pub a: ::core::primitive::u32,
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct TupleStruct(#[codec(compact)] pub ::core::primitive::u32,);
}
}
@@ -408,7 +409,7 @@ fn generate_array_field() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
pub a: [::core::primitive::u8; 32usize],
}
@@ -445,7 +446,7 @@ fn option_fields() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
pub a: ::core::option::Option<::core::primitive::bool>,
pub b: ::core::option::Option<::core::primitive::u32>,
@@ -485,7 +486,7 @@ fn box_fields_struct() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
pub a: ::std::boxed::Box<::core::primitive::bool>,
pub b: ::std::boxed::Box<::core::primitive::u32>,
@@ -525,7 +526,7 @@ fn box_fields_enum() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub enum E {
# [codec (index = 0)]
A(::std::boxed::Box<::core::primitive::bool>,),
@@ -565,7 +566,7 @@ fn range_fields() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
pub a: ::core::ops::Range<::core::primitive::u32>,
pub b: ::core::ops::RangeInclusive<::core::primitive::u32>,
@@ -609,12 +610,12 @@ fn generics() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Bar {
pub b: root::subxt_codegen::types::tests::Foo<::core::primitive::u32>,
pub c: root::subxt_codegen::types::tests::Foo<::core::primitive::u8>,
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Foo<_0> {
pub a: _0,
}
@@ -657,12 +658,12 @@ fn generics_nested() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Bar<_0> {
pub b: root::subxt_codegen::types::tests::Foo<_0, ::core::primitive::u32>,
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Foo<_0, _1> {
pub a: _0,
pub b: ::core::option::Option<(_0, _1,)>,
@@ -708,7 +709,7 @@ fn generate_bitvec() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct S {
pub lsb: ::subxt::bitvec::vec::BitVec<::core::primitive::u8, root::bitvec::order::Lsb0>,
pub msb: ::subxt::bitvec::vec::BitVec<::core::primitive::u16, root::bitvec::order::Msb0>,
@@ -761,12 +762,12 @@ fn generics_with_alias_adds_phantom_data_marker() {
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug, ::subxt::codec::CompactAs)]
#[derive(::subxt::codec::CompactAs, ::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct NamedFields<_0> {
pub b: ::core::primitive::u32,
#[codec(skip)] pub __subxt_unused_type_params: ::core::marker::PhantomData<_0>
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct UnnamedFields<_0, _1> (
pub (::core::primitive::u32, ::core::primitive::u32,),
#[codec(skip)] pub ::core::marker::PhantomData<(_0, _1)>
@@ -829,20 +830,20 @@ fn modules() {
pub mod b {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Bar {
pub a: root::subxt_codegen::types::tests::m::a::Foo,
}
}
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Foo;
}
pub mod c {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct Foo {
pub a: root::subxt_codegen::types::tests::m::a::b::Bar,
}
@@ -879,10 +880,112 @@ fn dont_force_struct_names_camel_case() {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Encode, ::subxt::codec::Decode, Debug)]
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug)]
pub struct AB;
}
}
.to_string()
)
}
#[test]
fn apply_user_defined_derives_for_all_types() {
#[allow(unused)]
#[derive(TypeInfo)]
struct A(B);
#[allow(unused)]
#[derive(TypeInfo)]
struct B;
let mut registry = Registry::new();
registry.register_type(&meta_type::<A>());
let portable_types: PortableRegistry = registry.into();
// configure derives
let mut derives = DerivesRegistry::default();
derives.extend_for_all(vec![parse_quote!(Clone), parse_quote!(Eq)]);
let type_gen =
TypeGenerator::new(&portable_types, "root", Default::default(), derives);
let types = type_gen.generate_types_mod();
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
assert_eq!(
tests_mod.into_token_stream().to_string(),
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Clone, Debug, Eq)]
pub struct A(pub root :: subxt_codegen :: types :: tests :: B,);
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Clone, Debug, Eq)]
pub struct B;
}
}
.to_string()
)
}
#[test]
fn apply_user_defined_derives_for_specific_types() {
#[allow(unused)]
#[derive(TypeInfo)]
struct A(B);
#[allow(unused)]
#[derive(TypeInfo)]
struct B(C);
#[allow(unused)]
#[derive(TypeInfo)]
struct C;
let mut registry = Registry::new();
registry.register_type(&meta_type::<A>());
let portable_types: PortableRegistry = registry.into();
// configure derives
let mut derives = DerivesRegistry::default();
// for all types
derives.extend_for_all(vec![parse_quote!(Eq)]);
// for specific types
derives.extend_for_type(
parse_quote!(subxt_codegen::types::tests::B),
vec![parse_quote!(Hash)],
);
// duplicates (in this case `Eq`) will be combined (i.e. a set union)
derives.extend_for_type(
parse_quote!(subxt_codegen::types::tests::C),
vec![
parse_quote!(Eq),
parse_quote!(Ord),
parse_quote!(PartialOrd),
],
);
let type_gen =
TypeGenerator::new(&portable_types, "root", Default::default(), derives);
let types = type_gen.generate_types_mod();
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
assert_eq!(
tests_mod.into_token_stream().to_string(),
quote! {
pub mod tests {
use super::root;
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug, Eq)]
pub struct A(pub root :: subxt_codegen :: types :: tests :: B,);
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug, Eq, Hash)]
pub struct B(pub root :: subxt_codegen :: types :: tests :: C,);
#[derive(::subxt::codec::Decode, ::subxt::codec::Encode, Debug, Eq, Ord, PartialOrd)]
pub struct C;
}
}
.to_string()
)
}
+9 -8
View File
@@ -17,7 +17,7 @@
use super::{
CompositeDef,
CompositeDefFields,
GeneratedTypeDerives,
Derives,
TypeDefParameters,
TypeGenerator,
TypeParameter,
@@ -39,19 +39,19 @@ use syn::parse_quote;
/// Field type paths are resolved via the `TypeGenerator`, which contains the registry of all
/// generated types in the module.
#[derive(Debug)]
pub struct TypeDefGen<'a> {
pub struct TypeDefGen {
/// The type parameters of the type to be generated
type_params: TypeDefParameters,
/// The derives with which to annotate the generated type.
derives: &'a GeneratedTypeDerives,
derives: Derives,
/// The kind of type to be generated.
ty_kind: TypeDefGenKind,
}
impl<'a> TypeDefGen<'a> {
impl TypeDefGen {
/// Construct a type definition for codegen from the given [`scale_info::Type`].
pub fn from_type(ty: Type<PortableForm>, type_gen: &'a TypeGenerator) -> Self {
let derives = type_gen.derives();
pub fn from_type(ty: Type<PortableForm>, type_gen: &TypeGenerator) -> Self {
let derives = type_gen.type_derives(&ty);
let type_params = ty
.type_params()
@@ -85,6 +85,7 @@ impl<'a> TypeDefGen<'a> {
);
type_params.update_unused(fields.field_types());
let composite_def = CompositeDef::struct_def(
&ty,
&type_name,
type_params.clone(),
fields,
@@ -126,7 +127,7 @@ impl<'a> TypeDefGen<'a> {
}
}
impl<'a> quote::ToTokens for TypeDefGen<'a> {
impl quote::ToTokens for TypeDefGen {
fn to_tokens(&self, tokens: &mut TokenStream) {
match &self.ty_kind {
TypeDefGenKind::Struct(composite) => composite.to_tokens(tokens),
@@ -150,7 +151,7 @@ impl<'a> quote::ToTokens for TypeDefGen<'a> {
let enum_ident = format_ident!("{}", type_name);
let type_params = &self.type_params;
let derives = self.derives;
let derives = &self.derives;
let ty_toks = quote! {
#derives
pub enum #enum_ident #type_params {