frame_support_procedural/runtime/parse/
pallet.rs1use crate::{
19 construct_runtime::parse::{Pallet, PalletPart, PalletPartKeyword, PalletPath},
20 runtime::parse::PalletDeclaration,
21};
22use frame_support_procedural_tools::get_doc_literals;
23use quote::ToTokens;
24use syn::{punctuated::Punctuated, token, Error};
25
26impl Pallet {
27 pub fn try_from(
28 attr_span: proc_macro2::Span,
29 item: &syn::ItemType,
30 pallet_index: u8,
31 disable_call: bool,
32 disable_unsigned: bool,
33 bounds: &Punctuated<syn::TypeParamBound, token::Plus>,
34 ) -> syn::Result<Self> {
35 let name = item.ident.clone();
36
37 let mut pallet_path = None;
38 let mut pallet_parts = vec![];
39
40 for (index, bound) in bounds.into_iter().enumerate() {
41 if let syn::TypeParamBound::Trait(syn::TraitBound { path, .. }) = bound {
42 if index == 0 {
43 pallet_path = Some(PalletPath { inner: path.clone() });
44 } else {
45 let pallet_part = syn::parse2::<PalletPart>(bound.into_token_stream())?;
46 pallet_parts.push(pallet_part);
47 }
48 } else {
49 return Err(Error::new(
50 attr_span,
51 "Invalid pallet declaration, expected a path or a trait object",
52 ));
53 };
54 }
55
56 let mut path = pallet_path.ok_or(Error::new(
57 attr_span,
58 "Invalid pallet declaration, expected a path or a trait object",
59 ))?;
60
61 let PalletDeclaration { path: inner, instance, .. } =
62 PalletDeclaration::try_from(attr_span, item, &path.inner)?;
63
64 path = PalletPath { inner };
65
66 pallet_parts = pallet_parts
67 .into_iter()
68 .filter(|part| {
69 if let (true, &PalletPartKeyword::Call(_)) = (disable_call, &part.keyword) {
70 false
71 } else if let (true, &PalletPartKeyword::ValidateUnsigned(_)) =
72 (disable_unsigned, &part.keyword)
73 {
74 false
75 } else {
76 true
77 }
78 })
79 .collect();
80
81 let cfg_pattern = vec![];
82
83 let docs = get_doc_literals(&item.attrs);
84
85 Ok(Pallet {
86 is_expanded: true,
87 name,
88 index: pallet_index,
89 path,
90 instance,
91 cfg_pattern,
92 pallet_parts,
93 docs,
94 })
95 }
96}
97
98#[test]
99fn pallet_parsing_works() {
100 use syn::{parse_quote, ItemType};
101
102 let item: ItemType = parse_quote! {
103 pub type System = frame_system + Call;
104 };
105 let ItemType { ty, .. } = item.clone();
106 let syn::Type::TraitObject(syn::TypeTraitObject { bounds, .. }) = *ty else {
107 panic!("Expected a trait object");
108 };
109
110 let index = 0;
111 let pallet =
112 Pallet::try_from(proc_macro2::Span::call_site(), &item, index, false, false, &bounds)
113 .unwrap();
114
115 assert_eq!(pallet.name.to_string(), "System");
116 assert_eq!(pallet.index, index);
117 assert_eq!(pallet.path.to_token_stream().to_string(), "frame_system");
118 assert_eq!(pallet.instance, None);
119}
120
121#[test]
122fn pallet_parsing_works_with_instance() {
123 use syn::{parse_quote, ItemType};
124
125 let item: ItemType = parse_quote! {
126 pub type System = frame_system<Instance1> + Call;
127 };
128 let ItemType { ty, .. } = item.clone();
129 let syn::Type::TraitObject(syn::TypeTraitObject { bounds, .. }) = *ty else {
130 panic!("Expected a trait object");
131 };
132
133 let index = 0;
134 let pallet =
135 Pallet::try_from(proc_macro2::Span::call_site(), &item, index, false, false, &bounds)
136 .unwrap();
137
138 assert_eq!(pallet.name.to_string(), "System");
139 assert_eq!(pallet.index, index);
140 assert_eq!(pallet.path.to_token_stream().to_string(), "frame_system");
141 assert_eq!(pallet.instance, Some(parse_quote! { Instance1 }));
142}
143
144#[test]
145fn pallet_parsing_works_with_pallet() {
146 use syn::{parse_quote, ItemType};
147
148 let item: ItemType = parse_quote! {
149 pub type System = frame_system::Pallet<Runtime> + Call;
150 };
151 let ItemType { ty, .. } = item.clone();
152 let syn::Type::TraitObject(syn::TypeTraitObject { bounds, .. }) = *ty else {
153 panic!("Expected a trait object");
154 };
155
156 let index = 0;
157 let pallet =
158 Pallet::try_from(proc_macro2::Span::call_site(), &item, index, false, false, &bounds)
159 .unwrap();
160
161 assert_eq!(pallet.name.to_string(), "System");
162 assert_eq!(pallet.index, index);
163 assert_eq!(pallet.path.to_token_stream().to_string(), "frame_system");
164 assert_eq!(pallet.instance, None);
165}
166
167#[test]
168fn pallet_parsing_works_with_instance_and_pallet() {
169 use syn::{parse_quote, ItemType};
170
171 let item: ItemType = parse_quote! {
172 pub type System = frame_system::Pallet<Runtime, Instance1> + Call;
173 };
174 let ItemType { ty, .. } = item.clone();
175 let syn::Type::TraitObject(syn::TypeTraitObject { bounds, .. }) = *ty else {
176 panic!("Expected a trait object");
177 };
178
179 let index = 0;
180 let pallet =
181 Pallet::try_from(proc_macro2::Span::call_site(), &item, index, false, false, &bounds)
182 .unwrap();
183
184 assert_eq!(pallet.name.to_string(), "System");
185 assert_eq!(pallet.index, index);
186 assert_eq!(pallet.path.to_token_stream().to_string(), "frame_system");
187 assert_eq!(pallet.instance, Some(parse_quote! { Instance1 }));
188}