referrerpolicy=no-referrer-when-downgrade

frame_support_procedural/runtime/parse/
pallet_decl.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 syn::{Ident, PathArguments};
19
20/// The declaration of a pallet.
21#[derive(Debug, Clone)]
22pub struct PalletDeclaration {
23	/// The name of the pallet, e.g.`System` in `pub type System = frame_system`.
24	pub name: Ident,
25	/// The path of the pallet, e.g. `frame_system` in `pub type System = frame_system`.
26	pub path: syn::Path,
27	/// The segment of the pallet, e.g. `Pallet` in `pub type System = frame_system::Pallet`.
28	pub pallet_segment: Option<syn::PathSegment>,
29	/// The runtime parameter of the pallet, e.g. `Runtime` in
30	/// `pub type System = frame_system::Pallet<Runtime>`.
31	pub runtime_param: Option<Ident>,
32	/// The instance of the pallet, e.g. `Instance1` in `pub type Council =
33	/// pallet_collective<Instance1>`.
34	pub instance: Option<Ident>,
35}
36
37impl PalletDeclaration {
38	pub fn try_from(
39		_attr_span: proc_macro2::Span,
40		item: &syn::ItemType,
41		path: &syn::Path,
42	) -> syn::Result<Self> {
43		let name = item.ident.clone();
44
45		let mut path = path.clone();
46
47		let mut pallet_segment = None;
48		let mut runtime_param = None;
49		let mut instance = None;
50		if let Some(segment) = path.segments.iter_mut().find(|seg| !seg.arguments.is_empty()) {
51			if let PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
52				args, ..
53			}) = segment.arguments.clone()
54			{
55				if segment.ident == "Pallet" {
56					let mut segment = segment.clone();
57					segment.arguments = PathArguments::None;
58					pallet_segment = Some(segment.clone());
59				}
60				let mut args_iter = args.iter();
61				if let Some(syn::GenericArgument::Type(syn::Type::Path(arg_path))) =
62					args_iter.next()
63				{
64					let ident = arg_path.path.require_ident()?.clone();
65					if segment.ident == "Pallet" {
66						runtime_param = Some(ident);
67						if let Some(syn::GenericArgument::Type(syn::Type::Path(arg_path))) =
68							args_iter.next()
69						{
70							instance = Some(arg_path.path.require_ident()?.clone());
71						}
72					} else {
73						instance = Some(ident);
74						segment.arguments = PathArguments::None;
75					}
76				}
77			}
78		}
79
80		if pallet_segment.is_some() {
81			path = syn::Path {
82				leading_colon: None,
83				segments: path
84					.segments
85					.iter()
86					.filter(|seg| seg.arguments.is_empty())
87					.cloned()
88					.collect(),
89			};
90		}
91
92		Ok(Self { name, path, pallet_segment, runtime_param, instance })
93	}
94}
95
96#[test]
97fn declaration_works() {
98	use syn::parse_quote;
99
100	let decl: PalletDeclaration = PalletDeclaration::try_from(
101		proc_macro2::Span::call_site(),
102		&parse_quote! { pub type System = frame_system; },
103		&parse_quote! { frame_system },
104	)
105	.expect("Failed to parse pallet declaration");
106
107	assert_eq!(decl.name, "System");
108	assert_eq!(decl.path, parse_quote! { frame_system });
109	assert_eq!(decl.pallet_segment, None);
110	assert_eq!(decl.runtime_param, None);
111	assert_eq!(decl.instance, None);
112}
113
114#[test]
115fn declaration_works_with_instance() {
116	use syn::parse_quote;
117
118	let decl: PalletDeclaration = PalletDeclaration::try_from(
119		proc_macro2::Span::call_site(),
120		&parse_quote! { pub type System = frame_system<Instance1>; },
121		&parse_quote! { frame_system<Instance1> },
122	)
123	.expect("Failed to parse pallet declaration");
124
125	assert_eq!(decl.name, "System");
126	assert_eq!(decl.path, parse_quote! { frame_system });
127	assert_eq!(decl.pallet_segment, None);
128	assert_eq!(decl.runtime_param, None);
129	assert_eq!(decl.instance, Some(parse_quote! { Instance1 }));
130}
131
132#[test]
133fn declaration_works_with_pallet() {
134	use syn::parse_quote;
135
136	let decl: PalletDeclaration = PalletDeclaration::try_from(
137		proc_macro2::Span::call_site(),
138		&parse_quote! { pub type System = frame_system::Pallet<Runtime>; },
139		&parse_quote! { frame_system::Pallet<Runtime> },
140	)
141	.expect("Failed to parse pallet declaration");
142
143	assert_eq!(decl.name, "System");
144	assert_eq!(decl.path, parse_quote! { frame_system });
145
146	let segment: syn::PathSegment =
147		syn::PathSegment { ident: parse_quote! { Pallet }, arguments: PathArguments::None };
148	assert_eq!(decl.pallet_segment, Some(segment));
149	assert_eq!(decl.runtime_param, Some(parse_quote! { Runtime }));
150	assert_eq!(decl.instance, None);
151}
152
153#[test]
154fn declaration_works_with_pallet_and_instance() {
155	use syn::parse_quote;
156
157	let decl: PalletDeclaration = PalletDeclaration::try_from(
158		proc_macro2::Span::call_site(),
159		&parse_quote! { pub type System = frame_system::Pallet<Runtime, Instance1>; },
160		&parse_quote! { frame_system::Pallet<Runtime, Instance1> },
161	)
162	.expect("Failed to parse pallet declaration");
163
164	assert_eq!(decl.name, "System");
165	assert_eq!(decl.path, parse_quote! { frame_system });
166
167	let segment: syn::PathSegment =
168		syn::PathSegment { ident: parse_quote! { Pallet }, arguments: PathArguments::None };
169	assert_eq!(decl.pallet_segment, Some(segment));
170	assert_eq!(decl.runtime_param, Some(parse_quote! { Runtime }));
171	assert_eq!(decl.instance, Some(parse_quote! { Instance1 }));
172}