referrerpolicy=no-referrer-when-downgrade

frame_support_procedural/pallet/parse/
error.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use super::helper;
19use crate::deprecation::extract_or_return_allow_attrs;
20use quote::ToTokens;
21use syn::{spanned::Spanned, Fields};
22
23/// List of additional token to be used for parsing.
24mod keyword {
25	syn::custom_keyword!(Error);
26}
27
28/// Records information about the error enum variant field.
29pub struct VariantField {
30	/// Whether or not the field is named, i.e. whether it is a tuple variant or struct variant.
31	pub is_named: bool,
32}
33
34/// Records information about the error enum variants.
35pub struct VariantDef {
36	/// The variant ident.
37	pub ident: syn::Ident,
38	/// The variant field, if any.
39	pub field: Option<VariantField>,
40	/// The `cfg` attributes.
41	pub cfg_attrs: Vec<syn::Attribute>,
42	/// The `allow` attributes.
43	pub maybe_allow_attrs: Vec<syn::Attribute>,
44}
45
46/// This checks error declaration as a enum declaration with only variants without fields nor
47/// discriminant.
48pub struct ErrorDef {
49	/// The index of error item in pallet module.
50	pub index: usize,
51	/// Variant definitions.
52	pub variants: Vec<VariantDef>,
53	/// A set of usage of instance, must be check for consistency with trait.
54	pub instances: Vec<helper::InstanceUsage>,
55	/// The keyword error used (contains span).
56	pub error: keyword::Error,
57	/// The span of the pallet::error attribute.
58	pub attr_span: proc_macro2::Span,
59}
60
61impl ErrorDef {
62	pub fn try_from(
63		attr_span: proc_macro2::Span,
64		index: usize,
65		item: &mut syn::Item,
66	) -> syn::Result<Self> {
67		let item = if let syn::Item::Enum(item) = item {
68			item
69		} else {
70			return Err(syn::Error::new(item.span(), "Invalid pallet::error, expected item enum"))
71		};
72		if !matches!(item.vis, syn::Visibility::Public(_)) {
73			let msg = "Invalid pallet::error, `Error` must be public";
74			return Err(syn::Error::new(item.span(), msg))
75		}
76
77		crate::deprecation::prevent_deprecation_attr_on_outer_enum(&item.attrs)?;
78
79		let instances =
80			vec![helper::check_type_def_gen_no_bounds(&item.generics, item.ident.span())?];
81
82		if item.generics.where_clause.is_some() {
83			let msg = "Invalid pallet::error, where clause is not allowed on pallet error item";
84			return Err(syn::Error::new(item.generics.where_clause.as_ref().unwrap().span(), msg))
85		}
86
87		let error = syn::parse2::<keyword::Error>(item.ident.to_token_stream())?;
88
89		let variants = item
90			.variants
91			.iter()
92			.map(|variant| {
93				let field_ty = match &variant.fields {
94					Fields::Unit => None,
95					Fields::Named(_) => Some(VariantField { is_named: true }),
96					Fields::Unnamed(_) => Some(VariantField { is_named: false }),
97				};
98
99				match &variant.discriminant {
100					None |
101					Some((_, syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(_), .. }))) => {},
102					Some((_, expr)) => {
103						let msg = "Invalid pallet::error, only integer discriminants are supported";
104						return Err(syn::Error::new(expr.span(), msg))
105					},
106				}
107				let cfg_attrs: Vec<syn::Attribute> = helper::get_item_cfg_attrs(&variant.attrs);
108				let maybe_allow_attrs = extract_or_return_allow_attrs(&variant.attrs).collect();
109
110				Ok(VariantDef {
111					ident: variant.ident.clone(),
112					field: field_ty,
113					cfg_attrs,
114					maybe_allow_attrs,
115				})
116			})
117			.collect::<Result<_, _>>()?;
118
119		Ok(ErrorDef { attr_span, index, variants, instances, error })
120	}
121}