diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 054d90d7bbaeb..060882d1123bf 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -15,9 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// tag::description[] //! Proc macro of Support code for the runtime. -// end::description[] #![recursion_limit="512"] @@ -296,7 +294,7 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream { /// The return type of the annotated function must be `Result`. All changes to storage performed /// by the annotated function are discarded if it returns `Err`, or committed if `Ok`. /// -/// #Example +/// # Example /// /// ```nocompile /// #[transactional] @@ -313,5 +311,5 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream { /// ``` #[proc_macro_attribute] pub fn transactional(attr: TokenStream, input: TokenStream) -> TokenStream { - transactional::transactional(attr, input) + transactional::transactional(attr, input).unwrap_or_else(|e| e.to_compile_error().into()) } diff --git a/frame/support/procedural/src/transactional.rs b/frame/support/procedural/src/transactional.rs index a001f44c4d482..fbd0c9ca0b3c4 100644 --- a/frame/support/procedural/src/transactional.rs +++ b/frame/support/procedural/src/transactional.rs @@ -17,15 +17,17 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, ItemFn}; +use syn::{ItemFn, Result}; +use frame_support_procedural_tools::generate_crate_access_2018; -pub fn transactional(_attr: TokenStream, input: TokenStream) -> TokenStream { - let ItemFn { attrs, vis, sig, block } = parse_macro_input!(input as ItemFn); +pub fn transactional(_attr: TokenStream, input: TokenStream) -> Result { + let ItemFn { attrs, vis, sig, block } = syn::parse(input)?; + let crate_ = generate_crate_access_2018()?; let output = quote! { #(#attrs)* - #vis #sig { - use frame_support::storage::{with_transaction, TransactionOutcome}; + #vis #sig { + use #crate_::storage::{with_transaction, TransactionOutcome}; with_transaction(|| { let r = #block; if r.is_ok() { @@ -34,7 +36,8 @@ pub fn transactional(_attr: TokenStream, input: TokenStream) -> TokenStream { TransactionOutcome::Rollback(r) } }) - } - }; - output.into() + } + }; + + Ok(output.into()) } diff --git a/frame/support/procedural/tools/src/lib.rs b/frame/support/procedural/tools/src/lib.rs index 0033787a7c045..c5a27c809aff8 100644 --- a/frame/support/procedural/tools/src/lib.rs +++ b/frame/support/procedural/tools/src/lib.rs @@ -46,6 +46,25 @@ pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream { } } +/// Generate the crate access for the `frame-support` crate using 2018 syntax. +/// +/// Output will for example be `frame_support`. +pub fn generate_crate_access_2018() -> Result { + if std::env::var("CARGO_PKG_NAME").unwrap() == "frame-support" { + Ok(quote::quote!( frame_support )) + } else { + match crate_name("frame-support") { + Ok(name) => { + let name = Ident::new(&name, Span::call_site()); + Ok(quote!( #name )) + }, + Err(e) => { + Err(Error::new(Span::call_site(), &e)) + } + } + } +} + /// Generates the hidden includes that are required to make the macro independent from its scope. pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream { if std::env::var("CARGO_PKG_NAME").unwrap() == def_crate {