1pub mod call;
23pub mod composite;
24pub mod config;
25pub mod error;
26pub mod event;
27pub mod extra_constants;
28pub mod genesis_build;
29pub mod genesis_config;
30pub mod helper;
31pub mod hooks;
32pub mod inherent;
33pub mod origin;
34pub mod pallet_struct;
35pub mod storage;
36pub mod tasks;
37pub mod type_value;
38pub mod validate_unsigned;
39pub mod view_functions;
40
41#[cfg(test)]
42pub mod tests;
43
44use composite::{keyword::CompositeKeyword, CompositeDef};
45use frame_support_procedural_tools::generate_access_from_frame_or_crate;
46use quote::ToTokens;
47use syn::spanned::Spanned;
48
49pub struct Def {
51 pub item: syn::ItemMod,
54 pub config: config::ConfigDef,
55 pub pallet_struct: pallet_struct::PalletStructDef,
56 pub hooks: Option<hooks::HooksDef>,
57 pub call: Option<call::CallDef>,
58 pub tasks: Option<tasks::TasksDef>,
59 pub task_enum: Option<tasks::TaskEnumDef>,
60 pub storages: Vec<storage::StorageDef>,
61 pub error: Option<error::ErrorDef>,
62 pub event: Option<event::EventDef>,
63 pub origin: Option<origin::OriginDef>,
64 pub inherent: Option<inherent::InherentDef>,
65 pub genesis_config: Option<genesis_config::GenesisConfigDef>,
66 pub genesis_build: Option<genesis_build::GenesisBuildDef>,
67 pub validate_unsigned: Option<validate_unsigned::ValidateUnsignedDef>,
68 pub extra_constants: Option<extra_constants::ExtraConstantsDef>,
69 pub composites: Vec<composite::CompositeDef>,
70 pub type_values: Vec<type_value::TypeValueDef>,
71 pub frame_system: syn::Path,
72 pub frame_support: syn::Path,
73 pub dev_mode: bool,
74 pub view_functions: Option<view_functions::ViewFunctionsImplDef>,
75 pub is_frame_system: bool,
76}
77
78impl Def {
79 pub fn try_from(mut item: syn::ItemMod, dev_mode: bool) -> syn::Result<Self> {
80 let frame_system = generate_access_from_frame_or_crate("frame-system")?;
81 let frame_support = generate_access_from_frame_or_crate("frame-support")?;
82 let item_span = item.span();
83 let items = &mut item
84 .content
85 .as_mut()
86 .ok_or_else(|| {
87 let msg = "Invalid pallet definition, expected mod to be inlined.";
88 syn::Error::new(item_span, msg)
89 })?
90 .1;
91
92 let mut config = None;
93 let mut pallet_struct = None;
94 let mut hooks = None;
95 let mut call = None;
96 let mut tasks = None;
97 let mut task_enum = None;
98 let mut error = None;
99 let mut event = None;
100 let mut origin = None;
101 let mut inherent = None;
102 let mut genesis_config = None;
103 let mut genesis_build = None;
104 let mut validate_unsigned = None;
105 let mut extra_constants = None;
106 let mut storages = vec![];
107 let mut type_values = vec![];
108 let mut composites: Vec<CompositeDef> = vec![];
109 let mut view_functions = None;
110 let mut is_frame_system = false;
111
112 for (index, item) in items.iter_mut().enumerate() {
113 let pallet_attr: Option<PalletAttr> = helper::take_first_item_pallet_attr(item)?;
114
115 match pallet_attr {
116 Some(PalletAttr::Config{ with_default, frame_system_config: is_frame_system_val, without_automatic_metadata, ..}) if config.is_none() => {
117 is_frame_system = is_frame_system_val;
118 config = Some(config::ConfigDef::try_from(
119 &frame_system,
120 index,
121 item,
122 with_default,
123 without_automatic_metadata,
124 is_frame_system,
125 )?);
126 },
127 Some(PalletAttr::Pallet(span)) if pallet_struct.is_none() => {
128 let p = pallet_struct::PalletStructDef::try_from(span, index, item)?;
129 pallet_struct = Some(p);
130 },
131 Some(PalletAttr::Hooks(span)) if hooks.is_none() => {
132 let m = hooks::HooksDef::try_from(span, item)?;
133 hooks = Some(m);
134 },
135 Some(PalletAttr::RuntimeCall(cw, span)) if call.is_none() =>
136 call = Some(call::CallDef::try_from(span, index, item, dev_mode, cw)?),
137 Some(PalletAttr::Tasks(span)) if tasks.is_none() => {
138 let item_tokens = item.to_token_stream();
139 tasks = Some(syn::parse2::<tasks::TasksDef>(quote::quote_spanned! { span =>
142 #[pallet::tasks_experimental]
143 #item_tokens
144 })?);
145
146 *item = syn::Item::Verbatim(quote::quote!());
148 }
149 Some(PalletAttr::TaskCondition(span)) => return Err(syn::Error::new(
150 span,
151 "`#[pallet::task_condition]` can only be used on items within an `impl` statement."
152 )),
153 Some(PalletAttr::TaskIndex(span)) => return Err(syn::Error::new(
154 span,
155 "`#[pallet::task_index]` can only be used on items within an `impl` statement."
156 )),
157 Some(PalletAttr::TaskList(span)) => return Err(syn::Error::new(
158 span,
159 "`#[pallet::task_list]` can only be used on items within an `impl` statement."
160 )),
161 Some(PalletAttr::RuntimeTask(_)) if task_enum.is_none() =>
162 task_enum = Some(syn::parse2::<tasks::TaskEnumDef>(item.to_token_stream())?),
163 Some(PalletAttr::Error(span)) if error.is_none() =>
164 error = Some(error::ErrorDef::try_from(span, index, item)?),
165 Some(PalletAttr::RuntimeEvent(span)) if event.is_none() =>
166 event = Some(event::EventDef::try_from(span, index, item)?),
167 Some(PalletAttr::GenesisConfig(_)) if genesis_config.is_none() => {
168 let g = genesis_config::GenesisConfigDef::try_from(index, item)?;
169 genesis_config = Some(g);
170 },
171 Some(PalletAttr::GenesisBuild(span)) if genesis_build.is_none() => {
172 let g = genesis_build::GenesisBuildDef::try_from(span, item)?;
173 genesis_build = Some(g);
174 },
175 Some(PalletAttr::RuntimeOrigin(_)) if origin.is_none() =>
176 origin = Some(origin::OriginDef::try_from(item)?),
177 Some(PalletAttr::Inherent(_)) if inherent.is_none() =>
178 inherent = Some(inherent::InherentDef::try_from(item)?),
179 Some(PalletAttr::Storage(span)) =>
180 storages.push(storage::StorageDef::try_from(span, index, item, dev_mode)?),
181 Some(PalletAttr::ValidateUnsigned(_)) if validate_unsigned.is_none() => {
182 let v = validate_unsigned::ValidateUnsignedDef::try_from(item)?;
183 validate_unsigned = Some(v);
184 },
185 Some(PalletAttr::TypeValue(span)) =>
186 type_values.push(type_value::TypeValueDef::try_from(span, index, item)?),
187 Some(PalletAttr::ExtraConstants(_)) =>
188 extra_constants =
189 Some(extra_constants::ExtraConstantsDef::try_from(item)?),
190 Some(PalletAttr::Composite(span)) => {
191 let composite =
192 composite::CompositeDef::try_from(span, &frame_support, item)?;
193 if composites.iter().any(|def| {
194 match (&def.composite_keyword, &composite.composite_keyword) {
195 (
196 CompositeKeyword::FreezeReason(_),
197 CompositeKeyword::FreezeReason(_),
198 ) |
199 (CompositeKeyword::HoldReason(_), CompositeKeyword::HoldReason(_)) |
200 (CompositeKeyword::LockId(_), CompositeKeyword::LockId(_)) |
201 (
202 CompositeKeyword::SlashReason(_),
203 CompositeKeyword::SlashReason(_),
204 ) => true,
205 _ => false,
206 }
207 }) {
208 let msg = format!(
209 "Invalid duplicated `{}` definition",
210 composite.composite_keyword
211 );
212 return Err(syn::Error::new(composite.composite_keyword.span(), &msg))
213 }
214 composites.push(composite);
215 },
216 Some(PalletAttr::ViewFunctions(span)) => {
217 view_functions = Some(view_functions::ViewFunctionsImplDef::try_from(span, item)?);
218 }
219 Some(attr) => {
220 let msg = "Invalid duplicated attribute";
221 return Err(syn::Error::new(attr.span(), msg))
222 },
223 None => (),
224 }
225 }
226
227 if genesis_config.is_some() != genesis_build.is_some() {
228 let msg = format!(
229 "`#[pallet::genesis_config]` and `#[pallet::genesis_build]` attributes must be \
230 either both used or both not used, instead genesis_config is {} and genesis_build \
231 is {}",
232 genesis_config.as_ref().map_or("unused", |_| "used"),
233 genesis_build.as_ref().map_or("unused", |_| "used"),
234 );
235 return Err(syn::Error::new(item_span, msg));
236 }
237
238 Self::resolve_tasks(&item_span, &mut tasks, &mut task_enum, items)?;
239
240 let def = Def {
241 item,
242 config: config
243 .ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::config]`"))?,
244 pallet_struct: pallet_struct
245 .ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::pallet]`"))?,
246 hooks,
247 call,
248 tasks,
249 task_enum,
250 extra_constants,
251 genesis_config,
252 genesis_build,
253 validate_unsigned,
254 error,
255 event,
256 origin,
257 inherent,
258 storages,
259 composites,
260 type_values,
261 frame_system,
262 frame_support,
263 dev_mode,
264 view_functions,
265 is_frame_system,
266 };
267
268 def.check_instance_usage()?;
269
270 Ok(def)
271 }
272
273 fn resolve_tasks(
275 item_span: &proc_macro2::Span,
276 tasks: &mut Option<tasks::TasksDef>,
277 task_enum: &mut Option<tasks::TaskEnumDef>,
278 items: &mut Vec<syn::Item>,
279 ) -> syn::Result<()> {
280 Self::resolve_manual_tasks_impl(tasks, task_enum, items)?;
282
283 Self::resolve_manual_task_enum(tasks, task_enum, items)?;
285
286 match (&task_enum, &tasks) {
288 (Some(_), None) =>
289 return Err(syn::Error::new(
290 *item_span,
291 "Missing `#[pallet::tasks_experimental]` impl",
292 )),
293 (None, Some(tasks)) =>
294 if tasks.tasks_attr.is_none() {
295 return Err(syn::Error::new(
296 tasks.item_impl.impl_token.span(),
297 "A `#[pallet::tasks_experimental]` attribute must be attached to your `Task` impl if the \
298 task enum has been omitted",
299 ));
300 } else {
301 },
302 _ => (),
303 }
304
305 Ok(())
306 }
307
308 fn resolve_manual_task_enum(
311 tasks: &Option<tasks::TasksDef>,
312 task_enum: &mut Option<tasks::TaskEnumDef>,
313 items: &mut Vec<syn::Item>,
314 ) -> syn::Result<()> {
315 let (None, Some(tasks)) = (&task_enum, &tasks) else { return Ok(()) };
316 let syn::Type::Path(type_path) = &*tasks.item_impl.self_ty else { return Ok(()) };
317 let type_path = type_path.path.segments.iter().collect::<Vec<_>>();
318 let (Some(seg), None) = (type_path.get(0), type_path.get(1)) else { return Ok(()) };
319 let mut result = None;
320 for item in items {
321 let syn::Item::Enum(item_enum) = item else { continue };
322 if item_enum.ident == seg.ident {
323 result = Some(syn::parse2::<tasks::TaskEnumDef>(item_enum.to_token_stream())?);
324 *item = syn::Item::Verbatim(quote::quote!());
328 break;
329 }
330 }
331 *task_enum = result;
332 Ok(())
333 }
334
335 pub fn resolve_manual_tasks_impl(
338 tasks: &mut Option<tasks::TasksDef>,
339 task_enum: &Option<tasks::TaskEnumDef>,
340 items: &Vec<syn::Item>,
341 ) -> syn::Result<()> {
342 let None = tasks else { return Ok(()) };
343 let mut result = None;
344 for item in items {
345 let syn::Item::Impl(item_impl) = item else { continue };
346 let Some((_, path, _)) = &item_impl.trait_ else { continue };
347 let Some(trait_last_seg) = path.segments.last() else { continue };
348 let syn::Type::Path(target_path) = &*item_impl.self_ty else { continue };
349 let target_path = target_path.path.segments.iter().collect::<Vec<_>>();
350 let (Some(target_ident), None) = (target_path.get(0), target_path.get(1)) else {
351 continue;
352 };
353 let matches_task_enum = match task_enum {
354 Some(task_enum) => task_enum.item_enum.ident == target_ident.ident,
355 None => true,
356 };
357 if trait_last_seg.ident == "Task" && matches_task_enum {
358 result = Some(syn::parse2::<tasks::TasksDef>(item_impl.to_token_stream())?);
359 break;
360 }
361 }
362 *tasks = result;
363 Ok(())
364 }
365
366 fn check_instance_usage(&self) -> syn::Result<()> {
369 let mut instances = vec![];
370 instances.extend_from_slice(&self.pallet_struct.instances[..]);
371 instances.extend(&mut self.storages.iter().flat_map(|s| s.instances.clone()));
372 if let Some(call) = &self.call {
373 instances.extend_from_slice(&call.instances[..]);
374 }
375 if let Some(hooks) = &self.hooks {
376 instances.extend_from_slice(&hooks.instances[..]);
377 }
378 if let Some(event) = &self.event {
379 instances.extend_from_slice(&event.instances[..]);
380 }
381 if let Some(error) = &self.error {
382 instances.extend_from_slice(&error.instances[..]);
383 }
384 if let Some(inherent) = &self.inherent {
385 instances.extend_from_slice(&inherent.instances[..]);
386 }
387 if let Some(origin) = &self.origin {
388 instances.extend_from_slice(&origin.instances[..]);
389 }
390 if let Some(genesis_config) = &self.genesis_config {
391 instances.extend_from_slice(&genesis_config.instances[..]);
392 }
393 if let Some(genesis_build) = &self.genesis_build {
394 genesis_build.instances.as_ref().map(|i| instances.extend_from_slice(&i));
395 }
396 if let Some(extra_constants) = &self.extra_constants {
397 instances.extend_from_slice(&extra_constants.instances[..]);
398 }
399 if let Some(task_enum) = &self.task_enum {
400 instances.push(task_enum.instance_usage.clone());
401 }
402
403 let mut errors = instances.into_iter().filter_map(|instances| {
404 if instances.has_instance == self.config.has_instance {
405 return None;
406 }
407 let msg = if self.config.has_instance {
408 "Invalid generic declaration, trait is defined with instance but generic use none"
409 } else {
410 "Invalid generic declaration, trait is defined without instance but generic use \
411 some"
412 };
413 Some(syn::Error::new(instances.span, msg))
414 });
415
416 if let Some(mut first_error) = errors.next() {
417 for error in errors {
418 first_error.combine(error)
419 }
420 Err(first_error)
421 } else {
422 Ok(())
423 }
424 }
425
426 pub fn type_impl_generics(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
430 if self.config.has_instance {
431 quote::quote_spanned!(span => T: Config<I>, I: 'static)
432 } else {
433 quote::quote_spanned!(span => T: Config)
434 }
435 }
436
437 pub fn type_decl_bounded_generics(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
441 if self.config.has_instance {
442 quote::quote_spanned!(span => T: Config<I>, I: 'static = ())
443 } else {
444 quote::quote_spanned!(span => T: Config)
445 }
446 }
447
448 pub fn type_decl_generics(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
452 if self.config.has_instance {
453 quote::quote_spanned!(span => T, I = ())
454 } else {
455 quote::quote_spanned!(span => T)
456 }
457 }
458
459 pub fn trait_use_generics(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
464 if self.config.has_instance {
465 quote::quote_spanned!(span => <I>)
466 } else {
467 quote::quote_spanned!(span => )
468 }
469 }
470
471 pub fn type_use_generics(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
475 if self.config.has_instance {
476 quote::quote_spanned!(span => T, I)
477 } else {
478 quote::quote_spanned!(span => T)
479 }
480 }
481}
482
483pub enum GenericKind {
486 None,
487 Config,
488 ConfigAndInstance,
489}
490
491impl GenericKind {
492 pub fn from_gens(has_config: bool, has_instance: bool) -> Result<Self, ()> {
494 match (has_config, has_instance) {
495 (false, false) => Ok(GenericKind::None),
496 (true, false) => Ok(GenericKind::Config),
497 (true, true) => Ok(GenericKind::ConfigAndInstance),
498 (false, true) => Err(()),
499 }
500 }
501
502 pub fn type_use_gen(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
506 match self {
507 GenericKind::None => quote::quote!(),
508 GenericKind::Config => quote::quote_spanned!(span => T),
509 GenericKind::ConfigAndInstance => quote::quote_spanned!(span => T, I),
510 }
511 }
512
513 pub fn type_impl_gen(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
515 match self {
516 GenericKind::None => quote::quote!(),
517 GenericKind::Config => quote::quote_spanned!(span => T: Config),
518 GenericKind::ConfigAndInstance => {
519 quote::quote_spanned!(span => T: Config<I>, I: 'static)
520 },
521 }
522 }
523
524 pub fn is_generic(&self) -> bool {
526 match self {
527 GenericKind::None => false,
528 GenericKind::Config | GenericKind::ConfigAndInstance => true,
529 }
530 }
531}
532
533mod keyword {
535 syn::custom_keyword!(origin);
536 syn::custom_keyword!(call);
537 syn::custom_keyword!(tasks_experimental);
538 syn::custom_keyword!(task_enum);
539 syn::custom_keyword!(task_list);
540 syn::custom_keyword!(task_condition);
541 syn::custom_keyword!(task_index);
542 syn::custom_keyword!(weight);
543 syn::custom_keyword!(event);
544 syn::custom_keyword!(config);
545 syn::custom_keyword!(with_default);
546 syn::custom_keyword!(without_automatic_metadata);
547 syn::custom_keyword!(frame_system_config);
548 syn::custom_keyword!(hooks);
549 syn::custom_keyword!(inherent);
550 syn::custom_keyword!(error);
551 syn::custom_keyword!(storage);
552 syn::custom_keyword!(genesis_build);
553 syn::custom_keyword!(genesis_config);
554 syn::custom_keyword!(validate_unsigned);
555 syn::custom_keyword!(type_value);
556 syn::custom_keyword!(pallet);
557 syn::custom_keyword!(extra_constants);
558 syn::custom_keyword!(composite_enum);
559 syn::custom_keyword!(view_functions);
560}
561
562#[derive(Debug, Clone, PartialEq, Eq, Hash)]
564enum ConfigValue {
565 WithDefault(keyword::with_default),
567 WithoutAutomaticMetadata(keyword::without_automatic_metadata),
569 FrameSystemConfig(keyword::frame_system_config),
571}
572
573impl syn::parse::Parse for ConfigValue {
574 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
575 let lookahead = input.lookahead1();
576
577 if lookahead.peek(keyword::with_default) {
578 input.parse().map(ConfigValue::WithDefault)
579 } else if lookahead.peek(keyword::without_automatic_metadata) {
580 input.parse().map(ConfigValue::WithoutAutomaticMetadata)
581 } else if lookahead.peek(keyword::frame_system_config) {
582 input.parse().map(ConfigValue::FrameSystemConfig)
583 } else {
584 Err(lookahead.error())
585 }
586 }
587}
588
589enum PalletAttr {
592 Config {
593 span: proc_macro2::Span,
594 with_default: bool,
595 without_automatic_metadata: bool,
596 frame_system_config: bool,
597 },
598 Pallet(proc_macro2::Span),
599 Hooks(proc_macro2::Span),
600 RuntimeCall(Option<InheritedCallWeightAttr>, proc_macro2::Span),
638 Error(proc_macro2::Span),
639 Tasks(proc_macro2::Span),
640 TaskList(proc_macro2::Span),
641 TaskCondition(proc_macro2::Span),
642 TaskIndex(proc_macro2::Span),
643 RuntimeTask(proc_macro2::Span),
644 RuntimeEvent(proc_macro2::Span),
645 RuntimeOrigin(proc_macro2::Span),
646 Inherent(proc_macro2::Span),
647 Storage(proc_macro2::Span),
648 GenesisConfig(proc_macro2::Span),
649 GenesisBuild(proc_macro2::Span),
650 ValidateUnsigned(proc_macro2::Span),
651 TypeValue(proc_macro2::Span),
652 ExtraConstants(proc_macro2::Span),
653 Composite(proc_macro2::Span),
654 ViewFunctions(proc_macro2::Span),
655}
656
657impl PalletAttr {
658 fn span(&self) -> proc_macro2::Span {
659 match self {
660 Self::Config { span, .. } => *span,
661 Self::Pallet(span) => *span,
662 Self::Hooks(span) => *span,
663 Self::Tasks(span) => *span,
664 Self::TaskCondition(span) => *span,
665 Self::TaskIndex(span) => *span,
666 Self::TaskList(span) => *span,
667 Self::Error(span) => *span,
668 Self::RuntimeTask(span) => *span,
669 Self::RuntimeCall(_, span) => *span,
670 Self::RuntimeEvent(span) => *span,
671 Self::RuntimeOrigin(span) => *span,
672 Self::Inherent(span) => *span,
673 Self::Storage(span) => *span,
674 Self::GenesisConfig(span) => *span,
675 Self::GenesisBuild(span) => *span,
676 Self::ValidateUnsigned(span) => *span,
677 Self::TypeValue(span) => *span,
678 Self::ExtraConstants(span) => *span,
679 Self::Composite(span) => *span,
680 Self::ViewFunctions(span) => *span,
681 }
682 }
683}
684
685impl syn::parse::Parse for PalletAttr {
686 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
687 input.parse::<syn::Token![#]>()?;
688 let content;
689 syn::bracketed!(content in input);
690 content.parse::<keyword::pallet>()?;
691 content.parse::<syn::Token![::]>()?;
692
693 let lookahead = content.lookahead1();
694 if lookahead.peek(keyword::config) {
695 let span = content.parse::<keyword::config>()?.span();
696 if content.peek(syn::token::Paren) {
697 let inside_config;
698
699 let _paren = syn::parenthesized!(inside_config in content);
701
702 let fields: syn::punctuated::Punctuated<ConfigValue, syn::Token![,]> =
703 inside_config.parse_terminated(ConfigValue::parse, syn::Token![,])?;
704 let config_values = fields.iter().collect::<Vec<_>>();
705
706 let mut with_default = false;
707 let mut without_automatic_metadata = false;
708 let mut frame_system_config = false;
709 for config in config_values {
710 match config {
711 ConfigValue::WithDefault(_) => {
712 if with_default {
713 return Err(syn::Error::new(
714 span,
715 "Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates: with_default.",
716 ));
717 }
718 with_default = true;
719 },
720 ConfigValue::WithoutAutomaticMetadata(_) => {
721 if without_automatic_metadata {
722 return Err(syn::Error::new(
723 span,
724 "Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates: without_automatic_metadata.",
725 ));
726 }
727 without_automatic_metadata = true;
728 },
729 ConfigValue::FrameSystemConfig(_) => {
730 if frame_system_config {
731 return Err(syn::Error::new(
732 span,
733 "Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates: frame_system_config.",
734 ));
735 }
736 frame_system_config = true;
737 },
738 }
739 }
740
741 Ok(PalletAttr::Config {
742 span,
743 with_default,
744 without_automatic_metadata,
745 frame_system_config,
746 })
747 } else {
748 Ok(PalletAttr::Config {
749 span,
750 with_default: false,
751 without_automatic_metadata: false,
752 frame_system_config: false,
753 })
754 }
755 } else if lookahead.peek(keyword::pallet) {
756 Ok(PalletAttr::Pallet(content.parse::<keyword::pallet>()?.span()))
757 } else if lookahead.peek(keyword::hooks) {
758 Ok(PalletAttr::Hooks(content.parse::<keyword::hooks>()?.span()))
759 } else if lookahead.peek(keyword::call) {
760 let span = content.parse::<keyword::call>().expect("peeked").span();
761 let attr = match content.is_empty() {
762 true => None,
763 false => Some(InheritedCallWeightAttr::parse(&content)?),
764 };
765 Ok(PalletAttr::RuntimeCall(attr, span))
766 } else if lookahead.peek(keyword::tasks_experimental) {
767 Ok(PalletAttr::Tasks(content.parse::<keyword::tasks_experimental>()?.span()))
768 } else if lookahead.peek(keyword::task_enum) {
769 Ok(PalletAttr::RuntimeTask(content.parse::<keyword::task_enum>()?.span()))
770 } else if lookahead.peek(keyword::task_condition) {
771 Ok(PalletAttr::TaskCondition(content.parse::<keyword::task_condition>()?.span()))
772 } else if lookahead.peek(keyword::task_index) {
773 Ok(PalletAttr::TaskIndex(content.parse::<keyword::task_index>()?.span()))
774 } else if lookahead.peek(keyword::task_list) {
775 Ok(PalletAttr::TaskList(content.parse::<keyword::task_list>()?.span()))
776 } else if lookahead.peek(keyword::error) {
777 Ok(PalletAttr::Error(content.parse::<keyword::error>()?.span()))
778 } else if lookahead.peek(keyword::event) {
779 Ok(PalletAttr::RuntimeEvent(content.parse::<keyword::event>()?.span()))
780 } else if lookahead.peek(keyword::origin) {
781 Ok(PalletAttr::RuntimeOrigin(content.parse::<keyword::origin>()?.span()))
782 } else if lookahead.peek(keyword::inherent) {
783 Ok(PalletAttr::Inherent(content.parse::<keyword::inherent>()?.span()))
784 } else if lookahead.peek(keyword::storage) {
785 Ok(PalletAttr::Storage(content.parse::<keyword::storage>()?.span()))
786 } else if lookahead.peek(keyword::genesis_config) {
787 Ok(PalletAttr::GenesisConfig(content.parse::<keyword::genesis_config>()?.span()))
788 } else if lookahead.peek(keyword::genesis_build) {
789 Ok(PalletAttr::GenesisBuild(content.parse::<keyword::genesis_build>()?.span()))
790 } else if lookahead.peek(keyword::validate_unsigned) {
791 Ok(PalletAttr::ValidateUnsigned(content.parse::<keyword::validate_unsigned>()?.span()))
792 } else if lookahead.peek(keyword::type_value) {
793 Ok(PalletAttr::TypeValue(content.parse::<keyword::type_value>()?.span()))
794 } else if lookahead.peek(keyword::extra_constants) {
795 Ok(PalletAttr::ExtraConstants(content.parse::<keyword::extra_constants>()?.span()))
796 } else if lookahead.peek(keyword::composite_enum) {
797 Ok(PalletAttr::Composite(content.parse::<keyword::composite_enum>()?.span()))
798 } else if lookahead.peek(keyword::view_functions) {
799 Ok(PalletAttr::ViewFunctions(content.parse::<keyword::view_functions>()?.span()))
800 } else {
801 Err(lookahead.error())
802 }
803 }
804}
805
806#[derive(Clone)]
808pub struct InheritedCallWeightAttr {
809 pub typename: syn::Type,
810}
811
812impl syn::parse::Parse for InheritedCallWeightAttr {
813 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
815 let content;
816 syn::parenthesized!(content in input);
817 content.parse::<keyword::weight>()?;
818 let lookahead = content.lookahead1();
819
820 let buffer = if lookahead.peek(syn::token::Paren) {
821 let inner;
822 syn::parenthesized!(inner in content);
823 inner
824 } else if lookahead.peek(syn::Token![=]) {
825 content.parse::<syn::Token![=]>().expect("peeked");
826 content
827 } else {
828 return Err(lookahead.error());
829 };
830
831 Ok(Self { typename: buffer.parse()? })
832 }
833}