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