Support pallet::storage conditional compilation (#8324)

* Support pallet::storage conditional compilation.

* Add docs for cfg attributes.

* Keep strong types for get cfg attrs return.

* Update frame/support/procedural/src/pallet/parse/helper.rs

* Update frame/support/procedural/src/pallet/parse/storage.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Shaun Wang
2021-03-16 21:51:51 +13:00
committed by GitHub
parent 900bf2832a
commit 844e25522c
13 changed files with 117 additions and 12 deletions
@@ -172,7 +172,7 @@ impl CallDef {
}
let mut call_var_attrs: Vec<FunctionAttr> =
helper::take_item_attrs(&mut method.attrs)?;
helper::take_item_pallet_attrs(&mut method.attrs)?;
if call_var_attrs.len() != 1 {
let msg = if call_var_attrs.is_empty() {
@@ -193,7 +193,7 @@ impl CallDef {
};
let arg_attrs: Vec<ArgAttrIsCompact> =
helper::take_item_attrs(&mut arg.attrs)?;
helper::take_item_pallet_attrs(&mut arg.attrs)?;
if arg_attrs.len() > 1 {
let msg = "Invalid pallet::call, argument has too many attributes";
@@ -309,7 +309,7 @@ impl ConfigDef {
|| check_event_type(frame_system, trait_item, has_instance)?;
// Parse for constant
let type_attrs_const: Vec<TypeAttrConst> = helper::take_item_attrs(trait_item)?;
let type_attrs_const: Vec<TypeAttrConst> = helper::take_item_pallet_attrs(trait_item)?;
if type_attrs_const.len() > 1 {
let msg = "Invalid attribute in pallet::config, only one attribute is expected";
@@ -339,7 +339,7 @@ impl ConfigDef {
}
}
let attr: Option<DisableFrameSystemSupertraitCheck> = helper::take_first_item_attr(
let attr: Option<DisableFrameSystemSupertraitCheck> = helper::take_first_item_pallet_attr(
&mut item.attrs
)?;
@@ -163,7 +163,7 @@ impl EventDef {
return Err(syn::Error::new(item.span(), "Invalid pallet::event, expected item enum"))
};
let event_attrs: Vec<PalletEventAttr> = helper::take_item_attrs(&mut item.attrs)?;
let event_attrs: Vec<PalletEventAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
let attr_info = PalletEventAttrInfo::from_attrs(event_attrs)?;
let metadata = attr_info.metadata.unwrap_or_else(Vec::new);
let deposit_event = attr_info.deposit_event;
@@ -47,7 +47,7 @@ pub trait MutItemAttrs {
}
/// Take the first pallet attribute (e.g. attribute like `#[pallet..]`) and decode it to `Attr`
pub fn take_first_item_attr<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Option<Attr>> where
pub fn take_first_item_pallet_attr<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Option<Attr>> where
Attr: syn::parse::Parse,
{
let attrs = if let Some(attrs) = item.mut_item_attrs() {
@@ -69,18 +69,29 @@ pub fn take_first_item_attr<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<O
}
/// Take all the pallet attributes (e.g. attribute like `#[pallet..]`) and decode them to `Attr`
pub fn take_item_attrs<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Vec<Attr>> where
pub fn take_item_pallet_attrs<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Vec<Attr>> where
Attr: syn::parse::Parse,
{
let mut pallet_attrs = Vec::new();
while let Some(attr) = take_first_item_attr(item)? {
while let Some(attr) = take_first_item_pallet_attr(item)? {
pallet_attrs.push(attr)
}
Ok(pallet_attrs)
}
/// Get all the cfg attributes (e.g. attribute like `#[cfg..]`) and decode them to `Attr`
pub fn get_item_cfg_attrs(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> {
attrs.iter().filter_map(|attr| {
if attr.path.segments.first().map_or(false, |segment| segment.ident == "cfg") {
Some(attr.clone())
} else {
None
}
}).collect::<Vec<_>>()
}
impl MutItemAttrs for syn::Item {
fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
match self {
@@ -89,7 +89,7 @@ impl Def {
let mut type_values = vec![];
for (index, item) in items.iter_mut().enumerate() {
let pallet_attr: Option<PalletAttr> = helper::take_first_item_attr(item)?;
let pallet_attr: Option<PalletAttr> = helper::take_first_item_pallet_attr(item)?;
match pallet_attr {
Some(PalletAttr::Config(span)) if config.is_none() =>
@@ -78,7 +78,7 @@ impl PalletStructDef {
return Err(syn::Error::new(item.span(), msg));
};
let mut event_attrs: Vec<PalletStructAttr> = helper::take_item_attrs(&mut item.attrs)?;
let mut event_attrs: Vec<PalletStructAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
if event_attrs.len() > 1 {
let msg = "Invalid pallet::pallet, multiple argument pallet::generate_store found";
return Err(syn::Error::new(event_attrs[1].keyword.span(), msg));
@@ -91,6 +91,8 @@ pub struct StorageDef {
pub where_clause: Option<syn::WhereClause>,
/// The span of the pallet::storage attribute.
pub attr_span: proc_macro2::Span,
/// The `cfg` attributes.
pub cfg_attrs: Vec<syn::Attribute>,
}
/// In `Foo<A, B, C>` retrieve the argument at given position, i.e. A is argument at position 0.
@@ -125,13 +127,15 @@ impl StorageDef {
return Err(syn::Error::new(item.span(), "Invalid pallet::storage, expected item type"));
};
let mut attrs: Vec<PalletStorageAttr> = helper::take_item_attrs(&mut item.attrs)?;
let mut attrs: Vec<PalletStorageAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
if attrs.len() > 1 {
let msg = "Invalid pallet::storage, multiple argument pallet::getter found";
return Err(syn::Error::new(attrs[1].getter.span(), msg));
}
let getter = attrs.pop().map(|attr| attr.getter);
let cfg_attrs = helper::get_item_cfg_attrs(&item.attrs);
let mut instances = vec![];
instances.push(helper::check_type_def_gen(&item.generics, item.ident.span())?);
@@ -223,6 +227,7 @@ impl StorageDef {
getter,
query_kind,
where_clause,
cfg_attrs,
})
}
}