frame_support_procedural/pallet/parse/
helper.rs
1use proc_macro2::TokenStream;
19use quote::{quote, ToTokens};
20use syn::spanned::Spanned;
21
22mod keyword {
24 syn::custom_keyword!(I);
25 syn::custom_keyword!(compact);
26 syn::custom_keyword!(GenesisBuild);
27 syn::custom_keyword!(BuildGenesisConfig);
28 syn::custom_keyword!(Config);
29 syn::custom_keyword!(T);
30 syn::custom_keyword!(Pallet);
31 syn::custom_keyword!(origin);
32 syn::custom_keyword!(DispatchResult);
33 syn::custom_keyword!(DispatchResultWithPostInfo);
34}
35
36#[derive(Clone)]
39pub struct InstanceUsage {
40 pub has_instance: bool,
41 pub span: proc_macro2::Span,
42}
43
44pub trait MutItemAttrs {
48 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>>;
49}
50
51pub(crate) fn take_first_item_pallet_attr<Attr>(
53 item: &mut impl MutItemAttrs,
54) -> syn::Result<Option<Attr>>
55where
56 Attr: syn::parse::Parse,
57{
58 let Some(attrs) = item.mut_item_attrs() else { return Ok(None) };
59
60 let Some(index) = attrs.iter().position(|attr| {
61 attr.path().segments.first().map_or(false, |segment| segment.ident == "pallet")
62 }) else {
63 return Ok(None)
64 };
65
66 let pallet_attr = attrs.remove(index);
67 Ok(Some(syn::parse2(pallet_attr.into_token_stream())?))
68}
69
70pub(crate) fn take_item_pallet_attrs<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Vec<Attr>>
72where
73 Attr: syn::parse::Parse,
74{
75 let mut pallet_attrs = Vec::new();
76
77 while let Some(attr) = take_first_item_pallet_attr(item)? {
78 pallet_attrs.push(attr)
79 }
80
81 Ok(pallet_attrs)
82}
83
84pub fn get_item_cfg_attrs(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> {
86 attrs
87 .iter()
88 .filter_map(|attr| {
89 if attr.path().segments.first().map_or(false, |segment| segment.ident == "cfg") {
90 Some(attr.clone())
91 } else {
92 None
93 }
94 })
95 .collect::<Vec<_>>()
96}
97
98impl MutItemAttrs for syn::Item {
99 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
100 match self {
101 Self::Const(item) => Some(item.attrs.as_mut()),
102 Self::Enum(item) => Some(item.attrs.as_mut()),
103 Self::ExternCrate(item) => Some(item.attrs.as_mut()),
104 Self::Fn(item) => Some(item.attrs.as_mut()),
105 Self::ForeignMod(item) => Some(item.attrs.as_mut()),
106 Self::Impl(item) => Some(item.attrs.as_mut()),
107 Self::Macro(item) => Some(item.attrs.as_mut()),
108 Self::Mod(item) => Some(item.attrs.as_mut()),
109 Self::Static(item) => Some(item.attrs.as_mut()),
110 Self::Struct(item) => Some(item.attrs.as_mut()),
111 Self::Trait(item) => Some(item.attrs.as_mut()),
112 Self::TraitAlias(item) => Some(item.attrs.as_mut()),
113 Self::Type(item) => Some(item.attrs.as_mut()),
114 Self::Union(item) => Some(item.attrs.as_mut()),
115 Self::Use(item) => Some(item.attrs.as_mut()),
116 _ => None,
117 }
118 }
119}
120
121impl MutItemAttrs for syn::TraitItem {
122 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
123 match self {
124 Self::Const(item) => Some(item.attrs.as_mut()),
125 Self::Fn(item) => Some(item.attrs.as_mut()),
126 Self::Type(item) => Some(item.attrs.as_mut()),
127 Self::Macro(item) => Some(item.attrs.as_mut()),
128 _ => None,
129 }
130 }
131}
132
133impl MutItemAttrs for Vec<syn::Attribute> {
134 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
135 Some(self)
136 }
137}
138
139impl MutItemAttrs for syn::ItemMod {
140 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
141 Some(&mut self.attrs)
142 }
143}
144
145impl MutItemAttrs for syn::ImplItemFn {
146 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
147 Some(&mut self.attrs)
148 }
149}
150
151impl MutItemAttrs for syn::ItemType {
152 fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
153 Some(&mut self.attrs)
154 }
155}
156
157struct Unit;
159impl syn::parse::Parse for Unit {
160 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
161 let content;
162 syn::parenthesized!(content in input);
163 if !content.is_empty() {
164 let msg = "unexpected tokens, expected nothing inside parenthesis as `()`";
165 return Err(syn::Error::new(content.span(), msg))
166 }
167 Ok(Self)
168 }
169}
170
171struct StaticLifetime;
173impl syn::parse::Parse for StaticLifetime {
174 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
175 let lifetime = input.parse::<syn::Lifetime>()?;
176 if lifetime.ident != "static" {
177 let msg = "unexpected tokens, expected `static`";
178 return Err(syn::Error::new(lifetime.ident.span(), msg))
179 }
180 Ok(Self)
181 }
182}
183
184pub fn check_config_def_gen(gen: &syn::Generics, span: proc_macro2::Span) -> syn::Result<()> {
190 let expected = "expected `I: 'static = ()`";
191 pub struct CheckTraitDefGenerics;
192 impl syn::parse::Parse for CheckTraitDefGenerics {
193 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
194 input.parse::<keyword::I>()?;
195 input.parse::<syn::Token![:]>()?;
196 input.parse::<StaticLifetime>()?;
197 input.parse::<syn::Token![=]>()?;
198 input.parse::<Unit>()?;
199
200 Ok(Self)
201 }
202 }
203
204 syn::parse2::<CheckTraitDefGenerics>(gen.params.to_token_stream()).map_err(|e| {
205 let msg = format!("Invalid generics: {}", expected);
206 let mut err = syn::Error::new(span, msg);
207 err.combine(e);
208 err
209 })?;
210
211 Ok(())
212}
213
214pub fn check_type_def_gen_no_bounds(
222 gen: &syn::Generics,
223 span: proc_macro2::Span,
224) -> syn::Result<InstanceUsage> {
225 let expected = "expected `T` or `T, I = ()`";
226 pub struct Checker(InstanceUsage);
227 impl syn::parse::Parse for Checker {
228 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
229 let mut instance_usage = InstanceUsage { has_instance: false, span: input.span() };
230
231 input.parse::<keyword::T>()?;
232 if input.peek(syn::Token![,]) {
233 instance_usage.has_instance = true;
234 input.parse::<syn::Token![,]>()?;
235 input.parse::<keyword::I>()?;
236 input.parse::<syn::Token![=]>()?;
237 input.parse::<Unit>()?;
238 }
239
240 Ok(Self(instance_usage))
241 }
242 }
243
244 let i = syn::parse2::<Checker>(gen.params.to_token_stream())
245 .map_err(|e| {
246 let msg = format!("Invalid type def generics: {}", expected);
247 let mut err = syn::Error::new(span, msg);
248 err.combine(e);
249 err
250 })?
251 .0;
252
253 Ok(i)
254}
255
256pub fn check_type_def_optional_gen(
267 gen: &syn::Generics,
268 span: proc_macro2::Span,
269) -> syn::Result<Option<InstanceUsage>> {
270 let expected = "expected `` or `T` or `T: Config` or `T, I = ()` or \
271 `T: Config<I>, I: 'static = ()`";
272 pub struct Checker(Option<InstanceUsage>);
273 impl syn::parse::Parse for Checker {
274 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
275 if input.is_empty() {
276 return Ok(Self(None))
277 }
278
279 let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
280
281 input.parse::<keyword::T>()?;
282
283 if input.is_empty() {
284 return Ok(Self(Some(instance_usage)))
285 }
286
287 let lookahead = input.lookahead1();
288 if lookahead.peek(syn::Token![,]) {
289 instance_usage.has_instance = true;
290 input.parse::<syn::Token![,]>()?;
291 input.parse::<keyword::I>()?;
292 input.parse::<syn::Token![=]>()?;
293 input.parse::<Unit>()?;
294
295 Ok(Self(Some(instance_usage)))
296 } else if lookahead.peek(syn::Token![:]) {
297 input.parse::<syn::Token![:]>()?;
298 input.parse::<keyword::Config>()?;
299
300 if input.is_empty() {
301 return Ok(Self(Some(instance_usage)))
302 }
303
304 instance_usage.has_instance = true;
305 input.parse::<syn::Token![<]>()?;
306 input.parse::<keyword::I>()?;
307 input.parse::<syn::Token![>]>()?;
308 input.parse::<syn::Token![,]>()?;
309 input.parse::<keyword::I>()?;
310 input.parse::<syn::Token![:]>()?;
311 input.parse::<StaticLifetime>()?;
312 input.parse::<syn::Token![=]>()?;
313 input.parse::<Unit>()?;
314
315 Ok(Self(Some(instance_usage)))
316 } else {
317 Err(lookahead.error())
318 }
319 }
320 }
321
322 let i = syn::parse2::<Checker>(gen.params.to_token_stream())
323 .map_err(|e| {
324 let msg = format!("Invalid type def generics: {}", expected);
325 let mut err = syn::Error::new(span, msg);
326 err.combine(e);
327 err
328 })?
329 .0
330 .map(|mut i| {
332 i.span = span;
333 i
334 });
335
336 Ok(i)
337}
338
339pub fn check_pallet_struct_usage(type_: &Box<syn::Type>) -> syn::Result<InstanceUsage> {
345 let expected = "expected `Pallet<T>` or `Pallet<T, I>`";
346 pub struct Checker(InstanceUsage);
347 impl syn::parse::Parse for Checker {
348 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
349 let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
350
351 input.parse::<keyword::Pallet>()?;
352 input.parse::<syn::Token![<]>()?;
353 input.parse::<keyword::T>()?;
354 if input.peek(syn::Token![,]) {
355 instance_usage.has_instance = true;
356 input.parse::<syn::Token![,]>()?;
357 input.parse::<keyword::I>()?;
358 }
359 input.parse::<syn::Token![>]>()?;
360
361 Ok(Self(instance_usage))
362 }
363 }
364
365 let i = syn::parse2::<Checker>(type_.to_token_stream())
366 .map_err(|e| {
367 let msg = format!("Invalid pallet struct: {}", expected);
368 let mut err = syn::Error::new(type_.span(), msg);
369 err.combine(e);
370 err
371 })?
372 .0;
373
374 Ok(i)
375}
376
377pub fn check_impl_gen(gen: &syn::Generics, span: proc_macro2::Span) -> syn::Result<InstanceUsage> {
385 let expected = "expected `impl<T: Config>` or `impl<T: Config<I>, I: 'static>`";
386 pub struct Checker(InstanceUsage);
387 impl syn::parse::Parse for Checker {
388 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
389 let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
390
391 input.parse::<keyword::T>()?;
392 input.parse::<syn::Token![:]>()?;
393 input.parse::<keyword::Config>()?;
394 if input.peek(syn::Token![<]) {
395 instance_usage.has_instance = true;
396 input.parse::<syn::Token![<]>()?;
397 input.parse::<keyword::I>()?;
398 input.parse::<syn::Token![>]>()?;
399 input.parse::<syn::Token![,]>()?;
400 input.parse::<keyword::I>()?;
401 input.parse::<syn::Token![:]>()?;
402 input.parse::<StaticLifetime>()?;
403 }
404
405 Ok(Self(instance_usage))
406 }
407 }
408
409 let i = syn::parse2::<Checker>(gen.params.to_token_stream())
410 .map_err(|e| {
411 let mut err = syn::Error::new(span, format!("Invalid generics: {}", expected));
412 err.combine(e);
413 err
414 })?
415 .0;
416
417 Ok(i)
418}
419
420pub fn check_type_def_gen(
430 gen: &syn::Generics,
431 span: proc_macro2::Span,
432) -> syn::Result<InstanceUsage> {
433 let expected = "expected `T` or `T: Config` or `T, I = ()` or \
434 `T: Config<I>, I: 'static = ()`";
435 pub struct Checker(InstanceUsage);
436 impl syn::parse::Parse for Checker {
437 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
438 let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
439
440 input.parse::<keyword::T>()?;
441
442 if input.is_empty() {
443 return Ok(Self(instance_usage))
444 }
445
446 let lookahead = input.lookahead1();
447 if lookahead.peek(syn::Token![,]) {
448 instance_usage.has_instance = true;
449 input.parse::<syn::Token![,]>()?;
450 input.parse::<keyword::I>()?;
451 input.parse::<syn::Token![=]>()?;
452 input.parse::<Unit>()?;
453
454 Ok(Self(instance_usage))
455 } else if lookahead.peek(syn::Token![:]) {
456 input.parse::<syn::Token![:]>()?;
457 input.parse::<keyword::Config>()?;
458
459 if input.is_empty() {
460 return Ok(Self(instance_usage))
461 }
462
463 instance_usage.has_instance = true;
464 input.parse::<syn::Token![<]>()?;
465 input.parse::<keyword::I>()?;
466 input.parse::<syn::Token![>]>()?;
467 input.parse::<syn::Token![,]>()?;
468 input.parse::<keyword::I>()?;
469 input.parse::<syn::Token![:]>()?;
470 input.parse::<StaticLifetime>()?;
471 input.parse::<syn::Token![=]>()?;
472 input.parse::<Unit>()?;
473
474 Ok(Self(instance_usage))
475 } else {
476 Err(lookahead.error())
477 }
478 }
479 }
480
481 let mut i = syn::parse2::<Checker>(gen.params.to_token_stream())
482 .map_err(|e| {
483 let msg = format!("Invalid type def generics: {}", expected);
484 let mut err = syn::Error::new(span, msg);
485 err.combine(e);
486 err
487 })?
488 .0;
489
490 i.span = span;
492
493 Ok(i)
494}
495
496pub fn check_genesis_builder_usage(type_: &syn::Path) -> syn::Result<Option<InstanceUsage>> {
504 let expected = "expected `BuildGenesisConfig` (or the deprecated `GenesisBuild<T>` or `GenesisBuild<T, I>`)";
505 pub struct Checker(Option<InstanceUsage>);
506 impl syn::parse::Parse for Checker {
507 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
508 let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
509
510 if input.peek(keyword::GenesisBuild) {
511 input.parse::<keyword::GenesisBuild>()?;
512 input.parse::<syn::Token![<]>()?;
513 input.parse::<keyword::T>()?;
514 if input.peek(syn::Token![,]) {
515 instance_usage.has_instance = true;
516 input.parse::<syn::Token![,]>()?;
517 input.parse::<keyword::I>()?;
518 }
519 input.parse::<syn::Token![>]>()?;
520 return Ok(Self(Some(instance_usage)))
521 } else {
522 input.parse::<keyword::BuildGenesisConfig>()?;
523 return Ok(Self(None))
524 }
525 }
526 }
527
528 let i = syn::parse2::<Checker>(type_.to_token_stream())
529 .map_err(|e| {
530 let msg = format!("Invalid genesis builder: {}", expected);
531 let mut err = syn::Error::new(type_.span(), msg);
532 err.combine(e);
533 err
534 })?
535 .0;
536
537 Ok(i)
538}
539
540pub fn check_type_value_gen(
549 gen: &syn::Generics,
550 span: proc_macro2::Span,
551) -> syn::Result<Option<InstanceUsage>> {
552 let expected = "expected `` or `T: Config` or `T: Config<I>, I: 'static`";
553 pub struct Checker(Option<InstanceUsage>);
554 impl syn::parse::Parse for Checker {
555 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
556 if input.is_empty() {
557 return Ok(Self(None))
558 }
559
560 input.parse::<keyword::T>()?;
561 input.parse::<syn::Token![:]>()?;
562 input.parse::<keyword::Config>()?;
563
564 let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
565
566 if input.is_empty() {
567 return Ok(Self(Some(instance_usage)))
568 }
569
570 instance_usage.has_instance = true;
571 input.parse::<syn::Token![<]>()?;
572 input.parse::<keyword::I>()?;
573 input.parse::<syn::Token![>]>()?;
574 input.parse::<syn::Token![,]>()?;
575 input.parse::<keyword::I>()?;
576 input.parse::<syn::Token![:]>()?;
577 input.parse::<StaticLifetime>()?;
578
579 Ok(Self(Some(instance_usage)))
580 }
581 }
582
583 let i = syn::parse2::<Checker>(gen.params.to_token_stream())
584 .map_err(|e| {
585 let msg = format!("Invalid type def generics: {}", expected);
586 let mut err = syn::Error::new(span, msg);
587 err.combine(e);
588 err
589 })?
590 .0
591 .map(|mut i| {
593 i.span = span;
594 i
595 });
596
597 Ok(i)
598}
599
600#[derive(Clone)]
602pub enum CallReturnType {
603 DispatchResult,
604 DispatchResultWithPostInfo,
605}
606
607pub fn check_pallet_call_return_type(sig: &syn::Signature) -> syn::Result<CallReturnType> {
609 let syn::ReturnType::Type(_, type_) = &sig.output else {
610 let msg = "Invalid pallet::call, require return type \
611 DispatchResultWithPostInfo";
612 return Err(syn::Error::new(sig.span(), msg))
613 };
614
615 pub struct Checker(CallReturnType);
616 impl syn::parse::Parse for Checker {
617 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
618 let lookahead = input.lookahead1();
619 if lookahead.peek(keyword::DispatchResultWithPostInfo) {
620 input.parse::<keyword::DispatchResultWithPostInfo>()?;
621 Ok(Self(CallReturnType::DispatchResultWithPostInfo))
622 } else if lookahead.peek(keyword::DispatchResult) {
623 input.parse::<keyword::DispatchResult>()?;
624 Ok(Self(CallReturnType::DispatchResult))
625 } else {
626 Err(lookahead.error())
627 }
628 }
629 }
630
631 syn::parse2::<Checker>(type_.to_token_stream()).map(|c| c.0)
632}
633
634pub(crate) fn two128_str(s: &str) -> TokenStream {
635 bytes_to_array(sp_crypto_hashing::twox_128(s.as_bytes()).into_iter())
636}
637
638pub(crate) fn bytes_to_array(bytes: impl IntoIterator<Item = u8>) -> TokenStream {
639 let bytes = bytes.into_iter();
640
641 quote!(
642 [ #( #bytes ),* ]
643 )
644 .into()
645}