frame_support_procedural/construct_runtime/expand/
config.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License
17
18use crate::construct_runtime::Pallet;
19use inflector::Inflector;
20use proc_macro2::TokenStream;
21use quote::{format_ident, quote, ToTokens};
22use std::str::FromStr;
23use syn::Ident;
24
25pub fn expand_outer_config(
26	runtime: &Ident,
27	pallet_decls: &[Pallet],
28	scrate: &TokenStream,
29) -> TokenStream {
30	let mut types = TokenStream::new();
31	let mut fields = TokenStream::new();
32	let mut genesis_build_calls = TokenStream::new();
33	let mut query_genesis_config_part_macros = Vec::new();
34
35	for decl in pallet_decls {
36		if let Some(pallet_entry) = decl.find_part("Config") {
37			let path = &decl.path;
38			let pallet_name = &decl.name;
39			let path_str = path.into_token_stream().to_string();
40			let config = format_ident!("{}Config", pallet_name);
41			let field_name =
42				&Ident::new(&pallet_name.to_string().to_snake_case(), decl.name.span());
43			let part_is_generic = !pallet_entry.generics.params.is_empty();
44			let attr = &decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| {
45				let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original()))
46					.expect("was successfully parsed before; qed");
47				quote! {
48					#acc
49					#attr
50				}
51			});
52
53			types.extend(expand_config_types(attr, runtime, decl, &config, part_is_generic));
54			fields.extend(quote!(#attr pub #field_name: #config,));
55			genesis_build_calls
56				.extend(expand_config_build_storage_call(scrate, &config, attr, field_name));
57			query_genesis_config_part_macros.push(quote! {
58				#path::__substrate_genesis_config_check::is_genesis_config_defined!(#pallet_name);
59				#[cfg(feature = "std")]
60				#path::__substrate_genesis_config_check::is_std_enabled_for_genesis!(#pallet_name, #path_str);
61			});
62		}
63	}
64
65	quote! {
66		#( #query_genesis_config_part_macros )*
67
68		#types
69
70		use #scrate::__private::serde as __genesis_config_serde_import__;
71		#[derive(#scrate::__private::serde::Serialize, #scrate::__private::serde::Deserialize, Default)]
72		#[serde(rename_all = "camelCase")]
73		#[serde(deny_unknown_fields)]
74		#[serde(crate = "__genesis_config_serde_import__")]
75		pub struct RuntimeGenesisConfig {
76			#fields
77		}
78
79		#[cfg(any(feature = "std", test))]
80		impl #scrate::sp_runtime::BuildStorage for RuntimeGenesisConfig {
81			fn assimilate_storage(
82				&self,
83				storage: &mut #scrate::sp_runtime::Storage,
84			) -> std::result::Result<(), String> {
85				#scrate::__private::BasicExternalities::execute_with_storage(storage, || {
86					<Self as #scrate::traits::BuildGenesisConfig>::build(&self);
87					Ok(())
88				})
89			}
90		}
91
92		impl #scrate::traits::BuildGenesisConfig for RuntimeGenesisConfig {
93			fn build(&self) {
94				#genesis_build_calls
95				<AllPalletsWithSystem as #scrate::traits::OnGenesis>::on_genesis();
96			}
97		}
98
99		/// Test the `Default` derive impl of the `RuntimeGenesisConfig`.
100		#[cfg(test)]
101		#[test]
102		fn test_genesis_config_builds() {
103			#scrate::__private::sp_io::TestExternalities::default().execute_with(|| {
104				<RuntimeGenesisConfig as #scrate::traits::BuildGenesisConfig>::build(
105					&RuntimeGenesisConfig::default()
106				);
107			});
108		}
109	}
110}
111
112fn expand_config_types(
113	attr: &TokenStream,
114	runtime: &Ident,
115	decl: &Pallet,
116	config: &Ident,
117	part_is_generic: bool,
118) -> TokenStream {
119	let path = &decl.path;
120
121	match (decl.instance.as_ref(), part_is_generic) {
122		(Some(inst), true) => quote! {
123			#attr
124			pub type #config = #path::GenesisConfig<#runtime, #path::#inst>;
125		},
126		(None, true) => quote! {
127			#attr
128			pub type #config = #path::GenesisConfig<#runtime>;
129		},
130		(_, false) => quote! {
131			#attr
132			pub type #config = #path::GenesisConfig;
133		},
134	}
135}
136
137fn expand_config_build_storage_call(
138	scrate: &TokenStream,
139	pallet_genesis_config: &Ident,
140	attr: &TokenStream,
141	field_name: &Ident,
142) -> TokenStream {
143	quote! {
144		#attr
145		<#pallet_genesis_config as #scrate::traits::BuildGenesisConfig>::build(&self.#field_name);
146	}
147}