frame_support_procedural/pallet/parse/
pallet_struct.rs1use super::helper;
19use quote::ToTokens;
20use syn::spanned::Spanned;
21
22mod keyword {
24 syn::custom_keyword!(pallet);
25 syn::custom_keyword!(Pallet);
26 syn::custom_keyword!(without_storage_info);
27 syn::custom_keyword!(storage_version);
28}
29
30pub struct PalletStructDef {
32 pub index: usize,
34 pub instances: Vec<helper::InstanceUsage>,
36 pub pallet: keyword::Pallet,
38 pub attr_span: proc_macro2::Span,
40 pub without_storage_info: Option<proc_macro2::Span>,
43 pub storage_version: Option<syn::Path>,
45}
46
47pub enum PalletStructAttr {
51 WithoutStorageInfoTrait(proc_macro2::Span),
52 StorageVersion { storage_version: syn::Path, span: proc_macro2::Span },
53}
54
55impl PalletStructAttr {
56 fn span(&self) -> proc_macro2::Span {
57 match self {
58 Self::WithoutStorageInfoTrait(span) | Self::StorageVersion { span, .. } => *span,
59 }
60 }
61}
62
63impl syn::parse::Parse for PalletStructAttr {
64 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
65 input.parse::<syn::Token![#]>()?;
66 let content;
67 syn::bracketed!(content in input);
68 content.parse::<keyword::pallet>()?;
69 content.parse::<syn::Token![::]>()?;
70
71 let lookahead = content.lookahead1();
72 if lookahead.peek(keyword::without_storage_info) {
73 let span = content.parse::<keyword::without_storage_info>()?.span();
74 Ok(Self::WithoutStorageInfoTrait(span))
75 } else if lookahead.peek(keyword::storage_version) {
76 let span = content.parse::<keyword::storage_version>()?.span();
77
78 let version_content;
79 syn::parenthesized!(version_content in content);
80 let storage_version = version_content.parse::<syn::Path>()?;
81
82 Ok(Self::StorageVersion { storage_version, span })
83 } else {
84 Err(lookahead.error())
85 }
86 }
87}
88
89impl PalletStructDef {
90 pub fn try_from(
91 attr_span: proc_macro2::Span,
92 index: usize,
93 item: &mut syn::Item,
94 ) -> syn::Result<Self> {
95 let item = if let syn::Item::Struct(item) = item {
96 item
97 } else {
98 let msg = "Invalid pallet::pallet, expected struct definition";
99 return Err(syn::Error::new(item.span(), msg))
100 };
101
102 let mut without_storage_info = None;
103 let mut storage_version_found = None;
104
105 let struct_attrs: Vec<PalletStructAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
106 for attr in struct_attrs {
107 match attr {
108 PalletStructAttr::WithoutStorageInfoTrait(span)
109 if without_storage_info.is_none() =>
110 {
111 without_storage_info = Some(span);
112 },
113 PalletStructAttr::StorageVersion { storage_version, .. }
114 if storage_version_found.is_none() =>
115 {
116 storage_version_found = Some(storage_version);
117 },
118 attr => {
119 let msg = "Unexpected duplicated attribute";
120 return Err(syn::Error::new(attr.span(), msg))
121 },
122 }
123 }
124
125 let pallet = syn::parse2::<keyword::Pallet>(item.ident.to_token_stream())?;
126
127 if !matches!(item.vis, syn::Visibility::Public(_)) {
128 let msg = "Invalid pallet::pallet, Pallet must be public";
129 return Err(syn::Error::new(item.span(), msg))
130 }
131
132 if item.generics.where_clause.is_some() {
133 let msg = "Invalid pallet::pallet, where clause not supported on Pallet declaration";
134 return Err(syn::Error::new(item.generics.where_clause.span(), msg))
135 }
136
137 let instances =
138 vec![helper::check_type_def_gen_no_bounds(&item.generics, item.ident.span())?];
139
140 Ok(Self {
141 index,
142 instances,
143 pallet,
144 attr_span,
145 without_storage_info,
146 storage_version: storage_version_found,
147 })
148 }
149}