mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 09:57:56 +00:00
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:
@@ -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>,
|
||||
},
|
||||
|
||||
@@ -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("e::quote!(#b).to_string())
|
||||
});
|
||||
let derives: Punctuated<syn::Path, syn::Token![,]> =
|
||||
sorted.iter().cloned().collect();
|
||||
tokens.extend(quote::quote! {
|
||||
#[derive(#derives)]
|
||||
})
|
||||
|
||||
+26
-13
@@ -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
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user