referrerpolicy=no-referrer-when-downgrade

frame_support_procedural/pallet/expand/
tt_default_parts.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::{
19	pallet::{CompositeKeyword, Def},
20	COUNTER,
21};
22use syn::spanned::Spanned;
23
24/// Generate the `tt_default_parts` macro.
25pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream {
26	let count = COUNTER.with(|counter| counter.borrow_mut().inc());
27	let default_parts_unique_id =
28		syn::Ident::new(&format!("__tt_default_parts_{}", count), def.item.span());
29	let extra_parts_unique_id =
30		syn::Ident::new(&format!("__tt_extra_parts_{}", count), def.item.span());
31	let default_parts_unique_id_v2 =
32		syn::Ident::new(&format!("__tt_default_parts_v2_{}", count), def.item.span());
33
34	let call_part = def.call.as_ref().map(|_| quote::quote!(Call,));
35
36	let task_part = def.tasks.as_ref().map(|_| quote::quote!(Task,));
37
38	let storage_part = (!def.storages.is_empty()).then(|| quote::quote!(Storage,));
39
40	let event_part = def.event.as_ref().map(|event| {
41		let gen = event.gen_kind.is_generic().then(|| quote::quote!( <T> ));
42		quote::quote!( Event #gen , )
43	});
44
45	let error_part = def.error.as_ref().map(|_| quote::quote!(Error<T>,));
46
47	let origin_part = def.origin.as_ref().map(|origin| {
48		let gen = origin.is_generic.then(|| quote::quote!( <T> ));
49		quote::quote!( Origin #gen , )
50	});
51
52	let config_part = def.genesis_config.as_ref().map(|genesis_config| {
53		let gen = genesis_config.gen_kind.is_generic().then(|| quote::quote!( <T> ));
54		quote::quote!( Config #gen , )
55	});
56
57	let inherent_part = def.inherent.as_ref().map(|_| quote::quote!(Inherent,));
58
59	let validate_unsigned_part =
60		def.validate_unsigned.as_ref().map(|_| quote::quote!(ValidateUnsigned,));
61
62	let freeze_reason_part = def
63		.composites
64		.iter()
65		.any(|c| matches!(c.composite_keyword, CompositeKeyword::FreezeReason(_)))
66		.then_some(quote::quote!(FreezeReason,));
67
68	let hold_reason_part = def
69		.composites
70		.iter()
71		.any(|c| matches!(c.composite_keyword, CompositeKeyword::HoldReason(_)))
72		.then_some(quote::quote!(HoldReason,));
73
74	let lock_id_part = def
75		.composites
76		.iter()
77		.any(|c| matches!(c.composite_keyword, CompositeKeyword::LockId(_)))
78		.then_some(quote::quote!(LockId,));
79
80	let slash_reason_part = def
81		.composites
82		.iter()
83		.any(|c| matches!(c.composite_keyword, CompositeKeyword::SlashReason(_)))
84		.then_some(quote::quote!(SlashReason,));
85
86	let call_part_v2 = def.call.as_ref().map(|_| quote::quote!(+ Call));
87
88	let task_part_v2 = def.tasks.as_ref().map(|_| quote::quote!(+ Task));
89
90	let storage_part_v2 = (!def.storages.is_empty()).then(|| quote::quote!(+ Storage));
91
92	let event_part_v2 = def.event.as_ref().map(|event| {
93		let gen = event.gen_kind.is_generic().then(|| quote::quote!(<T>));
94		quote::quote!(+ Event #gen)
95	});
96
97	let error_part_v2 = def.error.as_ref().map(|_| quote::quote!(+ Error<T>));
98
99	let origin_part_v2 = def.origin.as_ref().map(|origin| {
100		let gen = origin.is_generic.then(|| quote::quote!(<T>));
101		quote::quote!(+ Origin #gen)
102	});
103
104	let config_part_v2 = def.genesis_config.as_ref().map(|genesis_config| {
105		let gen = genesis_config.gen_kind.is_generic().then(|| quote::quote!(<T>));
106		quote::quote!(+ Config #gen)
107	});
108
109	let inherent_part_v2 = def.inherent.as_ref().map(|_| quote::quote!(+ Inherent));
110
111	let validate_unsigned_part_v2 =
112		def.validate_unsigned.as_ref().map(|_| quote::quote!(+ ValidateUnsigned));
113
114	let freeze_reason_part_v2 = def
115		.composites
116		.iter()
117		.any(|c| matches!(c.composite_keyword, CompositeKeyword::FreezeReason(_)))
118		.then_some(quote::quote!(+ FreezeReason));
119
120	let hold_reason_part_v2 = def
121		.composites
122		.iter()
123		.any(|c| matches!(c.composite_keyword, CompositeKeyword::HoldReason(_)))
124		.then_some(quote::quote!(+ HoldReason));
125
126	let lock_id_part_v2 = def
127		.composites
128		.iter()
129		.any(|c| matches!(c.composite_keyword, CompositeKeyword::LockId(_)))
130		.then_some(quote::quote!(+ LockId));
131
132	let slash_reason_part_v2 = def
133		.composites
134		.iter()
135		.any(|c| matches!(c.composite_keyword, CompositeKeyword::SlashReason(_)))
136		.then_some(quote::quote!(+ SlashReason));
137
138	quote::quote!(
139		// This macro follows the conventions as laid out by the `tt-call` crate. It does not
140		// accept any arguments and simply returns the pallet parts, separated by commas, then
141		// wrapped inside of braces and finally prepended with double colons, to the caller inside
142		// of a key named `tokens`.
143		//
144		// We need to accept a path argument here, because this macro gets expanded on the
145		// crate that called the `construct_runtime!` macro, and the actual path is unknown.
146		#[macro_export]
147		#[doc(hidden)]
148		macro_rules! #default_parts_unique_id {
149			{
150				$caller:tt
151				your_tt_return = [{ $my_tt_return:path }]
152			} => {
153				$my_tt_return! {
154					$caller
155					tokens = [{
156						expanded::{
157							Pallet, #call_part #storage_part #event_part #error_part #origin_part #config_part
158							#inherent_part #validate_unsigned_part #freeze_reason_part #task_part
159							#hold_reason_part #lock_id_part #slash_reason_part
160						}
161					}]
162				}
163			};
164		}
165
166		pub use #default_parts_unique_id as tt_default_parts;
167
168
169		// This macro is similar to the `tt_default_parts!`. It expands the pallets that are declared
170		// explicitly (`System: frame_system::{Pallet, Call}`) with extra parts.
171		//
172		// For example, after expansion an explicit pallet would look like:
173		// `System: expanded::{Error} ::{Pallet, Call}`.
174		//
175		// The `expanded` keyword is a marker of the final state of the `construct_runtime!`.
176		#[macro_export]
177		#[doc(hidden)]
178		macro_rules! #extra_parts_unique_id {
179			{
180				$caller:tt
181				your_tt_return = [{ $my_tt_return:path }]
182			} => {
183				$my_tt_return! {
184					$caller
185					tokens = [{
186						expanded::{
187							#error_part
188						}
189					}]
190				}
191			};
192		}
193
194		pub use #extra_parts_unique_id as tt_extra_parts;
195
196		#[macro_export]
197		#[doc(hidden)]
198		macro_rules! #default_parts_unique_id_v2 {
199			{
200				$caller:tt
201				your_tt_return = [{ $my_tt_return:path }]
202			} => {
203				$my_tt_return! {
204					$caller
205					tokens = [{
206						+ Pallet #call_part_v2 #storage_part_v2 #event_part_v2 #error_part_v2 #origin_part_v2 #config_part_v2
207						#inherent_part_v2 #validate_unsigned_part_v2 #freeze_reason_part_v2 #task_part_v2
208						#hold_reason_part_v2 #lock_id_part_v2 #slash_reason_part_v2
209					}]
210				}
211			};
212		}
213
214		pub use #default_parts_unique_id_v2 as tt_default_parts_v2;
215	)
216}