codegen: Add codegen error (#841)

* codegen: Add codegen error

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Use codegen error instead of aborts

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Remove `proc-macro-error` dependency

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* macro/subxt: Transform codegen error into compile_error!

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* cli: Pretty printing for `CodegenError`

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Update cargo.lock

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests: Adjust testing for codegen error

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Fix documentation example

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Export `CodegenError`

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Use collect::<Result<_>, _>()

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* cli: Adjust comment regarding error printing

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Improve error messages

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2023-03-03 19:57:46 +02:00
committed by GitHub
parent 5320ca9d55
commit a7b45ef1d1
18 changed files with 405 additions and 322 deletions
+26 -31
View File
@@ -16,7 +16,6 @@ use frame_metadata::{
};
use heck::ToSnakeCase as _;
use proc_macro2::TokenStream as TokenStream2;
use proc_macro_error::abort_call_site;
use quote::{
format_ident,
quote,
@@ -26,6 +25,8 @@ use scale_info::{
TypeDef,
};
use super::CodegenError;
/// Generate functions which create storage addresses from the provided pallet's metadata.
/// These addresses can be used to access and iterate over storage values.
///
@@ -42,14 +43,12 @@ pub fn generate_storage(
types_mod_ident: &syn::Ident,
crate_path: &CratePath,
should_gen_docs: bool,
) -> TokenStream2 {
let storage = if let Some(ref storage) = pallet.storage {
storage
} else {
return quote!()
) -> Result<TokenStream2, CodegenError> {
let Some(storage) = &pallet.storage else {
return Ok(quote!())
};
let storage_fns: Vec<_> = storage
let storage_fns = storage
.entries
.iter()
.map(|entry| {
@@ -62,9 +61,9 @@ pub fn generate_storage(
should_gen_docs,
)
})
.collect();
.collect::<Result<Vec<_>, CodegenError>>()?;
quote! {
Ok(quote! {
pub mod storage {
use super::#types_mod_ident;
@@ -74,7 +73,7 @@ pub fn generate_storage(
#( #storage_fns )*
}
}
}
})
}
fn generate_storage_entry_fns(
@@ -84,7 +83,7 @@ fn generate_storage_entry_fns(
storage_entry: &StorageEntryMetadata<PortableForm>,
crate_path: &CratePath,
should_gen_docs: bool,
) -> TokenStream2 {
) -> Result<TokenStream2, CodegenError> {
let (fields, key_impl) = match storage_entry.ty {
StorageEntryType::Plain(_) => (vec![], quote!(vec![])),
StorageEntryType::Map {
@@ -146,13 +145,10 @@ fn generate_storage_entry_fns(
vec![ #crate_path::storage::address::StorageMapKey::new(&(#( #items.borrow() ),*), #hasher) ]
}
} else {
// If we hit this condition, we don't know how to handle the number of hashes vs fields
// that we've been handed, so abort.
abort_call_site!(
"Number of hashers ({}) does not equal 1 for StorageMap, or match number of fields ({}) for StorageNMap",
return Err(CodegenError::MismatchHashers(
hashers.len(),
fields.len()
)
fields.len(),
))
};
(fields, key_impl)
@@ -160,9 +156,9 @@ fn generate_storage_entry_fns(
_ => {
let ty_path = type_gen.resolve_type_path(key.id());
let fields = vec![(format_ident!("_0"), ty_path)];
let hasher = hashers.get(0).unwrap_or_else(|| {
abort_call_site!("No hasher found for single key")
});
let Some(hasher) = hashers.get(0) else {
return Err(CodegenError::MissingHasher)
};
let key_impl = quote! {
vec![ #crate_path::storage::address::StorageMapKey::new(_0.borrow(), #hasher) ]
};
@@ -174,15 +170,14 @@ fn generate_storage_entry_fns(
let pallet_name = &pallet.name;
let storage_name = &storage_entry.name;
let storage_hash =
subxt_metadata::get_storage_hash(metadata, pallet_name, storage_name)
.unwrap_or_else(|_| {
abort_call_site!(
"Metadata information for the storage entry {}_{} could not be found",
pallet_name,
storage_name
)
});
let storage_hash = subxt_metadata::get_storage_hash(
metadata,
pallet_name,
storage_name,
)
.map_err(|_| {
CodegenError::MissingStorageMetadata(pallet_name.into(), storage_name.into())
})?;
let fn_name = format_ident!("{}", storage_entry.name.to_snake_case());
let storage_entry_ty = match storage_entry.ty {
@@ -251,7 +246,7 @@ fn generate_storage_entry_fns(
quote!()
};
quote! {
Ok(quote! {
// Access a specific value from a storage entry
#docs
pub fn #fn_name(
@@ -267,5 +262,5 @@ fn generate_storage_entry_fns(
}
#root_entry_fn
}
})
}