mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 12:48:00 +00:00
Add pallet attribute macro to declare pallets (#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>
This commit is contained in:
committed by
GitHub
parent
8e3d8a6a09
commit
6dfad0921b
@@ -21,8 +21,8 @@
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
use quote::quote;
|
||||
use super::DeclStorageDefExt;
|
||||
use genesis_config_def::GenesisConfigDef;
|
||||
use builder_def::BuilderDef;
|
||||
pub use genesis_config_def::GenesisConfigDef;
|
||||
pub use builder_def::BuilderDef;
|
||||
|
||||
mod genesis_config_def;
|
||||
mod builder_def;
|
||||
|
||||
@@ -24,6 +24,9 @@ mod getters;
|
||||
mod metadata;
|
||||
mod instance_trait;
|
||||
mod genesis_config;
|
||||
mod print_pallet_upgrade;
|
||||
|
||||
pub(crate) use instance_trait::INHERENT_INSTANCE_NAME;
|
||||
|
||||
use quote::quote;
|
||||
use frame_support_procedural_tools::{
|
||||
@@ -397,6 +400,8 @@ pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStr
|
||||
let def = syn::parse_macro_input!(input as DeclStorageDef);
|
||||
let def_ext = DeclStorageDefExt::from(def);
|
||||
|
||||
print_pallet_upgrade::maybe_print_pallet_upgrade(&def_ext);
|
||||
|
||||
let hidden_crate_name = def_ext.hidden_crate.as_ref().map(|i| i.to_string())
|
||||
.unwrap_or_else(|| "decl_storage".to_string());
|
||||
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
use super::StorageLineTypeDef;
|
||||
use quote::ToTokens;
|
||||
use frame_support_procedural_tools::clean_type_string;
|
||||
|
||||
/// Environment variable that tells us to print pallet upgrade helper.
|
||||
const PRINT_PALLET_UPGRADE: &str = "PRINT_PALLET_UPGRADE";
|
||||
|
||||
fn check_print_pallet_upgrade() -> bool {
|
||||
std::env::var(PRINT_PALLET_UPGRADE).is_ok()
|
||||
}
|
||||
|
||||
/// Convert visibilty as now objects are defined in a module.
|
||||
fn convert_vis(vis: &syn::Visibility) -> &'static str{
|
||||
match vis {
|
||||
syn::Visibility::Inherited => "pub(super)",
|
||||
syn::Visibility::Public(_) => "pub",
|
||||
_ => "/* TODO_VISIBILITY */",
|
||||
}
|
||||
}
|
||||
|
||||
/// fn to convert to token stream then string using display and then call clean_type_string on it.
|
||||
fn to_cleaned_string(t: impl quote::ToTokens) -> String {
|
||||
clean_type_string(&format!("{}", t.into_token_stream()))
|
||||
}
|
||||
|
||||
/// Print an incomplete upgrade from decl_storage macro to new pallet attribute.
|
||||
pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
if !check_print_pallet_upgrade() {
|
||||
return
|
||||
}
|
||||
|
||||
let scrate = "e::quote!(frame_support);
|
||||
|
||||
let config_gen = if def.optional_instance.is_some() {
|
||||
"<I: 'static = ()>"
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let impl_gen = if def.optional_instance.is_some() {
|
||||
"<T: Config<I>, I: 'static>"
|
||||
} else {
|
||||
"<T: Config>"
|
||||
};
|
||||
|
||||
let decl_gen = if def.optional_instance.is_some() {
|
||||
"<T, I=()>"
|
||||
} else {
|
||||
"<T>"
|
||||
};
|
||||
|
||||
let full_decl_gen = if def.optional_instance.is_some() {
|
||||
"<T: Config<I>, I: 'static = ()>"
|
||||
} else {
|
||||
"<T: Config>"
|
||||
};
|
||||
|
||||
let use_gen = if def.optional_instance.is_some() {
|
||||
"<T, I>"
|
||||
} else {
|
||||
"<T>"
|
||||
};
|
||||
|
||||
let use_gen_tuple = if def.optional_instance.is_some() {
|
||||
"<(T, I)>"
|
||||
} else {
|
||||
"<T>"
|
||||
};
|
||||
|
||||
let mut genesis_config = String::new();
|
||||
let mut genesis_build = String::new();
|
||||
|
||||
let genesis_config_builder_def = super::genesis_config::BuilderDef::from_def(scrate, def);
|
||||
if !genesis_config_builder_def.blocks.is_empty() {
|
||||
let genesis_config_def = match super::genesis_config::GenesisConfigDef::from_def(def) {
|
||||
Ok(g) => g,
|
||||
Err(err) => {
|
||||
println!("Could not print upgrade due compile error: {:?}", err);
|
||||
return
|
||||
},
|
||||
};
|
||||
|
||||
let genesis_config_impl_gen = if genesis_config_def.is_generic {
|
||||
impl_gen.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let genesis_config_use_gen = if genesis_config_def.is_generic {
|
||||
use_gen.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let genesis_config_decl_gen = if genesis_config_def.is_generic {
|
||||
if def.optional_instance.is_some() {
|
||||
"<T: Config<I>, I: 'static = ()>"
|
||||
} else {
|
||||
"<T: Config>"
|
||||
}
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let mut genesis_config_decl_fields = String::new();
|
||||
let mut genesis_config_default_fields = String::new();
|
||||
for field in &genesis_config_def.fields {
|
||||
genesis_config_decl_fields.push_str(&format!("
|
||||
{attrs}pub {name}: {typ},",
|
||||
attrs = field.attrs.iter()
|
||||
.fold(String::new(), |res, attr| {
|
||||
format!("{}#[{}]
|
||||
",
|
||||
res, attr.to_token_stream())
|
||||
}),
|
||||
name = field.name,
|
||||
typ = to_cleaned_string(&field.typ),
|
||||
));
|
||||
|
||||
genesis_config_default_fields.push_str(&format!("
|
||||
{name}: {default},",
|
||||
name = field.name,
|
||||
default = to_cleaned_string(&field.default),
|
||||
));
|
||||
}
|
||||
|
||||
genesis_config = format!("
|
||||
#[pallet::genesis_config]
|
||||
pub struct GenesisConfig{genesis_config_decl_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
{{{genesis_config_decl_fields}
|
||||
}}
|
||||
|
||||
#[cfg(feature = \"std\")]
|
||||
impl{genesis_config_impl_gen} Default for GenesisConfig{genesis_config_use_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
{{
|
||||
fn default() -> Self {{
|
||||
Self {{{genesis_config_default_fields}
|
||||
}}
|
||||
}}
|
||||
}}",
|
||||
genesis_config_decl_gen = genesis_config_decl_gen,
|
||||
genesis_config_decl_fields = genesis_config_decl_fields,
|
||||
genesis_config_impl_gen = genesis_config_impl_gen,
|
||||
genesis_config_default_fields = genesis_config_default_fields,
|
||||
genesis_config_use_gen = genesis_config_use_gen,
|
||||
);
|
||||
|
||||
let genesis_config_build = genesis_config_builder_def.blocks.iter()
|
||||
.fold(String::new(), |res, block| {
|
||||
format!("{}
|
||||
{}",
|
||||
res,
|
||||
to_cleaned_string(block),
|
||||
)
|
||||
});
|
||||
|
||||
genesis_build = format!("
|
||||
#[pallet::genesis_build]
|
||||
impl{impl_gen} GenesisBuild{use_gen} for GenesisConfig{genesis_config_use_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
{{
|
||||
fn build(&self) {{{genesis_config_build}
|
||||
}}
|
||||
}}",
|
||||
impl_gen = impl_gen,
|
||||
use_gen = use_gen,
|
||||
genesis_config_use_gen = genesis_config_use_gen,
|
||||
genesis_config_build = genesis_config_build,
|
||||
);
|
||||
}
|
||||
|
||||
let mut storages = String::new();
|
||||
for line in &def.storage_lines {
|
||||
let storage_vis = convert_vis(&line.visibility);
|
||||
|
||||
let getter = if let Some(getter) = &line.getter {
|
||||
format!("
|
||||
#[pallet::getter(fn {getter})]",
|
||||
getter = getter
|
||||
)
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let value_type = &line.value_type;
|
||||
|
||||
let default_value_type_value = line.default_value.as_ref()
|
||||
.map(|default_expr| {
|
||||
format!("
|
||||
#[pallet::type_value]
|
||||
{storage_vis} fn DefaultFor{name} /* TODO_MAYBE_GENERICS */ () -> {value_type} {{
|
||||
{default_expr}
|
||||
}}
|
||||
",
|
||||
name = line.name,
|
||||
storage_vis = storage_vis,
|
||||
value_type = to_cleaned_string(&line.value_type),
|
||||
default_expr = to_cleaned_string(&default_expr),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| String::new());
|
||||
|
||||
let comma_query_kind = if line.is_option {
|
||||
if line.default_value.is_some() {
|
||||
", OptionQuery"
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
} else {
|
||||
", ValueQuery"
|
||||
};
|
||||
|
||||
let comma_default_value_getter_name = line.default_value.as_ref()
|
||||
.map(|_| format!(", DefaultFor{}", line.name))
|
||||
.unwrap_or_else(|| String::new());
|
||||
|
||||
let typ = match &line.storage_type {
|
||||
StorageLineTypeDef::Map(map) => {
|
||||
format!("StorageMap<_, {hasher}, {key}, {value_type}{comma_query_kind}\
|
||||
{comma_default_value_getter_name}>",
|
||||
hasher = &map.hasher.to_storage_hasher_struct(),
|
||||
key = to_cleaned_string(&map.key),
|
||||
value_type = to_cleaned_string(&value_type),
|
||||
comma_query_kind = comma_query_kind,
|
||||
comma_default_value_getter_name = comma_default_value_getter_name,
|
||||
)
|
||||
},
|
||||
StorageLineTypeDef::DoubleMap(double_map) => {
|
||||
format!("StorageDoubleMap<_, {hasher1}, {key1}, {hasher2}, {key2}, {value_type}\
|
||||
{comma_query_kind}{comma_default_value_getter_name}>",
|
||||
hasher1 = double_map.hasher1.to_storage_hasher_struct(),
|
||||
key1 = to_cleaned_string(&double_map.key1),
|
||||
hasher2 = double_map.hasher2.to_storage_hasher_struct(),
|
||||
key2 = to_cleaned_string(&double_map.key2),
|
||||
value_type = to_cleaned_string(&value_type),
|
||||
comma_query_kind = comma_query_kind,
|
||||
comma_default_value_getter_name = comma_default_value_getter_name,
|
||||
)
|
||||
},
|
||||
StorageLineTypeDef::Simple(_) => {
|
||||
format!("StorageValue<_, {value_type}{comma_query_kind}\
|
||||
{comma_default_value_getter_name}>",
|
||||
value_type = to_cleaned_string(&value_type),
|
||||
comma_query_kind = comma_query_kind,
|
||||
comma_default_value_getter_name = comma_default_value_getter_name,
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
let additional_comment = if line.is_option && line.default_value.is_some() {
|
||||
" // TODO: This type of storage is no longer supported: `OptionQuery` cannot be used \
|
||||
alongside a not-none value on empty storage. Please use `ValueQuery` instead."
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
storages.push_str(&format!("
|
||||
{default_value_type_value}{doc}
|
||||
#[pallet::storage]{getter}
|
||||
{storage_vis} type {name}{full_decl_gen} = {typ};{additional_comment}",
|
||||
default_value_type_value = default_value_type_value,
|
||||
getter = getter,
|
||||
storage_vis = storage_vis,
|
||||
name = line.name,
|
||||
full_decl_gen = full_decl_gen,
|
||||
typ = typ,
|
||||
additional_comment = additional_comment,
|
||||
doc = line.doc_attrs.iter()
|
||||
.fold(String::new(), |mut res, attr| {
|
||||
if let syn::Meta::NameValue(name_value) = attr {
|
||||
if name_value.path.is_ident("doc") {
|
||||
if let syn::Lit::Str(string) = &name_value.lit {
|
||||
res = format!("{}
|
||||
///{}",
|
||||
res,
|
||||
string.value(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
res
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
let deprecated_instance_stuff = if def.optional_instance.is_some() {
|
||||
"
|
||||
/// Old name for default instance generated by decl_storage.
|
||||
#[deprecated(note=\"use `()` instead\")]
|
||||
pub type DefaultInstance = ();
|
||||
|
||||
/// Old name for instance trait used by old macros.
|
||||
#[deprecated(note=\"use `'static` instead\")]
|
||||
pub trait Instance: 'static {}
|
||||
impl<I: 'static> Instance for I {}"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
println!("
|
||||
// Template for pallet upgrade for {pallet_name}
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {{
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
use super::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config{config_gen}: frame_system::Config
|
||||
// TODO_MAYBE_ADDITIONAL_BOUNDS_AND_WHERE_CLAUSE
|
||||
{{
|
||||
// TODO_ASSOCIATED_TYPE_AND_CONSTANTS
|
||||
}}
|
||||
|
||||
{deprecated_instance_stuff}
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store({store_vis} trait Store)]
|
||||
pub struct Pallet{decl_gen}(PhantomData{use_gen_tuple});
|
||||
|
||||
/// Old name for pallet.
|
||||
#[deprecated(note=\"use `Pallet` instead\")]
|
||||
pub type Module{decl_gen} = Pallet{use_gen};
|
||||
|
||||
#[pallet::interface]
|
||||
impl{impl_gen} Hooks<BlockNumberFor<T>> for Pallet{use_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
{{
|
||||
// TODO_ON_FINALIZE
|
||||
// TODO_ON_INITIALIZE
|
||||
// TODO_ON_RUNTIME_UPGRADE
|
||||
// TODO_INTEGRITY_TEST
|
||||
// TODO_OFFCHAIN_WORKER
|
||||
}}
|
||||
|
||||
#[pallet::call]
|
||||
impl{impl_gen} Pallet{use_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
{{
|
||||
// TODO_UPGRADE_DISPATCHABLES
|
||||
}}
|
||||
|
||||
#[pallet::inherent]
|
||||
// TODO_INHERENT
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
// TODO_EVENT
|
||||
|
||||
// TODO_REMOVE_IF_NO_EVENT
|
||||
/// Old name generated by `decl_event`.
|
||||
#[deprecated(note=\"use `Event` instead\")]
|
||||
pub type RawEvent /* TODO_PUT_EVENT_GENERICS */ = Event /* TODO_PUT_EVENT_GENERICS */;
|
||||
|
||||
#[pallet::error]
|
||||
// TODO_ERROR
|
||||
|
||||
#[pallet::origin]
|
||||
// TODO_ORIGIN
|
||||
|
||||
#[pallet::validate_unsigned]
|
||||
// TODO_VALIDATE_UNSIGNED
|
||||
|
||||
{storages}
|
||||
|
||||
{genesis_config}
|
||||
|
||||
{genesis_build}
|
||||
}}",
|
||||
config_gen = config_gen,
|
||||
store_vis = convert_vis(&def.visibility),
|
||||
impl_gen = impl_gen,
|
||||
use_gen = use_gen,
|
||||
use_gen_tuple = use_gen_tuple,
|
||||
decl_gen = decl_gen,
|
||||
storages = storages,
|
||||
genesis_config = genesis_config,
|
||||
genesis_build = genesis_build,
|
||||
pallet_name = def.crate_name,
|
||||
deprecated_instance_stuff = deprecated_instance_stuff,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user