From 73ce14949edbf8a5745e5516f8a364ecea060399 Mon Sep 17 00:00:00 2001 From: ascjones Date: Tue, 26 Apr 2022 17:49:00 +0100 Subject: [PATCH 01/21] WIP implement custom derives per type --- codegen/src/api/mod.rs | 5 +- codegen/src/lib.rs | 2 +- codegen/src/types/composite_def.rs | 1 - codegen/src/types/derives.rs | 73 +++++++++++++++++++++++------- codegen/src/types/mod.rs | 10 ++-- macro/src/lib.rs | 14 +++--- 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 949a530fc4..a2d4b8ed47 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -37,7 +37,7 @@ mod errors; mod events; mod storage; -use super::GeneratedTypeDerives; +use super::DerivesRegistry; use crate::{ ir, types::{ @@ -68,13 +68,12 @@ use std::{ }; use syn::{ parse_quote, - punctuated::Punctuated, }; pub fn generate_runtime_api

( item_mod: syn::ItemMod, path: P, - generated_type_derives: Option>, + generated_type_derives: &[GeneratedTypeDerives], ) -> TokenStream2 where P: AsRef, diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 523b0d72ca..a0b5775418 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -26,7 +26,7 @@ pub use self::{ RuntimeGenerator, }, types::{ - GeneratedTypeDerives, + DerivesRegistry, Module, TypeGenerator, }, diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 5f3379898f..0f97fa4914 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -16,7 +16,6 @@ use super::{ Field, - GeneratedTypeDerives, TypeDefParameters, TypeGenerator, TypeParameter, diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index db09aade91..8f1f581339 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -14,51 +14,92 @@ // You should have received a copy of the GNU General Public License // along with subxt. If not, see . -use syn::{ - parse_quote, - punctuated::Punctuated, +use syn::{parse_quote, Path, punctuated::Punctuated}; + +use std::borrow::Cow; +use std::collections::{ + HashMap, HashSet }; +#[derive(Debug, Clone)] +pub struct DerivesRegistry { + all_type_derives: GeneratedTypeDerives, + specific_type_derives: HashMap, +} + +impl DerivesRegistry { + pub fn new(defaults: impl IntoIterator) -> Self { + let all_type_derives = defaults.into_iter().collect(); + Self { + all_type_derives, + specific_type_derives: HashMap::new(), + } + } + + /// Insert derives to be applied to a specific generated type. + pub fn insert_for_type(&mut self, ty: syn::Path, derives: impl Iterator) { + let type_derives = self.specific_type_derives.entry(ty).or_insert_with(GeneratedTypeDerives::default); + type_derives.derives.extend(derives) + } + + /// Resolve the derives for a generated type. Includes: + /// - The default global derives e.g. `scale::Encode, scale::Decode` + /// - Any user-defined global derives via `generated_type_derives` + /// - Any user-defined derives for this specific type + pub fn resolve(&self, ty: &syn::Path) -> Cow { + if let Some(specific) = self.specific_type_derives.get(ty) { + let mut globals = self.all_type_derives.derives.clone(); + globals.extend(specific.derives.iter().cloned()); + Cow::Owned(GeneratedTypeDerives { derives: globals }) + } else { + Cow::Borrowed(&self.all_type_derives) + } + } +} + #[derive(Debug, Clone)] pub struct GeneratedTypeDerives { - derives: Punctuated, + derives: HashSet, } -impl GeneratedTypeDerives { - pub fn new(derives: Punctuated) -> Self { +impl FromIterator for GeneratedTypeDerives { + fn from_iter>(iter: T) -> Self { + let derives = iter.into_iter().collect(); Self { derives } } +} +impl GeneratedTypeDerives { /// Add `::subxt::codec::CompactAs` to the derives. pub fn push_codec_compact_as(&mut self) { - self.derives.push(parse_quote!(::subxt::codec::CompactAs)); + self.insert(parse_quote!(::subxt::codec::CompactAs)); } pub fn append(&mut self, derives: impl Iterator) { 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 { 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 { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { if !self.derives.is_empty() { - let derives = &self.derives; + let derives: Punctuated = self.derives.iter().cloned().collect(); tokens.extend(quote::quote! { #[derive(#derives)] }) diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index c29dbd3412..73a9eba6a6 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -48,7 +48,7 @@ pub use self::{ CompositeDefFieldType, CompositeDefFields, }, - derives::GeneratedTypeDerives, + derives::DerivesRegistry, type_def::TypeDefGen, type_def_params::TypeDefParameters, type_path::{ @@ -71,7 +71,7 @@ pub struct TypeGenerator<'a> { /// User defined overrides for generated types. type_substitutes: HashMap, /// Set of derives with which to annotate generated types. - derives: GeneratedTypeDerives, + derives: DerivesRegistry, } impl<'a> TypeGenerator<'a> { @@ -80,7 +80,7 @@ impl<'a> TypeGenerator<'a> { type_registry: &'a PortableRegistry, root_mod: &'static str, type_substitutes: HashMap, - derives: GeneratedTypeDerives, + derives: DerivesRegistry, ) -> Self { let root_mod_ident = Ident::new(root_mod, Span::call_site()); Self { @@ -215,8 +215,8 @@ impl<'a> TypeGenerator<'a> { } } - /// Returns the derives with which all generated type will be decorated. - pub fn derives(&self) -> &GeneratedTypeDerives { + /// Returns a registry of derives to be applied to generated types. + pub fn derives(&self) -> &DerivesRegistry { &self.derives } } diff --git a/macro/src/lib.rs b/macro/src/lib.rs index ee4c1d76db..824bb19664 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -27,12 +27,16 @@ use syn::{ #[derive(Debug, FromMeta)] struct RuntimeMetadataArgs { runtime_metadata_path: String, - #[darling(default)] - generated_type_derives: Option, + #[darling(multiple)] + generated_type_derives: Vec, } #[derive(Debug, FromMeta)] -struct GeneratedTypeDerives(Punctuated); +struct GeneratedTypeDerives{ + #[darling(rename = "type")] + ty: String, + derive: Punctuated +} #[proc_macro_attribute] #[proc_macro_error] @@ -48,7 +52,5 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { let root_path = std::path::Path::new(&root); let path = root_path.join(args.runtime_metadata_path); - let generated_type_derives = args.generated_type_derives.map(|derives| derives.0); - - subxt_codegen::generate_runtime_api(item_mod, &path, generated_type_derives).into() + subxt_codegen::generate_runtime_api(item_mod, &path, &args.generated_type_derives).into() } From 572e7495b8734ae4318be32fafd823746d1a5460 Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 10:06:00 +0100 Subject: [PATCH 02/21] WIP wiring up specific type derives --- codegen/src/api/mod.rs | 13 ++++------ codegen/src/lib.rs | 1 + codegen/src/types/composite_def.rs | 6 ++++- codegen/src/types/derives.rs | 36 ++++++++++++--------------- codegen/src/types/mod.rs | 39 +++++++++++++++++++++--------- codegen/src/types/tests.rs | 2 +- codegen/src/types/type_def.rs | 15 ++++++------ 7 files changed, 63 insertions(+), 49 deletions(-) diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index a2d4b8ed47..6d38be1cc7 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -73,7 +73,7 @@ use syn::{ pub fn generate_runtime_api

( item_mod: syn::ItemMod, path: P, - generated_type_derives: &[GeneratedTypeDerives], + derives: DerivesRegistry, ) -> TokenStream2 where P: AsRef, @@ -89,11 +89,6 @@ where let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..]) .unwrap_or_else(|e| abort_call_site!("Failed to decode metadata: {}", e)); - let mut derives = GeneratedTypeDerives::default(); - if let Some(user_derives) = generated_type_derives { - derives.append(user_derives.iter().cloned()) - } - let generator = RuntimeGenerator::new(metadata); generator.generate_runtime(item_mod, derives) } @@ -113,9 +108,10 @@ impl RuntimeGenerator { pub fn generate_runtime( &self, item_mod: syn::ItemMod, - derives: GeneratedTypeDerives, + derives: DerivesRegistry, ) -> TokenStream2 { let item_mod_ir = ir::ItemMod::from(item_mod); + let default_derives = derives.default_derives(); // some hardcoded default type substitutes, can be overridden by user let mut type_substitutes = [ @@ -236,7 +232,7 @@ impl RuntimeGenerator { }); let outer_event = quote! { - #derives + #default_derives pub enum Event { #( #outer_event_variants )* } @@ -406,6 +402,7 @@ where type_gen, ); CompositeDef::struct_def( + &ty, struct_name.as_ref(), Default::default(), fields, diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index a0b5775418..cd6bb29ff0 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -27,6 +27,7 @@ pub use self::{ }, types::{ DerivesRegistry, + GeneratedTypeDerives, Module, TypeGenerator, }, diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 0f97fa4914..2acac79ec3 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -16,6 +16,7 @@ use super::{ Field, + GeneratedTypeDerives, TypeDefParameters, TypeGenerator, TypeParameter, @@ -28,9 +29,11 @@ use quote::{ quote, }; use scale_info::{ + Type, TypeDef, TypeDefPrimitive, }; +use scale_info::form::PortableForm; /// Representation of a type which consists of a set of fields. Used to generate Rust code for /// either a standalone `struct` definition, or an `enum` variant. @@ -51,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, ident: &str, type_params: TypeDefParameters, fields_def: CompositeDefFields, @@ -58,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).clone(); let fields: Vec<_> = fields_def.field_types().collect(); if fields.len() == 1 { diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index 8f1f581339..233f4ee5d1 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -16,44 +16,38 @@ use syn::{parse_quote, Path, punctuated::Punctuated}; -use std::borrow::Cow; use std::collections::{ HashMap, HashSet }; -#[derive(Debug, Clone)] +#[derive(Debug, Default, Clone)] pub struct DerivesRegistry { - all_type_derives: GeneratedTypeDerives, - specific_type_derives: HashMap, + default_derives: GeneratedTypeDerives, + specific_type_derives: HashMap, } impl DerivesRegistry { - pub fn new(defaults: impl IntoIterator) -> Self { - let all_type_derives = defaults.into_iter().collect(); - Self { - all_type_derives, - specific_type_derives: HashMap::new(), - } - } - /// Insert derives to be applied to a specific generated type. - pub fn insert_for_type(&mut self, ty: syn::Path, derives: impl Iterator) { + pub fn insert_for_type(&mut self, ty: syn::TypePath, derives: impl Iterator) { let type_derives = self.specific_type_derives.entry(ty).or_insert_with(GeneratedTypeDerives::default); type_derives.derives.extend(derives) } + /// Returns a the derives to be applied to all generated types. + pub fn default_derives(&self) -> &GeneratedTypeDerives { + &self.default_derives + } + /// Resolve the derives for a generated type. Includes: - /// - The default global derives e.g. `scale::Encode, scale::Decode` - /// - Any user-defined global derives via `generated_type_derives` + /// - 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::Path) -> Cow { + pub fn resolve(&self, ty: &syn::TypePath) -> GeneratedTypeDerives { + let mut defaults = self.default_derives.derives.clone(); if let Some(specific) = self.specific_type_derives.get(ty) { - let mut globals = self.all_type_derives.derives.clone(); - globals.extend(specific.derives.iter().cloned()); - Cow::Owned(GeneratedTypeDerives { derives: globals }) - } else { - Cow::Borrowed(&self.all_type_derives) + defaults.extend(specific.derives.iter().cloned()); } + GeneratedTypeDerives { derives: defaults } } } diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index 73a9eba6a6..7954ba78c4 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -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::DerivesRegistry, + derives::{ + DerivesRegistry, + GeneratedTypeDerives, + }, type_def::TypeDefGen, type_def_params::TypeDefParameters, type_path::{ @@ -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, 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,35 @@ impl<'a> TypeGenerator<'a> { } } - /// Returns a registry of derives to be applied to generated types. - pub fn derives(&self) -> &DerivesRegistry { - &self.derives + /// Returns a the derives to be applied to all generated types. + pub fn default_derives(&self) -> &GeneratedTypeDerives { + self.derives.default_derives() + } + + /// Returns a the derives to be applied to a generated type. + pub fn type_derives(&self, ty: &Type) -> GeneratedTypeDerives { + 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>, - types: BTreeMap, TypeDefGen<'a>>, + children: BTreeMap, + types: BTreeMap, 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 +265,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 { diff --git a/codegen/src/types/tests.rs b/codegen/src/types/tests.rs index 507ca92ffa..27577a3562 100644 --- a/codegen/src/types/tests.rs +++ b/codegen/src/types/tests.rs @@ -24,7 +24,7 @@ use scale_info::{ 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)?; diff --git a/codegen/src/types/type_def.rs b/codegen/src/types/type_def.rs index 9b19ddb047..8bb8b7fa89 100644 --- a/codegen/src/types/type_def.rs +++ b/codegen/src/types/type_def.rs @@ -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: GeneratedTypeDerives, /// 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, type_gen: &'a TypeGenerator) -> Self { - let derives = type_gen.derives(); + pub fn from_type(ty: Type, 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 { From 1eca1a344c88879417255ccf88c32ed2b34d884e Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 10:08:09 +0100 Subject: [PATCH 03/21] Fmt --- codegen/src/api/mod.rs | 4 +--- codegen/src/types/composite_def.rs | 2 +- codegen/src/types/derives.rs | 25 +++++++++++++++++++------ codegen/src/types/mod.rs | 10 +++------- macro/src/lib.rs | 7 ++++--- 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 6d38be1cc7..9663610795 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -66,9 +66,7 @@ use std::{ path, string::ToString, }; -use syn::{ - parse_quote, -}; +use syn::parse_quote; pub fn generate_runtime_api

( item_mod: syn::ItemMod, diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 2acac79ec3..1ee8ec7e6e 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -29,11 +29,11 @@ use quote::{ quote, }; use scale_info::{ + form::PortableForm, Type, TypeDef, TypeDefPrimitive, }; -use scale_info::form::PortableForm; /// Representation of a type which consists of a set of fields. Used to generate Rust code for /// either a standalone `struct` definition, or an `enum` variant. diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index 233f4ee5d1..d6f88a2f37 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -14,10 +14,15 @@ // You should have received a copy of the GNU General Public License // along with subxt. If not, see . -use syn::{parse_quote, Path, punctuated::Punctuated}; +use syn::{ + parse_quote, + punctuated::Punctuated, + Path, +}; use std::collections::{ - HashMap, HashSet + HashMap, + HashSet, }; #[derive(Debug, Default, Clone)] @@ -28,8 +33,15 @@ pub struct DerivesRegistry { impl DerivesRegistry { /// Insert derives to be applied to a specific generated type. - pub fn insert_for_type(&mut self, ty: syn::TypePath, derives: impl Iterator) { - let type_derives = self.specific_type_derives.entry(ty).or_insert_with(GeneratedTypeDerives::default); + pub fn insert_for_type( + &mut self, + ty: syn::TypePath, + derives: impl Iterator, + ) { + let type_derives = self + .specific_type_derives + .entry(ty) + .or_insert_with(GeneratedTypeDerives::default); type_derives.derives.extend(derives) } @@ -57,7 +69,7 @@ pub struct GeneratedTypeDerives { } impl FromIterator for GeneratedTypeDerives { - fn from_iter>(iter: T) -> Self { + fn from_iter>(iter: T) -> Self { let derives = iter.into_iter().collect(); Self { derives } } @@ -93,7 +105,8 @@ impl Default for GeneratedTypeDerives { impl quote::ToTokens for GeneratedTypeDerives { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { if !self.derives.is_empty() { - let derives: Punctuated = self.derives.iter().cloned().collect(); + let derives: Punctuated = + self.derives.iter().cloned().collect(); tokens.extend(quote::quote! { #[derive(#derives)] }) diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index 7954ba78c4..51a50d6c51 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -227,13 +227,9 @@ impl<'a> TypeGenerator<'a> { /// Returns a the derives to be applied to a generated type. pub fn type_derives(&self, ty: &Type) -> GeneratedTypeDerives { 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, - ) - ); + 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) } } diff --git a/macro/src/lib.rs b/macro/src/lib.rs index 824bb19664..5aad22bfdf 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -32,10 +32,10 @@ struct RuntimeMetadataArgs { } #[derive(Debug, FromMeta)] -struct GeneratedTypeDerives{ +struct GeneratedTypeDerives { #[darling(rename = "type")] ty: String, - derive: Punctuated + derive: Punctuated, } #[proc_macro_attribute] @@ -52,5 +52,6 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { let root_path = std::path::Path::new(&root); let path = root_path.join(args.runtime_metadata_path); - subxt_codegen::generate_runtime_api(item_mod, &path, &args.generated_type_derives).into() + subxt_codegen::generate_runtime_api(item_mod, &path, &args.generated_type_derives) + .into() } From 0cf06544775e444c1fe30e5670d9131b5062b7aa Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 10:16:33 +0100 Subject: [PATCH 04/21] Rename GeneratedTypeDerives to Derives --- cli/src/main.rs | 4 ++-- codegen/src/lib.rs | 2 +- codegen/src/types/composite_def.rs | 4 ++-- codegen/src/types/derives.rs | 22 +++++++++++----------- codegen/src/types/mod.rs | 6 +++--- codegen/src/types/type_def.rs | 4 ++-- macro/src/lib.rs | 2 ++ 7 files changed, 23 insertions(+), 21 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 465755b573..5ff3c1d60a 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -33,7 +33,7 @@ use std::{ path::PathBuf, }; use structopt::StructOpt; -use subxt_codegen::GeneratedTypeDerives; +use subxt_codegen::Derives; /// Utilities for working with substrate metadata for subxt. #[derive(Debug, StructOpt)] @@ -163,7 +163,7 @@ fn codegen( .iter() .map(|raw| syn::parse_str(raw)) .collect::, _>>()?; - let mut derives = GeneratedTypeDerives::default(); + let mut derives = Derives::default(); derives.append(p.into_iter()); let runtime_api = generator.generate_runtime(item_mod, derives); diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index cd6bb29ff0..59b6334680 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -27,7 +27,7 @@ pub use self::{ }, types::{ DerivesRegistry, - GeneratedTypeDerives, + Derives, Module, TypeGenerator, }, diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 1ee8ec7e6e..53bf428033 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -16,7 +16,7 @@ use super::{ Field, - GeneratedTypeDerives, + Derives, TypeDefParameters, TypeGenerator, TypeParameter, @@ -168,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, }, diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index d6f88a2f37..f738055da2 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -27,8 +27,8 @@ use std::collections::{ #[derive(Debug, Default, Clone)] pub struct DerivesRegistry { - default_derives: GeneratedTypeDerives, - specific_type_derives: HashMap, + default_derives: Derives, + specific_type_derives: HashMap, } impl DerivesRegistry { @@ -41,12 +41,12 @@ impl DerivesRegistry { let type_derives = self .specific_type_derives .entry(ty) - .or_insert_with(GeneratedTypeDerives::default); + .or_insert_with(Derives::default); type_derives.derives.extend(derives) } /// Returns a the derives to be applied to all generated types. - pub fn default_derives(&self) -> &GeneratedTypeDerives { + pub fn default_derives(&self) -> &Derives { &self.default_derives } @@ -54,28 +54,28 @@ impl DerivesRegistry { /// - 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) -> GeneratedTypeDerives { + 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()); } - GeneratedTypeDerives { derives: defaults } + Derives { derives: defaults } } } #[derive(Debug, Clone)] -pub struct GeneratedTypeDerives { +pub struct Derives { derives: HashSet, } -impl FromIterator for GeneratedTypeDerives { +impl FromIterator for Derives { fn from_iter>(iter: T) -> Self { let derives = iter.into_iter().collect(); Self { derives } } } -impl GeneratedTypeDerives { +impl Derives { /// Add `::subxt::codec::CompactAs` to the derives. pub fn push_codec_compact_as(&mut self) { self.insert(parse_quote!(::subxt::codec::CompactAs)); @@ -92,7 +92,7 @@ impl GeneratedTypeDerives { } } -impl Default for GeneratedTypeDerives { +impl Default for Derives { fn default() -> Self { let mut derives = HashSet::new(); derives.insert(syn::parse_quote!(::subxt::codec::Encode)); @@ -102,7 +102,7 @@ impl Default for GeneratedTypeDerives { } } -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: Punctuated = diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index 51a50d6c51..d6f7114f7c 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -51,7 +51,7 @@ pub use self::{ }, derives::{ DerivesRegistry, - GeneratedTypeDerives, + Derives, }, type_def::TypeDefGen, type_def_params::TypeDefParameters, @@ -220,12 +220,12 @@ impl<'a> TypeGenerator<'a> { } /// Returns a the derives to be applied to all generated types. - pub fn default_derives(&self) -> &GeneratedTypeDerives { + pub fn default_derives(&self) -> &Derives { self.derives.default_derives() } /// Returns a the derives to be applied to a generated type. - pub fn type_derives(&self, ty: &Type) -> GeneratedTypeDerives { + pub fn type_derives(&self, ty: &Type) -> 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,) diff --git a/codegen/src/types/type_def.rs b/codegen/src/types/type_def.rs index 8bb8b7fa89..a66a80b519 100644 --- a/codegen/src/types/type_def.rs +++ b/codegen/src/types/type_def.rs @@ -17,7 +17,7 @@ use super::{ CompositeDef, CompositeDefFields, - GeneratedTypeDerives, + Derives, TypeDefParameters, TypeGenerator, TypeParameter, @@ -43,7 +43,7 @@ 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: GeneratedTypeDerives, + derives: Derives, /// The kind of type to be generated. ty_kind: TypeDefGenKind, } diff --git a/macro/src/lib.rs b/macro/src/lib.rs index 5aad22bfdf..a5793ac82f 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -19,6 +19,7 @@ extern crate proc_macro; use darling::FromMeta; use proc_macro::TokenStream; use proc_macro_error::proc_macro_error; +use subxt_codegen::{DerivesRegistry, Derives}; use syn::{ parse_macro_input, punctuated::Punctuated, @@ -52,6 +53,7 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { let root_path = std::path::Path::new(&root); let path = root_path.join(args.runtime_metadata_path); + subxt_codegen::generate_runtime_api(item_mod, &path, &args.generated_type_derives) .into() } From 87fe5b73f0ef39915e0af1ae9b2dd252288dead6 Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 10:16:44 +0100 Subject: [PATCH 05/21] Fmt --- codegen/src/lib.rs | 2 +- codegen/src/types/composite_def.rs | 2 +- codegen/src/types/mod.rs | 2 +- macro/src/lib.rs | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 59b6334680..d436a50c47 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -26,8 +26,8 @@ pub use self::{ RuntimeGenerator, }, types::{ - DerivesRegistry, Derives, + DerivesRegistry, Module, TypeGenerator, }, diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 53bf428033..76f5b5493f 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -15,8 +15,8 @@ // along with subxt. If not, see . use super::{ - Field, Derives, + Field, TypeDefParameters, TypeGenerator, TypeParameter, diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index d6f7114f7c..2c76fce100 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -50,8 +50,8 @@ pub use self::{ CompositeDefFields, }, derives::{ - DerivesRegistry, Derives, + DerivesRegistry, }, type_def::TypeDefGen, type_def_params::TypeDefParameters, diff --git a/macro/src/lib.rs b/macro/src/lib.rs index a5793ac82f..e1229c48cd 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -19,7 +19,10 @@ extern crate proc_macro; use darling::FromMeta; use proc_macro::TokenStream; use proc_macro_error::proc_macro_error; -use subxt_codegen::{DerivesRegistry, Derives}; +use subxt_codegen::{ + Derives, + DerivesRegistry, +}; use syn::{ parse_macro_input, punctuated::Punctuated, @@ -53,7 +56,6 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { let root_path = std::path::Path::new(&root); let path = root_path.join(args.runtime_metadata_path); - subxt_codegen::generate_runtime_api(item_mod, &path, &args.generated_type_derives) .into() } From 23aa4c4aaf4e3b0b55dd5c950f98ce37ba78f680 Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 11:30:02 +0100 Subject: [PATCH 06/21] Fix errors --- cli/src/main.rs | 6 +++--- codegen/src/types/derives.rs | 7 ++++++- examples/examples/custom_type_derives.rs | 2 +- macro/src/lib.rs | 24 +++++++++++++++--------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 5ff3c1d60a..5ea4dd1520 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -33,7 +33,7 @@ use std::{ path::PathBuf, }; use structopt::StructOpt; -use subxt_codegen::Derives; +use subxt_codegen::DerivesRegistry; /// Utilities for working with substrate metadata for subxt. #[derive(Debug, StructOpt)] @@ -163,8 +163,8 @@ fn codegen( .iter() .map(|raw| syn::parse_str(raw)) .collect::, _>>()?; - let mut derives = Derives::default(); - derives.append(p.into_iter()); + let mut derives = DerivesRegistry::default(); + derives.extend_for_all(p.into_iter()); let runtime_api = generator.generate_runtime(item_mod, derives); println!("{}", runtime_api); diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index f738055da2..f8b5a7fceb 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -32,8 +32,13 @@ pub struct DerivesRegistry { } impl DerivesRegistry { + /// Insert derives to be applied to all generated types. + pub fn extend_for_all(&mut self, derives: impl Iterator) { + self.default_derives.derives.extend(derives) + } + /// Insert derives to be applied to a specific generated type. - pub fn insert_for_type( + pub fn extend_for_type( &mut self, ty: syn::TypePath, derives: impl Iterator, diff --git a/examples/examples/custom_type_derives.rs b/examples/examples/custom_type_derives.rs index fbd5787135..575e145b33 100644 --- a/examples/examples/custom_type_derives.rs +++ b/examples/examples/custom_type_derives.rs @@ -24,7 +24,7 @@ // a comma separated list to the below attribute. Most useful for adding `Clone`. // The derives that we can add ultimately is limited to the traits that the base // types relied upon by the codegen implement. - generated_type_derives = "Clone, PartialEq, Hash" + derive_for_all_types = "Clone, PartialEq, Hash" )] pub mod polkadot {} diff --git a/macro/src/lib.rs b/macro/src/lib.rs index e1229c48cd..de413a2deb 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -19,10 +19,7 @@ extern crate proc_macro; use darling::FromMeta; use proc_macro::TokenStream; use proc_macro_error::proc_macro_error; -use subxt_codegen::{ - Derives, - DerivesRegistry, -}; +use subxt_codegen::DerivesRegistry; use syn::{ parse_macro_input, punctuated::Punctuated, @@ -31,14 +28,15 @@ use syn::{ #[derive(Debug, FromMeta)] struct RuntimeMetadataArgs { runtime_metadata_path: String, + #[darling(default)] + derive_for_all_types: Option>, #[darling(multiple)] - generated_type_derives: Vec, + derive_for_type: Vec, } #[derive(Debug, FromMeta)] struct GeneratedTypeDerives { - #[darling(rename = "type")] - ty: String, + ty: syn::TypePath, derive: Punctuated, } @@ -56,6 +54,14 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { let root_path = std::path::Path::new(&root); let path = root_path.join(args.runtime_metadata_path); - subxt_codegen::generate_runtime_api(item_mod, &path, &args.generated_type_derives) - .into() + let mut derives_registry = DerivesRegistry::default(); + if let Some(derive_for_all) = args.derive_for_all_types { + derives_registry.extend_for_all(derive_for_all.iter().cloned()); + } + for derives in &args.derive_for_type { + derives_registry + .extend_for_type(derives.ty.clone(), derives.derive.iter().cloned()) + } + + subxt_codegen::generate_runtime_api(item_mod, &path, derives_registry).into() } From f6adda760a44f266286e28edc55d9203def5d526 Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 11:36:54 +0100 Subject: [PATCH 07/21] Fix test runtime --- test-runtime/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-runtime/build.rs b/test-runtime/build.rs index c052cf4c69..4522e200e1 100644 --- a/test-runtime/build.rs +++ b/test-runtime/build.rs @@ -104,7 +104,7 @@ async fn run() { r#" #[subxt::subxt( runtime_metadata_path = "{}", - generated_type_derives = "Eq, PartialEq" + derive_for_all_types = "Eq, PartialEq" )] pub mod node_runtime {{ #[subxt(substitute_type = "sp_arithmetic::per_things::Perbill")] From 7046284d02f88c8d224a70796463e13542bb215e Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 11:57:09 +0100 Subject: [PATCH 08/21] Make derives appear in alphabetic order --- codegen/src/types/derives.rs | 8 ++++- codegen/src/types/tests.rs | 70 ++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index f8b5a7fceb..9477817feb 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -110,8 +110,14 @@ impl Default for Derives { impl quote::ToTokens for Derives { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { if !self.derives.is_empty() { + let mut sorted = self.derives.iter().cloned().collect::>(); + sorted.sort_by(|a, b| { + quote::quote!(#a) + .to_string() + .cmp("e::quote!(#b).to_string()) + }); let derives: Punctuated = - self.derives.iter().cloned().collect(); + sorted.iter().cloned().collect(); tokens.extend(quote::quote! { #[derive(#derives)] }) diff --git a/codegen/src/types/tests.rs b/codegen/src/types/tests.rs index 27577a3562..07fc404a62 100644 --- a/codegen/src/types/tests.rs +++ b/codegen/src/types/tests.rs @@ -64,7 +64,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 +110,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 +155,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 +237,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 +300,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 +358,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 +369,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 +408,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 +445,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 +485,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 +525,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 +565,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 +609,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 +657,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 +708,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 +761,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 +829,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,7 +879,7 @@ 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; } } From a7cb5cbda8b54cd167cadf4f054fa9fec17b6a7f Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 12:22:56 +0100 Subject: [PATCH 09/21] Clippy --- codegen/src/types/composite_def.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 76f5b5493f..366d9b112d 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -62,7 +62,7 @@ impl CompositeDef { type_gen: &TypeGenerator, docs: &[String], ) -> Self { - let mut derives = type_gen.type_derives(ty).clone(); + let mut derives = type_gen.type_derives(ty); let fields: Vec<_> = fields_def.field_types().collect(); if fields.len() == 1 { From 6c389c9d8e6a3a5fd877d6d6ebfaf995fd67dec8 Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 15:37:02 +0100 Subject: [PATCH 10/21] Add derive_for_type attribute to example --- examples/examples/custom_type_derives.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/examples/custom_type_derives.rs b/examples/examples/custom_type_derives.rs index 575e145b33..954be3d425 100644 --- a/examples/examples/custom_type_derives.rs +++ b/examples/examples/custom_type_derives.rs @@ -24,7 +24,9 @@ // a comma separated list to the below attribute. Most useful for adding `Clone`. // The derives that we can add ultimately is limited to the traits that the base // types relied upon by the codegen implement. - derive_for_all_types = "Clone, PartialEq, Hash" + derive_for_all_types = "Clone, PartialEq, Hash", + // todo: docs + derive_for_type(ty = "frame_support::PalletId", derive = "Eq, PartialEq"), )] pub mod polkadot {} From 99075f03bf8eddf067e9b9120071a643cc16c94a Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 15:44:53 +0100 Subject: [PATCH 11/21] Add docs to example --- examples/examples/custom_type_derives.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/examples/custom_type_derives.rs b/examples/examples/custom_type_derives.rs index 954be3d425..9c9aa36b36 100644 --- a/examples/examples/custom_type_derives.rs +++ b/examples/examples/custom_type_derives.rs @@ -20,13 +20,19 @@ #[subxt::subxt( runtime_metadata_path = "examples/polkadot_metadata.scale", + // We can add (certain) custom derives to the generated types by providing // a comma separated list to the below attribute. Most useful for adding `Clone`. // The derives that we can add ultimately is limited to the traits that the base // types relied upon by the codegen implement. - derive_for_all_types = "Clone, PartialEq, Hash", - // todo: docs - derive_for_type(ty = "frame_support::PalletId", derive = "Eq, PartialEq"), + derive_for_all_types = "Clone, PartialEq", + + // To apply derives to specific generated types, add a `derive_for_type` per type, + // mapping the type path to the derives which should be added for that type only. + // Note that these derives will be in addition to those specified above in + // `derive_for_all_types` + derive_for_type(ty = "frame_support::PalletId", derive = "Eq, Ord, PartialOrd"), + derive_for_type(ty = "sp_runtime::ModuleError", derive = "Eq, Hash"), )] pub mod polkadot {} From e47578f72baf4575ab0a6c36a8332505292a752b Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 15:47:10 +0100 Subject: [PATCH 12/21] Rename GeneratedTypeDerive --- macro/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macro/src/lib.rs b/macro/src/lib.rs index de413a2deb..013665f806 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -31,11 +31,11 @@ struct RuntimeMetadataArgs { #[darling(default)] derive_for_all_types: Option>, #[darling(multiple)] - derive_for_type: Vec, + derive_for_type: Vec, } #[derive(Debug, FromMeta)] -struct GeneratedTypeDerives { +struct DeriveForType { ty: syn::TypePath, derive: Punctuated, } From ba3e85a98e8ae58a4e35bef17b2a9b9e28d5258c Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 15:48:47 +0100 Subject: [PATCH 13/21] Rename ty to type in attribute --- examples/examples/custom_type_derives.rs | 4 ++-- macro/src/lib.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/examples/custom_type_derives.rs b/examples/examples/custom_type_derives.rs index 9c9aa36b36..acbcb2d61f 100644 --- a/examples/examples/custom_type_derives.rs +++ b/examples/examples/custom_type_derives.rs @@ -31,8 +31,8 @@ // mapping the type path to the derives which should be added for that type only. // Note that these derives will be in addition to those specified above in // `derive_for_all_types` - derive_for_type(ty = "frame_support::PalletId", derive = "Eq, Ord, PartialOrd"), - derive_for_type(ty = "sp_runtime::ModuleError", derive = "Eq, Hash"), + derive_for_type(type = "frame_support::PalletId", derive = "Eq, Ord, PartialOrd"), + derive_for_type(type = "sp_runtime::ModuleError", derive = "Eq, Hash"), )] pub mod polkadot {} diff --git a/macro/src/lib.rs b/macro/src/lib.rs index 013665f806..c6e613c982 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -36,6 +36,7 @@ struct RuntimeMetadataArgs { #[derive(Debug, FromMeta)] struct DeriveForType { + #[darling(rename = "type")] ty: syn::TypePath, derive: Punctuated, } From 528228f5be20d73e07e1a23a095b62af244c5736 Mon Sep 17 00:00:00 2001 From: ascjones Date: Wed, 27 Apr 2022 16:04:15 +0100 Subject: [PATCH 14/21] Update darling --- codegen/Cargo.toml | 2 +- macro/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index a50280d5cc..989e90cbe7 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -13,7 +13,7 @@ description = "Generate an API for interacting with a substrate node from FRAME [dependencies] async-trait = "0.1.49" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full", "bit-vec"] } -darling = "0.13.0" +darling = "0.14.0" frame-metadata = "15.0.0" heck = "0.4.0" proc-macro2 = "1.0.24" diff --git a/macro/Cargo.toml b/macro/Cargo.toml index 480d181296..c2bcf95603 100644 --- a/macro/Cargo.toml +++ b/macro/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] async-trait = "0.1.49" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } -darling = "0.13.0" +darling = "0.14.0" frame-metadata = "15.0.0" heck = "0.4.0" proc-macro2 = "1.0.24" From 7e72f82cc3f0920b4cb2868fc5b272f49c240495 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 28 Apr 2022 09:26:11 +0100 Subject: [PATCH 15/21] Update codegen/src/types/derives.rs Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> --- codegen/src/types/derives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index 9477817feb..5d539e7ff1 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -50,7 +50,7 @@ impl DerivesRegistry { type_derives.derives.extend(derives) } - /// Returns a the derives to be applied to all generated types. + /// Returns the derives to be applied to all generated types. pub fn default_derives(&self) -> &Derives { &self.default_derives } From e2c7817d825682a5ad13ba2093b1060c78cb33f4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 28 Apr 2022 09:26:24 +0100 Subject: [PATCH 16/21] Update codegen/src/types/mod.rs Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> --- codegen/src/types/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index 2c76fce100..01f04049b2 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -219,7 +219,7 @@ impl<'a> TypeGenerator<'a> { } } - /// Returns a the derives to be applied to all generated types. + /// Returns the derives to be applied to all generated types. pub fn default_derives(&self) -> &Derives { self.derives.default_derives() } From ee9d2f6963e3db46182bcacb4785c3d021c16d15 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 28 Apr 2022 09:26:37 +0100 Subject: [PATCH 17/21] Update codegen/src/types/mod.rs Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> --- codegen/src/types/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index 01f04049b2..5726d36a96 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -224,7 +224,7 @@ impl<'a> TypeGenerator<'a> { self.derives.default_derives() } - /// Returns a the derives to be applied to a generated type. + /// Returns the derives to be applied to a generated type. pub fn type_derives(&self, ty: &Type) -> Derives { let joined_path = ty.path().segments().join("::"); let ty_path: syn::TypePath = syn::parse_str(&joined_path).unwrap_or_else(|e| { From a8d76e632079ff3fac75637cddacb7f6d4ef49c2 Mon Sep 17 00:00:00 2001 From: ascjones Date: Thu, 28 Apr 2022 11:00:25 +0100 Subject: [PATCH 18/21] review: update method name --- codegen/src/types/composite_def.rs | 2 +- codegen/src/types/derives.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 366d9b112d..34a57c7c76 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -85,7 +85,7 @@ impl CompositeDef { | TypeDefPrimitive::U128 ) ) { - derives.push_codec_compact_as() + derives.insert_codec_compact_as() } } } diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index 9477817feb..a3bdc97fba 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -82,7 +82,7 @@ impl FromIterator for Derives { impl Derives { /// Add `::subxt::codec::CompactAs` to the derives. - pub fn push_codec_compact_as(&mut self) { + pub fn insert_codec_compact_as(&mut self) { self.insert(parse_quote!(::subxt::codec::CompactAs)); } From 21e62a7b2996ea45698a155180a70a9a8004565a Mon Sep 17 00:00:00 2001 From: ascjones Date: Thu, 28 Apr 2022 11:32:36 +0100 Subject: [PATCH 19/21] Add unit tests for combined derives --- codegen/src/types/derives.rs | 4 +- codegen/src/types/tests.rs | 103 +++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index 9af1e74b0f..085c8b7768 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -33,7 +33,7 @@ pub struct DerivesRegistry { impl DerivesRegistry { /// Insert derives to be applied to all generated types. - pub fn extend_for_all(&mut self, derives: impl Iterator) { + pub fn extend_for_all(&mut self, derives: impl IntoIterator) { self.default_derives.derives.extend(derives) } @@ -41,7 +41,7 @@ impl DerivesRegistry { pub fn extend_for_type( &mut self, ty: syn::TypePath, - derives: impl Iterator, + derives: impl IntoIterator, ) { let type_derives = self .specific_type_derives diff --git a/codegen/src/types/tests.rs b/codegen/src/types/tests.rs index 07fc404a62..7f2501677c 100644 --- a/codegen/src/types/tests.rs +++ b/codegen/src/types/tests.rs @@ -21,6 +21,7 @@ use scale_info::{ Registry, TypeInfo, }; +use syn::parse_quote; const MOD_PATH: &[&str] = &["subxt_codegen", "types", "tests"]; @@ -886,3 +887,105 @@ fn dont_force_struct_names_camel_case() { .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::()); + 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::()); + 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() + ) +} From 6753f4ece59856a9fd23ff5d49a971c286ae576a Mon Sep 17 00:00:00 2001 From: ascjones Date: Thu, 28 Apr 2022 11:35:50 +0100 Subject: [PATCH 20/21] Remove out of date docs --- codegen/src/api/mod.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 71e8caf543..a437f610c8 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -15,21 +15,6 @@ // along with subxt. If not, see . //! Generate code for submitting extrinsics and query storage of a Substrate runtime. -//! -//! ## Note -//! -//! By default the codegen will search for the `System` pallet's `Account` storage item, which is -//! the conventional location where an account's index (aka nonce) is stored. -//! -//! If this `System::Account` storage item is discovered, then it is assumed that: -//! -//! 1. The type of the storage item is a `struct` (aka a composite type) -//! 2. There exists a field called `nonce` which contains the account index. -//! -//! These assumptions are based on the fact that the `frame_system::AccountInfo` type is the default -//! configured type, and that the vast majority of chain configurations will use this. -//! -//! If either of these conditions are not satisfied, the codegen will fail. mod calls; mod constants; From 2eb05622f6e2afe8f7e675c10da3aa8be3c32da3 Mon Sep 17 00:00:00 2001 From: ascjones Date: Thu, 28 Apr 2022 12:03:30 +0100 Subject: [PATCH 21/21] Add macro usage docs --- macro/src/lib.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/macro/src/lib.rs b/macro/src/lib.rs index c6e613c982..7222930bce 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -14,6 +14,79 @@ // You should have received a copy of the GNU General Public License // along with subxt. If not, see . +//! Generate a strongly typed API for interacting with a Substrate runtime from its metadata. +//! +//! Usage: +//! +//! Download metadata from a running Substrate node using `subxt-cli`: +//! +//! ```bash +//! subxt metadata -f bytes > polkadot_metadata.scale +//! ``` +//! +//! Annotate a Rust module with the `subxt` attribute referencing the aforementioned metadata file. +//! +//! ```ignore +//! #[subxt::subxt( +//! runtime_metadata_path = "polkadot_metadata.scale", +//! )] +//! pub mod polkadot {} +//! ``` +//! +//! The `subxt` macro will populate the annotated module with all of the methods and types required +//! for submitting extrinsics and reading from storage for the given runtime. +//! +//! ## Substituting types +//! +//! In order to replace a generated type by a user-defined type, use `substitute_type`: +//! +//! ```ignore +//! #[subxt::subxt( +//! runtime_metadata_path = "polkadot_metadata.scale", +//! )] +//! pub mod polkadot { +//! #[subxt(substitute_type = "sp_arithmetic::per_things::Perbill")] +//! use sp_runtime::Perbill; +//! } +//! ``` +//! +//! This will replace the generated type and any usages with the specified type at the `use` import. +//! It is useful for using custom decoding for specific types, or to provide a type with foreign +//! trait implementations, or other specialized functionality. + +//! ## Custom Derives +//! +//! By default all generated types are annotated with `scale::Encode` and `scale::Decode` derives. +//! However when using the generated types in the client, they may require additional derives to be +//! useful. +//! +//! ### Adding derives for all types +//! +//! Add `derive_for_all_types` with a comma seperated list of the derives to apply to *all* types +//! +//! ```ignore +//! #[subxt::subxt( +//! runtime_metadata_path = "polkadot_metadata.scale", +//! derive_for_all_types = "Eq, PartialEq" +//! )] +//! pub mod polkadot {} +//! ``` +//! +//! ### Adding derives for specific types +//! +//! Add `derive_for_type` for each specific type with a comma seperated list of the derives to +//! apply for that type only. +//! +//! ```ignore +//! #[subxt::subxt( +//! runtime_metadata_path = "polkadot_metadata.scale", +//! derive_for_all_types = "Eq, PartialEq", +//! derive_for_type(type = "frame_support::PalletId", derive = "Ord, PartialOrd"), +//! derive_for_type(type = "sp_runtime::ModuleError", derive = "Hash"), +//! )] +//! pub mod polkadot {} +//! ``` + extern crate proc_macro; use darling::FromMeta;