diff --git a/substrate/frame/support/procedural/src/storage/parse.rs b/substrate/frame/support/procedural/src/storage/parse.rs
index 5d91fbcc0e..04af85a312 100644
--- a/substrate/frame/support/procedural/src/storage/parse.rs
+++ b/substrate/frame/support/procedural/src/storage/parse.rs
@@ -38,10 +38,37 @@ mod keyword {
syn::custom_keyword!(hasher);
}
+/// Specific `Opt` to implement structure with optional parsing
+#[derive(Debug, Clone)]
+pub struct Opt
{
+ pub inner: Option
,
+}
+impl syn::export::ToTokens for Opt {
+ fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+ if let Some(ref p) = self.inner {
+ p.to_tokens(tokens);
+ }
+ }
+}
+
+macro_rules! impl_parse_for_opt {
+ ($struct:ident => $token:path) => {
+ impl syn::parse::Parse for Opt<$struct> {
+ fn parse(input: syn::parse::ParseStream) -> syn::parse::Result {
+ if input.peek($token) {
+ input.parse().map(|p| Opt { inner: Some(p) })
+ } else {
+ Ok(Opt { inner: None })
+ }
+ }
+ }
+ };
+}
+
/// Parsing usage only
#[derive(Parse, ToTokens, Debug)]
struct StorageDefinition {
- pub hidden_crate: ext::Opt,
+ pub hidden_crate: Opt,
pub visibility: syn::Visibility,
pub trait_token: Token![trait],
pub ident: Ident,
@@ -62,7 +89,7 @@ struct StorageDefinition {
pub crate_ident: Ident,
pub where_clause: Option,
pub content: ext::Braces>,
- pub extra_genesis: ext::Opt,
+ pub extra_genesis: Opt,
}
#[derive(Parse, ToTokens, Debug)]
@@ -70,6 +97,7 @@ struct SpecificHiddenCrate {
pub keyword: keyword::hiddencrate,
pub ident: ext::Parens,
}
+impl_parse_for_opt!(SpecificHiddenCrate => keyword::hiddencrate);
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesis {
@@ -77,17 +105,36 @@ struct AddExtraGenesis {
pub content: ext::Braces,
}
+impl_parse_for_opt!(AddExtraGenesis => keyword::add_extra_genesis);
+
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesisContent {
pub lines: ext::Punctuated,
}
-#[derive(Parse, ToTokens, Debug)]
+#[derive(ToTokens, Debug)]
enum AddExtraGenesisLineEnum {
AddExtraGenesisLine(AddExtraGenesisLine),
AddExtraGenesisBuild(DeclStorageBuild),
}
+impl syn::parse::Parse for AddExtraGenesisLineEnum {
+ fn parse(input: syn::parse::ParseStream) -> syn::parse::Result {
+ let input_fork = input.fork();
+ // OuterAttributes are forbidden for build variant,
+ // However to have better documentation we match against the keyword after those attributes.
+ let _: ext::OuterAttributes = input_fork.parse()?;
+ let lookahead = input_fork.lookahead1();
+ if lookahead.peek(keyword::build) {
+ Ok(Self::AddExtraGenesisBuild(input.parse()?))
+ } else if lookahead.peek(keyword::config) {
+ Ok(Self::AddExtraGenesisLine(input.parse()?))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+}
+
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesisLine {
pub attrs: ext::OuterAttributes,
@@ -95,7 +142,7 @@ struct AddExtraGenesisLine {
pub extra_field: ext::Parens,
pub coldot_token: Token![:],
pub extra_type: syn::Type,
- pub default_value: ext::Opt,
+ pub default_value: Opt,
}
#[derive(Parse, ToTokens, Debug)]
@@ -106,12 +153,12 @@ struct DeclStorageLine {
pub visibility: syn::Visibility,
// name
pub name: Ident,
- pub getter: ext::Opt,
- pub config: ext::Opt,
- pub build: ext::Opt,
+ pub getter: Opt,
+ pub config: Opt,
+ pub build: Opt,
pub coldot_token: Token![:],
pub storage_type: DeclStorageType,
- pub default_value: ext::Opt,
+ pub default_value: Opt,
}
#[derive(Parse, ToTokens, Debug)]
@@ -126,19 +173,25 @@ struct DeclStorageGetter {
pub getfn: ext::Parens,
}
+impl_parse_for_opt!(DeclStorageGetter => keyword::get);
+
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageConfig {
pub config_keyword: keyword::config,
pub expr: ext::Parens