frame_support_procedural/pallet/parse/
composite.rs
1use super::helper;
19use quote::ToTokens;
20use syn::spanned::Spanned;
21
22pub mod keyword {
23 use super::*;
24
25 syn::custom_keyword!(FreezeReason);
26 syn::custom_keyword!(HoldReason);
27 syn::custom_keyword!(LockId);
28 syn::custom_keyword!(SlashReason);
29 syn::custom_keyword!(Task);
30
31 pub enum CompositeKeyword {
32 FreezeReason(FreezeReason),
33 HoldReason(HoldReason),
34 LockId(LockId),
35 SlashReason(SlashReason),
36 Task(Task),
37 }
38
39 impl ToTokens for CompositeKeyword {
40 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
41 use CompositeKeyword::*;
42 match self {
43 FreezeReason(inner) => inner.to_tokens(tokens),
44 HoldReason(inner) => inner.to_tokens(tokens),
45 LockId(inner) => inner.to_tokens(tokens),
46 SlashReason(inner) => inner.to_tokens(tokens),
47 Task(inner) => inner.to_tokens(tokens),
48 }
49 }
50 }
51
52 impl syn::parse::Parse for CompositeKeyword {
53 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
54 let lookahead = input.lookahead1();
55 if lookahead.peek(FreezeReason) {
56 Ok(Self::FreezeReason(input.parse()?))
57 } else if lookahead.peek(HoldReason) {
58 Ok(Self::HoldReason(input.parse()?))
59 } else if lookahead.peek(LockId) {
60 Ok(Self::LockId(input.parse()?))
61 } else if lookahead.peek(SlashReason) {
62 Ok(Self::SlashReason(input.parse()?))
63 } else if lookahead.peek(Task) {
64 Ok(Self::Task(input.parse()?))
65 } else {
66 Err(lookahead.error())
67 }
68 }
69 }
70
71 impl std::fmt::Display for CompositeKeyword {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 use CompositeKeyword::*;
74 write!(
75 f,
76 "{}",
77 match self {
78 FreezeReason(_) => "FreezeReason",
79 HoldReason(_) => "HoldReason",
80 Task(_) => "Task",
81 LockId(_) => "LockId",
82 SlashReason(_) => "SlashReason",
83 }
84 )
85 }
86 }
87}
88
89pub struct CompositeDef {
90 pub composite_keyword: keyword::CompositeKeyword,
92 pub ident: syn::Ident,
94 pub generics: syn::Generics,
96 pub attr_span: proc_macro2::Span,
98 pub variant_count: u32,
100}
101
102impl CompositeDef {
103 pub fn try_from(
104 attr_span: proc_macro2::Span,
105 scrate: &syn::Path,
106 item: &mut syn::Item,
107 ) -> syn::Result<Self> {
108 let item = if let syn::Item::Enum(item) = item {
109 for variant in &item.variants {
113 match variant.fields {
114 syn::Fields::Named(_) | syn::Fields::Unnamed(_) =>
115 return Err(syn::Error::new(
116 variant.ident.span(),
117 "The composite enum does not support variants with fields!",
118 )),
119 syn::Fields::Unit => (),
120 }
121 }
122 item
123 } else {
124 return Err(syn::Error::new(
125 item.span(),
126 "Invalid pallet::composite_enum, expected enum item",
127 ))
128 };
129
130 if !matches!(item.vis, syn::Visibility::Public(_)) {
131 let msg = format!("Invalid pallet::composite_enum, `{}` must be public", item.ident);
132 return Err(syn::Error::new(item.span(), msg))
133 }
134
135 let has_instance = if item.generics.params.first().is_some() {
136 helper::check_config_def_gen(&item.generics, item.ident.span())?;
137 true
138 } else {
139 false
140 };
141
142 let has_derive_attr = item.attrs.iter().any(|attr| {
143 if let syn::Meta::List(syn::MetaList { path, .. }) = &attr.meta {
144 path.get_ident().map(|ident| ident == "derive").unwrap_or(false)
145 } else {
146 false
147 }
148 });
149
150 if !has_derive_attr {
151 let derive_attr: syn::Attribute = syn::parse_quote! {
152 #[derive(
153 Copy, Clone, Eq, PartialEq,
154 #scrate::__private::codec::Encode,
155 #scrate::__private::codec::Decode,
156 #scrate::__private::codec::DecodeWithMemTracking,
157 #scrate::__private::codec::MaxEncodedLen,
158 #scrate::__private::scale_info::TypeInfo,
159 #scrate::__private::RuntimeDebug,
160 )]
161 };
162 item.attrs.push(derive_attr);
163 }
164
165 if has_instance {
166 item.attrs.push(syn::parse_quote! {
167 #[scale_info(skip_type_params(I))]
168 });
169
170 item.variants.push(syn::parse_quote! {
171 #[doc(hidden)]
172 #[codec(skip)]
173 __Ignore(
174 ::core::marker::PhantomData<I>,
175 )
176 });
177 }
178
179 let composite_keyword =
180 syn::parse2::<keyword::CompositeKeyword>(item.ident.to_token_stream())?;
181
182 Ok(CompositeDef {
183 composite_keyword,
184 attr_span,
185 generics: item.generics.clone(),
186 variant_count: item.variants.len() as u32,
187 ident: item.ident.clone(),
188 })
189 }
190}