sp-api: Support expanding the macro code (#13573)

* sp-api: Support expanding the macro code

This pr introduces the `expander` crate to expand the generated source code into a file. This gives
better error reporting when trying to fix issues in the macro itself as Rustc will point to the line
in this file. The feature can be enabled by setting `SP_API_EXPAND=1` at compile time.

Besides that the generated code is changed to fix warnings in the exanped version.

* Fixes
This commit is contained in:
Bastian Köcher
2023-03-14 22:14:58 +01:00
committed by GitHub
parent ef165cec3e
commit 4ef1d0df02
9 changed files with 124 additions and 101 deletions
+21
View File
@@ -1997,6 +1997,19 @@ dependencies = [
"futures", "futures",
] ]
[[package]]
name = "expander"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f360349150728553f92e4c997a16af8915f418d3a0f21b440d34c5632f16ed84"
dependencies = [
"blake2",
"fs-err",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "fake-simd" name = "fake-simd"
version = "0.1.2" version = "0.1.2"
@@ -2507,6 +2520,12 @@ dependencies = [
"sp-std", "sp-std",
] ]
[[package]]
name = "fs-err"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541"
[[package]] [[package]]
name = "fs2" name = "fs2"
version = "0.4.3" version = "0.4.3"
@@ -9925,7 +9944,9 @@ dependencies = [
name = "sp-api-proc-macro" name = "sp-api-proc-macro"
version = "4.0.0-dev" version = "4.0.0-dev"
dependencies = [ dependencies = [
"Inflector",
"blake2", "blake2",
"expander",
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -21,8 +21,10 @@ syn = { version = "1.0.98", features = ["full", "fold", "extra-traits", "visit"]
proc-macro2 = "1.0.37" proc-macro2 = "1.0.37"
blake2 = { version = "0.10.4", default-features = false } blake2 = { version = "0.10.4", default-features = false }
proc-macro-crate = "1.1.3" proc-macro-crate = "1.1.3"
expander = "1.0.0"
Inflector = "0.11.4"
# Required for the doc tests # Required for the doc tests
[features] [features]
default = [ "std" ] default = ["std"]
std = [] std = []
@@ -18,9 +18,6 @@
/// The ident used for the block generic parameter. /// The ident used for the block generic parameter.
pub const BLOCK_GENERIC_IDENT: &str = "Block"; pub const BLOCK_GENERIC_IDENT: &str = "Block";
/// Unique identifier used to make the hidden includes unique for this macro.
pub const HIDDEN_INCLUDES_ID: &str = "DECL_RUNTIME_APIS";
/// The `core_trait` attribute. /// The `core_trait` attribute.
pub const CORE_TRAIT_ATTRIBUTE: &str = "core_trait"; pub const CORE_TRAIT_ATTRIBUTE: &str = "core_trait";
/// The `api_version` attribute. /// The `api_version` attribute.
@@ -17,14 +17,14 @@
use crate::utils::{ use crate::utils::{
extract_parameter_names_types_and_borrows, fold_fn_decl_for_client_side, generate_crate_access, extract_parameter_names_types_and_borrows, fold_fn_decl_for_client_side, generate_crate_access,
generate_hidden_includes, generate_runtime_mod_name_for_trait, parse_runtime_api_version, generate_runtime_mod_name_for_trait, parse_runtime_api_version, prefix_function_with_trait,
prefix_function_with_trait, replace_wild_card_parameter_names, return_type_extract_type, replace_wild_card_parameter_names, return_type_extract_type, versioned_trait_name,
versioned_trait_name, AllowSelfRefInParameters, AllowSelfRefInParameters,
}; };
use crate::common::{ use crate::common::{
API_VERSION_ATTRIBUTE, BLOCK_GENERIC_IDENT, CHANGED_IN_ATTRIBUTE, CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE, BLOCK_GENERIC_IDENT, CHANGED_IN_ATTRIBUTE, CORE_TRAIT_ATTRIBUTE,
HIDDEN_INCLUDES_ID, RENAMED_ATTRIBUTE, SUPPORTED_ATTRIBUTE_NAMES, RENAMED_ATTRIBUTE, SUPPORTED_ATTRIBUTE_NAMES,
}; };
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
@@ -62,7 +62,7 @@ impl Parse for RuntimeApiDecls {
/// Extend the given generics with `Block: BlockT` as first generic parameter. /// Extend the given generics with `Block: BlockT` as first generic parameter.
fn extend_generics_with_block(generics: &mut Generics) { fn extend_generics_with_block(generics: &mut Generics) {
let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c = generate_crate_access();
generics.lt_token = Some(Default::default()); generics.lt_token = Some(Default::default());
generics.params.insert(0, parse_quote!( Block: #c::BlockT )); generics.params.insert(0, parse_quote!( Block: #c::BlockT ));
@@ -298,7 +298,7 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> Result<TokenStream> {
#[allow(dead_code)] #[allow(dead_code)]
#[allow(deprecated)] #[allow(deprecated)]
pub mod #mod_name { pub mod #mod_name {
use super::*; pub use super::*;
#( #versioned_api_traits )* #( #versioned_api_traits )*
@@ -495,10 +495,10 @@ impl<'a> ToClientSideDecl<'a> {
__runtime_api_at_param__, __runtime_api_at_param__,
#context, #context,
__runtime_api_impl_params_encoded__, __runtime_api_impl_params_encoded__,
&|version| { &|_version| {
#( #(
// Check if we need to call the function by an old name. // Check if we need to call the function by an old name.
if version.apis.iter().any(|(s, v)| { if _version.apis.iter().any(|(s, v)| {
s == &#runtime_mod::ID && *v < #versions s == &#runtime_mod::ID && *v < #versions
}) { }) {
return #old_names return #old_names
@@ -569,7 +569,7 @@ fn generate_runtime_api_version(version: u32) -> TokenStream {
/// Generates the implementation of `RuntimeApiInfo` for the given trait. /// Generates the implementation of `RuntimeApiInfo` for the given trait.
fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream { fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream {
let trait_name = &trait_.ident; let trait_name = &trait_.ident;
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
let id = generate_runtime_api_id(&trait_name.to_string()); let id = generate_runtime_api_id(&trait_name.to_string());
let version = generate_runtime_api_version(version as u32); let version = generate_runtime_api_version(version as u32);
@@ -620,7 +620,7 @@ fn generate_client_side_decls(decls: &[ItemTrait]) -> Result<TokenStream> {
for decl in decls { for decl in decls {
let decl = decl.clone(); let decl = decl.clone();
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
let block_hash = quote!( <Block as #crate_::BlockT>::Hash ); let block_hash = quote!( <Block as #crate_::BlockT>::Hash );
let mut found_attributes = HashMap::new(); let mut found_attributes = HashMap::new();
let mut errors = Vec::new(); let mut errors = Vec::new();
@@ -777,15 +777,20 @@ pub fn decl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::Tok
fn decl_runtime_apis_impl_inner(api_decls: &[ItemTrait]) -> Result<TokenStream> { fn decl_runtime_apis_impl_inner(api_decls: &[ItemTrait]) -> Result<TokenStream> {
check_trait_decls(api_decls)?; check_trait_decls(api_decls)?;
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let runtime_decls = generate_runtime_decls(api_decls)?; let runtime_decls = generate_runtime_decls(api_decls)?;
let client_side_decls = generate_client_side_decls(api_decls)?; let client_side_decls = generate_client_side_decls(api_decls)?;
Ok(quote!( let decl = quote! {
#hidden_includes
#runtime_decls #runtime_decls
#client_side_decls #client_side_decls
)) };
let decl = expander::Expander::new("decl_runtime_apis")
.dry(std::env::var("SP_API_EXPAND").is_err())
.verbose(true)
.write_to_out_dir(decl)
.expect("Does not fail because of IO in OUT_DIR; qed");
Ok(decl)
} }
@@ -17,7 +17,7 @@
use crate::utils::{ use crate::utils::{
extract_all_signature_types, extract_block_type_from_trait_path, extract_impl_trait, extract_all_signature_types, extract_block_type_from_trait_path, extract_impl_trait,
extract_parameter_names_types_and_borrows, generate_crate_access, generate_hidden_includes, extract_parameter_names_types_and_borrows, generate_crate_access,
generate_runtime_mod_name_for_trait, parse_runtime_api_version, prefix_function_with_trait, generate_runtime_mod_name_for_trait, parse_runtime_api_version, prefix_function_with_trait,
versioned_trait_name, AllowSelfRefInParameters, RequireQualifiedTraitPath, versioned_trait_name, AllowSelfRefInParameters, RequireQualifiedTraitPath,
}; };
@@ -38,9 +38,6 @@ use syn::{
use std::collections::HashSet; use std::collections::HashSet;
/// Unique identifier used to make the hidden includes unique for this macro.
const HIDDEN_INCLUDES_ID: &str = "IMPL_RUNTIME_APIS";
/// The structure used for parsing the runtime api implementations. /// The structure used for parsing the runtime api implementations.
struct RuntimeApiImpls { struct RuntimeApiImpls {
impls: Vec<ItemImpl>, impls: Vec<ItemImpl>,
@@ -73,7 +70,7 @@ fn generate_impl_call(
let params = let params =
extract_parameter_names_types_and_borrows(signature, AllowSelfRefInParameters::No)?; extract_parameter_names_types_and_borrows(signature, AllowSelfRefInParameters::No)?;
let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c = generate_crate_access();
let fn_name = &signature.ident; let fn_name = &signature.ident;
let fn_name_str = fn_name.to_string(); let fn_name_str = fn_name.to_string();
let pnames = params.iter().map(|v| &v.0); let pnames = params.iter().map(|v| &v.0);
@@ -81,15 +78,33 @@ fn generate_impl_call(
let ptypes = params.iter().map(|v| &v.1); let ptypes = params.iter().map(|v| &v.1);
let pborrow = params.iter().map(|v| &v.2); let pborrow = params.iter().map(|v| &v.2);
let decode_params = if params.is_empty() {
quote!()
} else {
let let_binding = if params.len() == 1 {
quote! {
let #( #pnames )* : #( #ptypes )*
}
} else {
quote! {
let ( #( #pnames ),* ) : ( #( #ptypes ),* )
}
};
quote!(
#let_binding =
match #c::DecodeLimit::decode_all_with_depth_limit(
#c::MAX_EXTRINSIC_DEPTH,
&mut #input,
) {
Ok(res) => res,
Err(e) => panic!("Bad input data provided to {}: {}", #fn_name_str, e),
};
)
};
Ok(quote!( Ok(quote!(
let (#( #pnames ),*) : ( #( #ptypes ),* ) = #decode_params
match #c::DecodeLimit::decode_all_with_depth_limit(
#c::MAX_EXTRINSIC_DEPTH,
&mut #input,
) {
Ok(res) => res,
Err(e) => panic!("Bad input data provided to {}: {}", #fn_name_str, e),
};
#[allow(deprecated)] #[allow(deprecated)]
<#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*) <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*)
@@ -134,8 +149,8 @@ fn generate_impl_calls(
/// Generate the dispatch function that is used in native to call into the runtime. /// Generate the dispatch function that is used in native to call into the runtime.
fn generate_dispatch_function(impls: &[ItemImpl]) -> Result<TokenStream> { fn generate_dispatch_function(impls: &[ItemImpl]) -> Result<TokenStream> {
let data = Ident::new("__sp_api__input_data", Span::call_site()); let data = Ident::new("_sp_api_input_data_", Span::call_site());
let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c = generate_crate_access();
let impl_calls = let impl_calls =
generate_impl_calls(impls, &data)? generate_impl_calls(impls, &data)?
.into_iter() .into_iter()
@@ -161,7 +176,7 @@ fn generate_dispatch_function(impls: &[ItemImpl]) -> Result<TokenStream> {
/// Generate the interface functions that are used to call into the runtime in wasm. /// Generate the interface functions that are used to call into the runtime in wasm.
fn generate_wasm_interface(impls: &[ItemImpl]) -> Result<TokenStream> { fn generate_wasm_interface(impls: &[ItemImpl]) -> Result<TokenStream> {
let input = Ident::new("input", Span::call_site()); let input = Ident::new("input", Span::call_site());
let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c = generate_crate_access();
let impl_calls = let impl_calls =
generate_impl_calls(impls, &input)? generate_impl_calls(impls, &input)?
@@ -195,7 +210,7 @@ fn generate_wasm_interface(impls: &[ItemImpl]) -> Result<TokenStream> {
} }
fn generate_runtime_api_base_structures() -> Result<TokenStream> { fn generate_runtime_api_base_structures() -> Result<TokenStream> {
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
Ok(quote!( Ok(quote!(
pub struct RuntimeApi {} pub struct RuntimeApi {}
@@ -414,7 +429,7 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
fn process(mut self, input: ItemImpl) -> ItemImpl { fn process(mut self, input: ItemImpl) -> ItemImpl {
let mut input = self.fold_item_impl(input); let mut input = self.fold_item_impl(input);
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
// Delete all functions, because all of them are default implemented by // Delete all functions, because all of them are default implemented by
// `decl_runtime_apis!`. We only need to implement the `__runtime_api_internal_call_api_at` // `decl_runtime_apis!`. We only need to implement the `__runtime_api_internal_call_api_at`
@@ -423,7 +438,7 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
input.items.push(parse_quote! { input.items.push(parse_quote! {
fn __runtime_api_internal_call_api_at( fn __runtime_api_internal_call_api_at(
&self, &self,
at: <__SR_API_BLOCK__ as #crate_::BlockT>::Hash, at: <__SrApiBlock__ as #crate_::BlockT>::Hash,
context: #crate_::ExecutionContext, context: #crate_::ExecutionContext,
params: std::vec::Vec<u8>, params: std::vec::Vec<u8>,
fn_name: &dyn Fn(#crate_::RuntimeVersion) -> &'static str, fn_name: &dyn Fn(#crate_::RuntimeVersion) -> &'static str,
@@ -435,7 +450,7 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
} }
let res = (|| { let res = (|| {
let version = #crate_::CallApiAt::<__SR_API_BLOCK__>::runtime_version_at( let version = #crate_::CallApiAt::<__SrApiBlock__>::runtime_version_at(
self.call, self.call,
at, at,
)?; )?;
@@ -450,7 +465,7 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
recorder: &self.recorder, recorder: &self.recorder,
}; };
#crate_::CallApiAt::<__SR_API_BLOCK__>::call_api_at( #crate_::CallApiAt::<__SrApiBlock__>::call_api_at(
self.call, self.call,
params, params,
) )
@@ -469,7 +484,7 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
fn fold_type_path(&mut self, input: TypePath) -> TypePath { fn fold_type_path(&mut self, input: TypePath) -> TypePath {
let new_ty_path = let new_ty_path =
if input == *self.runtime_block { parse_quote!(__SR_API_BLOCK__) } else { input }; if input == *self.runtime_block { parse_quote!(__SrApiBlock__) } else { input };
fold::fold_type_path(self, new_ty_path) fold::fold_type_path(self, new_ty_path)
} }
@@ -480,25 +495,26 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
// Before we directly had the final block type and rust could determine that it is unwind // Before we directly had the final block type and rust could determine that it is unwind
// safe, but now we just have a generic parameter `Block`. // safe, but now we just have a generic parameter `Block`.
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
// Implement the trait for the `RuntimeApiImpl` // Implement the trait for the `RuntimeApiImpl`
input.self_ty = input.self_ty =
Box::new(parse_quote!( RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall> )); Box::new(parse_quote!( RuntimeApiImpl<__SrApiBlock__, RuntimeApiImplCall> ));
input.generics.params.push(parse_quote!( input.generics.params.push(parse_quote!(
__SR_API_BLOCK__: #crate_::BlockT + std::panic::UnwindSafe + __SrApiBlock__: #crate_::BlockT + std::panic::UnwindSafe +
std::panic::RefUnwindSafe std::panic::RefUnwindSafe
)); ));
input.generics.params.push( input
parse_quote!( RuntimeApiImplCall: #crate_::CallApiAt<__SR_API_BLOCK__> + 'static ), .generics
); .params
.push(parse_quote!( RuntimeApiImplCall: #crate_::CallApiAt<__SrApiBlock__> + 'static ));
let where_clause = input.generics.make_where_clause(); let where_clause = input.generics.make_where_clause();
where_clause.predicates.push(parse_quote! { where_clause.predicates.push(parse_quote! {
RuntimeApiImplCall::StateBackend: RuntimeApiImplCall::StateBackend:
#crate_::StateBackend<#crate_::HashFor<__SR_API_BLOCK__>> #crate_::StateBackend<#crate_::HashFor<__SrApiBlock__>>
}); });
where_clause.predicates.push(parse_quote! { &'static RuntimeApiImplCall: Send }); where_clause.predicates.push(parse_quote! { &'static RuntimeApiImplCall: Send });
@@ -511,7 +527,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
}); });
where_clause.predicates.push(parse_quote! { where_clause.predicates.push(parse_quote! {
__SR_API_BLOCK__::Header: std::panic::UnwindSafe + std::panic::RefUnwindSafe __SrApiBlock__::Header: std::panic::UnwindSafe + std::panic::RefUnwindSafe
}); });
input.attrs = filter_cfg_attrs(&input.attrs); input.attrs = filter_cfg_attrs(&input.attrs);
@@ -574,7 +590,7 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result<TokenStream> {
let mut sections = Vec::<TokenStream>::with_capacity(impls.len()); let mut sections = Vec::<TokenStream>::with_capacity(impls.len());
let mut processed_traits = HashSet::new(); let mut processed_traits = HashSet::new();
let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c = generate_crate_access();
for impl_ in impls { for impl_ in impls {
let api_ver = extract_api_version(&impl_.attrs, impl_.span())?.map(|a| a as u32); let api_ver = extract_api_version(&impl_.attrs, impl_.span())?.map(|a| a as u32);
@@ -629,14 +645,11 @@ fn impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> {
let dispatch_impl = generate_dispatch_function(api_impls)?; let dispatch_impl = generate_dispatch_function(api_impls)?;
let api_impls_for_runtime = generate_api_impl_for_runtime(api_impls)?; let api_impls_for_runtime = generate_api_impl_for_runtime(api_impls)?;
let base_runtime_api = generate_runtime_api_base_structures()?; let base_runtime_api = generate_runtime_api_base_structures()?;
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let runtime_api_versions = generate_runtime_api_versions(api_impls)?; let runtime_api_versions = generate_runtime_api_versions(api_impls)?;
let wasm_interface = generate_wasm_interface(api_impls)?; let wasm_interface = generate_wasm_interface(api_impls)?;
let api_impls_for_runtime_api = generate_api_impl_for_runtime_api(api_impls)?; let api_impls_for_runtime_api = generate_api_impl_for_runtime_api(api_impls)?;
Ok(quote!( let impl_ = quote!(
#hidden_includes
#base_runtime_api #base_runtime_api
#api_impls_for_runtime #api_impls_for_runtime
@@ -652,7 +665,15 @@ fn impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> {
#wasm_interface #wasm_interface
} }
)) );
let impl_ = expander::Expander::new("impl_runtime_apis")
.dry(std::env::var("SP_API_EXPAND").is_err())
.verbose(true)
.write_to_out_dir(impl_)
.expect("Does not fail because of IO in OUT_DIR; qed");
Ok(impl_)
} }
// Filters all attributes except the cfg ones. // Filters all attributes except the cfg ones.
@@ -17,8 +17,8 @@
use crate::utils::{ use crate::utils::{
extract_block_type_from_trait_path, extract_impl_trait, extract_block_type_from_trait_path, extract_impl_trait,
extract_parameter_names_types_and_borrows, generate_crate_access, generate_hidden_includes, extract_parameter_names_types_and_borrows, generate_crate_access, return_type_extract_type,
return_type_extract_type, AllowSelfRefInParameters, RequireQualifiedTraitPath, AllowSelfRefInParameters, RequireQualifiedTraitPath,
}; };
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
@@ -33,9 +33,6 @@ use syn::{
Attribute, ItemImpl, Pat, Type, TypePath, Attribute, ItemImpl, Pat, Type, TypePath,
}; };
/// Unique identifier used to make the hidden includes unique for this macro.
const HIDDEN_INCLUDES_ID: &str = "MOCK_IMPL_RUNTIME_APIS";
/// The `advanced` attribute. /// The `advanced` attribute.
/// ///
/// If this attribute is given to a function, the function gets access to the `Hash` as first /// If this attribute is given to a function, the function gets access to the `Hash` as first
@@ -65,7 +62,7 @@ impl Parse for RuntimeApiImpls {
/// Implement the `ApiExt` trait and the `Core` runtime api. /// Implement the `ApiExt` trait and the `Core` runtime api.
fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result<TokenStream> { fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result<TokenStream> {
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
Ok(quote!( Ok(quote!(
impl #crate_::ApiExt<#block_type> for #self_ty { impl #crate_::ApiExt<#block_type> for #self_ty {
@@ -256,7 +253,7 @@ impl<'a> FoldRuntimeApiImpl<'a> {
fn process(mut self, impl_item: syn::ItemImpl) -> syn::ItemImpl { fn process(mut self, impl_item: syn::ItemImpl) -> syn::ItemImpl {
let mut impl_item = self.fold_item_impl(impl_item); let mut impl_item = self.fold_item_impl(impl_item);
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
// We also need to overwrite all the `_with_context` methods. To do this, // We also need to overwrite all the `_with_context` methods. To do this,
// we clone all methods and add them again with the new name plus one more argument. // we clone all methods and add them again with the new name plus one more argument.
@@ -295,7 +292,7 @@ impl<'a> FoldRuntimeApiImpl<'a> {
impl<'a> Fold for FoldRuntimeApiImpl<'a> { impl<'a> Fold for FoldRuntimeApiImpl<'a> {
fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod { fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod {
let block = { let block = {
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access();
let is_advanced = has_advanced_attribute(&mut input.attrs); let is_advanced = has_advanced_attribute(&mut input.attrs);
let mut errors = Vec::new(); let mut errors = Vec::new();
@@ -469,14 +466,11 @@ pub fn mock_impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro
} }
fn mock_impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> { fn mock_impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> {
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let GeneratedRuntimeApiImpls { impls, block_type, self_ty } = let GeneratedRuntimeApiImpls { impls, block_type, self_ty } =
generate_runtime_api_impls(api_impls)?; generate_runtime_api_impls(api_impls)?;
let api_traits = implement_common_api_traits(block_type, self_ty)?; let api_traits = implement_common_api_traits(block_type, self_ty)?;
Ok(quote!( Ok(quote!(
#hidden_includes
#impls #impls
#api_traits #api_traits
@@ -24,29 +24,19 @@ use syn::{
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use std::env;
use proc_macro_crate::{crate_name, FoundCrate}; use proc_macro_crate::{crate_name, FoundCrate};
use crate::common::API_VERSION_ATTRIBUTE; use crate::common::API_VERSION_ATTRIBUTE;
fn generate_hidden_includes_mod_name(unique_id: &'static str) -> Ident { use inflector::Inflector;
Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site())
}
/// Generates the hidden includes that are required to make the macro independent from its scope. /// Generates the access to the `sc_client` crate.
pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream { pub fn generate_crate_access() -> TokenStream {
let mod_name = generate_hidden_includes_mod_name(unique_id);
match crate_name("sp-api") { match crate_name("sp-api") {
Ok(FoundCrate::Itself) => quote!(), Ok(FoundCrate::Itself) => quote!(sp_api),
Ok(FoundCrate::Name(client_name)) => { Ok(FoundCrate::Name(renamed_name)) => {
let client_name = Ident::new(&client_name, Span::call_site()); let renamed_name = Ident::new(&renamed_name, Span::call_site());
quote!( quote!(#renamed_name)
#[doc(hidden)]
mod #mod_name {
pub extern crate #client_name as sp_api;
}
)
}, },
Err(e) => { Err(e) => {
let err = Error::new(Span::call_site(), e).to_compile_error(); let err = Error::new(Span::call_site(), e).to_compile_error();
@@ -55,19 +45,12 @@ pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream {
} }
} }
/// Generates the access to the `sc_client` crate.
pub fn generate_crate_access(unique_id: &'static str) -> TokenStream {
if env::var("CARGO_PKG_NAME").unwrap() == "sp-api" {
quote!(sp_api)
} else {
let mod_name = generate_hidden_includes_mod_name(unique_id);
quote!( self::#mod_name::sp_api )
}
}
/// Generates the name of the module that contains the trait declaration for the runtime. /// Generates the name of the module that contains the trait declaration for the runtime.
pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident { pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident {
Ident::new(&format!("runtime_decl_for_{}", trait_), Span::call_site()) Ident::new(
&format!("runtime_decl_for_{}", trait_.to_string().to_snake_case()),
Span::call_site(),
)
} }
/// Get the type of a `syn::ReturnType`. /// Get the type of a `syn::ReturnType`.
@@ -166,17 +166,17 @@ fn test_client_side_function_signature() {
#[test] #[test]
fn check_runtime_api_info() { fn check_runtime_api_info() {
assert_eq!(&<dyn Api::<Block>>::ID, &runtime_decl_for_Api::ID); assert_eq!(&<dyn Api::<Block>>::ID, &runtime_decl_for_api::ID);
assert_eq!(<dyn Api::<Block>>::VERSION, runtime_decl_for_Api::VERSION); assert_eq!(<dyn Api::<Block>>::VERSION, runtime_decl_for_api::VERSION);
assert_eq!(<dyn Api::<Block>>::VERSION, 1); assert_eq!(<dyn Api::<Block>>::VERSION, 1);
assert_eq!( assert_eq!(
<dyn ApiWithCustomVersion::<Block>>::VERSION, <dyn ApiWithCustomVersion::<Block>>::VERSION,
runtime_decl_for_ApiWithCustomVersion::VERSION, runtime_decl_for_api_with_custom_version::VERSION,
); );
assert_eq!( assert_eq!(
&<dyn ApiWithCustomVersion::<Block>>::ID, &<dyn ApiWithCustomVersion::<Block>>::ID,
&runtime_decl_for_ApiWithCustomVersion::ID, &runtime_decl_for_api_with_custom_version::ID,
); );
assert_eq!(<dyn ApiWithCustomVersion::<Block>>::VERSION, 2); assert_eq!(<dyn ApiWithCustomVersion::<Block>>::VERSION, 2);
@@ -1,10 +1,10 @@
error[E0433]: failed to resolve: could not find `ApiV4` in `runtime_decl_for_Api` error[E0433]: failed to resolve: could not find `ApiV4` in `runtime_decl_for_api`
--> tests/ui/impl_missing_version.rs:21:13 --> tests/ui/impl_missing_version.rs:21:13
| |
21 | impl self::Api<Block> for Runtime { 21 | impl self::Api<Block> for Runtime {
| ^^^ could not find `ApiV4` in `runtime_decl_for_Api` | ^^^ could not find `ApiV4` in `runtime_decl_for_api`
error[E0405]: cannot find trait `ApiV4` in module `self::runtime_decl_for_Api` error[E0405]: cannot find trait `ApiV4` in module `self::runtime_decl_for_api`
--> tests/ui/impl_missing_version.rs:21:13 --> tests/ui/impl_missing_version.rs:21:13
| |
11 | pub trait Api { 11 | pub trait Api {