mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 19:01:08 +00:00
Refactor construct_runtime to procedural (#3810)
* interim * interim * interim * first working section * cleanup * finished parsing * cleanup * added system module search * added clone and find_entry * generic find_module_entry * interim * working event * added generic event with no instance error * cleanup * added decl origin * cleanup * added all modules * added outer dispatch * added modules expansion * refactored transformations * updated error message * added resolve mechanics * added metadata * finished config * finished inherents * added validate_unsigned * added compares * cleanup * cleanup * cleanup * fix * updated modules for last one wins * cleanup * made nested modules * updated impl version * removed comment * cleanup * added ui tests * added optional comma * removed unnecessary to string cast * removed no compile * cleanup * fmt * returned nocompile * Update srml/support/procedural/src/construct_runtime/parse.rs Co-Authored-By: thiolliere <gui.thiolliere@gmail.com> * added where definition * updated ui tests * updated ui test cases * added test case * updated tests * interim * added parse for module part * removed totokens * fixes * fixed multiple iter * changed TokenStream * fmt * updated trybuild * added test for arguments * fmt * fixes + more tests * fixes * fmt * rolled back runtime * minor fixes * empty * fixes * fmt * Update paint/support/procedural/src/lib.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update paint/support/procedural/src/lib.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update paint/support/procedural/src/construct_runtime/parse.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * interim * refactored seen_keys * refactored hash_set * Update paint/support/procedural/src/construct_runtime/mod.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * refactored find * fix * fixed all_modules * added double declaration check * small fix * fmt * fix * fix default * format
This commit is contained in:
@@ -246,7 +246,7 @@ construct_runtime!(
|
||||
Timestamp: timestamp::{Module, Call, Storage, Inherent},
|
||||
Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
|
||||
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
|
||||
Indices: indices::{default, Config<T>},
|
||||
Indices: indices,
|
||||
Balances: balances::{default, Error},
|
||||
TransactionPayment: transaction_payment::{Module, Storage},
|
||||
Sudo: sudo,
|
||||
|
||||
@@ -79,7 +79,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
// implementation changes and behavior does not, then leave spec_version as
|
||||
// is and increment impl_version.
|
||||
spec_version: 195,
|
||||
impl_version: 195,
|
||||
impl_version: 196,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
mod parse;
|
||||
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use frame_support_procedural_tools::{generate_crate_access, generate_hidden_includes};
|
||||
use parse::{ModuleDeclaration, RuntimeDefinition, WhereSection};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use quote::quote;
|
||||
use syn::{Ident, Result};
|
||||
|
||||
pub fn construct_runtime(input: TokenStream) -> TokenStream {
|
||||
let definition = syn::parse_macro_input!(input as RuntimeDefinition);
|
||||
construct_runtime_parsed(definition)
|
||||
.unwrap_or_else(|e| e.to_compile_error())
|
||||
.into()
|
||||
}
|
||||
|
||||
fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream2> {
|
||||
let RuntimeDefinition {
|
||||
name,
|
||||
where_section: WhereSection {
|
||||
block,
|
||||
node_block,
|
||||
unchecked_extrinsic,
|
||||
..
|
||||
},
|
||||
modules:
|
||||
ext::Braces {
|
||||
content: ext::Punctuated { inner: modules, .. },
|
||||
token: modules_token,
|
||||
},
|
||||
..
|
||||
} = definition;
|
||||
|
||||
// Assert we have system module declared
|
||||
let system_module = match find_system_module(modules.iter()) {
|
||||
Some(sm) => sm,
|
||||
None => {
|
||||
return Err(syn::Error::new(
|
||||
modules_token.span,
|
||||
"`System` module declaration is missing. \
|
||||
Please add this line: `System: system::{Module, Call, Storage, Config, Event},`",
|
||||
))
|
||||
}
|
||||
};
|
||||
let hidden_crate_name = "construct_runtime";
|
||||
let scrate = generate_crate_access(&hidden_crate_name, "frame-support");
|
||||
let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support");
|
||||
|
||||
let all_but_system_modules = modules.iter().filter(|module| module.name != "System");
|
||||
|
||||
let outer_event = decl_outer_event_or_origin(
|
||||
&name,
|
||||
all_but_system_modules.clone(),
|
||||
&system_module,
|
||||
&scrate,
|
||||
DeclOuterKind::Event,
|
||||
)?;
|
||||
let outer_origin = decl_outer_event_or_origin(
|
||||
&name,
|
||||
all_but_system_modules.clone(),
|
||||
&system_module,
|
||||
&scrate,
|
||||
DeclOuterKind::Origin,
|
||||
)?;
|
||||
let all_modules = decl_all_modules(&name, all_but_system_modules);
|
||||
|
||||
let dispatch = decl_outer_dispatch(&name, modules.iter(), &scrate);
|
||||
let metadata = decl_runtime_metadata(&name, modules.iter(), &scrate);
|
||||
let outer_config = decl_outer_config(&name, modules.iter(), &scrate);
|
||||
let inherent = decl_outer_inherent(&block, &unchecked_extrinsic, modules.iter(), &scrate);
|
||||
let validate_unsigned = decl_validate_unsigned(&name, modules.iter(), &scrate);
|
||||
|
||||
Ok(quote!(
|
||||
#scrate_decl
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub struct #name;
|
||||
impl #scrate::sr_primitives::traits::GetNodeBlockType for #name {
|
||||
type NodeBlock = #node_block;
|
||||
}
|
||||
impl #scrate::sr_primitives::traits::GetRuntimeBlockType for #name {
|
||||
type RuntimeBlock = #block;
|
||||
}
|
||||
|
||||
#outer_event
|
||||
|
||||
#outer_origin
|
||||
|
||||
#all_modules
|
||||
|
||||
#dispatch
|
||||
|
||||
#metadata
|
||||
|
||||
#outer_config
|
||||
|
||||
#inherent
|
||||
|
||||
#validate_unsigned
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
fn decl_validate_unsigned<'a>(
|
||||
runtime: &'a Ident,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let modules_tokens = module_declarations
|
||||
.filter(|module_declaration| module_declaration.exists_part("ValidateUnsigned"))
|
||||
.map(|module_declaration| &module_declaration.name);
|
||||
quote!(
|
||||
#scrate::impl_outer_validate_unsigned!(
|
||||
impl ValidateUnsigned for #runtime {
|
||||
#( #modules_tokens )*
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_outer_inherent<'a>(
|
||||
block: &'a syn::TypePath,
|
||||
unchecked_extrinsic: &'a syn::TypePath,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let modules_tokens = module_declarations.filter_map(|module_declaration| {
|
||||
let maybe_config_part = module_declaration.find_part("Inherent");
|
||||
maybe_config_part.map(|config_part| {
|
||||
let arg = config_part
|
||||
.args
|
||||
.as_ref()
|
||||
.and_then(|parens| parens.content.inner.iter().next())
|
||||
.unwrap_or(&module_declaration.name);
|
||||
let name = &module_declaration.name;
|
||||
quote!(#name : #arg,)
|
||||
})
|
||||
});
|
||||
quote!(
|
||||
#scrate::impl_outer_inherent!(
|
||||
impl Inherents where Block = #block, UncheckedExtrinsic = #unchecked_extrinsic {
|
||||
#(#modules_tokens)*
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_outer_config<'a>(
|
||||
runtime: &'a Ident,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let modules_tokens = module_declarations
|
||||
.filter_map(|module_declaration| {
|
||||
module_declaration.find_part("Config").map(|part| {
|
||||
let transformed_generics: Vec<_> = part
|
||||
.generics
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| quote!(<#param>))
|
||||
.collect();
|
||||
(module_declaration, transformed_generics)
|
||||
})
|
||||
})
|
||||
.map(|(module_declaration, generics)| {
|
||||
let module = &module_declaration.module;
|
||||
let name = Ident::new(
|
||||
&format!("{}Config", module_declaration.name),
|
||||
module_declaration.name.span(),
|
||||
);
|
||||
let instance = module_declaration.instance.as_ref().into_iter();
|
||||
quote!(
|
||||
#name =>
|
||||
#module #(#instance)* #(#generics)*,
|
||||
)
|
||||
});
|
||||
quote!(
|
||||
#scrate::sr_primitives::impl_outer_config! {
|
||||
pub struct GenesisConfig for #runtime {
|
||||
#(#modules_tokens)*
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_runtime_metadata<'a>(
|
||||
runtime: &'a Ident,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let modules_tokens = module_declarations
|
||||
.filter_map(|module_declaration| {
|
||||
module_declaration.find_part("Module").map(|_| {
|
||||
let filtered_names: Vec<_> = module_declaration
|
||||
.module_parts()
|
||||
.into_iter()
|
||||
.filter(|part| part.name != "Module")
|
||||
.map(|part| part.name.clone())
|
||||
.collect();
|
||||
(module_declaration, filtered_names)
|
||||
})
|
||||
})
|
||||
.map(|(module_declaration, filtered_names)| {
|
||||
let module = &module_declaration.module;
|
||||
let name = &module_declaration.name;
|
||||
let instance = module_declaration
|
||||
.instance
|
||||
.as_ref()
|
||||
.map(|name| quote!(<#name>))
|
||||
.into_iter();
|
||||
quote!(#module::Module #(#instance)* as #name with #(#filtered_names)* ,)
|
||||
});
|
||||
quote!(
|
||||
#scrate::impl_runtime_metadata!{
|
||||
for #runtime with modules
|
||||
#(#modules_tokens)*
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_outer_dispatch<'a>(
|
||||
runtime: &'a Ident,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let modules_tokens = module_declarations
|
||||
.filter(|module_declaration| module_declaration.exists_part("Call"))
|
||||
.map(|module_declaration| {
|
||||
let module = &module_declaration.module;
|
||||
let name = &module_declaration.name;
|
||||
quote!(#module::#name)
|
||||
});
|
||||
quote!(
|
||||
#scrate::impl_outer_dispatch! {
|
||||
pub enum Call for #runtime where origin: Origin {
|
||||
#(#modules_tokens,)*
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
enum DeclOuterKind {
|
||||
Event,
|
||||
Origin,
|
||||
}
|
||||
|
||||
fn decl_outer_event_or_origin<'a>(
|
||||
runtime_name: &'a Ident,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
system_name: &'a Ident,
|
||||
scrate: &'a TokenStream2,
|
||||
kind: DeclOuterKind,
|
||||
) -> syn::Result<TokenStream2> {
|
||||
let mut modules_tokens = TokenStream2::new();
|
||||
let kind_str = format!("{:?}", kind);
|
||||
for module_declaration in module_declarations {
|
||||
match module_declaration.find_part(&kind_str) {
|
||||
Some(module_entry) => {
|
||||
let module = &module_declaration.module;
|
||||
let instance = module_declaration.instance.as_ref();
|
||||
let generics = &module_entry.generics;
|
||||
if instance.is_some() && generics.params.len() == 0 {
|
||||
let msg = format!(
|
||||
"Instantiable module with no generic `{}` cannot \
|
||||
be constructed: module `{}` must have generic `{}`",
|
||||
kind_str, module_declaration.name, kind_str
|
||||
);
|
||||
return Err(syn::Error::new(module_declaration.name.span(), msg));
|
||||
}
|
||||
let tokens = quote!(#module #instance #generics ,);
|
||||
modules_tokens.extend(tokens);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
let macro_call = match kind {
|
||||
DeclOuterKind::Event => quote!(#scrate::impl_outer_event!),
|
||||
DeclOuterKind::Origin => quote!(#scrate::impl_outer_origin!),
|
||||
};
|
||||
let enum_name = Ident::new(kind_str.as_str(), Span::call_site());
|
||||
Ok(quote!(
|
||||
#macro_call {
|
||||
pub enum #enum_name for #runtime_name where system = #system_name {
|
||||
#modules_tokens
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
fn decl_all_modules<'a>(
|
||||
runtime: &'a Ident,
|
||||
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
) -> TokenStream2 {
|
||||
let mut types = TokenStream2::new();
|
||||
let mut names = Vec::new();
|
||||
for module_declaration in module_declarations {
|
||||
let type_name = &module_declaration.name;
|
||||
let module = &module_declaration.module;
|
||||
let mut generics = vec![quote!(#runtime)];
|
||||
generics.extend(
|
||||
module_declaration
|
||||
.instance
|
||||
.iter()
|
||||
.map(|name| quote!(#module::#name)),
|
||||
);
|
||||
let type_decl = quote!(
|
||||
pub type #type_name = #module::Module <#(#generics),*>;
|
||||
);
|
||||
types.extend(type_decl);
|
||||
names.push(&module_declaration.name);
|
||||
}
|
||||
// Make nested tuple structure like (((Babe, Consensus), Grandpa), ...)
|
||||
let all_modules = names.iter().fold(
|
||||
TokenStream2::default(),
|
||||
|combined, name| quote!((#name, #combined)),
|
||||
);
|
||||
|
||||
quote!(
|
||||
pub type System = system::Module<#runtime>;
|
||||
#types
|
||||
type AllModules = ( #all_modules );
|
||||
)
|
||||
}
|
||||
|
||||
fn find_system_module<'a>(
|
||||
mut module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
|
||||
) -> Option<&'a Ident> {
|
||||
module_declarations
|
||||
.find(|decl| decl.name == "System")
|
||||
.map(|decl| &decl.module)
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use proc_macro2::Span;
|
||||
use std::collections::HashSet;
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
spanned::Spanned,
|
||||
token, Error, Ident, Result, Token,
|
||||
};
|
||||
|
||||
mod keyword {
|
||||
syn::custom_keyword!(Block);
|
||||
syn::custom_keyword!(NodeBlock);
|
||||
syn::custom_keyword!(UncheckedExtrinsic);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RuntimeDefinition {
|
||||
pub visibility_token: Token![pub],
|
||||
pub enum_token: Token![enum],
|
||||
pub name: Ident,
|
||||
pub where_section: WhereSection,
|
||||
pub modules: ext::Braces<ext::Punctuated<ModuleDeclaration, Token![,]>>,
|
||||
}
|
||||
|
||||
impl Parse for RuntimeDefinition {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(Self {
|
||||
visibility_token: input.parse()?,
|
||||
enum_token: input.parse()?,
|
||||
name: input.parse()?,
|
||||
where_section: input.parse()?,
|
||||
modules: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WhereSection {
|
||||
pub block: syn::TypePath,
|
||||
pub node_block: syn::TypePath,
|
||||
pub unchecked_extrinsic: syn::TypePath,
|
||||
}
|
||||
|
||||
impl Parse for WhereSection {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
input.parse::<token::Where>()?;
|
||||
let mut definitions = Vec::new();
|
||||
while !input.peek(token::Brace) {
|
||||
let definition: WhereDefinition = input.parse()?;
|
||||
definitions.push(definition);
|
||||
if !input.peek(Token![,]) {
|
||||
if !input.peek(token::Brace) {
|
||||
return Err(input.error("Expected `,` or `{`"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
let block = remove_kind(input, WhereKind::Block, &mut definitions)?.value;
|
||||
let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value;
|
||||
let unchecked_extrinsic =
|
||||
remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value;
|
||||
if let Some(WhereDefinition {
|
||||
ref kind_span,
|
||||
ref kind,
|
||||
..
|
||||
}) = definitions.first()
|
||||
{
|
||||
let msg = format!(
|
||||
"`{:?}` was declared above. Please use exactly one delcataion for `{:?}`.",
|
||||
kind, kind
|
||||
);
|
||||
return Err(Error::new(*kind_span, msg));
|
||||
}
|
||||
Ok(Self {
|
||||
block,
|
||||
node_block,
|
||||
unchecked_extrinsic,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum WhereKind {
|
||||
Block,
|
||||
NodeBlock,
|
||||
UncheckedExtrinsic,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WhereDefinition {
|
||||
pub kind_span: Span,
|
||||
pub kind: WhereKind,
|
||||
pub value: syn::TypePath,
|
||||
}
|
||||
|
||||
impl Parse for WhereDefinition {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
let (kind_span, kind) = if lookahead.peek(keyword::Block) {
|
||||
(input.parse::<keyword::Block>()?.span(), WhereKind::Block)
|
||||
} else if lookahead.peek(keyword::NodeBlock) {
|
||||
(
|
||||
input.parse::<keyword::NodeBlock>()?.span(),
|
||||
WhereKind::NodeBlock,
|
||||
)
|
||||
} else if lookahead.peek(keyword::UncheckedExtrinsic) {
|
||||
(
|
||||
input.parse::<keyword::UncheckedExtrinsic>()?.span(),
|
||||
WhereKind::UncheckedExtrinsic,
|
||||
)
|
||||
} else {
|
||||
return Err(lookahead.error());
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
kind_span,
|
||||
kind,
|
||||
value: {
|
||||
let _: Token![=] = input.parse()?;
|
||||
input.parse()?
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleDeclaration {
|
||||
pub name: Ident,
|
||||
pub module: Ident,
|
||||
pub instance: Option<Ident>,
|
||||
pub details: Option<ext::Braces<ext::Punctuated<ModuleEntry, Token![,]>>>,
|
||||
}
|
||||
|
||||
impl Parse for ModuleDeclaration {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let name = input.parse()?;
|
||||
let _: Token![:] = input.parse()?;
|
||||
let module = input.parse()?;
|
||||
let instance = if input.peek(Token![::]) && input.peek3(Token![<]) {
|
||||
let _: Token![::] = input.parse()?;
|
||||
let _: Token![<] = input.parse()?;
|
||||
let res = Some(input.parse()?);
|
||||
let _: Token![>] = input.parse()?;
|
||||
res
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let details = if input.peek(Token![::]) {
|
||||
let _: Token![::] = input.parse()?;
|
||||
Some(input.parse()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let parsed = Self {
|
||||
name,
|
||||
module,
|
||||
instance,
|
||||
details,
|
||||
};
|
||||
if let Some(ref details) = parsed.details {
|
||||
let parts = &details.content.inner;
|
||||
let mut resolved = HashSet::new();
|
||||
let has_default = parts.into_iter().any(|m| m.is_default());
|
||||
for entry in parts {
|
||||
match entry {
|
||||
ModuleEntry::Part(part) if has_default => {
|
||||
if part.is_included_in_default() {
|
||||
let msg = format!(
|
||||
"`{}` is already included in `default`. Either remove `default` or remove `{}`",
|
||||
part.name,
|
||||
part.name
|
||||
);
|
||||
return Err(Error::new(part.name.span(), msg));
|
||||
}
|
||||
}
|
||||
ModuleEntry::Part(part) => {
|
||||
if !resolved.insert(part.name.clone()) {
|
||||
let msg = format!(
|
||||
"`{}` was already declared before. Please remove the duplicate declaration",
|
||||
part.name
|
||||
);
|
||||
return Err(Error::new(part.name.span(), msg));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(parsed)
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleDeclaration {
|
||||
/// Get resolved module parts, i.e. after expanding `default` keyword
|
||||
/// or empty declaration
|
||||
pub fn module_parts(&self) -> Vec<ModulePart> {
|
||||
if let Some(ref details) = self.details {
|
||||
details
|
||||
.content
|
||||
.inner
|
||||
.iter()
|
||||
.flat_map(|entry| match entry {
|
||||
ModuleEntry::Default(ref token) => Self::default_modules(token.span()),
|
||||
ModuleEntry::Part(ref part) => vec![part.clone()],
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Self::default_modules(self.module.span())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_part(&self, name: &str) -> Option<ModulePart> {
|
||||
self.module_parts()
|
||||
.into_iter()
|
||||
.find(|part| part.name == name)
|
||||
}
|
||||
|
||||
pub fn exists_part(&self, name: &str) -> bool {
|
||||
self.find_part(name).is_some()
|
||||
}
|
||||
|
||||
fn default_modules(span: Span) -> Vec<ModulePart> {
|
||||
let mut res: Vec<_> = ["Module", "Call", "Storage"]
|
||||
.into_iter()
|
||||
.map(|name| ModulePart::with_name(name, span))
|
||||
.collect();
|
||||
res.extend(
|
||||
["Event", "Config"]
|
||||
.into_iter()
|
||||
.map(|name| ModulePart::with_generics(name, span)),
|
||||
);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ModuleEntry {
|
||||
Default(Token![default]),
|
||||
Part(ModulePart),
|
||||
}
|
||||
|
||||
impl Parse for ModuleEntry {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![default]) {
|
||||
Ok(ModuleEntry::Default(input.parse()?))
|
||||
} else if lookahead.peek(Ident) {
|
||||
Ok(ModuleEntry::Part(input.parse()?))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleEntry {
|
||||
pub fn is_default(&self) -> bool {
|
||||
match self {
|
||||
ModuleEntry::Default(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModulePart {
|
||||
pub name: Ident,
|
||||
pub generics: syn::Generics,
|
||||
pub args: Option<ext::Parens<ext::Punctuated<Ident, Token![,]>>>,
|
||||
}
|
||||
|
||||
impl Parse for ModulePart {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let name = input.parse()?;
|
||||
let generics: syn::Generics = input.parse()?;
|
||||
if !generics.params.is_empty() && !Self::is_allowed_generic(&name) {
|
||||
let valid_generics = ModulePart::format_names(ModulePart::allowed_generics());
|
||||
let msg = format!(
|
||||
"`{}` is not allowed to have generics. \
|
||||
Only the following modules are allowed to have generics: {}.",
|
||||
name, valid_generics
|
||||
);
|
||||
return Err(syn::Error::new(name.span(), msg));
|
||||
}
|
||||
let args = if input.peek(token::Paren) {
|
||||
if !Self::is_allowed_arg(&name) {
|
||||
let syn::group::Parens { token: parens, .. } = syn::group::parse_parens(input)?;
|
||||
let valid_names = ModulePart::format_names(ModulePart::allowed_args());
|
||||
let msg = format!(
|
||||
"`{}` is not allowed to have arguments in parens. \
|
||||
Only the following modules are allowed to have arguments in parens: {}.",
|
||||
name, valid_names
|
||||
);
|
||||
return Err(syn::Error::new(parens.span, msg));
|
||||
}
|
||||
Some(input.parse()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Self {
|
||||
name,
|
||||
generics,
|
||||
args,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ModulePart {
|
||||
pub fn is_allowed_generic(ident: &Ident) -> bool {
|
||||
Self::allowed_generics().into_iter().any(|n| ident == n)
|
||||
}
|
||||
|
||||
pub fn is_allowed_arg(ident: &Ident) -> bool {
|
||||
Self::allowed_args().into_iter().any(|n| ident == n)
|
||||
}
|
||||
|
||||
pub fn allowed_generics() -> Vec<&'static str> {
|
||||
vec!["Event", "Origin", "Config"]
|
||||
}
|
||||
|
||||
pub fn allowed_args() -> Vec<&'static str> {
|
||||
vec!["Inherent"]
|
||||
}
|
||||
|
||||
pub fn format_names(names: Vec<&'static str>) -> String {
|
||||
let res: Vec<_> = names.into_iter().map(|s| format!("`{}`", s)).collect();
|
||||
res.join(", ")
|
||||
}
|
||||
|
||||
pub fn is_included_in_default(&self) -> bool {
|
||||
["Module", "Call", "Storage", "Event", "Config"]
|
||||
.into_iter()
|
||||
.any(|name| self.name == name)
|
||||
}
|
||||
|
||||
/// Plain module name like `Event` or `Call`, etc.
|
||||
pub fn with_name(name: &str, span: Span) -> Self {
|
||||
let name = Ident::new(name, span);
|
||||
Self {
|
||||
name,
|
||||
generics: syn::Generics {
|
||||
lt_token: None,
|
||||
gt_token: None,
|
||||
where_clause: None,
|
||||
..Default::default()
|
||||
},
|
||||
args: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Module name with generic like `Event<T>` or `Call<T>`, etc.
|
||||
pub fn with_generics(name: &str, span: Span) -> Self {
|
||||
let name = Ident::new(name, span);
|
||||
let typ = Ident::new("T", span);
|
||||
let generic_param = syn::GenericParam::Type(typ.into());
|
||||
let generic_params = vec![generic_param].into_iter().collect();
|
||||
let generics = syn::Generics {
|
||||
lt_token: Some(syn::token::Lt { spans: [span] }),
|
||||
params: generic_params,
|
||||
gt_token: Some(syn::token::Gt { spans: [span] }),
|
||||
where_clause: None,
|
||||
};
|
||||
Self {
|
||||
name,
|
||||
generics,
|
||||
args: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_kind(
|
||||
input: ParseStream,
|
||||
kind: WhereKind,
|
||||
definitions: &mut Vec<WhereDefinition>,
|
||||
) -> Result<WhereDefinition> {
|
||||
if let Some(pos) = definitions.iter().position(|d| d.kind == kind) {
|
||||
Ok(definitions.remove(pos))
|
||||
} else {
|
||||
let msg = format!(
|
||||
"Missing associated type for `{:?}`. Add `{:?}` = ... to where section.",
|
||||
kind, kind
|
||||
);
|
||||
Err(input.error(msg))
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
mod storage;
|
||||
mod construct_runtime;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
@@ -219,3 +220,63 @@ use proc_macro::TokenStream;
|
||||
pub fn decl_storage(input: TokenStream) -> TokenStream {
|
||||
storage::decl_storage_impl(input)
|
||||
}
|
||||
|
||||
/// Construct a runtime, with the given name and the given modules.
|
||||
///
|
||||
/// The parameters here are specific types for `Block`, `NodeBlock`, and `UncheckedExtrinsic`
|
||||
/// and the modules that are used by the runtime.
|
||||
/// `Block` is the block type that is used in the runtime and `NodeBlock` is the block type
|
||||
/// that is used in the node. For instance they can differ in the extrinsics type.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```nocompile
|
||||
/// construct_runtime!(
|
||||
/// pub enum Runtime where
|
||||
/// Block = Block,
|
||||
/// NodeBlock = runtime::Block,
|
||||
/// UncheckedExtrinsic = UncheckedExtrinsic
|
||||
/// {
|
||||
/// System: system,
|
||||
/// Test: test::{default},
|
||||
/// Test2: test_with_long_module::{Module},
|
||||
///
|
||||
/// // Module with instances
|
||||
/// Test3_Instance1: test3::<Instance1>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>},
|
||||
/// Test3_DefaultInstance: test3::{Module, Call, Storage, Event<T>, Config<T>, Origin<T>},
|
||||
/// }
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// The module `System: system` will expand to `System: system::{Module, Call, Storage, Event<T>, Config<T>}`.
|
||||
/// The identifier `System` is the name of the module and the lower case identifier `system` is the
|
||||
/// name of the Rust module/crate for this Substrate module.
|
||||
///
|
||||
/// The module `Test: test::{default}` will expand to
|
||||
/// `Test: test::{Module, Call, Storage, Event<T>, Config<T>}`.
|
||||
///
|
||||
/// The module `Test2: test_with_long_module::{Module}` will expand to
|
||||
/// `Test2: test_with_long_module::{Module}`.
|
||||
///
|
||||
/// We provide support for the following types in a module:
|
||||
///
|
||||
/// - `Module`
|
||||
/// - `Call`
|
||||
/// - `Storage`
|
||||
/// - `Event` or `Event<T>` (if the event is generic)
|
||||
/// - `Origin` or `Origin<T>` (if the origin is generic)
|
||||
/// - `Config` or `Config<T>` (if the config is generic)
|
||||
/// - `Inherent ( $(CALL),* )` - If the module provides/can check inherents. The optional parameter
|
||||
/// is for modules that use a `Call` from a different module as
|
||||
/// inherent.
|
||||
/// - `ValidateUnsigned` - If the module validates unsigned extrinsics.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// The population of the genesis storage depends on the order of modules. So, if one of your
|
||||
/// modules depends on another module, the module that is depended upon needs to come before
|
||||
/// the module depending on it.
|
||||
#[proc_macro]
|
||||
pub fn construct_runtime(input: TokenStream) -> TokenStream {
|
||||
construct_runtime::construct_runtime(input)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,11 @@ macro_rules! groups_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl <P: Clone> Clone for $name<P> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { token: self.token.clone(), content: self.content.clone() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,11 +77,11 @@ pub struct PunctuatedInner<P,T,V> {
|
||||
pub variant: V,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NoTrailing;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Trailing;
|
||||
|
||||
pub type Punctuated<P,T> = PunctuatedInner<P,T,NoTrailing>;
|
||||
@@ -107,6 +112,12 @@ impl<P: ToTokens, T: ToTokens, V> ToTokens for PunctuatedInner<P,T,V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl <P: Clone, T: Clone, V: Clone> Clone for PunctuatedInner<P, T, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { inner: self.inner.clone(), variant: self.variant.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Note that syn Meta is almost fine for use case (lacks only `ToToken`)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Meta {
|
||||
@@ -178,6 +189,14 @@ impl<P: ToTokens> ToTokens for Opt<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl <P: Clone> Clone for Opt<P> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_type_option(typ: &syn::Type) -> Option<syn::Type> {
|
||||
if let syn::Type::Path(ref path) = typ {
|
||||
let v = path.path.segments.last()?;
|
||||
|
||||
@@ -58,8 +58,6 @@ mod origin;
|
||||
#[macro_use]
|
||||
pub mod metadata;
|
||||
#[macro_use]
|
||||
mod runtime;
|
||||
#[macro_use]
|
||||
pub mod inherent;
|
||||
#[macro_use]
|
||||
pub mod unsigned;
|
||||
@@ -116,7 +114,7 @@ macro_rules! parameter_types {
|
||||
}
|
||||
|
||||
#[doc(inline)]
|
||||
pub use frame_support_procedural::decl_storage;
|
||||
pub use frame_support_procedural::{decl_storage, construct_runtime};
|
||||
|
||||
/// Return Err of the expression: `return Err($expression);`.
|
||||
///
|
||||
|
||||
@@ -1,948 +0,0 @@
|
||||
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Macros to define a runtime. A runtime is basically all your logic running in Substrate,
|
||||
//! consisting of selected SRML modules and maybe some of your own modules.
|
||||
//! A lot of supporting logic is automatically generated for a runtime,
|
||||
//! mostly to combine data types and metadata of the included modules.
|
||||
|
||||
/// Construct a runtime, with the given name and the given modules.
|
||||
///
|
||||
/// The parameters here are specific types for `Block`, `NodeBlock`, and `InherentData`
|
||||
/// and the modules that are used by the runtime.
|
||||
/// `Block` is the block type that is used in the runtime and `NodeBlock` is the block type
|
||||
/// that is used in the node. For instance they can differ in the extrinsics type.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```nocompile
|
||||
/// construct_runtime!(
|
||||
/// pub enum Runtime where
|
||||
/// Block = Block,
|
||||
/// NodeBlock = runtime::Block,
|
||||
/// UncheckedExtrinsic = UncheckedExtrinsic
|
||||
/// {
|
||||
/// System: system,
|
||||
/// Test: test::{default},
|
||||
/// Test2: test_with_long_module::{Module},
|
||||
///
|
||||
/// // Module with instances
|
||||
/// Test3_Instance1: test3::<Instance1>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>},
|
||||
/// Test3_DefaultInstance: test3::{Module, Call, Storage, Event<T>, Config<T>, Origin<T>},
|
||||
/// }
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// The module `System: system` will expand to `System: system::{Module, Call, Storage, Event<T>, Config<T>}`.
|
||||
/// The identifier `System` is the name of the module and the lower case identifier `system` is the
|
||||
/// name of the Rust module/crate for this Substrate module.
|
||||
///
|
||||
/// The module `Test: test::{default}` will expand to
|
||||
/// `Test: test::{Module, Call, Storage, Event<T>, Config<T>}`.
|
||||
///
|
||||
/// The module `Test2: test_with_long_module::{Module}` will expand to
|
||||
/// `Test2: test_with_long_module::{Module}`.
|
||||
///
|
||||
/// We provide support for the following types in a module:
|
||||
///
|
||||
/// - `Module`
|
||||
/// - `Call`
|
||||
/// - `Storage`
|
||||
/// - `Event` or `Event<T>` (if the event is generic)
|
||||
/// - `Origin` or `Origin<T>` (if the origin is generic)
|
||||
/// - `Config` or `Config<T>` (if the config is generic)
|
||||
/// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter
|
||||
/// is for modules that use a `Call` from a different module as
|
||||
/// inherent.
|
||||
/// - `ValidateUnsigned` - If the module validates unsigned extrinsics.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// The population of the genesis storage depends on the order of modules. So, if one of your
|
||||
/// modules depends on another module, the module that is depended upon needs to come before
|
||||
/// the module depending on it.
|
||||
#[macro_export]
|
||||
macro_rules! construct_runtime {
|
||||
|
||||
// Macro transformations (to convert invocations with incomplete parameters to the canonical
|
||||
// form)
|
||||
|
||||
(
|
||||
pub enum $runtime:ident
|
||||
where
|
||||
Block = $block:ident,
|
||||
NodeBlock = $node_block:ty,
|
||||
UncheckedExtrinsic = $uncheckedextrinsic:ident
|
||||
{
|
||||
$( $rest:tt )*
|
||||
}
|
||||
) => {
|
||||
$crate::construct_runtime!(
|
||||
{
|
||||
$runtime;
|
||||
$block;
|
||||
$node_block;
|
||||
$uncheckedextrinsic;
|
||||
};
|
||||
{};
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// No modules given, expand to the default module set.
|
||||
(
|
||||
{ $( $preset:tt )* };
|
||||
{ $( $expanded:tt )* };
|
||||
$name:ident: $module:ident,
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::construct_runtime!(
|
||||
{ $( $preset )* };
|
||||
{ $( $expanded )* };
|
||||
$name: $module::{default},
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// `default` identifier given, expand to default + given extra modules
|
||||
(
|
||||
{ $( $preset:tt )* };
|
||||
{ $( $expanded:tt )* };
|
||||
$name:ident: $module:ident::{
|
||||
default
|
||||
$(,
|
||||
$modules:ident
|
||||
$( <$modules_generic:ident> )*
|
||||
$( ( $( $modules_args:ident ),* ) )*
|
||||
)*
|
||||
},
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::construct_runtime!(
|
||||
{ $( $preset )* };
|
||||
{
|
||||
$( $expanded )*
|
||||
$name: $module::{
|
||||
Module, Call, Storage, Event<T>, Config<T>
|
||||
$(,
|
||||
$modules $( <$modules_generic> )*
|
||||
$( ( $( $modules_args ),* ) )*
|
||||
)*
|
||||
},
|
||||
};
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// Take all modules as given by the user.
|
||||
(
|
||||
{ $( $preset:tt )* };
|
||||
{ $( $expanded:tt )* };
|
||||
$name:ident: $module:ident :: $( < $module_instance:ident >:: )? {
|
||||
$(
|
||||
$modules:ident
|
||||
$( <$modules_generic:ident> )*
|
||||
$( ( $( $modules_args:ident ),* ) )*
|
||||
),*
|
||||
},
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::construct_runtime!(
|
||||
{ $( $preset )* };
|
||||
{
|
||||
$( $expanded )*
|
||||
$name: $module:: $( < $module_instance >:: )? {
|
||||
$(
|
||||
$modules $( <$modules_generic> )*
|
||||
$( ( $( $modules_args ),* ) )*
|
||||
),*
|
||||
},
|
||||
};
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// The main macro expansion that actually renders the Runtime code.
|
||||
(
|
||||
{
|
||||
$runtime:ident;
|
||||
$block:ident;
|
||||
$node_block:ty;
|
||||
$uncheckedextrinsic:ident;
|
||||
};
|
||||
{
|
||||
$(
|
||||
$name:ident: $module:ident :: $( < $module_instance:ident >:: )? {
|
||||
$(
|
||||
$modules:ident
|
||||
$( <$modules_generic:ident> )*
|
||||
$( ( $( $modules_args:ident ),* ) )*
|
||||
),*
|
||||
},
|
||||
)*
|
||||
};
|
||||
) => {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)]
|
||||
pub struct $runtime;
|
||||
impl $crate::sr_primitives::traits::GetNodeBlockType for $runtime {
|
||||
type NodeBlock = $node_block;
|
||||
}
|
||||
impl $crate::sr_primitives::traits::GetRuntimeBlockType for $runtime {
|
||||
type RuntimeBlock = $block;
|
||||
}
|
||||
$crate::__decl_outer_event!(
|
||||
$runtime;
|
||||
$(
|
||||
$name: $module:: $( < $module_instance >:: )? {
|
||||
$( $modules $( <$modules_generic> )* ),*
|
||||
}
|
||||
),*
|
||||
);
|
||||
$crate::__decl_outer_origin!(
|
||||
$runtime;
|
||||
$(
|
||||
$name: $module:: $( < $module_instance >:: )? {
|
||||
$( $modules $( <$modules_generic> )* ),*
|
||||
}
|
||||
),*
|
||||
);
|
||||
$crate::__decl_all_modules!(
|
||||
$runtime;
|
||||
;
|
||||
{};
|
||||
{};
|
||||
$(
|
||||
$name: $module:: $( < $module_instance >:: )? { $( $modules ),* },
|
||||
)*
|
||||
);
|
||||
$crate::__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules ),* }
|
||||
),*;
|
||||
);
|
||||
$crate::__decl_runtime_metadata!(
|
||||
$runtime;
|
||||
{};
|
||||
$(
|
||||
$name: $module:: $( < $module_instance >:: )? { $( $modules )* }
|
||||
)*
|
||||
);
|
||||
$crate::__decl_outer_config!(
|
||||
$runtime;
|
||||
{};
|
||||
$(
|
||||
$name: $module:: $( < $module_instance >:: )? {
|
||||
$( $modules $( <$modules_generic> )* ),*
|
||||
},
|
||||
)*
|
||||
);
|
||||
$crate::__decl_outer_inherent!(
|
||||
$runtime;
|
||||
$block;
|
||||
$uncheckedextrinsic;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( ( $( $modules_args )* ) )* ),* }
|
||||
),*;
|
||||
);
|
||||
$crate::__impl_outer_validate_unsigned!(
|
||||
$runtime;
|
||||
{};
|
||||
$(
|
||||
$name: $module::{ $( $modules $( ( $( $modules_args )* ) )* )* }
|
||||
)*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A macro that generates a "__decl" private macro that transforms parts of the runtime definition
|
||||
/// to feed them into a public "impl" macro which accepts the format
|
||||
/// "pub enum $name for $runtime where system = $system".
|
||||
///
|
||||
/// Used to define Event and Origin associated types.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __create_decl_macro {
|
||||
(
|
||||
// Parameter $d is a hack for the following issue:
|
||||
// https://github.com/rust-lang/rust/issues/35853
|
||||
$macro_name:ident, $macro_outer_name:ident, $macro_enum_name:ident, $d:tt
|
||||
) => {
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! $macro_name {
|
||||
(
|
||||
$runtime:ident;
|
||||
$d( $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? {
|
||||
$d( $modules:ident $d( <$modules_generic:ident> ),* ),*
|
||||
}),*
|
||||
) => {
|
||||
$d crate::$macro_name!(@inner
|
||||
$runtime;
|
||||
;
|
||||
{};
|
||||
$d(
|
||||
$name: $module:: $d( < $module_instance >:: )? {
|
||||
$d( $modules $d( <$modules_generic> )* ),*
|
||||
},
|
||||
)*
|
||||
);
|
||||
};
|
||||
// Parse system module
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
; // there can not be multiple `System`s
|
||||
{ $d( $parsed:tt )* };
|
||||
System: $module:ident::{
|
||||
$d( $modules:ident $d( <$modules_generic:ident> )* ),*
|
||||
},
|
||||
$d( $rest:tt )*
|
||||
) => {
|
||||
$d crate::$macro_name!(@inner
|
||||
$runtime;
|
||||
$module;
|
||||
{ $d( $parsed )* };
|
||||
$d( $rest )*
|
||||
);
|
||||
};
|
||||
// Parse instantiable module with generic
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
$d( $system:ident )?;
|
||||
{ $d( $parsed:tt )* };
|
||||
$name:ident : $module:ident:: < $module_instance:ident >:: {
|
||||
$macro_enum_name <$event_generic:ident> $d(, $ingore:ident $d( <$ignor:ident> )* )*
|
||||
},
|
||||
$d( $rest:tt )*
|
||||
) => {
|
||||
$d crate::$macro_name!(@inner
|
||||
$runtime;
|
||||
$d( $system )?;
|
||||
{
|
||||
$d( $parsed )*
|
||||
$module $module_instance <$event_generic>,
|
||||
};
|
||||
$d( $rest )*
|
||||
);
|
||||
};
|
||||
// Parse instantiable module with no generic
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
$d( $system:ident )?;
|
||||
{ $d( $parsed:tt )* };
|
||||
$name:ident : $module:ident:: < $module_instance:ident >:: {
|
||||
$macro_enum_name $d(, $ingore:ident $d( <$ignor:ident> )* )*
|
||||
},
|
||||
$d( $rest:tt )*
|
||||
) => {
|
||||
compile_error!(concat!(
|
||||
"Instantiable module with not generic ", stringify!($macro_enum_name),
|
||||
" cannot be constructed: module `", stringify!($name), "` must have generic ",
|
||||
stringify!($macro_enum_name), "."
|
||||
));
|
||||
};
|
||||
// Parse instantiable module with no generic
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
$d( $system:ident )?;
|
||||
{ $d( $parsed:tt )* };
|
||||
$name:ident : $module:ident:: {
|
||||
$macro_enum_name $d( <$event_generic:ident> )* $d(, $ignore:ident $d( <$ignor:ident> )* )*
|
||||
},
|
||||
$d( $rest:tt )*
|
||||
) => {
|
||||
$d crate::$macro_name!(@inner
|
||||
$runtime;
|
||||
$d( $system )?;
|
||||
{
|
||||
$d( $parsed )*
|
||||
$module $d( <$event_generic> )*,
|
||||
};
|
||||
$d( $rest )*
|
||||
);
|
||||
};
|
||||
// Ignore keyword
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
$d( $system:ident )?;
|
||||
{ $d( $parsed:tt )* };
|
||||
$name:ident : $module:ident:: $d( < $module_instance:ident >:: )? {
|
||||
$ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
|
||||
},
|
||||
$d( $rest:tt )*
|
||||
) => {
|
||||
$d crate::$macro_name!(@inner
|
||||
$runtime;
|
||||
$d( $system )?;
|
||||
{ $d( $parsed )* };
|
||||
$name: $module:: $d( < $module_instance >:: )? { $d( $modules $d( <$modules_generic> )* ),* },
|
||||
$d( $rest )*
|
||||
);
|
||||
};
|
||||
// Ignore module
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
$d( $system:ident )?;
|
||||
{ $d( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $d( < $module_instance:ident >:: )? {},
|
||||
$d( $rest:tt )*
|
||||
) => {
|
||||
$d crate::$macro_name!(@inner
|
||||
$runtime;
|
||||
$d( $system )?;
|
||||
{ $d( $parsed )* };
|
||||
$d( $rest )*
|
||||
);
|
||||
};
|
||||
// Expand
|
||||
(@inner
|
||||
$runtime:ident;
|
||||
$system:ident;
|
||||
{ $d( $parsed_modules:ident $d( $instance:ident )? $d( <$parsed_generic:ident> )? ,)* };
|
||||
) => {
|
||||
$d crate::$macro_outer_name! {
|
||||
pub enum $macro_enum_name for $runtime where system = $system {
|
||||
$d(
|
||||
$parsed_modules $d( $instance )? $d( <$parsed_generic> )?,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__create_decl_macro!(__decl_outer_event, impl_outer_event, Event, $);
|
||||
__create_decl_macro!(__decl_outer_origin, impl_outer_origin, Origin, $);
|
||||
|
||||
/// A macro that defines all modules as an associated types of the Runtime type.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_all_modules {
|
||||
(
|
||||
$runtime:ident;
|
||||
;
|
||||
{ $( $parsed:tt )* };
|
||||
{ $( $parsed_nested:tt )* };
|
||||
System: $module:ident::{ Module $(, $modules:ident )* },
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_all_modules!(
|
||||
$runtime;
|
||||
$module;
|
||||
{ $( $parsed )* };
|
||||
{ $( $parsed_nested )* };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )?;
|
||||
{ $( $parsed:tt )* };
|
||||
{};
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* },
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )?;
|
||||
{
|
||||
$( $parsed )*
|
||||
$module::$name $(<$module_instance>)?,
|
||||
};
|
||||
{ $name };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )?;
|
||||
{ $( $parsed:tt )* };
|
||||
{ $( $parsed_nested:tt )* };
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* },
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )?;
|
||||
{
|
||||
$( $parsed )*
|
||||
$module::$name $(<$module_instance>)?,
|
||||
};
|
||||
{ ( $( $parsed_nested )*, $name, ) };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )?;
|
||||
{ $( $parsed:tt )* };
|
||||
{ $( $parsed_nested:tt )* };
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? { $ignore:ident $(, $modules:ident )* },
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )?;
|
||||
{ $( $parsed )* };
|
||||
{ $( $parsed_nested )* };
|
||||
$name: $module::{ $( $modules ),* },
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )?;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {},
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )?;
|
||||
{ $( $parsed )* };
|
||||
{ $( $parsed_nested )* };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$system:ident;
|
||||
{ $( $parsed_module:ident :: $parsed_name:ident $(<$instance:ident>)? ,)*};
|
||||
{ $( $parsed_nested:tt )* };
|
||||
) => {
|
||||
pub type System = system::Module<$runtime>;
|
||||
$(
|
||||
pub type $parsed_name = $parsed_module::Module<$runtime $(, $parsed_module::$instance )?>;
|
||||
)*
|
||||
type AllModules = ( $( $parsed_nested )* );
|
||||
}
|
||||
}
|
||||
|
||||
/// A macro that defines the Call enum to represent calls to functions in the modules included
|
||||
/// in the runtime (by wrapping the values of all FooModule::Call enums).
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_outer_dispatch {
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Call $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name, )* $module::$name;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ignore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
;
|
||||
) => {
|
||||
$crate::impl_outer_dispatch!(
|
||||
pub enum Call for $runtime where origin: Origin {
|
||||
$( $parsed_modules::$parsed_name, )*
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/// A private macro that generates metadata() method for the runtime. See impl_runtime_metadata macro.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_runtime_metadata {
|
||||
// leading is Module : parse
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$( { leading_module: $( $leading_module:ident )* } )?
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {
|
||||
Module $( $modules:ident )*
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_runtime_metadata!(
|
||||
$runtime;
|
||||
{
|
||||
$( $parsed )*
|
||||
$module $( < $module_instance > )? as $name {
|
||||
$( $( $leading_module )* )? $( $modules )*
|
||||
}
|
||||
};
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// leading isn't Module : put it in leadings
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$( { leading_module: $( $leading_module:ident )* } )?
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {
|
||||
$other_module:ident $( $modules:ident )*
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_runtime_metadata!(
|
||||
$runtime;
|
||||
{ $( $parsed )* };
|
||||
{ leading_module: $( $( $leading_module )* )? $other_module }
|
||||
$name: $module:: $( < $module_instance >:: )? {
|
||||
$( $modules )*
|
||||
}
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// does not contain Module : skip
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$( { leading_module: $( $leading_module:ident )* } )?
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_runtime_metadata!(
|
||||
$runtime;
|
||||
{ $( $parsed )* };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// end of decl
|
||||
(
|
||||
$runtime:ident;
|
||||
{
|
||||
$(
|
||||
$parsed_modules:ident $( < $module_instance:ident > )? as $parsed_name:ident {
|
||||
$( $withs:ident )*
|
||||
}
|
||||
)*
|
||||
};
|
||||
) => {
|
||||
$crate::impl_runtime_metadata!(
|
||||
for $runtime with modules
|
||||
$( $parsed_modules::Module $( < $module_instance > )? as $parsed_name
|
||||
with $( $withs )* , )*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A private macro that generates GenesisConfig for the runtime. See `impl_outer_config!` macro.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_outer_config {
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {
|
||||
Config $( <$config_generic:ident> )?
|
||||
$(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
},
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_outer_config!(
|
||||
$runtime;
|
||||
{
|
||||
$( $parsed )*
|
||||
$module::$name $( $module_instance )? $( <$config_generic> )?,
|
||||
};
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {
|
||||
$ingore:ident $( <$ignore_gen:ident> )*
|
||||
$(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
},
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_outer_config!(
|
||||
$runtime;
|
||||
{ $( $parsed )* };
|
||||
$name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic> )* ),* },
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {},
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__decl_outer_config!(
|
||||
$runtime;
|
||||
{ $( $parsed )* };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
{
|
||||
$(
|
||||
$parsed_modules:ident :: $parsed_name:ident $( $parsed_instance:ident )?
|
||||
$(
|
||||
<$parsed_generic:ident>
|
||||
)*
|
||||
,)*
|
||||
};
|
||||
) => {
|
||||
$crate::paste::item! {
|
||||
$crate::sr_primitives::impl_outer_config!(
|
||||
pub struct GenesisConfig for $runtime {
|
||||
$(
|
||||
[< $parsed_name Config >] =>
|
||||
$parsed_modules $( $parsed_instance )? $( <$parsed_generic> )*,
|
||||
)*
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A private macro that generates check_inherents() implementation for the runtime.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_outer_inherent {
|
||||
(
|
||||
$runtime:ident;
|
||||
$block:ident;
|
||||
$uncheckedextrinsic:ident;
|
||||
$( $parsed_name:ident :: $parsed_call:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Inherent $(, $modules:ident $( ( $( $modules_call:ident )* ) )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_inherent!(
|
||||
$runtime;
|
||||
$block;
|
||||
$uncheckedextrinsic;
|
||||
$( $parsed_name :: $parsed_call, )* $name::$name;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_call )* ) )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$block:ident;
|
||||
$uncheckedextrinsic:ident;
|
||||
$( $parsed_name:ident :: $parsed_call:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Inherent ( $call:ident ) $(, $modules:ident $( ( $( $modules_call:ident )* ) )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_inherent!(
|
||||
$runtime;
|
||||
$block;
|
||||
$uncheckedextrinsic;
|
||||
$( $parsed_name :: $parsed_call, )* $name::$call;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_call )* ) )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$block:ident;
|
||||
$uncheckedextrinsic:ident;
|
||||
$( $parsed_name:ident :: $parsed_call:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ignore:ident $( ( $( $ignor:ident )* ) )*
|
||||
$(, $modules:ident $( ( $( $modules_call:ident )* ) )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_inherent!(
|
||||
$runtime;
|
||||
$block;
|
||||
$uncheckedextrinsic;
|
||||
$( $parsed_name :: $parsed_call ),*;
|
||||
$name: $module::{ $( $modules $( ( $( $modules_call )* ) )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_call )* ) )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$block:ident;
|
||||
$uncheckedextrinsic:ident;
|
||||
$( $parsed_name:ident :: $parsed_call:ident ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$crate::__decl_outer_inherent!(
|
||||
$runtime;
|
||||
$block;
|
||||
$uncheckedextrinsic;
|
||||
$( $parsed_name :: $parsed_call ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_call )* ) )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$block:ident;
|
||||
$uncheckedextrinsic:ident;
|
||||
$( $parsed_name:ident :: $parsed_call:ident ),*;
|
||||
;
|
||||
) => {
|
||||
$crate::impl_outer_inherent!(
|
||||
impl Inherents where Block = $block, UncheckedExtrinsic = $uncheckedextrinsic {
|
||||
$( $parsed_name : $parsed_call, )*
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
// Those imports are used by event, config, origin and log macros to get access to its inner type
|
||||
macro_rules! __decl_instance_import {
|
||||
( $( $module:ident <$instance:ident> )* ) => {
|
||||
$crate::paste::item! {
|
||||
$(use $module as [< $module _ $instance >];)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A private macro that calls impl_outer_validate_unsigned for Call.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __impl_outer_validate_unsigned {
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $(<$module_instance:ident>::)? {
|
||||
ValidateUnsigned $( $modules:ident $( ( $( $modules_args:ident )* ) )* )*
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__impl_outer_validate_unsigned!(
|
||||
$runtime;
|
||||
{ $( $parsed )* $name };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $(<$module_instance:ident>::)? {
|
||||
$ignore:ident $( ( $( $args_ignore:ident )* ) )*
|
||||
$( $modules:ident $( ( $( $modules_args:ident )* ) )* )*
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__impl_outer_validate_unsigned!(
|
||||
$runtime;
|
||||
{ $( $parsed )* };
|
||||
$name: $module:: $(<$module_instance>::)? {
|
||||
$( $modules $( ( $( $modules_args )* ) )* )*
|
||||
}
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $( $parsed:tt )* };
|
||||
$name:ident: $module:ident:: $(<$module_instance:ident>::)? {}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::__impl_outer_validate_unsigned!(
|
||||
$runtime;
|
||||
{ $( $parsed )* };
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
{ $(
|
||||
$parsed_modules:ident
|
||||
)* };
|
||||
) => {
|
||||
$crate::impl_outer_validate_unsigned!(
|
||||
impl ValidateUnsigned for $runtime {
|
||||
$( $parsed_modules )*
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
use std::env;
|
||||
|
||||
#[test]
|
||||
fn ui() {
|
||||
// As trybuild is using `cargo check`, we don't need the real WASM binaries.
|
||||
env::set_var("BUILD_DUMMY_WASM_BINARY", "1");
|
||||
|
||||
let t = trybuild::TestCases::new();
|
||||
t.compile_fail("tests/construct_runtime_ui/*.rs");
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
Block = Block1,
|
||||
UncheckedExtrinsic = Uxt,
|
||||
{}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: `Block` was declared above. Please use exactly one delcataion for `Block`.
|
||||
--> $DIR/abundant_where_param.rs:7:3
|
||||
|
|
||||
7 | Block = Block1,
|
||||
| ^^^^^
|
||||
@@ -0,0 +1,14 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
Balance: balances::{Config, Call, Config<T>, Origin<T>},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: `Config` was already declared before. Please remove the duplicate declaration
|
||||
--> $DIR/double_module_parts.rs:10:37
|
||||
|
|
||||
10 | Balance: balances::{Config, Call, Config<T>, Origin<T>},
|
||||
| ^^^^^^
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
Balance: balances::{default, Config},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: `Config` is already included in `default`. Either remove `default` or remove `Config`
|
||||
--> $DIR/double_module_parts_default.rs:10:32
|
||||
|
|
||||
10 | Balance: balances::{default, Config},
|
||||
| ^^^^^^
|
||||
@@ -0,0 +1,14 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
Balance: balances::<Instance1>::{Call<T>, Origin<T>},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: `Call` is not allowed to have generics. Only the following modules are allowed to have generics: `Event`, `Origin`, `Config`.
|
||||
--> $DIR/generics_in_invalid_module.rs:10:36
|
||||
|
|
||||
10 | Balance: balances::<Instance1>::{Call<T>, Origin<T>},
|
||||
| ^^^^
|
||||
@@ -0,0 +1,13 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
system: System::(),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: expected curly braces
|
||||
--> $DIR/invalid_module_details.rs:9:19
|
||||
|
|
||||
9 | system: System::(),
|
||||
| ^^
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
system: System::{enum},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: expected `default` or identifier
|
||||
--> $DIR/invalid_module_details_keyword.rs:9:20
|
||||
|
|
||||
9 | system: System::{enum},
|
||||
| ^^^^
|
||||
@@ -0,0 +1,13 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
system: System ?
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: expected `,`
|
||||
--> $DIR/invalid_token_after_module.rs:9:18
|
||||
|
|
||||
9 | system: System ?
|
||||
| ^
|
||||
@@ -0,0 +1,13 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
system ?
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: expected `:`
|
||||
--> $DIR/invalid_token_after_name.rs:9:10
|
||||
|
|
||||
9 | system ?
|
||||
| ^
|
||||
@@ -0,0 +1,12 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
TypeX = Block,
|
||||
UnchekcedExtrinsic = UnchekcedExtrinsic,
|
||||
{}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: expected one of: `Block`, `NodeBlock`, `UncheckedExtrinsic`
|
||||
--> $DIR/invalid_where_param.rs:7:3
|
||||
|
|
||||
7 | TypeX = Block,
|
||||
| ^^^^^
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
Balance: balances::<Instance1>::{Event},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: Instantiable module with no generic `Event` cannot be constructed: module `Balance` must have generic `Event`
|
||||
--> $DIR/missing_event_generic_on_module_with_instance.rs:10:3
|
||||
|
|
||||
10 | Balance: balances::<Instance1>::{Event},
|
||||
| ^^^^^^^
|
||||
@@ -0,0 +1,13 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
system: System::<>,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: expected identifier
|
||||
--> $DIR/missing_module_instance.rs:9:20
|
||||
|
|
||||
9 | system: System::<>,
|
||||
| ^
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
Balance: balances::<Instance1>::{Origin},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: Instantiable module with no generic `Origin` cannot be constructed: module `Balance` must have generic `Origin`
|
||||
--> $DIR/missing_origin_generic_on_module_with_instance.rs:10:3
|
||||
|
|
||||
10 | Balance: balances::<Instance1>::{Origin},
|
||||
| ^^^^^^^
|
||||
@@ -0,0 +1,12 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,7 @@
|
||||
error: `System` module declaration is missing. Please add this line: `System: system::{Module, Call, Storage, Config, Event},`
|
||||
--> $DIR/missing_system_module.rs:8:2
|
||||
|
|
||||
8 | {
|
||||
| _____^
|
||||
9 | | }
|
||||
| |_____^
|
||||
@@ -0,0 +1,7 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: expected `where`
|
||||
--> $DIR/missing_where_block.rs:4:19
|
||||
|
|
||||
4 | pub enum Runtime {}
|
||||
| ^^
|
||||
@@ -0,0 +1,10 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
{}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Missing associated type for `UncheckedExtrinsic`. Add `UncheckedExtrinsic` = ... to where section.
|
||||
--> $DIR/missing_where_param.rs:7:2
|
||||
|
|
||||
7 | {}
|
||||
| ^^
|
||||
@@ -0,0 +1,13 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
{
|
||||
System: system,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Expected `,` or `{`
|
||||
--> $DIR/no_comma_after_where.rs:6:3
|
||||
|
|
||||
6 | Block = Block,
|
||||
| ^^^^^
|
||||
@@ -0,0 +1,14 @@
|
||||
use support::construct_runtime;
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
Balance: balances::<Instance1>::{Call(toto), Origin<I>},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: `Call` is not allowed to have arguments in parens. Only the following modules are allowed to have arguments in parens: `Inherent`.
|
||||
--> $DIR/params_in_invalid_module.rs:10:40
|
||||
|
|
||||
10 | Balance: balances::<Instance1>::{Call(toto), Origin<I>},
|
||||
| ^^^^^^
|
||||
Reference in New Issue
Block a user