mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 21:58:06 +00:00
Allow for remapping type parameters in type substitutions (#735)
* feat!: Allow for remapping type parameters in type substitutions * chore: cargo fmt * chore: cargo clippy * chore: Remove some old code * a little tidy * address comment nit Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
+24
-54
@@ -18,6 +18,7 @@ use crate::{
|
||||
CompositeDef,
|
||||
CompositeDefFields,
|
||||
TypeGenerator,
|
||||
TypeSubstitutes,
|
||||
},
|
||||
utils::{
|
||||
fetch_metadata_bytes_blocking,
|
||||
@@ -39,7 +40,6 @@ use quote::{
|
||||
quote,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
io::Read,
|
||||
path,
|
||||
@@ -54,6 +54,7 @@ use syn::parse_quote;
|
||||
/// * `item_mod` - The module declaration for which the API is implemented.
|
||||
/// * `path` - The path to the scale encoded metadata of the runtime node.
|
||||
/// * `derives` - Provide custom derives for the generated types.
|
||||
/// * `type_substitutes` - Provide custom type substitutes.
|
||||
/// * `crate_path` - Path to the `subxt` crate.
|
||||
///
|
||||
/// **Note:** This is a wrapper over [RuntimeGenerator] for static metadata use-cases.
|
||||
@@ -61,6 +62,7 @@ pub fn generate_runtime_api_from_path<P>(
|
||||
item_mod: syn::ItemMod,
|
||||
path: P,
|
||||
derives: DerivesRegistry,
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
) -> TokenStream2
|
||||
where
|
||||
@@ -74,7 +76,13 @@ where
|
||||
file.read_to_end(&mut bytes)
|
||||
.unwrap_or_else(|e| abort_call_site!("Failed to read metadata file: {}", e));
|
||||
|
||||
generate_runtime_api_from_bytes(item_mod, &bytes, derives, crate_path)
|
||||
generate_runtime_api_from_bytes(
|
||||
item_mod,
|
||||
&bytes,
|
||||
derives,
|
||||
type_substitutes,
|
||||
crate_path,
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates the API for interacting with a substrate runtime, using metadata
|
||||
@@ -86,6 +94,7 @@ where
|
||||
/// * `item_mod` - The module declaration for which the API is implemented.
|
||||
/// * `url` - HTTP/WS URL to the substrate node you'd like to pull metadata from.
|
||||
/// * `derives` - Provide custom derives for the generated types.
|
||||
/// * `type_substitutes` - Provide custom type substitutes.
|
||||
/// * `crate_path` - Path to the `subxt` crate.
|
||||
///
|
||||
/// **Note:** This is a wrapper over [RuntimeGenerator] for static metadata use-cases.
|
||||
@@ -93,12 +102,19 @@ pub fn generate_runtime_api_from_url(
|
||||
item_mod: syn::ItemMod,
|
||||
url: &Uri,
|
||||
derives: DerivesRegistry,
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
) -> TokenStream2 {
|
||||
let bytes = fetch_metadata_bytes_blocking(url)
|
||||
.unwrap_or_else(|e| abort_call_site!("Failed to obtain metadata: {}", e));
|
||||
|
||||
generate_runtime_api_from_bytes(item_mod, &bytes, derives, crate_path)
|
||||
generate_runtime_api_from_bytes(
|
||||
item_mod,
|
||||
&bytes,
|
||||
derives,
|
||||
type_substitutes,
|
||||
crate_path,
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates the API for interacting with a substrate runtime, using metadata bytes.
|
||||
@@ -106,8 +122,9 @@ pub fn generate_runtime_api_from_url(
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `item_mod` - The module declaration for which the API is implemented.
|
||||
/// * `url` - HTTP/WS URL to the substrate node you'd like to pull metadata from.
|
||||
/// * `bytes` - The raw metadata bytes.
|
||||
/// * `derives` - Provide custom derives for the generated types.
|
||||
/// * `type_substitutes` - Provide custom type substitutes.
|
||||
/// * `crate_path` - Path to the `subxt` crate.
|
||||
///
|
||||
/// **Note:** This is a wrapper over [RuntimeGenerator] for static metadata use-cases.
|
||||
@@ -115,13 +132,14 @@ pub fn generate_runtime_api_from_bytes(
|
||||
item_mod: syn::ItemMod,
|
||||
bytes: &[u8],
|
||||
derives: DerivesRegistry,
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
) -> TokenStream2 {
|
||||
let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..])
|
||||
.unwrap_or_else(|e| abort_call_site!("Failed to decode metadata: {}", e));
|
||||
|
||||
let generator = RuntimeGenerator::new(metadata);
|
||||
generator.generate_runtime(item_mod, derives, crate_path)
|
||||
generator.generate_runtime(item_mod, derives, type_substitutes, crate_path)
|
||||
}
|
||||
|
||||
/// Create the API for interacting with a Substrate runtime.
|
||||
@@ -152,61 +170,13 @@ impl RuntimeGenerator {
|
||||
&self,
|
||||
item_mod: syn::ItemMod,
|
||||
derives: DerivesRegistry,
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
) -> TokenStream2 {
|
||||
let item_mod_attrs = item_mod.attrs.clone();
|
||||
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 = [
|
||||
(
|
||||
"bitvec::order::Lsb0",
|
||||
parse_quote!(#crate_path::utils::bits::Lsb0),
|
||||
),
|
||||
(
|
||||
"bitvec::order::Msb0",
|
||||
parse_quote!(#crate_path::utils::bits::Msb0),
|
||||
),
|
||||
(
|
||||
"sp_core::crypto::AccountId32",
|
||||
parse_quote!(#crate_path::utils::AccountId32),
|
||||
),
|
||||
(
|
||||
"sp_runtime::multiaddress::MultiAddress",
|
||||
parse_quote!(#crate_path::utils::MultiAddress),
|
||||
),
|
||||
(
|
||||
"primitive_types::H160",
|
||||
parse_quote!(#crate_path::utils::H160),
|
||||
),
|
||||
(
|
||||
"primitive_types::H256",
|
||||
parse_quote!(#crate_path::utils::H256),
|
||||
),
|
||||
(
|
||||
"primitive_types::H512",
|
||||
parse_quote!(#crate_path::utils::H512),
|
||||
),
|
||||
(
|
||||
"frame_support::traits::misc::WrapperKeepOpaque",
|
||||
parse_quote!(#crate_path::utils::WrapperKeepOpaque),
|
||||
),
|
||||
// BTreeMap and BTreeSet impose an `Ord` constraint on their key types. This
|
||||
// can cause an issue with generated code that doesn't impl `Ord` by default.
|
||||
// Decoding them to Vec by default (KeyedVec is just an alias for Vec with
|
||||
// suitable type params) avoids these issues.
|
||||
("BTreeMap", parse_quote!(#crate_path::utils::KeyedVec)),
|
||||
("BTreeSet", parse_quote!(::std::vec::Vec)),
|
||||
]
|
||||
.iter()
|
||||
.map(|(path, substitute): &(&str, syn::TypePath)| {
|
||||
(path.to_string(), substitute.clone())
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
type_substitutes.extend(item_mod_ir.type_substitutes().into_iter());
|
||||
|
||||
let type_gen = TypeGenerator::new(
|
||||
&self.metadata.types,
|
||||
"runtime_types",
|
||||
|
||||
+4
-125
@@ -3,11 +3,7 @@
|
||||
// see LICENSE for license details.
|
||||
|
||||
use proc_macro_error::abort;
|
||||
use std::collections::HashMap;
|
||||
use syn::{
|
||||
spanned::Spanned as _,
|
||||
token,
|
||||
};
|
||||
use syn::token;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct ItemMod {
|
||||
@@ -15,7 +11,7 @@ pub struct ItemMod {
|
||||
mod_token: token::Mod,
|
||||
pub ident: syn::Ident,
|
||||
brace: token::Brace,
|
||||
items: Vec<Item>,
|
||||
items: Vec<syn::Item>,
|
||||
}
|
||||
|
||||
impl From<syn::ItemMod> for ItemMod {
|
||||
@@ -32,130 +28,13 @@ impl From<syn::ItemMod> for ItemMod {
|
||||
mod_token: module.mod_token,
|
||||
ident: module.ident,
|
||||
brace,
|
||||
items: items.into_iter().map(From::from).collect(),
|
||||
items,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemMod {
|
||||
pub fn type_substitutes(&self) -> HashMap<String, syn::TypePath> {
|
||||
self.items
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
if let Item::Subxt(SubxtItem::TypeSubstitute {
|
||||
generated_type_path,
|
||||
substitute_with: substitute_type,
|
||||
}) = item
|
||||
{
|
||||
Some((generated_type_path.clone(), substitute_type.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn rust_items(&self) -> impl Iterator<Item = &syn::Item> {
|
||||
self.items.iter().filter_map(Item::as_rust)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Item {
|
||||
Rust(syn::Item),
|
||||
Subxt(SubxtItem),
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn as_rust(&self) -> Option<&syn::Item> {
|
||||
match self {
|
||||
Item::Rust(item) => Some(item),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<syn::Item> for Item {
|
||||
fn from(item: syn::Item) -> Self {
|
||||
if let syn::Item::Use(ref use_) = item {
|
||||
let substitute_attrs = use_
|
||||
.attrs
|
||||
.iter()
|
||||
.map(|attr| {
|
||||
let meta = attr.parse_meta().unwrap_or_else(|e| {
|
||||
abort!(attr.span(), "Error parsing attribute: {}", e)
|
||||
});
|
||||
<attrs::Subxt as darling::FromMeta>::from_meta(&meta).unwrap_or_else(
|
||||
|e| abort!(attr.span(), "Error parsing attribute meta: {}", e),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if substitute_attrs.len() > 1 {
|
||||
abort!(
|
||||
use_.attrs[0].span(),
|
||||
"Duplicate `substitute_type` attributes"
|
||||
)
|
||||
}
|
||||
if let Some(attr) = substitute_attrs.get(0) {
|
||||
let use_path = &use_.tree;
|
||||
let substitute_with: syn::TypePath = syn::parse_quote!( #use_path );
|
||||
|
||||
let is_crate = substitute_with
|
||||
.path
|
||||
.segments
|
||||
.first()
|
||||
.map(|segment| segment.ident == "crate")
|
||||
.unwrap_or(false);
|
||||
|
||||
// Check if the substitute path is a global absolute path, meaning it
|
||||
// is prefixed with `::` or `crate`.
|
||||
//
|
||||
// Note: the leading colon is lost when parsing to `syn::TypePath` via
|
||||
// `syn::parse_quote!`. Therefore, inspect `use_`'s leading colon.
|
||||
if use_.leading_colon.is_none() && !is_crate {
|
||||
abort!(
|
||||
use_path.span(),
|
||||
"The substitute path must be a global absolute path; try prefixing with `::` or `crate`"
|
||||
)
|
||||
}
|
||||
|
||||
let type_substitute = SubxtItem::TypeSubstitute {
|
||||
generated_type_path: attr.substitute_type(),
|
||||
substitute_with,
|
||||
};
|
||||
Self::Subxt(type_substitute)
|
||||
} else {
|
||||
Self::Rust(item)
|
||||
}
|
||||
} else {
|
||||
Self::Rust(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum SubxtItem {
|
||||
TypeSubstitute {
|
||||
generated_type_path: String,
|
||||
substitute_with: syn::TypePath,
|
||||
},
|
||||
}
|
||||
|
||||
mod attrs {
|
||||
use darling::FromMeta;
|
||||
|
||||
#[derive(Debug, FromMeta)]
|
||||
#[darling(rename_all = "snake_case")]
|
||||
pub enum Subxt {
|
||||
SubstituteType(String),
|
||||
}
|
||||
|
||||
impl Subxt {
|
||||
pub fn substitute_type(&self) -> String {
|
||||
match self {
|
||||
Self::SubstituteType(path) => path.clone(),
|
||||
}
|
||||
}
|
||||
self.items.iter()
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -21,7 +21,7 @@
|
||||
//! use std::fs;
|
||||
//! use codec::Decode;
|
||||
//! use frame_metadata::RuntimeMetadataPrefixed;
|
||||
//! use subxt_codegen::{CratePath, DerivesRegistry};
|
||||
//! use subxt_codegen::{CratePath, DerivesRegistry, TypeSubstitutes};
|
||||
//!
|
||||
//! let encoded = fs::read("../artifacts/polkadot_metadata.scale").unwrap();
|
||||
//!
|
||||
@@ -33,9 +33,11 @@
|
||||
//! );
|
||||
//! // Default module derivatives.
|
||||
//! let mut derives = DerivesRegistry::new(&CratePath::default());
|
||||
//! // Default type substitutes.
|
||||
//! let substs = TypeSubstitutes::new(&CratePath::default());
|
||||
//! // Generate the Runtime API.
|
||||
//! let generator = subxt_codegen::RuntimeGenerator::new(metadata);
|
||||
//! let runtime_api = generator.generate_runtime(item_mod, derives, CratePath::default());
|
||||
//! let runtime_api = generator.generate_runtime(item_mod, derives, substs, CratePath::default());
|
||||
//! println!("{}", runtime_api);
|
||||
//! ```
|
||||
|
||||
@@ -60,5 +62,6 @@ pub use self::{
|
||||
DerivesRegistry,
|
||||
Module,
|
||||
TypeGenerator,
|
||||
TypeSubstitutes,
|
||||
},
|
||||
};
|
||||
|
||||
+43
-53
@@ -4,6 +4,7 @@
|
||||
|
||||
mod composite_def;
|
||||
mod derives;
|
||||
mod substitutes;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod type_def;
|
||||
@@ -27,10 +28,7 @@ use scale_info::{
|
||||
Type,
|
||||
TypeDef,
|
||||
};
|
||||
use std::collections::{
|
||||
BTreeMap,
|
||||
HashMap,
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub use self::{
|
||||
composite_def::{
|
||||
@@ -42,6 +40,7 @@ pub use self::{
|
||||
Derives,
|
||||
DerivesRegistry,
|
||||
},
|
||||
substitutes::TypeSubstitutes,
|
||||
type_def::TypeDefGen,
|
||||
type_def_params::TypeDefParameters,
|
||||
type_path::{
|
||||
@@ -61,7 +60,7 @@ pub struct TypeGenerator<'a> {
|
||||
/// Registry of type definitions to be transformed into Rust type definitions.
|
||||
type_registry: &'a PortableRegistry,
|
||||
/// User defined overrides for generated types.
|
||||
type_substitutes: HashMap<String, syn::TypePath>,
|
||||
type_substitutes: TypeSubstitutes,
|
||||
/// Set of derives with which to annotate generated types.
|
||||
derives: DerivesRegistry,
|
||||
/// The `subxt` crate access path in the generated code.
|
||||
@@ -73,7 +72,7 @@ impl<'a> TypeGenerator<'a> {
|
||||
pub fn new(
|
||||
type_registry: &'a PortableRegistry,
|
||||
root_mod: &'static str,
|
||||
type_substitutes: HashMap<String, syn::TypePath>,
|
||||
type_substitutes: TypeSubstitutes,
|
||||
derives: DerivesRegistry,
|
||||
crate_path: CratePath,
|
||||
) -> Self {
|
||||
@@ -89,55 +88,43 @@ impl<'a> TypeGenerator<'a> {
|
||||
|
||||
/// Generate a module containing all types defined in the supplied type registry.
|
||||
pub fn generate_types_mod(&self) -> Module {
|
||||
let mut root_mod =
|
||||
Module::new(self.types_mod_ident.clone(), self.types_mod_ident.clone());
|
||||
let root_mod_ident = &self.types_mod_ident;
|
||||
let mut root_mod = Module::new(root_mod_ident.clone(), root_mod_ident.clone());
|
||||
|
||||
for ty in self.type_registry.types().iter() {
|
||||
if ty.ty().path().namespace().is_empty() {
|
||||
// prelude types e.g. Option/Result have no namespace, so we don't generate them
|
||||
for ty in self.type_registry.types() {
|
||||
let path = ty.ty().path();
|
||||
// Don't generate a type if it was substituted - the target type might
|
||||
// not be in the type registry + our resolution already performs the substitution.
|
||||
if self.type_substitutes.for_path(path).is_some() {
|
||||
continue
|
||||
}
|
||||
self.insert_type(
|
||||
ty.ty().clone(),
|
||||
ty.ty().path().namespace().to_vec(),
|
||||
&self.types_mod_ident,
|
||||
&mut root_mod,
|
||||
)
|
||||
|
||||
let namespace = path.namespace();
|
||||
// prelude types e.g. Option/Result have no namespace, so we don't generate them
|
||||
if namespace.is_empty() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Lazily create submodules for the encountered namespace path, if they don't exist
|
||||
let innermost_module = namespace
|
||||
.iter()
|
||||
.map(|segment| Ident::new(segment, Span::call_site()))
|
||||
.fold(&mut root_mod, |module, ident| {
|
||||
module
|
||||
.children
|
||||
.entry(ident.clone())
|
||||
.or_insert_with(|| Module::new(ident, root_mod_ident.clone()))
|
||||
});
|
||||
|
||||
innermost_module.types.insert(
|
||||
path.clone(),
|
||||
TypeDefGen::from_type(ty.ty(), self, &self.crate_path),
|
||||
);
|
||||
}
|
||||
|
||||
root_mod
|
||||
}
|
||||
|
||||
fn insert_type(
|
||||
&'a self,
|
||||
ty: Type<PortableForm>,
|
||||
path: Vec<String>,
|
||||
root_mod_ident: &Ident,
|
||||
module: &mut Module,
|
||||
) {
|
||||
let joined_path = path.join("::");
|
||||
if self.type_substitutes.contains_key(&joined_path) {
|
||||
return
|
||||
}
|
||||
|
||||
let segment = path.first().expect("path has at least one segment");
|
||||
let mod_ident = Ident::new(segment, Span::call_site());
|
||||
|
||||
let child_mod = module
|
||||
.children
|
||||
.entry(mod_ident.clone())
|
||||
.or_insert_with(|| Module::new(mod_ident, root_mod_ident.clone()));
|
||||
|
||||
if path.len() == 1 {
|
||||
child_mod.types.insert(
|
||||
ty.path().clone(),
|
||||
TypeDefGen::from_type(ty, self, &self.crate_path),
|
||||
);
|
||||
} else {
|
||||
self.insert_type(ty, path[1..].to_vec(), root_mod_ident, child_mod)
|
||||
}
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// If no type with the given id found in the type registry.
|
||||
@@ -208,7 +195,7 @@ impl<'a> TypeGenerator<'a> {
|
||||
)
|
||||
}
|
||||
|
||||
let params = ty
|
||||
let params: Vec<_> = ty
|
||||
.type_params()
|
||||
.iter()
|
||||
.filter_map(|f| {
|
||||
@@ -220,13 +207,16 @@ impl<'a> TypeGenerator<'a> {
|
||||
|
||||
let ty = match ty.type_def() {
|
||||
TypeDef::Composite(_) | TypeDef::Variant(_) => {
|
||||
let joined_path = ty.path().segments().join("::");
|
||||
if let Some(substitute_type_path) =
|
||||
self.type_substitutes.get(&joined_path)
|
||||
if let Some((path, params)) = self
|
||||
.type_substitutes
|
||||
.for_path_with_params(ty.path(), ¶ms)
|
||||
{
|
||||
TypePathType::Path {
|
||||
path: substitute_type_path.clone(),
|
||||
params,
|
||||
path: syn::TypePath {
|
||||
qself: None,
|
||||
path: path.clone(),
|
||||
},
|
||||
params: params.to_vec(),
|
||||
}
|
||||
} else {
|
||||
TypePathType::from_type_def_path(
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
// Copyright 2019-2023 Parity Technologies (UK) Ltd.
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use crate::CratePath;
|
||||
use proc_macro_error::abort;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
};
|
||||
use syn::{
|
||||
parse_quote,
|
||||
spanned::Spanned as _,
|
||||
};
|
||||
|
||||
use super::TypePath;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeSubstitutes {
|
||||
substitutes: HashMap<PathSegments, Substitute>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Substitute {
|
||||
path: syn::Path,
|
||||
param_mapping: TypeParamMapping,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TypeParamMapping {
|
||||
None,
|
||||
Specified(Vec<u8>),
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! path_segments {
|
||||
($($ident: ident)::*) => {
|
||||
PathSegments(
|
||||
[$(stringify!($ident)),*].into_iter().map(String::from).collect::<Vec<_>>()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeSubstitutes {
|
||||
pub fn new(crate_path: &CratePath) -> Self {
|
||||
// Some hardcoded default type substitutes, can be overridden by user
|
||||
let defaults = [
|
||||
(
|
||||
path_segments!(bitvec::order::Lsb0),
|
||||
parse_quote!(#crate_path::utils::bits::Lsb0),
|
||||
),
|
||||
(
|
||||
path_segments!(bitvec::order::Msb0),
|
||||
parse_quote!(#crate_path::utils::bits::Msb0),
|
||||
),
|
||||
(
|
||||
path_segments!(sp_core::crypto::AccountId32),
|
||||
parse_quote!(#crate_path::utils::AccountId32),
|
||||
),
|
||||
(
|
||||
path_segments!(sp_runtime::multiaddress::MultiAddress),
|
||||
parse_quote!(#crate_path::utils::MultiAddress),
|
||||
),
|
||||
(
|
||||
path_segments!(primitive_types::H160),
|
||||
parse_quote!(#crate_path::utils::H160),
|
||||
),
|
||||
(
|
||||
path_segments!(primitive_types::H256),
|
||||
parse_quote!(#crate_path::utils::H256),
|
||||
),
|
||||
(
|
||||
path_segments!(primitive_types::H512),
|
||||
parse_quote!(#crate_path::utils::H512),
|
||||
),
|
||||
(
|
||||
path_segments!(frame_support::traits::misc::WrapperKeepOpaque),
|
||||
parse_quote!(#crate_path::utils::WrapperKeepOpaque),
|
||||
),
|
||||
// BTreeMap and BTreeSet impose an `Ord` constraint on their key types. This
|
||||
// can cause an issue with generated code that doesn't impl `Ord` by default.
|
||||
// Decoding them to Vec by default (KeyedVec is just an alias for Vec with
|
||||
// suitable type params) avoids these issues.
|
||||
(
|
||||
path_segments!(BTreeMap),
|
||||
parse_quote!(#crate_path::utils::KeyedVec),
|
||||
),
|
||||
(path_segments!(BTreeSet), parse_quote!(::std::vec::Vec)),
|
||||
];
|
||||
|
||||
let default_substitutes = defaults
|
||||
.into_iter()
|
||||
.map(|(k, v)| {
|
||||
(
|
||||
k,
|
||||
Substitute {
|
||||
path: v,
|
||||
param_mapping: TypeParamMapping::None,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
substitutes: default_substitutes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, elems: impl IntoIterator<Item = (syn::Path, AbsolutePath)>) {
|
||||
self.substitutes
|
||||
.extend(elems.into_iter().map(|(path, AbsolutePath(mut with))| {
|
||||
let Some(syn::PathSegment { arguments: src_path_args, ..}) = path.segments.last() else { abort!(path.span(), "Empty path") };
|
||||
let Some(syn::PathSegment { arguments: target_path_args, ..}) = with.segments.last_mut() else { abort!(with.span(), "Empty path") };
|
||||
|
||||
let source_args: Vec<_> = type_args(src_path_args).collect();
|
||||
|
||||
let param_mapping = if source_args.is_empty() {
|
||||
// If the type parameters on the source type are not specified, then this means that
|
||||
// the type is either not generic or the user wants to pass through all the parameters
|
||||
TypeParamMapping::None
|
||||
} else {
|
||||
// Describe the mapping in terms of "which source param idx is used for each target param".
|
||||
// So, for each target param, find the matching source param index.
|
||||
let mapping = type_args(target_path_args)
|
||||
.filter_map(|arg|
|
||||
source_args
|
||||
.iter()
|
||||
.position(|&src| src == arg)
|
||||
.map(|src_idx|
|
||||
u8::try_from(src_idx).expect("type arguments to be fewer than 256; qed"),
|
||||
)
|
||||
).collect();
|
||||
TypeParamMapping::Specified(mapping)
|
||||
};
|
||||
|
||||
// NOTE: Params are late bound and held separately, so clear them
|
||||
// here to not mess pretty printing this path and params together
|
||||
*target_path_args = syn::PathArguments::None;
|
||||
|
||||
(PathSegments::from(&path), Substitute { path: with, param_mapping })
|
||||
}));
|
||||
}
|
||||
|
||||
/// Given a source type path, return a substituted type path if a substitution is defined.
|
||||
pub fn for_path(&self, path: impl Into<PathSegments>) -> Option<&syn::Path> {
|
||||
self.substitutes.get(&path.into()).map(|s| &s.path)
|
||||
}
|
||||
|
||||
/// Given a source type path and the resolved, supplied type parameters,
|
||||
/// return a new path and optionally overwritten type parameters.
|
||||
pub fn for_path_with_params<'a: 'b, 'b>(
|
||||
&'a self,
|
||||
path: impl Into<PathSegments>,
|
||||
params: &'b [TypePath],
|
||||
) -> Option<(&'a syn::Path, Cow<'b, [TypePath]>)> {
|
||||
// For now, we only support:
|
||||
// 1. Reordering the generics
|
||||
// 2. Omitting certain generics
|
||||
fn reorder_params<'a>(
|
||||
params: &'a [TypePath],
|
||||
mapping: &TypeParamMapping,
|
||||
) -> Cow<'a, [TypePath]> {
|
||||
match mapping {
|
||||
TypeParamMapping::Specified(mapping) => {
|
||||
Cow::Owned(
|
||||
mapping
|
||||
.iter()
|
||||
.filter_map(|&idx| params.get(idx as usize))
|
||||
.cloned()
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
_ => Cow::Borrowed(params),
|
||||
}
|
||||
}
|
||||
|
||||
let path = path.into();
|
||||
|
||||
self.substitutes
|
||||
.get(&path)
|
||||
.map(|sub| (&sub.path, reorder_params(params, &sub.param_mapping)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Identifiers joined by the `::` separator.
|
||||
///
|
||||
/// We use this as a common denominator, since we need a consistent keys for both
|
||||
/// `syn::TypePath` and `scale_info::ty::path::Path` types.
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub struct PathSegments(Vec<String>);
|
||||
|
||||
impl From<&syn::Path> for PathSegments {
|
||||
fn from(path: &syn::Path) -> Self {
|
||||
PathSegments(path.segments.iter().map(|x| x.ident.to_string()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: scale_info::form::Form> From<&scale_info::Path<T>> for PathSegments {
|
||||
fn from(path: &scale_info::Path<T>) -> Self {
|
||||
PathSegments(
|
||||
path.segments()
|
||||
.iter()
|
||||
.map(|x| x.as_ref().to_owned())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over generic type parameters for `syn::PathArguments`.
|
||||
/// For example:
|
||||
/// - `<'a, T>` should only return T
|
||||
/// - `(A, B) -> String` shouldn't return anything
|
||||
fn type_args(path_args: &syn::PathArguments) -> impl Iterator<Item = &syn::Path> {
|
||||
let args_opt = match path_args {
|
||||
syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
|
||||
ref args,
|
||||
..
|
||||
}) => Some(args),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
args_opt.into_iter().flatten().filter_map(|arg| {
|
||||
match arg {
|
||||
syn::GenericArgument::Type(syn::Type::Path(type_path)) => {
|
||||
Some(&type_path.path)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether a path is absolute - starts with `::` or `crate`.
|
||||
fn is_absolute(path: &syn::Path) -> bool {
|
||||
path.leading_colon.is_some()
|
||||
|| path
|
||||
.segments
|
||||
.first()
|
||||
.map_or(false, |segment| segment.ident == "crate")
|
||||
}
|
||||
|
||||
pub struct AbsolutePath(syn::Path);
|
||||
|
||||
impl TryFrom<syn::Path> for AbsolutePath {
|
||||
type Error = (syn::Path, String);
|
||||
fn try_from(value: syn::Path) -> Result<Self, Self::Error> {
|
||||
if is_absolute(&value) {
|
||||
Ok(AbsolutePath(value))
|
||||
} else {
|
||||
Err(
|
||||
(value, "The substitute path must be a global absolute path; try prefixing with `::` or `crate`".to_owned())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+82
-74
@@ -39,12 +39,13 @@ fn generate_struct_with_primitives() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -86,12 +87,13 @@ fn generate_struct_with_a_struct_field() {
|
||||
registry.register_type(&meta_type::<Parent>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -132,12 +134,13 @@ fn generate_tuple_struct() {
|
||||
registry.register_type(&meta_type::<Parent>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -215,12 +218,13 @@ fn derive_compact_as_for_uint_wrapper_structs() {
|
||||
registry.register_type(&meta_type::<TSu128>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -280,12 +284,13 @@ fn generate_enum() {
|
||||
registry.register_type(&meta_type::<E>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -339,12 +344,13 @@ fn compact_fields() {
|
||||
registry.register_type(&meta_type::<E>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -396,12 +402,13 @@ fn compact_generic_parameter() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -438,12 +445,13 @@ fn generate_array_field() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -476,12 +484,13 @@ fn option_fields() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -517,12 +526,13 @@ fn box_fields_struct() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -558,12 +568,13 @@ fn box_fields_enum() {
|
||||
registry.register_type(&meta_type::<E>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -599,12 +610,13 @@ fn range_fields() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -644,12 +656,13 @@ fn generics() {
|
||||
registry.register_type(&meta_type::<Bar>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -693,12 +706,13 @@ fn generics_nested() {
|
||||
registry.register_type(&meta_type::<Bar<bool>>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -745,24 +759,13 @@ fn generate_bitvec() {
|
||||
registry.register_type(&meta_type::<S>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let substitutes = [
|
||||
(
|
||||
String::from("bitvec::order::Lsb0"),
|
||||
parse_quote!(::subxt_path::utils::bits::Lsb0),
|
||||
),
|
||||
(
|
||||
String::from("bitvec::order::Msb0"),
|
||||
parse_quote!(::subxt_path::utils::bits::Msb0),
|
||||
),
|
||||
]
|
||||
.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
substitutes,
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -811,12 +814,13 @@ fn generics_with_alias_adds_phantom_data_marker() {
|
||||
registry.register_type(&meta_type::<UnnamedFields<bool, bool>>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -872,12 +876,13 @@ fn modules() {
|
||||
registry.register_type(&meta_type::<m::c::Foo>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -930,12 +935,13 @@ fn dont_force_struct_names_camel_case() {
|
||||
registry.register_type(&meta_type::<AB>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
DerivesRegistry::new(&"::subxt_path".into()),
|
||||
"::subxt_path".into(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
DerivesRegistry::new(&crate_path),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -968,16 +974,17 @@ fn apply_user_defined_derives_for_all_types() {
|
||||
registry.register_type(&meta_type::<A>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
// configure derives
|
||||
let mut derives = DerivesRegistry::new(&"::subxt_path".into());
|
||||
let mut derives = DerivesRegistry::new(&crate_path);
|
||||
derives.extend_for_all(vec![parse_quote!(Clone), parse_quote!(Eq)]);
|
||||
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
derives,
|
||||
"::subxt_path".into(),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
@@ -1017,15 +1024,16 @@ fn apply_user_defined_derives_for_specific_types() {
|
||||
registry.register_type(&meta_type::<A>());
|
||||
let portable_types: PortableRegistry = registry.into();
|
||||
|
||||
let crate_path = "::subxt_path".into();
|
||||
// configure derives
|
||||
let mut derives = DerivesRegistry::new(&"::subxt_path".into());
|
||||
let mut derives = DerivesRegistry::new(&crate_path);
|
||||
// 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)],
|
||||
&"::subxt_path".into(),
|
||||
&crate_path,
|
||||
);
|
||||
// duplicates (in this case `Eq`) will be combined (i.e. a set union)
|
||||
derives.extend_for_type(
|
||||
@@ -1035,15 +1043,15 @@ fn apply_user_defined_derives_for_specific_types() {
|
||||
parse_quote!(Ord),
|
||||
parse_quote!(PartialOrd),
|
||||
],
|
||||
&"::subxt_path".into(),
|
||||
&crate_path,
|
||||
);
|
||||
|
||||
let type_gen = TypeGenerator::new(
|
||||
&portable_types,
|
||||
"root",
|
||||
Default::default(),
|
||||
TypeSubstitutes::new(&crate_path),
|
||||
derives,
|
||||
"::subxt_path".into(),
|
||||
crate_path,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
@@ -42,11 +42,11 @@ pub struct TypeDefGen {
|
||||
impl TypeDefGen {
|
||||
/// Construct a type definition for codegen from the given [`scale_info::Type`].
|
||||
pub fn from_type(
|
||||
ty: Type<PortableForm>,
|
||||
ty: &Type<PortableForm>,
|
||||
type_gen: &TypeGenerator,
|
||||
crate_path: &CratePath,
|
||||
) -> Self {
|
||||
let derives = type_gen.type_derives(&ty);
|
||||
let derives = type_gen.type_derives(ty);
|
||||
|
||||
let type_params = ty
|
||||
.type_params()
|
||||
@@ -80,7 +80,7 @@ impl TypeDefGen {
|
||||
);
|
||||
type_params.update_unused(fields.field_types());
|
||||
let composite_def = CompositeDef::struct_def(
|
||||
&ty,
|
||||
ty,
|
||||
&type_name,
|
||||
type_params.clone(),
|
||||
fields,
|
||||
|
||||
Reference in New Issue
Block a user