// This file is part of Substrate. // Copyright (C) 2018-2022 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. //! Macros that define an Event types. Events can be used to easily report changes or conditions //! in your runtime to external entities like users, chain explorers, or dApps. // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . /// Implement the `Event` for a module. /// /// # Simple Event Example: /// /// ```rust /// frame_support::decl_event!( /// pub enum Event { /// Success, /// Failure(String), /// } /// ); /// /// # fn main() {} /// ``` /// /// # Generic Event Example: /// /// ```rust /// trait Config { /// type Balance; /// type Token; /// } /// /// mod event1 { /// // Event that specifies the generic parameter explicitly (`Balance`). /// frame_support::decl_event!( /// pub enum Event where Balance = ::Balance { /// Message(Balance), /// } /// ); /// } /// /// mod event2 { /// // Event that uses the generic parameter `Balance`. /// // If no name for the generic parameter is specified explicitly, /// // the name will be taken from the type name of the trait. /// frame_support::decl_event!( /// pub enum Event where ::Balance { /// Message(Balance), /// } /// ); /// } /// /// mod event3 { /// // And we even support declaring multiple generic parameters! /// frame_support::decl_event!( /// pub enum Event where ::Balance, ::Token { /// Message(Balance, Token), /// } /// ); /// } /// /// # fn main() {} /// ``` /// /// The syntax for generic events requires the `where`. /// /// # Generic Event with Instance Example: /// /// ```rust /// # struct DefaultInstance; /// # trait Instance {} /// # impl Instance for DefaultInstance {} /// trait Config { /// type Balance; /// type Token; /// } /// /// // For module with instances, DefaultInstance is optional /// frame_support::decl_event!( /// pub enum Event where /// ::Balance, /// ::Token /// { /// Message(Balance, Token), /// } /// ); /// # fn main() {} /// ``` #[macro_export] macro_rules! decl_event { ( $(#[$attr:meta])* pub enum Event<$evt_generic_param:ident $(, $instance:ident $(: $instantiable:ident)? $( = $event_default_instance:path)? )?> where $( $tt:tt )* ) => { $crate::__decl_generic_event!( $( #[ $attr ] )*; $evt_generic_param; $($instance $( = $event_default_instance)? )?; { $( $tt )* }; ); }; ( $(#[$attr:meta])* pub enum Event { $( $events:tt )* } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive( Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode, $crate::scale_info::TypeInfo, $crate::RuntimeDebug, )] #[scale_info(capture_docs = "always")] /// Events for this module. /// $(#[$attr])* pub enum Event { $( $events )* } impl From for () { fn from(_: Event) -> () { () } } } } #[macro_export] #[doc(hidden)] // This parsing to retrieve last ident on unnamed generic could be improved. // but user can still name it if the parsing fails. And improving parsing seems difficult. macro_rules! __decl_generic_event { ( $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { $( $tt:tt )* }; ) => { $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; $($instance $( = $event_default_instance)? )?; { $( $tt )* }; {}; ); }; // Finish formatting on an unnamed one (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { <$generic:ident as $trait:path>::$trait_type:ident $(,)? { $( $events:tt )* } }; {$( $parsed:tt)*}; ) => { $crate::__decl_generic_event!(@generate $( #[ $attr ] )*; $event_generic_param; $($instance $( = $event_default_instance)? )?; { $($events)* }; { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type }; ); }; // Finish formatting on a named one (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { $generic_rename:ident = $generic_type:ty $(,)? { $( $events:tt )* } }; { $($parsed:tt)* }; ) => { $crate::__decl_generic_event!(@generate $(#[$attr])*; $event_generic_param; $($instance $( = $event_default_instance)? )?; { $($events)* }; { $($parsed)*, $generic_rename = $generic_type }; ); }; // Parse named (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { $generic_rename:ident = $generic_type:ty, $($rest:tt)* }; {$( $parsed:tt)*}; ) => { $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; $( $instance $( = $event_default_instance)? )?; { $($rest)* }; { $($parsed)*, $generic_rename = $generic_type }; ); }; // Parse unnamed (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { <$generic:ident as $trait:path>::$trait_type:ident, $($rest:tt)* }; {$($parsed:tt)*}; ) => { $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; $($instance $( = $event_default_instance)? )?; { $($rest)* }; { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type }; ); }; // Unnamed type can't be parsed (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { $generic_type:ty, $($rest:tt)* }; { $($parsed:tt)* }; ) => { $crate::__decl_generic_event!(@cannot_parse $generic_type); }; // Final unnamed type can't be parsed (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { $generic_type:ty { $( $events:tt )* } }; {$( $parsed:tt)*}; ) => { $crate::__decl_generic_event!(@cannot_parse $generic_type); }; (@generate $(#[$attr:meta])*; $event_generic_param:ident; $($instance:ident $( = $event_default_instance:path)? )?; { $( $events:tt )* }; { ,$( $generic_param:ident = $generic_type:ty ),* }; ) => { /// [`RawEvent`] specialized for the configuration [`Config`] /// /// [`RawEvent`]: enum.RawEvent.html /// [`Config`]: trait.Config.html pub type Event<$event_generic_param $(, $instance $( = $event_default_instance)? )?> = RawEvent<$( $generic_type ),* $(, $instance)? >; #[derive( Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode, $crate::scale_info::TypeInfo, $crate::RuntimeDebug, )] #[scale_info(capture_docs = "always")] /// Events for this module. /// $(#[$attr])* pub enum RawEvent<$( $generic_param ),* $(, $instance)? > { $( $events )* $( #[doc(hidden)] #[codec(skip)] PhantomData($crate::sp_std::marker::PhantomData<$instance>), )? } impl<$( $generic_param ),* $(, $instance)? > From> for () { fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () } } }; (@cannot_parse $ty:ty) => { compile_error!(concat!("The type `", stringify!($ty), "` can't be parsed as an unnamed one, please name it `Name = ", stringify!($ty), "`")); } }