mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 10:27:59 +00:00
Allow usage of path in construct_runtime! (#8801)
* Allow usage of path in construct_runtime! * Fix whitespace * Fix whitespace * Make expand_runtime_metadata accept slice instead of Iterator * Include Call and Event in construct_runtime for testing * Migrate impl_outer_event to proc macro * Fix integrity_test_works * Update UI test expectations * Factor in module path while generating enum variant or fn names * Use ParseStream::lookahead for more helpful error messages * Remove generating outer_event_metadata * Ensure pallets with different paths but same last path segment can coexist * Remove unnecessary generated function * Migrate decl_outer_config to proc macro * Add default_filter test for expand_outer_origin * Allow crate, self and super keywords to appear in pallet path * Add UI test for specifying empty pallet paths in construct_runtime
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2021 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::construct_runtime::Pallet;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::Ident;
|
||||
|
||||
pub fn expand_outer_config(
|
||||
runtime: &Ident,
|
||||
pallet_decls: &[Pallet],
|
||||
scrate: &TokenStream,
|
||||
) -> TokenStream {
|
||||
let mut types = TokenStream::new();
|
||||
let mut fields = TokenStream::new();
|
||||
let mut build_storage_calls = TokenStream::new();
|
||||
|
||||
for decl in pallet_decls {
|
||||
if let Some(pallet_entry) = decl.find_part("Config") {
|
||||
let config = format_ident!("{}Config", decl.name);
|
||||
let mod_name = decl.pallet.mod_name();
|
||||
let field_name = if let Some(inst) = decl.instance.as_ref() {
|
||||
format_ident!("{}_{}", mod_name, inst)
|
||||
} else {
|
||||
mod_name
|
||||
};
|
||||
let part_is_generic = !pallet_entry.generics.params.is_empty();
|
||||
|
||||
types.extend(expand_config_types(runtime, decl, &config, part_is_generic));
|
||||
fields.extend(quote!(pub #field_name: #config,));
|
||||
build_storage_calls.extend(expand_config_build_storage_call(scrate, runtime, decl, &field_name));
|
||||
}
|
||||
}
|
||||
|
||||
quote!{
|
||||
#types
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use #scrate::serde as __genesis_config_serde_import__;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
#[derive(#scrate::serde::Serialize, #scrate::serde::Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[serde(crate = "__genesis_config_serde_import__")]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct GenesisConfig {
|
||||
#fields
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl #scrate::sp_runtime::BuildStorage for GenesisConfig {
|
||||
fn assimilate_storage(
|
||||
&self,
|
||||
storage: &mut #scrate::sp_runtime::Storage,
|
||||
) -> std::result::Result<(), String> {
|
||||
#build_storage_calls
|
||||
|
||||
#scrate::BasicExternalities::execute_with_storage(storage, || {
|
||||
<AllPalletsWithSystem as #scrate::traits::OnGenesis>::on_genesis();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_config_types(
|
||||
runtime: &Ident,
|
||||
decl: &Pallet,
|
||||
config: &Ident,
|
||||
part_is_generic: bool,
|
||||
) -> TokenStream {
|
||||
let path = &decl.pallet;
|
||||
|
||||
match (decl.instance.as_ref(), part_is_generic) {
|
||||
(Some(inst), true) => quote!{
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type #config = #path::GenesisConfig<#runtime, #path::#inst>;
|
||||
},
|
||||
(None, true) => quote!{
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type #config = #path::GenesisConfig<#runtime>;
|
||||
},
|
||||
(_, false) => quote!{
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type #config = #path::GenesisConfig;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_config_build_storage_call(
|
||||
scrate: &TokenStream,
|
||||
runtime: &Ident,
|
||||
decl: &Pallet,
|
||||
field_name: &Ident,
|
||||
) -> TokenStream {
|
||||
let path = &decl.pallet;
|
||||
let instance = if let Some(inst) = decl.instance.as_ref() {
|
||||
quote!(#path::#inst)
|
||||
} else {
|
||||
quote!(#path::__InherentHiddenInstance)
|
||||
};
|
||||
|
||||
quote!{
|
||||
#scrate::sp_runtime::BuildModuleGenesisStorage::
|
||||
<#runtime, #instance>::build_module_genesis_storage(&self.#field_name, storage)?;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2021 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::construct_runtime::{Pallet, parse::PalletPath};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{Generics, Ident};
|
||||
|
||||
pub fn expand_outer_event(
|
||||
runtime: &Ident,
|
||||
pallet_decls: &[Pallet],
|
||||
scrate: &TokenStream,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let mut event_variants = TokenStream::new();
|
||||
let mut event_conversions = TokenStream::new();
|
||||
let mut events_metadata = TokenStream::new();
|
||||
|
||||
for pallet_decl in pallet_decls {
|
||||
if let Some(pallet_entry) = pallet_decl.find_part("Event") {
|
||||
let path = &pallet_decl.pallet;
|
||||
let index = pallet_decl.index;
|
||||
let instance = pallet_decl.instance.as_ref();
|
||||
let generics = &pallet_entry.generics;
|
||||
|
||||
if instance.is_some() && generics.params.is_empty() {
|
||||
let msg = format!(
|
||||
"Instantiable pallet with no generic `Event` cannot \
|
||||
be constructed: pallet `{}` must have generic `Event`",
|
||||
pallet_decl.name,
|
||||
);
|
||||
return Err(syn::Error::new(pallet_decl.name.span(), msg));
|
||||
}
|
||||
|
||||
let part_is_generic = !generics.params.is_empty();
|
||||
let pallet_event = match (instance, part_is_generic) {
|
||||
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
|
||||
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
|
||||
(None, true) => quote!(#path::Event::<#runtime>),
|
||||
(None, false) => quote!(#path::Event),
|
||||
};
|
||||
|
||||
event_variants.extend(expand_event_variant(runtime, path, index, instance, generics));
|
||||
event_conversions.extend(expand_event_conversion(scrate, path, instance, &pallet_event));
|
||||
events_metadata.extend(expand_event_metadata(scrate, path, &pallet_event));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(quote!{
|
||||
#[derive(
|
||||
Clone, PartialEq, Eq,
|
||||
#scrate::codec::Encode,
|
||||
#scrate::codec::Decode,
|
||||
#scrate::RuntimeDebug,
|
||||
)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Event {
|
||||
#event_variants
|
||||
}
|
||||
|
||||
#event_conversions
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_event_variant(
|
||||
runtime: &Ident,
|
||||
path: &PalletPath,
|
||||
index: u8,
|
||||
instance: Option<&Ident>,
|
||||
generics: &Generics,
|
||||
) -> TokenStream {
|
||||
let part_is_generic = !generics.params.is_empty();
|
||||
let mod_name = &path.mod_name();
|
||||
|
||||
match (instance, part_is_generic) {
|
||||
(Some(inst), true) => {
|
||||
let variant = format_ident!("{}_{}", mod_name, inst);
|
||||
quote!(#[codec(index = #index)] #variant(#path::Event<#runtime, #path::#inst>),)
|
||||
}
|
||||
(Some(inst), false) => {
|
||||
let variant = format_ident!("{}_{}", mod_name, inst);
|
||||
quote!(#[codec(index = #index)] #variant(#path::Event<#path::#inst>),)
|
||||
}
|
||||
(None, true) => {
|
||||
quote!(#[codec(index = #index)] #mod_name(#path::Event<#runtime>),)
|
||||
}
|
||||
(None, false) => {
|
||||
quote!(#[codec(index = #index)] #mod_name(#path::Event),)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_event_conversion(
|
||||
scrate: &TokenStream,
|
||||
path: &PalletPath,
|
||||
instance: Option<&Ident>,
|
||||
pallet_event: &TokenStream,
|
||||
) -> TokenStream {
|
||||
let mod_name = path.mod_name();
|
||||
let variant = if let Some(inst) = instance {
|
||||
format_ident!("{}_{}", mod_name, inst)
|
||||
} else {
|
||||
mod_name
|
||||
};
|
||||
|
||||
quote!{
|
||||
impl From<#pallet_event> for Event {
|
||||
fn from(x: #pallet_event) -> Self {
|
||||
Event::#variant(x)
|
||||
}
|
||||
}
|
||||
impl #scrate::sp_std::convert::TryInto<#pallet_event> for Event {
|
||||
type Error = ();
|
||||
|
||||
fn try_into(self) -> #scrate::sp_std::result::Result<#pallet_event, Self::Error> {
|
||||
match self {
|
||||
Self::#variant(evt) => Ok(evt),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_event_metadata(
|
||||
scrate: &TokenStream,
|
||||
path: &PalletPath,
|
||||
pallet_event: &TokenStream,
|
||||
) -> TokenStream {
|
||||
let mod_name = path.mod_name();
|
||||
|
||||
quote!{(stringify!(#mod_name), #scrate::event::FnEncode(#pallet_event::metadata)),}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2021 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 proc_macro2::TokenStream;
|
||||
use crate::construct_runtime::Pallet;
|
||||
use syn::{Ident, TypePath};
|
||||
use quote::quote;
|
||||
|
||||
pub fn expand_runtime_metadata(
|
||||
runtime: &Ident,
|
||||
pallet_declarations: &[Pallet],
|
||||
scrate: &TokenStream,
|
||||
extrinsic: &TypePath,
|
||||
) -> TokenStream {
|
||||
let modules = pallet_declarations
|
||||
.iter()
|
||||
.filter_map(|pallet_declaration| {
|
||||
pallet_declaration.find_part("Pallet").map(|_| {
|
||||
let filtered_names: Vec<_> = pallet_declaration
|
||||
.pallet_parts()
|
||||
.iter()
|
||||
.filter(|part| part.name() != "Pallet")
|
||||
.map(|part| part.name())
|
||||
.collect();
|
||||
(pallet_declaration, filtered_names)
|
||||
})
|
||||
})
|
||||
.map(|(decl, filtered_names)| {
|
||||
let name = &decl.name;
|
||||
let index = &decl.index;
|
||||
let storage = expand_pallet_metadata_storage(&filtered_names, runtime, scrate, decl);
|
||||
let calls = expand_pallet_metadata_calls(&filtered_names, runtime, scrate, decl);
|
||||
let event = expand_pallet_metadata_events(&filtered_names, runtime, scrate, decl);
|
||||
let constants = expand_pallet_metadata_constants(runtime, scrate, decl);
|
||||
let errors = expand_pallet_metadata_errors(runtime, scrate, decl);
|
||||
|
||||
quote!{
|
||||
#scrate::metadata::ModuleMetadata {
|
||||
name: #scrate::metadata::DecodeDifferent::Encode(stringify!(#name)),
|
||||
index: #index,
|
||||
storage: #storage,
|
||||
calls: #calls,
|
||||
event: #event,
|
||||
constants: #constants,
|
||||
errors: #errors,
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote!{
|
||||
impl #runtime {
|
||||
pub fn metadata() -> #scrate::metadata::RuntimeMetadataPrefixed {
|
||||
#scrate::metadata::RuntimeMetadataLastVersion {
|
||||
modules: #scrate::metadata::DecodeDifferent::Encode(&[ #(#modules),* ]),
|
||||
extrinsic: #scrate::metadata::ExtrinsicMetadata {
|
||||
version: <#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata>::VERSION,
|
||||
signed_extensions: <
|
||||
<
|
||||
#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata
|
||||
>::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension
|
||||
>::identifier()
|
||||
.into_iter()
|
||||
.map(#scrate::metadata::DecodeDifferent::Encode)
|
||||
.collect(),
|
||||
},
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_pallet_metadata_storage(
|
||||
filtered_names: &[&'static str],
|
||||
runtime: &Ident,
|
||||
scrate: &TokenStream,
|
||||
decl: &Pallet,
|
||||
) -> TokenStream {
|
||||
if filtered_names.contains(&"Storage") {
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
let path = &decl.pallet;
|
||||
|
||||
quote!{
|
||||
Some(#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
#path::Pallet::<#runtime #(, #path::#instance)*>::storage_metadata
|
||||
)
|
||||
))
|
||||
}
|
||||
} else {
|
||||
quote!(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_pallet_metadata_calls(
|
||||
filtered_names: &[&'static str],
|
||||
runtime: &Ident,
|
||||
scrate: &TokenStream,
|
||||
decl: &Pallet,
|
||||
) -> TokenStream {
|
||||
if filtered_names.contains(&"Call") {
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
let path = &decl.pallet;
|
||||
|
||||
quote!{
|
||||
Some(#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
#path::Pallet::<#runtime #(, #path::#instance)*>::call_functions
|
||||
)
|
||||
))
|
||||
}
|
||||
} else {
|
||||
quote!(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_pallet_metadata_events(
|
||||
filtered_names: &[&'static str],
|
||||
runtime: &Ident,
|
||||
scrate: &TokenStream,
|
||||
decl: &Pallet,
|
||||
) -> TokenStream {
|
||||
if filtered_names.contains(&"Event") {
|
||||
let path = &decl.pallet;
|
||||
let part_is_generic =
|
||||
!decl.find_part("Event").expect("Event part exists; qed").generics.params.is_empty();
|
||||
let pallet_event = match (decl.instance.as_ref(), part_is_generic) {
|
||||
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
|
||||
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
|
||||
(None, true) => quote!(#path::Event::<#runtime>),
|
||||
(None, false) => quote!(#path::Event),
|
||||
};
|
||||
|
||||
quote!{
|
||||
Some(#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(#pallet_event::metadata)
|
||||
))
|
||||
}
|
||||
} else {
|
||||
quote!(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_pallet_metadata_constants(
|
||||
runtime: &Ident,
|
||||
scrate: &TokenStream,
|
||||
decl: &Pallet,
|
||||
) -> TokenStream {
|
||||
let path = &decl.pallet;
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
|
||||
quote!{
|
||||
#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
#path::Pallet::<#runtime #(, #path::#instance)*>::module_constants_metadata
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_pallet_metadata_errors(
|
||||
runtime: &Ident,
|
||||
scrate: &TokenStream,
|
||||
decl: &Pallet,
|
||||
) -> TokenStream {
|
||||
let path = &decl.pallet;
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
|
||||
quote!{
|
||||
#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
<#path::Pallet::<#runtime #(, #path::#instance)*> as #scrate::metadata::ModuleErrorMetadata>::metadata
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2021 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
|
||||
|
||||
mod config;
|
||||
mod event;
|
||||
mod metadata;
|
||||
mod origin;
|
||||
|
||||
pub use config::expand_outer_config;
|
||||
pub use event::expand_outer_event;
|
||||
pub use metadata::expand_runtime_metadata;
|
||||
pub use origin::expand_outer_origin;
|
||||
@@ -0,0 +1,341 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2021 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::construct_runtime::{parse::PalletPath, Pallet, SYSTEM_PALLET_NAME};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{token, Ident, Generics};
|
||||
|
||||
pub fn expand_outer_origin(
|
||||
runtime: &Ident,
|
||||
pallets: &[Pallet],
|
||||
pallets_token: token::Brace,
|
||||
scrate: &TokenStream,
|
||||
) -> syn::Result<TokenStream> {
|
||||
let system_pallet = pallets.iter()
|
||||
.find(|decl| decl.name == SYSTEM_PALLET_NAME)
|
||||
.ok_or_else(|| syn::Error::new(
|
||||
pallets_token.span,
|
||||
"`System` pallet declaration is missing. \
|
||||
Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
|
||||
))?;
|
||||
|
||||
let mut caller_variants = TokenStream::new();
|
||||
let mut pallet_conversions = TokenStream::new();
|
||||
|
||||
for pallet_decl in pallets.iter().filter(|pallet| pallet.name != SYSTEM_PALLET_NAME) {
|
||||
if let Some(pallet_entry) = pallet_decl.find_part("Origin") {
|
||||
let path = &pallet_decl.pallet;
|
||||
let instance = pallet_decl.instance.as_ref();
|
||||
let index = pallet_decl.index;
|
||||
let generics = &pallet_entry.generics;
|
||||
|
||||
if instance.is_some() && generics.params.is_empty() {
|
||||
let msg = format!(
|
||||
"Instantiable pallet with no generic `Origin` cannot \
|
||||
be constructed: pallet `{}` must have generic `Origin`",
|
||||
pallet_decl.name
|
||||
);
|
||||
return Err(syn::Error::new(pallet_decl.name.span(), msg));
|
||||
}
|
||||
|
||||
caller_variants.extend(
|
||||
expand_origin_caller_variant(runtime, path, index, instance, generics),
|
||||
);
|
||||
pallet_conversions.extend(
|
||||
expand_origin_pallet_conversions(scrate, runtime, path, instance, generics),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let system_path = &system_pallet.pallet;
|
||||
let system_index = system_pallet.index;
|
||||
|
||||
Ok(quote!{
|
||||
// WARNING: All instance must hold the filter `frame_system::Config::BaseCallFilter`, except
|
||||
// when caller is system Root. One can use `OriginTrait::reset_filter` to do so.
|
||||
#[derive(Clone)]
|
||||
pub struct Origin {
|
||||
caller: OriginCaller,
|
||||
filter: #scrate::sp_std::rc::Rc<Box<dyn Fn(&<#runtime as #system_path::Config>::Call) -> bool>>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl #scrate::sp_std::fmt::Debug for Origin {
|
||||
fn fmt(
|
||||
&self,
|
||||
fmt: &mut #scrate::sp_std::fmt::Formatter,
|
||||
) -> #scrate::sp_std::result::Result<(), #scrate::sp_std::fmt::Error> {
|
||||
fmt.write_str("<wasm:stripped>")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl #scrate::sp_std::fmt::Debug for Origin {
|
||||
fn fmt(
|
||||
&self,
|
||||
fmt: &mut #scrate::sp_std::fmt::Formatter,
|
||||
) -> #scrate::sp_std::result::Result<(), #scrate::sp_std::fmt::Error> {
|
||||
fmt.debug_struct("Origin")
|
||||
.field("caller", &self.caller)
|
||||
.field("filter", &"[function ptr]")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl #scrate::traits::OriginTrait for Origin {
|
||||
type Call = <#runtime as #system_path::Config>::Call;
|
||||
type PalletsOrigin = OriginCaller;
|
||||
type AccountId = <#runtime as #system_path::Config>::AccountId;
|
||||
|
||||
fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static) {
|
||||
let f = self.filter.clone();
|
||||
|
||||
self.filter = #scrate::sp_std::rc::Rc::new(Box::new(move |call| {
|
||||
f(call) && filter(call)
|
||||
}));
|
||||
}
|
||||
|
||||
fn reset_filter(&mut self) {
|
||||
let filter = <
|
||||
<#runtime as #system_path::Config>::BaseCallFilter
|
||||
as #scrate::traits::Filter<<#runtime as #system_path::Config>::Call>
|
||||
>::filter;
|
||||
|
||||
self.filter = #scrate::sp_std::rc::Rc::new(Box::new(filter));
|
||||
}
|
||||
|
||||
fn set_caller_from(&mut self, other: impl Into<Self>) {
|
||||
self.caller = other.into().caller;
|
||||
}
|
||||
|
||||
fn filter_call(&self, call: &Self::Call) -> bool {
|
||||
(self.filter)(call)
|
||||
}
|
||||
|
||||
fn caller(&self) -> &Self::PalletsOrigin {
|
||||
&self.caller
|
||||
}
|
||||
|
||||
fn try_with_caller<R>(
|
||||
mut self,
|
||||
f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
|
||||
) -> Result<R, Self> {
|
||||
match f(self.caller) {
|
||||
Ok(r) => Ok(r),
|
||||
Err(caller) => { self.caller = caller; Err(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Create with system none origin and `frame-system::Config::BaseCallFilter`.
|
||||
fn none() -> Self {
|
||||
#system_path::RawOrigin::None.into()
|
||||
}
|
||||
/// Create with system root origin and no filter.
|
||||
fn root() -> Self {
|
||||
#system_path::RawOrigin::Root.into()
|
||||
}
|
||||
/// Create with system signed origin and `frame-system::Config::BaseCallFilter`.
|
||||
fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self {
|
||||
#system_path::RawOrigin::Signed(by).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, #scrate::RuntimeDebug, #scrate::codec::Encode, #scrate::codec::Decode)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum OriginCaller {
|
||||
#[codec(index = #system_index)]
|
||||
system(#system_path::Origin<#runtime>),
|
||||
#caller_variants
|
||||
#[allow(dead_code)]
|
||||
Void(#scrate::Void)
|
||||
}
|
||||
|
||||
// For backwards compatibility and ease of accessing these functions.
|
||||
#[allow(dead_code)]
|
||||
impl Origin {
|
||||
/// Create with system none origin and `frame-system::Config::BaseCallFilter`.
|
||||
pub fn none() -> Self {
|
||||
<Origin as #scrate::traits::OriginTrait>::none()
|
||||
}
|
||||
/// Create with system root origin and no filter.
|
||||
pub fn root() -> Self {
|
||||
<Origin as #scrate::traits::OriginTrait>::root()
|
||||
}
|
||||
/// Create with system signed origin and `frame-system::Config::BaseCallFilter`.
|
||||
pub fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self {
|
||||
<Origin as #scrate::traits::OriginTrait>::signed(by)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<#system_path::Origin<#runtime>> for OriginCaller {
|
||||
fn from(x: #system_path::Origin<#runtime>) -> Self {
|
||||
OriginCaller::system(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl #scrate::sp_std::convert::TryFrom<OriginCaller> for #system_path::Origin<#runtime> {
|
||||
type Error = OriginCaller;
|
||||
fn try_from(x: OriginCaller)
|
||||
-> #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, OriginCaller>
|
||||
{
|
||||
if let OriginCaller::system(l) = x {
|
||||
Ok(l)
|
||||
} else {
|
||||
Err(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<#system_path::Origin<#runtime>> for Origin {
|
||||
/// Convert to runtime origin:
|
||||
/// * root origin is built with no filter
|
||||
/// * others use `frame-system::Config::BaseCallFilter`
|
||||
fn from(x: #system_path::Origin<#runtime>) -> Self {
|
||||
let o: OriginCaller = x.into();
|
||||
o.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OriginCaller> for Origin {
|
||||
fn from(x: OriginCaller) -> Self {
|
||||
let mut o = Origin {
|
||||
caller: x,
|
||||
filter: #scrate::sp_std::rc::Rc::new(Box::new(|_| true)),
|
||||
};
|
||||
|
||||
// Root has no filter
|
||||
if !matches!(o.caller, OriginCaller::system(#system_path::Origin::<#runtime>::Root)) {
|
||||
#scrate::traits::OriginTrait::reset_filter(&mut o);
|
||||
}
|
||||
|
||||
o
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<#scrate::sp_std::result::Result<#system_path::Origin<#runtime>, Origin>> for Origin {
|
||||
/// NOTE: converting to pallet origin loses the origin filter information.
|
||||
fn into(self) -> #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, Self> {
|
||||
if let OriginCaller::system(l) = self.caller {
|
||||
Ok(l)
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<Option<<#runtime as #system_path::Config>::AccountId>> for Origin {
|
||||
/// Convert to runtime origin with caller being system signed or none and use filter
|
||||
/// `frame-system::Config::BaseCallFilter`.
|
||||
fn from(x: Option<<#runtime as #system_path::Config>::AccountId>) -> Self {
|
||||
<#system_path::Origin<#runtime>>::from(x).into()
|
||||
}
|
||||
}
|
||||
|
||||
#pallet_conversions
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_origin_caller_variant(
|
||||
runtime: &Ident,
|
||||
path: &PalletPath,
|
||||
index: u8,
|
||||
instance: Option<&Ident>,
|
||||
generics: &Generics,
|
||||
) -> TokenStream {
|
||||
let part_is_generic = !generics.params.is_empty();
|
||||
let mod_name = &path.mod_name();
|
||||
|
||||
match (instance, part_is_generic) {
|
||||
(Some(inst), true) => {
|
||||
let variant = format_ident!("{}_{}", mod_name, inst);
|
||||
quote!(#[codec(index = #index)] #variant(#path::Origin<#runtime, #path::#inst>),)
|
||||
}
|
||||
(Some(inst), false) => {
|
||||
let variant = format_ident!("{}_{}", mod_name, inst);
|
||||
quote!(#[codec(index = #index)] #variant(#path::Origin<#path::#inst>),)
|
||||
}
|
||||
(None, true) => {
|
||||
quote!(#[codec(index = #index)] #mod_name(#path::Origin<#runtime>),)
|
||||
}
|
||||
(None, false) => {
|
||||
quote!(#[codec(index = #index)] #mod_name(#path::Origin),)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_origin_pallet_conversions(
|
||||
scrate: &TokenStream,
|
||||
runtime: &Ident,
|
||||
path: &PalletPath,
|
||||
instance: Option<&Ident>,
|
||||
generics: &Generics,
|
||||
) -> TokenStream {
|
||||
let mod_name = path.mod_name();
|
||||
let variant = if let Some(inst) = instance {
|
||||
format_ident!("{}_{}", mod_name, inst)
|
||||
} else {
|
||||
mod_name
|
||||
};
|
||||
|
||||
let part_is_generic = !generics.params.is_empty();
|
||||
let pallet_origin = match (instance, part_is_generic) {
|
||||
(Some(inst), true) => quote!(#path::Origin<#runtime, #path::#inst>),
|
||||
(Some(inst), false) => quote!(#path::Origin<#path::#inst>),
|
||||
(None, true) => quote!(#path::Origin<#runtime>),
|
||||
(None, false) => quote!(#path::Origin),
|
||||
};
|
||||
|
||||
quote!{
|
||||
impl From<#pallet_origin> for OriginCaller {
|
||||
fn from(x: #pallet_origin) -> Self {
|
||||
OriginCaller::#variant(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<#pallet_origin> for Origin {
|
||||
/// Convert to runtime origin using `frame-system::Config::BaseCallFilter`.
|
||||
fn from(x: #pallet_origin) -> Self {
|
||||
let x: OriginCaller = x.into();
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<#scrate::sp_std::result::Result<#pallet_origin, Origin>> for Origin {
|
||||
/// NOTE: converting to pallet origin loses the origin filter information.
|
||||
fn into(self) -> #scrate::sp_std::result::Result<#pallet_origin, Self> {
|
||||
if let OriginCaller::#variant(l) = self.caller {
|
||||
Ok(l)
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl #scrate::sp_std::convert::TryFrom<OriginCaller> for #pallet_origin {
|
||||
type Error = OriginCaller;
|
||||
fn try_from(
|
||||
x: OriginCaller,
|
||||
) -> #scrate::sp_std::result::Result<#pallet_origin, OriginCaller> {
|
||||
if let OriginCaller::#variant(l) = x {
|
||||
Ok(l)
|
||||
} else {
|
||||
Err(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,15 +15,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod expand;
|
||||
mod parse;
|
||||
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use frame_support_procedural_tools::{generate_crate_access, generate_hidden_includes};
|
||||
use parse::{PalletDeclaration, RuntimeDefinition, WhereSection, PalletPart};
|
||||
use parse::{PalletDeclaration, PalletPart, PalletPath, RuntimeDefinition, WhereSection};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{TokenStream as TokenStream2};
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use syn::{Ident, Result, TypePath};
|
||||
use syn::{Ident, Result};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// The fixed name of the system pallet.
|
||||
@@ -34,7 +35,7 @@ const SYSTEM_PALLET_NAME: &str = "System";
|
||||
pub struct Pallet {
|
||||
pub name: Ident,
|
||||
pub index: u8,
|
||||
pub pallet: Ident,
|
||||
pub pallet: PalletPath,
|
||||
pub instance: Option<Ident>,
|
||||
pub pallet_parts: Vec<PalletPart>,
|
||||
}
|
||||
@@ -134,38 +135,19 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
|
||||
|
||||
let pallets = complete_pallets(pallets.into_iter())?;
|
||||
|
||||
let system_pallet = pallets.iter()
|
||||
.find(|decl| decl.name == SYSTEM_PALLET_NAME)
|
||||
.ok_or_else(|| syn::Error::new(
|
||||
pallets_token.span,
|
||||
"`System` pallet declaration is missing. \
|
||||
Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
|
||||
))?;
|
||||
|
||||
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_pallets = pallets.iter().filter(|pallet| pallet.name != SYSTEM_PALLET_NAME);
|
||||
let outer_event = expand::expand_outer_event(&name, &pallets, &scrate)?;
|
||||
|
||||
let outer_event = decl_outer_event(
|
||||
&name,
|
||||
pallets.iter(),
|
||||
&scrate,
|
||||
)?;
|
||||
|
||||
let outer_origin = decl_outer_origin(
|
||||
&name,
|
||||
all_but_system_pallets,
|
||||
&system_pallet,
|
||||
&scrate,
|
||||
)?;
|
||||
let outer_origin = expand::expand_outer_origin(&name, &pallets, pallets_token, &scrate)?;
|
||||
let all_pallets = decl_all_pallets(&name, pallets.iter());
|
||||
let pallet_to_index = decl_pallet_runtime_setup(&pallets, &scrate);
|
||||
|
||||
let dispatch = decl_outer_dispatch(&name, pallets.iter(), &scrate);
|
||||
let metadata = decl_runtime_metadata(&name, pallets.iter(), &scrate, &unchecked_extrinsic);
|
||||
let outer_config = decl_outer_config(&name, pallets.iter(), &scrate);
|
||||
let metadata = expand::expand_runtime_metadata(&name, &pallets, &scrate, &unchecked_extrinsic);
|
||||
let outer_config = expand::expand_outer_config(&name, &pallets, &scrate);
|
||||
let inherent = decl_outer_inherent(
|
||||
&name,
|
||||
&block,
|
||||
@@ -262,85 +244,6 @@ fn decl_outer_inherent<'a>(
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_outer_config<'a>(
|
||||
runtime: &'a Ident,
|
||||
pallet_declarations: impl Iterator<Item = &'a Pallet>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let pallets_tokens = pallet_declarations
|
||||
.filter_map(|pallet_declaration| {
|
||||
pallet_declaration.find_part("Config").map(|part| {
|
||||
let transformed_generics: Vec<_> = part
|
||||
.generics
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| quote!(<#param>))
|
||||
.collect();
|
||||
(pallet_declaration, transformed_generics)
|
||||
})
|
||||
})
|
||||
.map(|(pallet_declaration, generics)| {
|
||||
let pallet = &pallet_declaration.pallet;
|
||||
let name = Ident::new(
|
||||
&format!("{}Config", pallet_declaration.name),
|
||||
pallet_declaration.name.span(),
|
||||
);
|
||||
let instance = pallet_declaration.instance.as_ref().into_iter();
|
||||
quote!(
|
||||
#name =>
|
||||
#pallet #(#instance)* #(#generics)*,
|
||||
)
|
||||
});
|
||||
quote!(
|
||||
#scrate::impl_outer_config! {
|
||||
pub struct GenesisConfig for #runtime where AllPalletsWithSystem = AllPalletsWithSystem {
|
||||
#(#pallets_tokens)*
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_runtime_metadata<'a>(
|
||||
runtime: &'a Ident,
|
||||
pallet_declarations: impl Iterator<Item = &'a Pallet>,
|
||||
scrate: &'a TokenStream2,
|
||||
extrinsic: &TypePath,
|
||||
) -> TokenStream2 {
|
||||
let pallets_tokens = pallet_declarations
|
||||
.filter_map(|pallet_declaration| {
|
||||
pallet_declaration.find_part("Pallet").map(|_| {
|
||||
let filtered_names: Vec<_> = pallet_declaration
|
||||
.pallet_parts()
|
||||
.iter()
|
||||
.filter(|part| part.name() != "Pallet")
|
||||
.map(|part| part.ident())
|
||||
.collect();
|
||||
(pallet_declaration, filtered_names)
|
||||
})
|
||||
})
|
||||
.map(|(pallet_declaration, filtered_names)| {
|
||||
let pallet = &pallet_declaration.pallet;
|
||||
let name = &pallet_declaration.name;
|
||||
let instance = pallet_declaration
|
||||
.instance
|
||||
.as_ref()
|
||||
.map(|name| quote!(<#name>))
|
||||
.into_iter();
|
||||
|
||||
let index = pallet_declaration.index;
|
||||
|
||||
quote!(
|
||||
#pallet::Pallet #(#instance)* as #name { index #index } with #(#filtered_names)*,
|
||||
)
|
||||
});
|
||||
quote!(
|
||||
#scrate::impl_runtime_metadata!{
|
||||
for #runtime with pallets where Extrinsic = #extrinsic
|
||||
#(#pallets_tokens)*
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_outer_dispatch<'a>(
|
||||
runtime: &'a Ident,
|
||||
pallet_declarations: impl Iterator<Item = &'a Pallet>,
|
||||
@@ -349,7 +252,7 @@ fn decl_outer_dispatch<'a>(
|
||||
let pallets_tokens = pallet_declarations
|
||||
.filter(|pallet_declaration| pallet_declaration.exists_part("Call"))
|
||||
.map(|pallet_declaration| {
|
||||
let pallet = &pallet_declaration.pallet;
|
||||
let pallet = &pallet_declaration.pallet.inner.segments.last().unwrap();
|
||||
let name = &pallet_declaration.name;
|
||||
let index = pallet_declaration.index;
|
||||
quote!(#[codec(index = #index)] #pallet::#name)
|
||||
@@ -364,82 +267,6 @@ fn decl_outer_dispatch<'a>(
|
||||
)
|
||||
}
|
||||
|
||||
fn decl_outer_origin<'a>(
|
||||
runtime_name: &'a Ident,
|
||||
pallets_except_system: impl Iterator<Item = &'a Pallet>,
|
||||
system_pallet: &'a Pallet,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> syn::Result<TokenStream2> {
|
||||
let mut pallets_tokens = TokenStream2::new();
|
||||
for pallet_declaration in pallets_except_system {
|
||||
if let Some(pallet_entry) = pallet_declaration.find_part("Origin") {
|
||||
let pallet = &pallet_declaration.pallet;
|
||||
let instance = pallet_declaration.instance.as_ref();
|
||||
let generics = &pallet_entry.generics;
|
||||
if instance.is_some() && generics.params.is_empty() {
|
||||
let msg = format!(
|
||||
"Instantiable pallet with no generic `Origin` cannot \
|
||||
be constructed: pallet `{}` must have generic `Origin`",
|
||||
pallet_declaration.name
|
||||
);
|
||||
return Err(syn::Error::new(pallet_declaration.name.span(), msg));
|
||||
}
|
||||
let index = pallet_declaration.index;
|
||||
let tokens = quote!(#[codec(index = #index)] #pallet #instance #generics,);
|
||||
pallets_tokens.extend(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
let system_name = &system_pallet.pallet;
|
||||
let system_index = system_pallet.index;
|
||||
|
||||
Ok(quote!(
|
||||
#scrate::impl_outer_origin! {
|
||||
pub enum Origin for #runtime_name where
|
||||
system = #system_name,
|
||||
system_index = #system_index
|
||||
{
|
||||
#pallets_tokens
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
fn decl_outer_event<'a>(
|
||||
runtime_name: &'a Ident,
|
||||
pallet_declarations: impl Iterator<Item = &'a Pallet>,
|
||||
scrate: &'a TokenStream2,
|
||||
) -> syn::Result<TokenStream2> {
|
||||
let mut pallets_tokens = TokenStream2::new();
|
||||
for pallet_declaration in pallet_declarations {
|
||||
if let Some(pallet_entry) = pallet_declaration.find_part("Event") {
|
||||
let pallet = &pallet_declaration.pallet;
|
||||
let instance = pallet_declaration.instance.as_ref();
|
||||
let generics = &pallet_entry.generics;
|
||||
if instance.is_some() && generics.params.is_empty() {
|
||||
let msg = format!(
|
||||
"Instantiable pallet with no generic `Event` cannot \
|
||||
be constructed: pallet `{}` must have generic `Event`",
|
||||
pallet_declaration.name,
|
||||
);
|
||||
return Err(syn::Error::new(pallet_declaration.name.span(), msg));
|
||||
}
|
||||
|
||||
let index = pallet_declaration.index;
|
||||
let tokens = quote!(#[codec(index = #index)] #pallet #instance #generics,);
|
||||
pallets_tokens.extend(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(quote!(
|
||||
#scrate::impl_outer_event! {
|
||||
pub enum Event for #runtime_name {
|
||||
#pallets_tokens
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
fn decl_all_pallets<'a>(
|
||||
runtime: &'a Ident,
|
||||
pallet_declarations: impl Iterator<Item = &'a Pallet>,
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
// limitations under the License.
|
||||
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use proc_macro2::Span;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use std::collections::HashSet;
|
||||
use syn::{
|
||||
ext::IdentExt,
|
||||
parse::{Parse, ParseStream},
|
||||
punctuated::Punctuated,
|
||||
spanned::Spanned,
|
||||
token, Error, Ident, Result, Token,
|
||||
token, Error, Ident, Path, PathArguments, PathSegment, Result, Token,
|
||||
};
|
||||
|
||||
mod keyword {
|
||||
@@ -154,7 +156,7 @@ pub struct PalletDeclaration {
|
||||
pub name: Ident,
|
||||
/// Optional fixed index (e.g. `MyPallet ... = 3,`)
|
||||
pub index: Option<u8>,
|
||||
pub pallet: Ident,
|
||||
pub pallet: PalletPath,
|
||||
pub instance: Option<Ident>,
|
||||
pub pallet_parts: Vec<PalletPart>,
|
||||
}
|
||||
@@ -164,17 +166,16 @@ impl Parse for PalletDeclaration {
|
||||
let name = input.parse()?;
|
||||
let _: Token![:] = input.parse()?;
|
||||
let pallet = input.parse()?;
|
||||
let instance = if input.peek(Token![::]) && input.peek3(Token![<]) {
|
||||
let _: Token![::] = input.parse()?;
|
||||
let instance = if input.peek(Token![<]) {
|
||||
let _: Token![<] = input.parse()?;
|
||||
let res = Some(input.parse()?);
|
||||
let _: Token![>] = input.parse()?;
|
||||
let _: Token![::] = input.parse()?;
|
||||
res
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let _: Token![::] = input.parse()?;
|
||||
let pallet_parts = parse_pallet_parts(input)?;
|
||||
|
||||
let index = if input.peek(Token![=]) {
|
||||
@@ -198,6 +199,84 @@ impl Parse for PalletDeclaration {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct representing a path to a pallet. `PalletPath` is almost identical to the standard
|
||||
/// Rust path with a few restrictions:
|
||||
/// - No leading colons allowed
|
||||
/// - Path segments can only consist of identifers; angle-bracketed or parenthesized segments will
|
||||
/// result in a parsing error (except when specifying instances)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PalletPath {
|
||||
pub inner: Path,
|
||||
}
|
||||
|
||||
impl Parse for PalletPath {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let mut lookahead = input.lookahead1();
|
||||
let mut segments = Punctuated::new();
|
||||
|
||||
if lookahead.peek(Token![crate])
|
||||
|| lookahead.peek(Token![self])
|
||||
|| lookahead.peek(Token![super])
|
||||
|| lookahead.peek(Ident)
|
||||
{
|
||||
let ident = input.call(Ident::parse_any)?;
|
||||
segments.push(PathSegment { ident, arguments: PathArguments::None });
|
||||
let _: Token![::] = input.parse()?;
|
||||
lookahead = input.lookahead1();
|
||||
} else {
|
||||
return Err(lookahead.error());
|
||||
}
|
||||
|
||||
while lookahead.peek(Ident) {
|
||||
let ident = input.parse()?;
|
||||
segments.push(PathSegment { ident, arguments: PathArguments::None });
|
||||
let _: Token![::] = input.parse()?;
|
||||
lookahead = input.lookahead1();
|
||||
}
|
||||
|
||||
if !lookahead.peek(token::Brace) && !lookahead.peek(Token![<]) {
|
||||
return Err(lookahead.error());
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
inner: Path {
|
||||
leading_colon: None,
|
||||
segments,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PalletPath {
|
||||
/// Return the snake-cased module name for this path.
|
||||
pub fn mod_name(&self) -> Ident {
|
||||
let mut iter = self.inner.segments.iter();
|
||||
let mut mod_name = match &iter.next().expect("Path should always have 1 segment; qed").ident {
|
||||
ident if ident == "self" || ident == "super" || ident == "crate" => {
|
||||
// Skip `crate`, `self` and `super` quasi-keywords when creating the module name
|
||||
iter.next()
|
||||
.expect("There must be a path segment pointing to a pallet following \
|
||||
`crate`, `self` or `super`; qed")
|
||||
.ident
|
||||
.clone()
|
||||
}
|
||||
ident => ident.clone(),
|
||||
};
|
||||
|
||||
for segment in iter {
|
||||
mod_name = quote::format_ident!("{}_{}", mod_name, segment.ident);
|
||||
}
|
||||
|
||||
mod_name
|
||||
}
|
||||
}
|
||||
|
||||
impl quote::ToTokens for PalletPath {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.inner.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse [`PalletPart`]'s from a braces enclosed list that is split by commas, e.g.
|
||||
///
|
||||
/// `{ Call, Event }`
|
||||
@@ -271,11 +350,6 @@ impl PalletPartKeyword {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name as `Ident`.
|
||||
fn ident(&self) -> Ident {
|
||||
Ident::new(self.name(), self.span())
|
||||
}
|
||||
|
||||
/// Returns `true` if this pallet part is allowed to have generic arguments.
|
||||
fn allows_generic(&self) -> bool {
|
||||
Self::all_generic_arg().iter().any(|n| *n == self.name())
|
||||
@@ -341,11 +415,6 @@ impl PalletPart {
|
||||
pub fn name(&self) -> &'static str {
|
||||
self.keyword.name()
|
||||
}
|
||||
|
||||
/// The name of this pallet part as `Ident`.
|
||||
pub fn ident(&self) -> Ident {
|
||||
self.keyword.ident()
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_kind(
|
||||
|
||||
Reference in New Issue
Block a user