frame_support_procedural/pallet/parse/
extra_constants.rs1use super::helper;
19use frame_support_procedural_tools::get_doc_literals;
20use syn::spanned::Spanned;
21
22mod keyword {
24 syn::custom_keyword!(DispatchResultWithPostInfo);
25 syn::custom_keyword!(Call);
26 syn::custom_keyword!(OriginFor);
27 syn::custom_keyword!(weight);
28 syn::custom_keyword!(compact);
29 syn::custom_keyword!(T);
30 syn::custom_keyword!(pallet);
31 syn::custom_keyword!(constant_name);
32}
33
34pub struct ExtraConstantsDef {
36 pub where_clause: Option<syn::WhereClause>,
38 pub instances: Vec<helper::InstanceUsage>,
40 pub extra_constants: Vec<ExtraConstantDef>,
42}
43
44pub struct ExtraConstantDef {
46 pub ident: syn::Ident,
48 pub type_: syn::Type,
50 pub doc: Vec<syn::Expr>,
52 pub metadata_name: Option<syn::Ident>,
54 pub attrs: Vec<syn::Attribute>,
56}
57
58pub struct ExtraConstAttr {
61 metadata_name: syn::Ident,
62}
63
64impl syn::parse::Parse for ExtraConstAttr {
65 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
66 input.parse::<syn::Token![#]>()?;
67 let content;
68 syn::bracketed!(content in input);
69 content.parse::<keyword::pallet>()?;
70 content.parse::<syn::Token![::]>()?;
71 content.parse::<keyword::constant_name>()?;
72
73 let metadata_name;
74 syn::parenthesized!(metadata_name in content);
75 Ok(ExtraConstAttr { metadata_name: metadata_name.parse::<syn::Ident>()? })
76 }
77}
78
79impl ExtraConstantsDef {
80 pub fn try_from(item: &mut syn::Item) -> syn::Result<Self> {
81 let item = if let syn::Item::Impl(item) = item {
82 item
83 } else {
84 return Err(syn::Error::new(
85 item.span(),
86 "Invalid pallet::extra_constants, expected item impl",
87 ));
88 };
89
90 let instances = vec![
91 helper::check_impl_gen(&item.generics, item.impl_token.span())?,
92 helper::check_pallet_struct_usage(&item.self_ty)?,
93 ];
94
95 if let Some((_, _, for_)) = item.trait_ {
96 let msg = "Invalid pallet::call, expected no trait ident as in \
97 `impl<..> Pallet<..> { .. }`";
98 return Err(syn::Error::new(for_.span(), msg));
99 }
100
101 let mut extra_constants = vec![];
102 for impl_item in &mut item.items {
103 let method = if let syn::ImplItem::Fn(method) = impl_item {
104 method
105 } else {
106 let msg = "Invalid pallet::call, only method accepted";
107 return Err(syn::Error::new(impl_item.span(), msg));
108 };
109
110 if !method.sig.inputs.is_empty() {
111 let msg = "Invalid pallet::extra_constants, method must have 0 args";
112 return Err(syn::Error::new(method.sig.span(), msg));
113 }
114
115 if !method.sig.generics.params.is_empty() {
116 let msg = "Invalid pallet::extra_constants, method must have 0 generics";
117 return Err(syn::Error::new(method.sig.generics.params[0].span(), msg));
118 }
119
120 if method.sig.generics.where_clause.is_some() {
121 let msg = "Invalid pallet::extra_constants, method must have no where clause";
122 return Err(syn::Error::new(method.sig.generics.where_clause.span(), msg));
123 }
124
125 let type_ = match &method.sig.output {
126 syn::ReturnType::Default => {
127 let msg = "Invalid pallet::extra_constants, method must have a return type";
128 return Err(syn::Error::new(method.span(), msg));
129 },
130 syn::ReturnType::Type(_, type_) => *type_.clone(),
131 };
132
133 let mut extra_constant_attrs: Vec<ExtraConstAttr> =
135 helper::take_item_pallet_attrs(method)?;
136
137 if extra_constant_attrs.len() > 1 {
138 let msg =
139 "Invalid attribute in pallet::constant_name, only one attribute is expected";
140 return Err(syn::Error::new(extra_constant_attrs[1].metadata_name.span(), msg));
141 }
142
143 let metadata_name = extra_constant_attrs.pop().map(|attr| attr.metadata_name);
144
145 extra_constants.push(ExtraConstantDef {
146 ident: method.sig.ident.clone(),
147 type_,
148 doc: get_doc_literals(&method.attrs),
149 metadata_name,
150 attrs: method.attrs.clone(),
151 });
152 }
153
154 Ok(Self { instances, where_clause: item.generics.where_clause.clone(), extra_constants })
155 }
156}