mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 20:01:08 +00:00
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:
Generated
+57
-57
@@ -27,7 +27,7 @@ version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
dependencies = [
|
||||
"gimli 0.27.1",
|
||||
"gimli 0.27.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -294,9 +294,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bounded-collections"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de2aff4807e40f478132150d80b031f2461d88f061851afcab537d7600c24120"
|
||||
checksum = "a071c348a5ef6da1d3a87166b408170b46002382b1dda83992b5c2208cefb370"
|
||||
dependencies = [
|
||||
"log",
|
||||
"parity-scale-codec",
|
||||
@@ -405,13 +405,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.6"
|
||||
version = "4.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
|
||||
checksum = "2f3061d6db6d8fcbbd4b05e057f2acace52e64e96b498c08c2d7a4e65addd340"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex 0.3.1",
|
||||
"clap_lex 0.3.2",
|
||||
"is-terminal",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
@@ -420,9 +420,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.1.0"
|
||||
version = "4.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
|
||||
checksum = "34d122164198950ba84a918270a3bb3f7ededd25e15f7451673d986f55bd2667"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@@ -442,9 +442,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
|
||||
checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
@@ -700,9 +700,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8"
|
||||
checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
@@ -712,9 +712,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38"
|
||||
checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
@@ -727,15 +727,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03"
|
||||
checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.90"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263"
|
||||
checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -863,9 +863,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60"
|
||||
checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
@@ -965,9 +965,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
@@ -1187,9 +1187,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.1"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
@@ -1250,9 +1250,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.15"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
|
||||
checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -1384,9 +1384,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
|
||||
checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -1597,9 +1597,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
|
||||
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"io-lifetimes",
|
||||
@@ -1924,14 +1924,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.42.0",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1940,15 +1940,6 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
|
||||
|
||||
[[package]]
|
||||
name = "nom8"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
@@ -2044,9 +2035,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
@@ -2284,9 +2275,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.3.0"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"
|
||||
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"toml_edit",
|
||||
@@ -2887,9 +2878,9 @@ checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
|
||||
checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@@ -3316,9 +3307,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "ss58-registry"
|
||||
version = "1.38.0"
|
||||
version = "1.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e40c020d72bc0a9c5660bb71e4a6fdef081493583062c474740a7d59f55f0e7b"
|
||||
checksum = "ecf0bd63593ef78eca595a7fc25e9a443ca46fe69fd472f8f09f5245cdcd769d"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"num-format",
|
||||
@@ -3427,7 +3418,7 @@ dependencies = [
|
||||
name = "subxt-cli"
|
||||
version = "0.27.1"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.7",
|
||||
"color-eyre",
|
||||
"frame-metadata",
|
||||
"hex",
|
||||
@@ -3453,12 +3444,12 @@ dependencies = [
|
||||
"jsonrpsee",
|
||||
"parity-scale-codec",
|
||||
"pretty_assertions",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scale-info",
|
||||
"subxt-metadata",
|
||||
"syn",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@@ -3692,19 +3683,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.5.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"
|
||||
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.18.1"
|
||||
version = "0.19.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
|
||||
checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"nom8",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4414,6 +4405,15 @@ version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.1"
|
||||
|
||||
Binary file not shown.
@@ -121,6 +121,14 @@ fn codegen(
|
||||
crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
println!("{runtime_api}");
|
||||
match runtime_api {
|
||||
Ok(runtime_api) => println!("{runtime_api}"),
|
||||
Err(e) => {
|
||||
// Print the error directly to avoid implementing `Send + Sync` on `CodegenError`.
|
||||
use color_eyre::owo_colors::OwoColorize;
|
||||
println!("{}", e.to_string().red())
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,6 @@ darling = "0.14.3"
|
||||
frame-metadata = "15.0.0"
|
||||
heck = "0.4.1"
|
||||
proc-macro2 = "1.0.51"
|
||||
proc-macro-error = "1.0.4"
|
||||
quote = "1.0.8"
|
||||
syn = "1.0.109"
|
||||
scale-info = "2.0.0"
|
||||
@@ -26,6 +25,7 @@ subxt-metadata = { version = "0.27.1", path = "../metadata" }
|
||||
jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport", "http-client"] }
|
||||
hex = "0.4.3"
|
||||
tokio = { version = "1.25", features = ["macros", "rt-multi-thread"] }
|
||||
thiserror = "1.0.24"
|
||||
|
||||
[dev-dependencies]
|
||||
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
|
||||
|
||||
+19
-24
@@ -2,6 +2,7 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use super::CodegenError;
|
||||
use crate::{
|
||||
types::{
|
||||
CompositeDefFields,
|
||||
@@ -18,7 +19,6 @@ use heck::{
|
||||
ToUpperCamelCase as _,
|
||||
};
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use proc_macro_error::abort_call_site;
|
||||
use quote::{
|
||||
format_ident,
|
||||
quote,
|
||||
@@ -41,12 +41,10 @@ pub fn generate_calls(
|
||||
types_mod_ident: &syn::Ident,
|
||||
crate_path: &CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2 {
|
||||
) -> Result<TokenStream2, CodegenError> {
|
||||
// Early return if the pallet has no calls.
|
||||
let call = if let Some(ref calls) = pallet.calls {
|
||||
calls
|
||||
} else {
|
||||
return quote!()
|
||||
let Some(call) = &pallet.calls else {
|
||||
return Ok(quote!());
|
||||
};
|
||||
|
||||
let mut struct_defs = super::generate_structs_from_variants(
|
||||
@@ -56,7 +54,7 @@ pub fn generate_calls(
|
||||
"Call",
|
||||
crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
)?;
|
||||
let (call_structs, call_fns): (Vec<_>, Vec<_>) = struct_defs
|
||||
.iter_mut()
|
||||
.map(|(variant_name, struct_def)| {
|
||||
@@ -77,26 +75,20 @@ pub fn generate_calls(
|
||||
}
|
||||
CompositeDefFields::NoFields => Default::default(),
|
||||
CompositeDefFields::Unnamed(_) => {
|
||||
abort_call_site!(
|
||||
"Call variant for type {} must have all named fields",
|
||||
call.ty.id()
|
||||
)
|
||||
return Err(CodegenError::InvalidCallVariant(call.ty.id()))
|
||||
}
|
||||
};
|
||||
|
||||
let pallet_name = &pallet.name;
|
||||
let call_name = &variant_name;
|
||||
let struct_name = &struct_def.name;
|
||||
let call_hash =
|
||||
subxt_metadata::get_call_hash(metadata, pallet_name, call_name)
|
||||
.unwrap_or_else(|_| {
|
||||
abort_call_site!(
|
||||
"Metadata information for the call {}_{} could not be found",
|
||||
pallet_name,
|
||||
call_name
|
||||
)
|
||||
});
|
||||
|
||||
let Ok(call_hash) =
|
||||
subxt_metadata::get_call_hash(metadata, pallet_name, call_name) else {
|
||||
return Err(CodegenError::MissingCallMetadata(
|
||||
pallet_name.into(),
|
||||
call_name.to_string(),
|
||||
))
|
||||
};
|
||||
let fn_name = format_ident!("{}", variant_name.to_snake_case());
|
||||
// Propagate the documentation just to `TransactionApi` methods, while
|
||||
// draining the documentation of inner call structures.
|
||||
@@ -121,8 +113,11 @@ pub fn generate_calls(
|
||||
)
|
||||
}
|
||||
};
|
||||
(call_struct, client_fn)
|
||||
|
||||
Ok((call_struct, client_fn))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.unzip();
|
||||
|
||||
let call_ty = type_gen.resolve_type(call.ty.id());
|
||||
@@ -131,7 +126,7 @@ pub fn generate_calls(
|
||||
.then_some(quote! { #( #[doc = #docs ] )* })
|
||||
.unwrap_or_default();
|
||||
|
||||
quote! {
|
||||
Ok(quote! {
|
||||
#docs
|
||||
pub mod calls {
|
||||
use super::root_mod;
|
||||
@@ -147,5 +142,5 @@ pub fn generate_calls(
|
||||
#( #call_fns )*
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -12,13 +12,14 @@ 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,
|
||||
};
|
||||
use scale_info::form::PortableForm;
|
||||
|
||||
use super::CodegenError;
|
||||
|
||||
/// Generate constants from the provided pallet's metadata.
|
||||
///
|
||||
/// The function creates a new module named `constants` under the pallet's module.
|
||||
@@ -49,10 +50,10 @@ pub fn generate_constants(
|
||||
types_mod_ident: &syn::Ident,
|
||||
crate_path: &CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2 {
|
||||
) -> Result<TokenStream2, CodegenError> {
|
||||
// Early return if the pallet has no constants.
|
||||
if pallet.constants.is_empty() {
|
||||
return quote!()
|
||||
return Ok(quote!())
|
||||
}
|
||||
let constants = &pallet.constants;
|
||||
|
||||
@@ -60,8 +61,9 @@ pub fn generate_constants(
|
||||
let fn_name = format_ident!("{}", constant.name.to_snake_case());
|
||||
let pallet_name = &pallet.name;
|
||||
let constant_name = &constant.name;
|
||||
let constant_hash = subxt_metadata::get_constant_hash(metadata, pallet_name, constant_name)
|
||||
.unwrap_or_else(|_| abort_call_site!("Metadata information for the constant {}_{} could not be found", pallet_name, constant_name));
|
||||
let Ok(constant_hash) = subxt_metadata::get_constant_hash(metadata, pallet_name, constant_name) else {
|
||||
return Err(CodegenError::MissingConstantMetadata(constant_name.into(), pallet_name.into()));
|
||||
};
|
||||
|
||||
let return_ty = type_gen.resolve_type_path(constant.ty.id());
|
||||
let docs = &constant.docs;
|
||||
@@ -69,7 +71,7 @@ pub fn generate_constants(
|
||||
.then_some(quote! { #( #[doc = #docs ] )* })
|
||||
.unwrap_or_default();
|
||||
|
||||
quote! {
|
||||
Ok(quote! {
|
||||
#docs
|
||||
pub fn #fn_name(&self) -> #crate_path::constants::StaticConstantAddress<#crate_path::metadata::DecodeStaticType<#return_ty>> {
|
||||
#crate_path::constants::StaticConstantAddress::new(
|
||||
@@ -78,10 +80,10 @@ pub fn generate_constants(
|
||||
[#(#constant_hash,)*]
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
quote! {
|
||||
Ok(quote! {
|
||||
pub mod constants {
|
||||
use super::#types_mod_ident;
|
||||
|
||||
@@ -91,5 +93,5 @@ pub fn generate_constants(
|
||||
#(#constant_fns)*
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use scale_info::form::PortableForm;
|
||||
|
||||
use super::CodegenError;
|
||||
|
||||
/// Generate events from the provided pallet metadata.
|
||||
///
|
||||
/// The function creates a new module named `events` under the pallet's module.
|
||||
@@ -46,12 +48,10 @@ pub fn generate_events(
|
||||
types_mod_ident: &syn::Ident,
|
||||
crate_path: &CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2 {
|
||||
) -> Result<TokenStream2, CodegenError> {
|
||||
// Early return if the pallet has no events.
|
||||
let event = if let Some(ref event) = pallet.event {
|
||||
event
|
||||
} else {
|
||||
return quote!()
|
||||
let Some(event) = &pallet.event else {
|
||||
return Ok(quote!())
|
||||
};
|
||||
|
||||
let struct_defs = super::generate_structs_from_variants(
|
||||
@@ -61,7 +61,8 @@ pub fn generate_events(
|
||||
"Event",
|
||||
crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
)?;
|
||||
|
||||
let event_structs = struct_defs.iter().map(|(variant_name, struct_def)| {
|
||||
let pallet_name = &pallet.name;
|
||||
let event_struct = &struct_def.name;
|
||||
@@ -83,12 +84,12 @@ pub fn generate_events(
|
||||
.then_some(quote! { #( #[doc = #docs ] )* })
|
||||
.unwrap_or_default();
|
||||
|
||||
quote! {
|
||||
Ok(quote! {
|
||||
#docs
|
||||
pub type Event = #event_type;
|
||||
pub mod events {
|
||||
use super::#types_mod_ident;
|
||||
#( #event_structs )*
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+159
-95
@@ -22,6 +22,7 @@ use crate::{
|
||||
},
|
||||
utils::{
|
||||
fetch_metadata_bytes_blocking,
|
||||
FetchMetadataError,
|
||||
Uri,
|
||||
},
|
||||
CratePath,
|
||||
@@ -33,8 +34,10 @@ use frame_metadata::{
|
||||
RuntimeMetadataPrefixed,
|
||||
};
|
||||
use heck::ToSnakeCase as _;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use proc_macro_error::abort_call_site;
|
||||
use proc_macro2::{
|
||||
Span,
|
||||
TokenStream as TokenStream2,
|
||||
};
|
||||
use quote::{
|
||||
format_ident,
|
||||
quote,
|
||||
@@ -47,6 +50,67 @@ use std::{
|
||||
};
|
||||
use syn::parse_quote;
|
||||
|
||||
/// Error returned when the Codegen cannot generate the runtime API.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CodegenError {
|
||||
/// Cannot fetch the metadata bytes.
|
||||
#[error("Failed to fetch metadata, make sure that you're pointing at a node which is providing V14 metadata: {0}")]
|
||||
Fetch(#[from] FetchMetadataError),
|
||||
/// Failed IO for the metadata file.
|
||||
#[error("Failed IO for {0}, make sure that you are providing the correct file path for metadata V14: {1}")]
|
||||
Io(String, std::io::Error),
|
||||
/// Cannot decode the metadata bytes.
|
||||
#[error("Could not decode metadata, only V14 metadata is supported: {0}")]
|
||||
Decode(#[from] codec::Error),
|
||||
/// Out of line modules are not supported.
|
||||
#[error("Out-of-line subxt modules are not supported, make sure you are providing a body to your module: pub mod polkadot {{ ... }}")]
|
||||
InvalidModule(Span),
|
||||
/// Expected named or unnamed fields.
|
||||
#[error("Fields should either be all named or all unnamed, make sure you are providing a valid metadata V14: {0}")]
|
||||
InvalidFields(String),
|
||||
/// Substitute types must have a valid path.
|
||||
#[error("Substitute types must have a valid path")]
|
||||
EmptySubstitutePath(Span),
|
||||
/// Invalid type path.
|
||||
#[error("Invalid type path {0}: {1}")]
|
||||
InvalidTypePath(String, syn::Error),
|
||||
/// Metadata for constant could not be found.
|
||||
#[error("Metadata for constant entry {0}_{1} could not be found. Make sure you are providing a valid metadata V14")]
|
||||
MissingConstantMetadata(String, String),
|
||||
/// Metadata for storage could not be found.
|
||||
#[error("Metadata for storage entry {0}_{1} could not be found. Make sure you are providing a valid metadata V14")]
|
||||
MissingStorageMetadata(String, String),
|
||||
/// StorageNMap should have N hashers.
|
||||
#[error("Number of hashers ({0}) does not equal 1 for StorageMap, or match number of fields ({1}) for StorageNMap. Make sure you are providing a valid metadata V14")]
|
||||
MismatchHashers(usize, usize),
|
||||
/// Expected to find one hasher for StorageMap.
|
||||
#[error("No hasher found for single key. Make sure you are providing a valid metadata V14")]
|
||||
MissingHasher,
|
||||
/// Metadata for call could not be found.
|
||||
#[error("Metadata for call entry {0}_{1} could not be found. Make sure you are providing a valid metadata V14")]
|
||||
MissingCallMetadata(String, String),
|
||||
/// Call variant must have all named fields.
|
||||
#[error("Call variant for type {0} must have all named fields. Make sure you are providing a valid metadata V14")]
|
||||
InvalidCallVariant(u32),
|
||||
/// Type should be an variant/enum.
|
||||
#[error("{0} type should be an variant/enum type. Make sure you are providing a valid metadata V14")]
|
||||
InvalidType(String),
|
||||
}
|
||||
|
||||
impl CodegenError {
|
||||
/// Render the error as an invocation of syn::compile_error!.
|
||||
pub fn into_compile_error(self) -> TokenStream2 {
|
||||
let msg = self.to_string();
|
||||
let span = match self {
|
||||
Self::InvalidModule(span) => span,
|
||||
Self::EmptySubstitutePath(span) => span,
|
||||
Self::InvalidTypePath(_, err) => err.span(),
|
||||
_ => proc_macro2::Span::call_site(),
|
||||
};
|
||||
syn::Error::new(span, msg).into_compile_error()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the API for interacting with a Substrate runtime.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -66,17 +130,15 @@ pub fn generate_runtime_api_from_path<P>(
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2
|
||||
) -> Result<TokenStream2, CodegenError>
|
||||
where
|
||||
P: AsRef<path::Path>,
|
||||
{
|
||||
let mut file = fs::File::open(&path).unwrap_or_else(|e| {
|
||||
abort_call_site!("Failed to open {}: {}", path.as_ref().to_string_lossy(), e)
|
||||
});
|
||||
let to_err = |err| CodegenError::Io(path.as_ref().to_string_lossy().into(), err);
|
||||
|
||||
let mut file = fs::File::open(&path).map_err(to_err)?;
|
||||
let mut bytes = Vec::new();
|
||||
file.read_to_end(&mut bytes)
|
||||
.unwrap_or_else(|e| abort_call_site!("Failed to read metadata file: {}", e));
|
||||
file.read_to_end(&mut bytes).map_err(to_err)?;
|
||||
|
||||
generate_runtime_api_from_bytes(
|
||||
item_mod,
|
||||
@@ -109,9 +171,8 @@ pub fn generate_runtime_api_from_url(
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2 {
|
||||
let bytes = fetch_metadata_bytes_blocking(url)
|
||||
.unwrap_or_else(|e| abort_call_site!("Failed to obtain metadata: {}", e));
|
||||
) -> Result<TokenStream2, CodegenError> {
|
||||
let bytes = fetch_metadata_bytes_blocking(url)?;
|
||||
|
||||
generate_runtime_api_from_bytes(
|
||||
item_mod,
|
||||
@@ -142,9 +203,8 @@ pub fn generate_runtime_api_from_bytes(
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2 {
|
||||
let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..])
|
||||
.unwrap_or_else(|e| abort_call_site!("Failed to decode metadata: {}", e));
|
||||
) -> Result<TokenStream2, CodegenError> {
|
||||
let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..])?;
|
||||
|
||||
let generator = RuntimeGenerator::new(metadata);
|
||||
generator.generate_runtime(
|
||||
@@ -187,9 +247,9 @@ impl RuntimeGenerator {
|
||||
type_substitutes: TypeSubstitutes,
|
||||
crate_path: CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> TokenStream2 {
|
||||
) -> Result<TokenStream2, CodegenError> {
|
||||
let item_mod_attrs = item_mod.attrs.clone();
|
||||
let item_mod_ir = ir::ItemMod::from(item_mod);
|
||||
let item_mod_ir = ir::ItemMod::try_from(item_mod)?;
|
||||
let default_derives = derives.default_derives();
|
||||
|
||||
let type_gen = TypeGenerator::new(
|
||||
@@ -200,7 +260,7 @@ impl RuntimeGenerator {
|
||||
crate_path.clone(),
|
||||
should_gen_docs,
|
||||
);
|
||||
let types_mod = type_gen.generate_types_mod();
|
||||
let types_mod = type_gen.generate_types_mod()?;
|
||||
let types_mod_ident = types_mod.ident();
|
||||
let pallets_with_mod_names = self
|
||||
.metadata
|
||||
@@ -227,53 +287,56 @@ impl RuntimeGenerator {
|
||||
|
||||
let metadata_hash = get_metadata_per_pallet_hash(&self.metadata, &pallet_names);
|
||||
|
||||
let modules = pallets_with_mod_names.iter().map(|(pallet, mod_name)| {
|
||||
let calls = calls::generate_calls(
|
||||
&self.metadata,
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
let modules = pallets_with_mod_names
|
||||
.iter()
|
||||
.map(|(pallet, mod_name)| {
|
||||
let calls = calls::generate_calls(
|
||||
&self.metadata,
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
)?;
|
||||
|
||||
let event = events::generate_events(
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
let event = events::generate_events(
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
)?;
|
||||
|
||||
let storage_mod = storage::generate_storage(
|
||||
&self.metadata,
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
let storage_mod = storage::generate_storage(
|
||||
&self.metadata,
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
)?;
|
||||
|
||||
let constants_mod = constants::generate_constants(
|
||||
&self.metadata,
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
);
|
||||
let constants_mod = constants::generate_constants(
|
||||
&self.metadata,
|
||||
&type_gen,
|
||||
pallet,
|
||||
types_mod_ident,
|
||||
&crate_path,
|
||||
should_gen_docs,
|
||||
)?;
|
||||
|
||||
quote! {
|
||||
pub mod #mod_name {
|
||||
use super::root_mod;
|
||||
use super::#types_mod_ident;
|
||||
#calls
|
||||
#event
|
||||
#storage_mod
|
||||
#constants_mod
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(quote! {
|
||||
pub mod #mod_name {
|
||||
use super::root_mod;
|
||||
use super::#types_mod_ident;
|
||||
#calls
|
||||
#event
|
||||
#storage_mod
|
||||
#constants_mod
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, CodegenError>>()?;
|
||||
|
||||
let outer_event_variants = self.metadata.pallets.iter().filter_map(|p| {
|
||||
let variant_name = format_ident!("{}", p.name);
|
||||
@@ -319,7 +382,7 @@ impl RuntimeGenerator {
|
||||
|
||||
let rust_items = item_mod_ir.rust_items();
|
||||
|
||||
quote! {
|
||||
Ok(quote! {
|
||||
#( #item_mod_attrs )*
|
||||
#[allow(dead_code, unused_imports, non_camel_case_types)]
|
||||
#[allow(clippy::all)]
|
||||
@@ -389,7 +452,7 @@ impl RuntimeGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,41 +464,42 @@ pub fn generate_structs_from_variants<F>(
|
||||
error_message_type_name: &str,
|
||||
crate_path: &CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> Vec<(String, CompositeDef)>
|
||||
) -> Result<Vec<(String, CompositeDef)>, CodegenError>
|
||||
where
|
||||
F: Fn(&str) -> std::borrow::Cow<str>,
|
||||
{
|
||||
let ty = type_gen.resolve_type(type_id);
|
||||
if let scale_info::TypeDef::Variant(variant) = ty.type_def() {
|
||||
variant
|
||||
.variants()
|
||||
.iter()
|
||||
.map(|var| {
|
||||
let struct_name = variant_to_struct_name(var.name());
|
||||
let fields = CompositeDefFields::from_scale_info_fields(
|
||||
struct_name.as_ref(),
|
||||
var.fields(),
|
||||
&[],
|
||||
type_gen,
|
||||
);
|
||||
let docs = should_gen_docs.then_some(var.docs()).unwrap_or_default();
|
||||
let struct_def = CompositeDef::struct_def(
|
||||
&ty,
|
||||
struct_name.as_ref(),
|
||||
Default::default(),
|
||||
fields,
|
||||
Some(parse_quote!(pub)),
|
||||
type_gen,
|
||||
docs,
|
||||
crate_path,
|
||||
);
|
||||
(var.name().to_string(), struct_def)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
abort_call_site!(
|
||||
"{} type should be an variant/enum type",
|
||||
error_message_type_name
|
||||
)
|
||||
}
|
||||
|
||||
let scale_info::TypeDef::Variant(variant) = ty.type_def() else {
|
||||
return Err(CodegenError::InvalidType(error_message_type_name.into()))
|
||||
};
|
||||
|
||||
variant
|
||||
.variants()
|
||||
.iter()
|
||||
.map(|var| {
|
||||
let struct_name = variant_to_struct_name(var.name());
|
||||
|
||||
let fields = CompositeDefFields::from_scale_info_fields(
|
||||
struct_name.as_ref(),
|
||||
var.fields(),
|
||||
&[],
|
||||
type_gen,
|
||||
)?;
|
||||
|
||||
let docs = should_gen_docs.then_some(var.docs()).unwrap_or_default();
|
||||
let struct_def = CompositeDef::struct_def(
|
||||
&ty,
|
||||
struct_name.as_ref(),
|
||||
Default::default(),
|
||||
fields,
|
||||
Some(parse_quote!(pub)),
|
||||
type_gen,
|
||||
docs,
|
||||
crate_path,
|
||||
)?;
|
||||
|
||||
Ok((var.name.to_string(), struct_def))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
+26
-31
@@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+8
-8
@@ -2,7 +2,7 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use proc_macro_error::abort;
|
||||
use crate::api::CodegenError;
|
||||
use syn::token;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@@ -14,22 +14,22 @@ pub struct ItemMod {
|
||||
items: Vec<syn::Item>,
|
||||
}
|
||||
|
||||
impl From<syn::ItemMod> for ItemMod {
|
||||
fn from(module: syn::ItemMod) -> Self {
|
||||
impl TryFrom<syn::ItemMod> for ItemMod {
|
||||
type Error = CodegenError;
|
||||
|
||||
fn try_from(module: syn::ItemMod) -> Result<Self, Self::Error> {
|
||||
let (brace, items) = match module.content {
|
||||
Some((brace, items)) => (brace, items),
|
||||
None => {
|
||||
abort!(module, "out-of-line subxt modules are not supported",)
|
||||
}
|
||||
None => return Err(CodegenError::InvalidModule(module.ident.span())),
|
||||
};
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
vis: module.vis,
|
||||
mod_token: module.mod_token,
|
||||
ident: module.ident,
|
||||
brace,
|
||||
items,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -39,7 +39,7 @@
|
||||
//! let generator = subxt_codegen::RuntimeGenerator::new(metadata);
|
||||
//! // Include metadata documentation in the Runtime API.
|
||||
//! let generate_docs = true;
|
||||
//! let runtime_api = generator.generate_runtime(item_mod, derives, substs, CratePath::default(), generate_docs);
|
||||
//! let runtime_api = generator.generate_runtime(item_mod, derives, substs, CratePath::default(), generate_docs).unwrap();
|
||||
//! println!("{}", runtime_api);
|
||||
//! ```
|
||||
|
||||
@@ -56,6 +56,7 @@ pub use self::{
|
||||
generate_runtime_api_from_bytes,
|
||||
generate_runtime_api_from_path,
|
||||
generate_runtime_api_from_url,
|
||||
CodegenError,
|
||||
RuntimeGenerator,
|
||||
},
|
||||
types::{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use crate::api::CodegenError;
|
||||
|
||||
use super::{
|
||||
CratePath,
|
||||
Derives,
|
||||
@@ -12,7 +14,6 @@ use super::{
|
||||
TypePath,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro_error::abort_call_site;
|
||||
use quote::{
|
||||
format_ident,
|
||||
quote,
|
||||
@@ -52,8 +53,8 @@ impl CompositeDef {
|
||||
type_gen: &TypeGenerator,
|
||||
docs: &[String],
|
||||
crate_path: &CratePath,
|
||||
) -> Self {
|
||||
let mut derives = type_gen.type_derives(ty);
|
||||
) -> Result<Self, CodegenError> {
|
||||
let mut derives = type_gen.type_derives(ty)?;
|
||||
let fields: Vec<_> = fields_def.field_types().collect();
|
||||
|
||||
if fields.len() == 1 {
|
||||
@@ -84,7 +85,7 @@ impl CompositeDef {
|
||||
let name = format_ident!("{}", ident);
|
||||
let docs_token = Some(quote! { #( #[doc = #docs ] )* });
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
name,
|
||||
kind: CompositeDefKind::Struct {
|
||||
derives,
|
||||
@@ -93,7 +94,7 @@ impl CompositeDef {
|
||||
},
|
||||
fields: fields_def,
|
||||
docs: docs_token,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Construct a definition which will generate code for an `enum` variant.
|
||||
@@ -183,9 +184,9 @@ impl CompositeDefFields {
|
||||
fields: &[Field],
|
||||
parent_type_params: &[TypeParameter],
|
||||
type_gen: &TypeGenerator,
|
||||
) -> Self {
|
||||
) -> Result<Self, CodegenError> {
|
||||
if fields.is_empty() {
|
||||
return Self::NoFields
|
||||
return Ok(Self::NoFields)
|
||||
}
|
||||
|
||||
let mut named_fields = Vec::new();
|
||||
@@ -209,17 +210,15 @@ impl CompositeDefFields {
|
||||
}
|
||||
|
||||
if !named_fields.is_empty() && !unnamed_fields.is_empty() {
|
||||
abort_call_site!(
|
||||
"'{}': Fields should either be all named or all unnamed.",
|
||||
name,
|
||||
)
|
||||
return Err(CodegenError::InvalidFields(name.into()))
|
||||
}
|
||||
|
||||
if !named_fields.is_empty() {
|
||||
let res = if !named_fields.is_empty() {
|
||||
Self::Named(named_fields)
|
||||
} else {
|
||||
Self::Unnamed(unnamed_fields)
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Returns the set of composite fields.
|
||||
|
||||
@@ -17,7 +17,6 @@ use proc_macro2::{
|
||||
Span,
|
||||
TokenStream,
|
||||
};
|
||||
use proc_macro_error::abort_call_site;
|
||||
use quote::{
|
||||
quote,
|
||||
ToTokens,
|
||||
@@ -30,6 +29,8 @@ use scale_info::{
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::api::CodegenError;
|
||||
|
||||
pub use self::{
|
||||
composite_def::{
|
||||
CompositeDef,
|
||||
@@ -91,7 +92,7 @@ impl<'a> TypeGenerator<'a> {
|
||||
}
|
||||
|
||||
/// Generate a module containing all types defined in the supplied type registry.
|
||||
pub fn generate_types_mod(&self) -> Module {
|
||||
pub fn generate_types_mod(&self) -> Result<Module, CodegenError> {
|
||||
let root_mod_ident = &self.types_mod_ident;
|
||||
let mut root_mod = Module::new(root_mod_ident.clone(), root_mod_ident.clone());
|
||||
|
||||
@@ -127,11 +128,11 @@ impl<'a> TypeGenerator<'a> {
|
||||
self,
|
||||
&self.crate_path,
|
||||
self.should_gen_docs,
|
||||
),
|
||||
)?,
|
||||
);
|
||||
}
|
||||
|
||||
root_mod
|
||||
Ok(root_mod)
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
@@ -311,12 +312,11 @@ impl<'a> TypeGenerator<'a> {
|
||||
}
|
||||
|
||||
/// Returns the derives to be applied to a generated type.
|
||||
pub fn type_derives(&self, ty: &Type<PortableForm>) -> Derives {
|
||||
pub fn type_derives(&self, ty: &Type<PortableForm>) -> Result<Derives, CodegenError> {
|
||||
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)
|
||||
let ty_path: syn::TypePath = syn::parse_str(&joined_path)
|
||||
.map_err(|e| CodegenError::InvalidTypePath(joined_path, e))?;
|
||||
Ok(self.derives.resolve(&ty_path))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// 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 crate::{
|
||||
api::CodegenError,
|
||||
CratePath,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
@@ -106,39 +108,48 @@ impl TypeSubstitutes {
|
||||
}
|
||||
}
|
||||
|
||||
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") };
|
||||
pub fn extend(
|
||||
&mut self,
|
||||
elems: impl IntoIterator<Item = (syn::Path, AbsolutePath)>,
|
||||
) -> Result<(), CodegenError> {
|
||||
let to_extend = elems.into_iter().map(|(path, AbsolutePath(mut with))| {
|
||||
let Some(syn::PathSegment { arguments: src_path_args, ..}) = path.segments.last() else {
|
||||
return Err(CodegenError::EmptySubstitutePath(path.span()))
|
||||
};
|
||||
let Some(syn::PathSegment { arguments: target_path_args, ..}) = with.segments.last_mut() else {
|
||||
return Err(CodegenError::EmptySubstitutePath(with.span()))
|
||||
};
|
||||
|
||||
let source_args: Vec<_> = type_args(src_path_args).collect();
|
||||
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)
|
||||
};
|
||||
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;
|
||||
// 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 })
|
||||
}));
|
||||
Ok((PathSegments::from(&path), Substitute { path: with, param_mapping }))
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
self.substitutes.extend(to_extend);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Given a source type path, return a substituted type path if a substitution is defined.
|
||||
|
||||
+20
-20
@@ -48,7 +48,7 @@ fn generate_struct_with_primitives() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -97,7 +97,7 @@ fn generate_struct_with_a_struct_field() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -145,7 +145,7 @@ fn generate_tuple_struct() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -230,7 +230,7 @@ fn derive_compact_as_for_uint_wrapper_structs() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -297,7 +297,7 @@ fn generate_enum() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -358,7 +358,7 @@ fn compact_fields() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -417,7 +417,7 @@ fn compact_generic_parameter() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -461,7 +461,7 @@ fn generate_array_field() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -501,7 +501,7 @@ fn option_fields() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -544,7 +544,7 @@ fn box_fields_struct() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -587,7 +587,7 @@ fn box_fields_enum() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -630,7 +630,7 @@ fn range_fields() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -677,7 +677,7 @@ fn generics() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -728,7 +728,7 @@ fn generics_nested() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -782,7 +782,7 @@ fn generate_bitvec() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -838,7 +838,7 @@ fn generics_with_alias_adds_phantom_data_marker() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -901,7 +901,7 @@ fn modules() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -961,7 +961,7 @@ fn dont_force_struct_names_camel_case() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -1005,7 +1005,7 @@ fn apply_user_defined_derives_for_all_types() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -1073,7 +1073,7 @@ fn apply_user_defined_derives_for_specific_types() {
|
||||
crate_path,
|
||||
true,
|
||||
);
|
||||
let types = type_gen.generate_types_mod();
|
||||
let types = type_gen.generate_types_mod().expect("Valid type mod; qed");
|
||||
let tests_mod = get_mod(&types, MOD_PATH).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
use crate::api::CodegenError;
|
||||
|
||||
use super::{
|
||||
CompositeDef,
|
||||
CompositeDefFields,
|
||||
@@ -46,8 +48,8 @@ impl TypeDefGen {
|
||||
type_gen: &TypeGenerator,
|
||||
crate_path: &CratePath,
|
||||
should_gen_docs: bool,
|
||||
) -> Self {
|
||||
let derives = type_gen.type_derives(ty);
|
||||
) -> Result<Self, CodegenError> {
|
||||
let derives = type_gen.type_derives(ty)?;
|
||||
|
||||
let type_params = ty
|
||||
.type_params()
|
||||
@@ -78,7 +80,7 @@ impl TypeDefGen {
|
||||
composite.fields(),
|
||||
type_params.params(),
|
||||
type_gen,
|
||||
);
|
||||
)?;
|
||||
type_params.update_unused(fields.field_types());
|
||||
let docs = should_gen_docs.then_some(ty.docs()).unwrap_or_default();
|
||||
let composite_def = CompositeDef::struct_def(
|
||||
@@ -90,11 +92,12 @@ impl TypeDefGen {
|
||||
type_gen,
|
||||
docs,
|
||||
crate_path,
|
||||
);
|
||||
)?;
|
||||
TypeDefGenKind::Struct(composite_def)
|
||||
}
|
||||
TypeDef::Variant(variant) => {
|
||||
let type_name = ty.path().ident().expect("variants should have a name");
|
||||
|
||||
let variants = variant
|
||||
.variants()
|
||||
.iter()
|
||||
@@ -104,15 +107,15 @@ impl TypeDefGen {
|
||||
v.fields(),
|
||||
type_params.params(),
|
||||
type_gen,
|
||||
);
|
||||
)?;
|
||||
type_params.update_unused(fields.field_types());
|
||||
let docs =
|
||||
should_gen_docs.then_some(v.docs()).unwrap_or_default();
|
||||
let variant_def =
|
||||
CompositeDef::enum_variant_def(v.name(), fields, docs);
|
||||
(v.index(), variant_def)
|
||||
Ok((v.index(), variant_def))
|
||||
})
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>, CodegenError>>()?;
|
||||
|
||||
TypeDefGenKind::Enum(type_name, variants)
|
||||
}
|
||||
@@ -124,12 +127,12 @@ impl TypeDefGen {
|
||||
.then_some(quote! { #( #[doc = #docs ] )* })
|
||||
.unwrap_or_default();
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
type_params,
|
||||
derives,
|
||||
ty_kind,
|
||||
ty_docs,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -180,7 +180,7 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
let mut type_substitutes = TypeSubstitutes::new(&crate_path);
|
||||
type_substitutes.extend(args.substitute_type.into_iter().map(
|
||||
if let Err(err) = type_substitutes.extend(args.substitute_type.into_iter().map(
|
||||
|SubstituteType { ty, with }| {
|
||||
(
|
||||
ty,
|
||||
@@ -190,7 +190,9 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
}),
|
||||
)
|
||||
},
|
||||
));
|
||||
)) {
|
||||
return err.into_compile_error().into()
|
||||
}
|
||||
|
||||
let should_gen_docs = args.generate_docs.is_present();
|
||||
match (args.runtime_metadata_path, args.runtime_metadata_url) {
|
||||
@@ -206,7 +208,7 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
crate_path,
|
||||
should_gen_docs,
|
||||
)
|
||||
.into()
|
||||
.map_or_else(|err| err.into_compile_error().into(), Into::into)
|
||||
}
|
||||
(None, Some(url_string)) => {
|
||||
let url = Uri::from_str(&url_string).unwrap_or_else(|_| {
|
||||
@@ -220,7 +222,7 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
crate_path,
|
||||
should_gen_docs,
|
||||
)
|
||||
.into()
|
||||
.map_or_else(|err| err.into_compile_error().into(), Into::into)
|
||||
}
|
||||
(None, None) => {
|
||||
abort_call_site!("One of 'runtime_metadata_path' or 'runtime_metadata_url' must be provided")
|
||||
|
||||
@@ -66,6 +66,7 @@ fn generate_runtime_interface(crate_path: CratePath, should_gen_docs: bool) -> S
|
||||
crate_path,
|
||||
should_gen_docs,
|
||||
)
|
||||
.expect("API generation must be valid")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
@@ -155,6 +156,7 @@ fn check_root_attrs_preserved() {
|
||||
CratePath::default(),
|
||||
true,
|
||||
)
|
||||
.expect("API generation must be valid")
|
||||
.to_string();
|
||||
|
||||
let doc_str_loc = generated_code
|
||||
|
||||
Reference in New Issue
Block a user