forked from paritytech/substrate
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
pallet
attribute macro to declare pallets (paritytech#6877)
* rename system Config to system Trait. command used: ``` find frame/ bin/ test-utils/ utils/ -name *.rs -exec sed -i 's/system::Trait>::/system::Config>::/g' {} \; find frame/ bin/ test-utils/ utils/ -name *.rs -exec sed -i 's/impl frame_system::Trait for /impl frame_system::Config for /g' {} \; find frame/ bin/ test-utils/ utils/ -name *.rs -exec sed -i 's/impl system::Trait for /impl system::Config for /g' {} \; ``` plus some manual ones especially for frame-support tests and frame-system * make construct_runtime handle Pallet and Module pallets can now be implemented on struct named Pallet or Module, both definition are valid. This is because next macro will generate only Pallet placeholder. * introduce pallet attribute macro currently just with tests, frame_system and other example hasn't been upgraded * allow to print some upgrade helper from decl_storage * Improved error msg, typo. Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Improved error msg, typo. Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Improved error message on unexpected attributes + ui test * add test for transactional * various typo * some tips when spans are lost * allow pallet to depend on other pallet instances * make event type metadata consistent with call and constant * error messages * ignore doc example * fix pallet upgrade template * fixup * fix doc * fix indentation * Apply suggestions code formatting Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * some renames + fix compilation * remove unsupported genesis config type alias * merge fixup * fix ui tests * additional doc * implement StorageInstance with new syntax * fix line width * fix doc: because pallet doc goes below reexport doc * Update frame/support/procedural/src/pallet/parse/event.rs Co-authored-by: Andrew Jones <ascjones@gmail.com> * Update frame/system/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/support/test/tests/pallet_ui.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * improve doc as suggested * revert construct_runtime Pallet part. This revert the changes on construct_runtime. Now construct_runtime is unchanged and instead pallet macro create a type alias `type Module<..> = Pallet<..>` to be used by construct_runtime * refactor with less intricated code * fix ui test with new image * fix ui tests * add minor tests Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Andrew Jones <ascjones@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
- Loading branch information
1 parent
911e2d9
commit 867d249
Showing
131 changed files
with
9,609 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
// This file is part of Substrate. | ||
|
||
// Copyright (C) 2020 Parity Technologies (UK) Ltd. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use crate::pallet::Def; | ||
use frame_support_procedural_tools::clean_type_string; | ||
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 frame_support = &def.frame_support; | ||
let frame_system = &def.frame_system; | ||
let type_impl_gen = &def.type_impl_generics(); | ||
let type_decl_bounded_gen = &def.type_decl_bounded_generics(); | ||
let type_use_gen = &def.type_use_generics(); | ||
let call_ident = syn::Ident::new("Call", def.call.attr_span.clone()); | ||
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_weight = def.call.methods.iter().map(|method| &method.weight); | ||
|
||
let fn_doc = def.call.methods.iter().map(|method| &method.docs).collect::<Vec<_>>(); | ||
|
||
let args_name = def.call.methods.iter() | ||
.map(|method| method.args.iter().map(|(_, name, _)| name.clone()).collect::<Vec<_>>()) | ||
.collect::<Vec<_>>(); | ||
|
||
let args_type = def.call.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| { | ||
method.args.iter() | ||
.map(|(is_compact, _, type_)| { | ||
if *is_compact { | ||
quote::quote_spanned!(type_.span() => #[codec(compact)] ) | ||
} else { | ||
quote::quote!() | ||
} | ||
}) | ||
.collect::<Vec<_>>() | ||
}); | ||
|
||
let args_metadata_type = def.call.methods.iter().map(|method| { | ||
method.args.iter() | ||
.map(|(is_compact, _, type_)| { | ||
let final_type = if *is_compact { | ||
quote::quote!(Compact<#type_>) | ||
} else { | ||
quote::quote!(#type_) | ||
}; | ||
clean_type_string(&final_type.to_string()) | ||
}) | ||
.collect::<Vec<_>>() | ||
}); | ||
|
||
quote::quote_spanned!(def.call.attr_span => | ||
#[derive( | ||
#frame_support::RuntimeDebugNoBound, | ||
#frame_support::CloneNoBound, | ||
#frame_support::EqNoBound, | ||
#frame_support::PartialEqNoBound, | ||
#frame_support::codec::Encode, | ||
#frame_support::codec::Decode, | ||
)] | ||
#[allow(non_camel_case_types)] | ||
pub enum #call_ident<#type_decl_bounded_gen> #where_clause { | ||
#[doc(hidden)] | ||
#[codec(skip)] | ||
__Ignore( | ||
#frame_support::sp_std::marker::PhantomData<(#type_use_gen,)>, | ||
#frame_support::Never, | ||
), | ||
#( #fn_name( #( #args_compact_attr #args_type ),* ), )* | ||
} | ||
|
||
impl<#type_impl_gen> #frame_support::dispatch::GetDispatchInfo | ||
for #call_ident<#type_use_gen> | ||
#where_clause | ||
{ | ||
fn get_dispatch_info(&self) -> #frame_support::dispatch::DispatchInfo { | ||
match *self { | ||
#( | ||
Self::#fn_name ( #( ref #args_name, )* ) => { | ||
let base_weight = #fn_weight; | ||
|
||
let weight = < | ||
dyn #frame_support::dispatch::WeighData<( #( & #args_type, )* )> | ||
>::weigh_data(&base_weight, ( #( #args_name, )* )); | ||
|
||
let class = < | ||
dyn #frame_support::dispatch::ClassifyDispatch< | ||
( #( & #args_type, )* ) | ||
> | ||
>::classify_dispatch(&base_weight, ( #( #args_name, )* )); | ||
|
||
let pays_fee = < | ||
dyn #frame_support::dispatch::PaysFee<( #( & #args_type, )* )> | ||
>::pays_fee(&base_weight, ( #( #args_name, )* )); | ||
|
||
#frame_support::dispatch::DispatchInfo { | ||
weight, | ||
class, | ||
pays_fee, | ||
} | ||
}, | ||
)* | ||
Self::__Ignore(_, _) => unreachable!("__Ignore cannot be used"), | ||
} | ||
} | ||
} | ||
|
||
impl<#type_impl_gen> #frame_support::dispatch::GetCallName for #call_ident<#type_use_gen> | ||
#where_clause | ||
{ | ||
fn get_call_name(&self) -> &'static str { | ||
match *self { | ||
#( Self::#fn_name(..) => stringify!(#fn_name), )* | ||
Self::__Ignore(_, _) => unreachable!("__PhantomItem cannot be used."), | ||
} | ||
} | ||
|
||
fn get_call_names() -> &'static [&'static str] { | ||
&[ #( stringify!(#fn_name), )* ] | ||
} | ||
} | ||
|
||
impl<#type_impl_gen> #frame_support::traits::UnfilteredDispatchable | ||
for #call_ident<#type_use_gen> | ||
#where_clause | ||
{ | ||
type Origin = #frame_system::pallet_prelude::OriginFor<T>; | ||
fn dispatch_bypass_filter( | ||
self, | ||
origin: Self::Origin | ||
) -> #frame_support::dispatch::DispatchResultWithPostInfo { | ||
match self { | ||
#( | ||
Self::#fn_name( #( #args_name, )* ) => | ||
<#pallet_ident<#type_use_gen>>::#fn_name(origin, #( #args_name, )* ) | ||
.map(Into::into).map_err(Into::into), | ||
)* | ||
Self::__Ignore(_, _) => { | ||
let _ = origin; // Use origin for empty Call enum | ||
unreachable!("__PhantomItem cannot be used."); | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl<#type_impl_gen> #frame_support::dispatch::Callable<T> for #pallet_ident<#type_use_gen> | ||
#where_clause | ||
{ | ||
type Call = #call_ident<#type_use_gen>; | ||
} | ||
|
||
impl<#type_impl_gen> #pallet_ident<#type_use_gen> #where_clause { | ||
#[doc(hidden)] | ||
pub fn call_functions() -> &'static [#frame_support::dispatch::FunctionMetadata] { | ||
&[ #( | ||
#frame_support::dispatch::FunctionMetadata { | ||
name: #frame_support::dispatch::DecodeDifferent::Encode( | ||
stringify!(#fn_name) | ||
), | ||
arguments: #frame_support::dispatch::DecodeDifferent::Encode( | ||
&[ #( | ||
#frame_support::dispatch::FunctionArgumentMetadata { | ||
name: #frame_support::dispatch::DecodeDifferent::Encode( | ||
stringify!(#args_name) | ||
), | ||
ty: #frame_support::dispatch::DecodeDifferent::Encode( | ||
#args_metadata_type | ||
), | ||
}, | ||
)* ] | ||
), | ||
documentation: #frame_support::dispatch::DecodeDifferent::Encode( | ||
&[ #( #fn_doc ),* ] | ||
), | ||
}, | ||
)* ] | ||
} | ||
} | ||
) | ||
} |
138 changes: 138 additions & 0 deletions
138
frame/support/procedural/src/pallet/expand/constants.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// This file is part of Substrate. | ||
|
||
// Copyright (C) 2020 Parity Technologies (UK) Ltd. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use crate::pallet::Def; | ||
use frame_support_procedural_tools::clean_type_string; | ||
use quote::ToTokens; | ||
|
||
struct ConstDef { | ||
/// Name of the associated type. | ||
pub ident: syn::Ident, | ||
/// The type in Get, e.g. `u32` in `type Foo: Get<u32>;`, but `Self` is replaced by `T` | ||
pub type_: syn::Type, | ||
/// The doc associated | ||
pub doc: Vec<syn::Lit>, | ||
/// default_byte implementation | ||
pub default_byte_impl: proc_macro2::TokenStream, | ||
} | ||
|
||
/// * Impl fn module_constant_metadata for pallet. | ||
pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { | ||
let frame_support = &def.frame_support; | ||
let type_impl_gen = &def.type_impl_generics(); | ||
let type_decl_gen = &def.type_decl_generics(); | ||
let type_use_gen = &def.type_use_generics(); | ||
let pallet_ident = &def.pallet_struct.pallet; | ||
|
||
let mut where_clauses = vec![&def.config.where_clause]; | ||
where_clauses.extend(def.extra_constants.iter().map(|d| &d.where_clause)); | ||
let completed_where_clause = super::merge_where_clauses(&where_clauses); | ||
|
||
let config_consts = def.config.consts_metadata.iter().map(|const_| { | ||
let ident = &const_.ident; | ||
let const_type = &const_.type_; | ||
|
||
ConstDef { | ||
ident: const_.ident.clone(), | ||
type_: const_.type_.clone(), | ||
doc: const_.doc.clone(), | ||
default_byte_impl: quote::quote!( | ||
let value = <T::#ident as #frame_support::traits::Get<#const_type>>::get(); | ||
#frame_support::codec::Encode::encode(&value) | ||
), | ||
} | ||
}); | ||
|
||
let extra_consts = def.extra_constants.iter().flat_map(|d| &d.extra_constants).map(|const_| { | ||
let ident = &const_.ident; | ||
|
||
ConstDef { | ||
ident: const_.ident.clone(), | ||
type_: const_.type_.clone(), | ||
doc: const_.doc.clone(), | ||
default_byte_impl: quote::quote!( | ||
let value = <Pallet<#type_use_gen>>::#ident(); | ||
#frame_support::codec::Encode::encode(&value) | ||
), | ||
} | ||
}); | ||
|
||
let consts = config_consts.chain(extra_consts) | ||
.map(|const_| { | ||
let const_type = &const_.type_; | ||
let const_type_str = clean_type_string(&const_type.to_token_stream().to_string()); | ||
let ident = &const_.ident; | ||
let ident_str = format!("{}", ident); | ||
let doc = const_.doc.clone().into_iter(); | ||
let default_byte_impl = &const_.default_byte_impl; | ||
let default_byte_getter = syn::Ident::new( | ||
&format!("{}DefaultByteGetter", ident), | ||
ident.span() | ||
); | ||
|
||
quote::quote!({ | ||
#[allow(non_upper_case_types)] | ||
#[allow(non_camel_case_types)] | ||
struct #default_byte_getter<#type_decl_gen>( | ||
#frame_support::sp_std::marker::PhantomData<(#type_use_gen)> | ||
); | ||
|
||
impl<#type_impl_gen> #frame_support::dispatch::DefaultByte for | ||
#default_byte_getter<#type_use_gen> | ||
#completed_where_clause | ||
{ | ||
fn default_byte(&self) -> #frame_support::sp_std::vec::Vec<u8> { | ||
#default_byte_impl | ||
} | ||
} | ||
|
||
unsafe impl<#type_impl_gen> Send for #default_byte_getter<#type_use_gen> | ||
#completed_where_clause | ||
{} | ||
unsafe impl<#type_impl_gen> Sync for #default_byte_getter<#type_use_gen> | ||
#completed_where_clause | ||
{} | ||
|
||
#frame_support::dispatch::ModuleConstantMetadata { | ||
name: #frame_support::dispatch::DecodeDifferent::Encode(#ident_str), | ||
ty: #frame_support::dispatch::DecodeDifferent::Encode(#const_type_str), | ||
value: #frame_support::dispatch::DecodeDifferent::Encode( | ||
#frame_support::dispatch::DefaultByteGetter( | ||
&#default_byte_getter::<#type_use_gen>( | ||
#frame_support::sp_std::marker::PhantomData | ||
) | ||
) | ||
), | ||
documentation: #frame_support::dispatch::DecodeDifferent::Encode( | ||
&[ #( #doc ),* ] | ||
), | ||
} | ||
}) | ||
}); | ||
|
||
quote::quote!( | ||
impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause{ | ||
|
||
#[doc(hidden)] | ||
pub fn module_constants_metadata() | ||
-> &'static [#frame_support::dispatch::ModuleConstantMetadata] | ||
{ | ||
&[ #( #consts ),* ] | ||
} | ||
} | ||
) | ||
} |
Oops, something went wrong.