// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::{pallet::Def, COUNTER};
use frame_support_procedural_tools::get_doc_literals;
use quote::ToTokens;
use syn::{spanned::Spanned, Ident};
///
/// * add various derive trait on GenesisConfig struct.
pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream {
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
let (genesis_config, def_macro_ident, std_macro_ident) =
if let Some(genesis_config) = &def.genesis_config {
let def_macro_ident = Ident::new(
&format!("__is_genesis_config_defined_{}", count),
genesis_config.genesis_config.span(),
);
let std_macro_ident = Ident::new(
&format!("__is_std_macro_defined_for_genesis_{}", count),
genesis_config.genesis_config.span(),
);
(genesis_config, def_macro_ident, std_macro_ident)
} else {
let def_macro_ident =
Ident::new(&format!("__is_genesis_config_defined_{}", count), def.item.span());
let std_macro_ident =
Ident::new(&format!("__is_std_enabled_for_genesis_{}", count), def.item.span());
return quote::quote! {
#[doc(hidden)]
pub mod __substrate_genesis_config_check {
#[macro_export]
#[doc(hidden)]
macro_rules! #def_macro_ident {
($pallet_name:ident) => {
compile_error!(concat!(
"`",
stringify!($pallet_name),
"` does not have #[pallet::genesis_config] defined, perhaps you should \
remove `Config` from construct_runtime?",
));
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! #std_macro_ident {
($pallet_name:ident, $pallet_path:expr) => {};
}
#[doc(hidden)]
pub use #def_macro_ident as is_genesis_config_defined;
#[doc(hidden)]
pub use #std_macro_ident as is_std_enabled_for_genesis;
}
}
};
let frame_support = &def.frame_support;
let genesis_config_item =
&mut def.item.content.as_mut().expect("Checked by def parser").1[genesis_config.index];
let serde_crate = format!("{}::__private::serde", frame_support.to_token_stream());
match genesis_config_item {
syn::Item::Enum(syn::ItemEnum { attrs, .. }) |
syn::Item::Struct(syn::ItemStruct { attrs, .. }) |
syn::Item::Type(syn::ItemType { attrs, .. }) => {
if get_doc_literals(attrs).is_empty() {
attrs.push(syn::parse_quote!(
#[doc = r"
Can be used to configure the
[genesis state](https://docs.substrate.io/build/genesis-configuration/)
of this pallet.
"]
));
}
attrs.push(syn::parse_quote!(
#[derive(#frame_support::Serialize, #frame_support::Deserialize)]
));
attrs.push(syn::parse_quote!( #[serde(rename_all = "camelCase")] ));
attrs.push(syn::parse_quote!( #[serde(deny_unknown_fields)] ));
attrs.push(syn::parse_quote!( #[serde(bound(serialize = ""))] ));
attrs.push(syn::parse_quote!( #[serde(bound(deserialize = ""))] ));
attrs.push(syn::parse_quote!( #[serde(crate = #serde_crate)] ));
},
_ => unreachable!("Checked by genesis_config parser"),
}
quote::quote! {
#[doc(hidden)]
pub mod __substrate_genesis_config_check {
#[macro_export]
#[doc(hidden)]
macro_rules! #def_macro_ident {
($pallet_name:ident) => {};
}
#[cfg(not(feature = "std"))]
#[macro_export]
#[doc(hidden)]
macro_rules! #std_macro_ident {
($pallet_name:ident, $pallet_path:expr) => {
compile_error!(concat!(
"`",
stringify!($pallet_name),
"` does not have the std feature enabled, this will cause the `",
$pallet_path,
"::GenesisConfig` type to not implement serde traits."
));
};
}
#[cfg(feature = "std")]
#[macro_export]
#[doc(hidden)]
macro_rules! #std_macro_ident {
($pallet_name:ident, $pallet_path:expr) => {};
}
#[doc(hidden)]
pub use #def_macro_ident as is_genesis_config_defined;
#[doc(hidden)]
pub use #std_macro_ident as is_std_enabled_for_genesis;
}
}
}