Make hooks and call attributes optional in pallet macro (#8853)

* Make #[pallet::hooks] optional

* Make #[pallet::call] optional

* Remove unused imports

* Update UI test expectations

* Update UI test expectations

* Remove unnecessary HooksDef::empty method

* Remove unnecessary CallDef::empty method

* Clarify what would happen when no call or hooks are specified in a pallet
This commit is contained in:
Keith Yeung
2021-05-20 12:31:56 -07:00
committed by GitHub
parent 029b8a1d07
commit e5954cf863
9 changed files with 90 additions and 57 deletions
@@ -22,30 +22,40 @@ use syn::spanned::Spanned;
/// * Generate enum call and implement various trait on it.
/// * Implement Callable and call_function on `Pallet`
pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
let (span, where_clause, methods, docs) = match def.call.as_ref() {
Some(call) => {
let span = call.attr_span;
let where_clause = call.where_clause.clone();
let methods = call.methods.clone();
let docs = call.docs.clone();
(span, where_clause, methods, docs)
}
None => (def.pallet_struct.attr_span, None, Vec::new(), Vec::new()),
};
let frame_support = &def.frame_support;
let frame_system = &def.frame_system;
let type_impl_gen = &def.type_impl_generics(def.call.attr_span);
let type_decl_bounded_gen = &def.type_decl_bounded_generics(def.call.attr_span);
let type_use_gen = &def.type_use_generics(def.call.attr_span);
let call_ident = syn::Ident::new("Call", def.call.attr_span);
let type_impl_gen = &def.type_impl_generics(span);
let type_decl_bounded_gen = &def.type_decl_bounded_generics(span);
let type_use_gen = &def.type_use_generics(span);
let call_ident = syn::Ident::new("Call", span);
let pallet_ident = &def.pallet_struct.pallet;
let where_clause = &def.call.where_clause;
let fn_name = def.call.methods.iter().map(|method| &method.name).collect::<Vec<_>>();
let fn_name = methods.iter().map(|method| &method.name).collect::<Vec<_>>();
let fn_weight = def.call.methods.iter().map(|method| &method.weight);
let fn_weight = methods.iter().map(|method| &method.weight);
let fn_doc = def.call.methods.iter().map(|method| &method.docs).collect::<Vec<_>>();
let fn_doc = methods.iter().map(|method| &method.docs).collect::<Vec<_>>();
let args_name = def.call.methods.iter()
let args_name = methods.iter()
.map(|method| method.args.iter().map(|(_, name, _)| name.clone()).collect::<Vec<_>>())
.collect::<Vec<_>>();
let args_type = def.call.methods.iter()
let args_type = methods.iter()
.map(|method| method.args.iter().map(|(_, _, type_)| type_.clone()).collect::<Vec<_>>())
.collect::<Vec<_>>();
let args_compact_attr = def.call.methods.iter().map(|method| {
let args_compact_attr = methods.iter().map(|method| {
method.args.iter()
.map(|(is_compact, _, type_)| {
if *is_compact {
@@ -57,7 +67,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
.collect::<Vec<_>>()
});
let args_metadata_type = def.call.methods.iter().map(|method| {
let args_metadata_type = methods.iter().map(|method| {
method.args.iter()
.map(|(is_compact, _, type_)| {
let final_type = if *is_compact {
@@ -73,13 +83,13 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
let default_docs = [syn::parse_quote!(
r"Contains one variant per dispatchable that can be called by an extrinsic."
)];
let docs = if def.call.docs.is_empty() {
let docs = if docs.is_empty() {
&default_docs[..]
} else {
&def.call.docs[..]
&docs[..]
};
quote::quote_spanned!(def.call.attr_span =>
quote::quote_spanned!(span =>
#( #[doc = #docs] )*
#[derive(
#frame_support::RuntimeDebugNoBound,
@@ -19,13 +19,21 @@ use crate::pallet::Def;
/// * implement the individual traits using the Hooks trait
pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
let (where_clause, span, has_runtime_upgrade) = match def.hooks.as_ref() {
Some(hooks) => {
let where_clause = hooks.where_clause.clone();
let span = hooks.attr_span;
let has_runtime_upgrade = hooks.has_runtime_upgrade;
(where_clause, span, has_runtime_upgrade)
},
None => (None, def.pallet_struct.attr_span, false),
};
let frame_support = &def.frame_support;
let type_impl_gen = &def.type_impl_generics(def.hooks.attr_span);
let type_use_gen = &def.type_use_generics(def.hooks.attr_span);
let type_impl_gen = &def.type_impl_generics(span);
let type_use_gen = &def.type_use_generics(span);
let pallet_ident = &def.pallet_struct.pallet;
let where_clause = &def.hooks.where_clause;
let frame_system = &def.frame_system;
let has_runtime_upgrade = def.hooks.has_runtime_upgrade;
let log_runtime_upgrade = if has_runtime_upgrade {
// a migration is defined here.
@@ -49,7 +57,20 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
}
};
quote::quote_spanned!(def.hooks.attr_span =>
let hooks_impl = if def.hooks.is_none() {
let frame_system = &def.frame_system;
quote::quote!{
impl<#type_impl_gen>
#frame_support::traits::Hooks<<T as #frame_system::Config>::BlockNumber>
for Pallet<#type_use_gen> {}
}
} else {
proc_macro2::TokenStream::new()
};
quote::quote_spanned!(span =>
#hooks_impl
impl<#type_impl_gen>
#frame_support::traits::OnFinalize<<T as #frame_system::Config>::BlockNumber>
for #pallet_ident<#type_use_gen> #where_clause
@@ -45,6 +45,7 @@ pub struct CallDef {
pub docs: Vec<syn::Lit>,
}
#[derive(Clone)]
/// Definition of dispatchable typically: `#[weight...] fn foo(origin .., param1: ...) -> ..`
pub struct CallVariantDef {
/// Function name.
@@ -45,8 +45,8 @@ pub struct Def {
pub item: syn::ItemMod,
pub config: config::ConfigDef,
pub pallet_struct: pallet_struct::PalletStructDef,
pub hooks: hooks::HooksDef,
pub call: call::CallDef,
pub hooks: Option<hooks::HooksDef>,
pub call: Option<call::CallDef>,
pub storages: Vec<storage::StorageDef>,
pub error: Option<error::ErrorDef>,
pub event: Option<event::EventDef>,
@@ -156,9 +156,8 @@ impl Def {
config: config.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::config]`"))?,
pallet_struct: pallet_struct
.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::pallet]`"))?,
hooks: hooks
.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::hooks]`"))?,
call: call.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::call]"))?,
hooks,
call,
extra_constants,
genesis_config,
genesis_build,
@@ -206,10 +205,14 @@ impl Def {
/// instance iff it is defined with instance.
fn check_instance_usage(&self) -> syn::Result<()> {
let mut instances = vec![];
instances.extend_from_slice(&self.call.instances[..]);
instances.extend_from_slice(&self.pallet_struct.instances[..]);
instances.extend_from_slice(&self.hooks.instances[..]);
instances.extend(&mut self.storages.iter().flat_map(|s| s.instances.clone()));
if let Some(call) = &self.call {
instances.extend_from_slice(&call.instances[..]);
}
if let Some(hooks) = &self.hooks {
instances.extend_from_slice(&hooks.instances[..]);
}
if let Some(event) = &self.event {
instances.extend_from_slice(&event.instances[..]);
}