From ea10494ca9585833484626d3858ba1a5c79c3058 Mon Sep 17 00:00:00 2001
From: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Date: Mon, 19 Apr 2021 12:09:23 +0200
Subject: [PATCH] Make pallet macro generate accessor to PalletInfo information
 on pallet placeholder (#8630)

* generate accessor to PalletInfo information on pallet placeholder

* remove unused

* use trait, and add tests

* less verbose doc

* add PalletInfoAccess to prelude for ease usage
---
 .../src/pallet/expand/pallet_struct.rs        | 23 +++++++++++++++++++
 substrate/frame/support/src/lib.rs            |  6 ++++-
 substrate/frame/support/src/traits.rs         |  2 +-
 .../frame/support/src/traits/metadata.rs      | 10 ++++++++
 substrate/frame/support/test/tests/pallet.rs  | 11 +++++++++
 .../support/test/tests/pallet_instance.rs     | 15 ++++++++++++
 .../tests/pallet_with_name_trait_is_valid.rs  |  2 +-
 substrate/frame/support/test/tests/system.rs  |  2 +-
 8 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
index fd3230edd1e..556c6515d47 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
@@ -23,6 +23,7 @@ use crate::pallet::{Def, parse::helper::get_doc_literals};
 /// * Implement ModuleErrorMetadata on Pallet
 /// * declare Module type alias for construct_runtime
 /// * replace the first field type of `struct Pallet` with `PhantomData` if it is `_`
+/// * implementation of `PalletInfoAccess` information
 pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
 	let frame_support = &def.frame_support;
 	let frame_system = &def.frame_system;
@@ -134,5 +135,27 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
 					.put_into_storage::<<T as #frame_system::Config>::PalletInfo, Self>();
 			}
 		}
+
+		// Implement `PalletInfoAccess` for `Pallet`
+		impl<#type_impl_gen> #frame_support::traits::PalletInfoAccess
+			for #pallet_ident<#type_use_gen>
+			#config_where_clause
+		{
+			fn index() -> usize {
+				<
+					<T as #frame_system::Config>::PalletInfo as #frame_support::traits::PalletInfo
+				>::index::<Self>()
+					.expect("Pallet is part of the runtime because pallet `Config` trait is \
+						implemented by the runtime")
+			}
+
+			fn name() -> &'static str {
+				<
+					<T as #frame_system::Config>::PalletInfo as #frame_support::traits::PalletInfo
+				>::name::<Self>()
+					.expect("Pallet is part of the runtime because pallet `Config` trait is \
+						implemented by the runtime")
+			}
+		}
 	)
 }
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index 5aa688ba28c..72c90018f75 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -1234,7 +1234,7 @@ pub mod pallet_prelude {
 		EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, DebugNoBound, CloneNoBound, Twox256,
 		Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, ensure,
 		RuntimeDebug, storage,
-		traits::{Get, Hooks, IsType, GetPalletVersion, EnsureOrigin},
+		traits::{Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess},
 		dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult},
 		weights::{DispatchClass, Pays, Weight},
 		storage::types::{StorageValue, StorageMap, StorageDoubleMap, ValueQuery, OptionQuery},
@@ -1362,6 +1362,10 @@ pub mod pallet_prelude {
 ///
 /// It declare `type Module` type alias for `Pallet`, used by [`construct_runtime`].
 ///
+/// It implements [`traits::PalletInfoAccess`] on `Pallet` to ease access to pallet informations
+/// given by [`frame_support::traits::PalletInfo`].
+/// (The implementation use the associated type `frame_system::Config::PalletInfo`).
+///
 /// If attribute generate_store then macro create the trait `Store` and implement it on `Pallet`.
 ///
 /// # Hooks: `#[pallet::hooks]` mandatory
diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs
index c629990dd66..7ee2b0a5609 100644
--- a/substrate/frame/support/src/traits.rs
+++ b/substrate/frame/support/src/traits.rs
@@ -61,7 +61,7 @@ pub use randomness::Randomness;
 mod metadata;
 pub use metadata::{
 	CallMetadata, GetCallMetadata, GetCallName, PalletInfo, PalletVersion, GetPalletVersion,
-	PALLET_VERSION_STORAGE_KEY_POSTFIX,
+	PALLET_VERSION_STORAGE_KEY_POSTFIX, PalletInfoAccess,
 };
 
 mod hooks;
diff --git a/substrate/frame/support/src/traits/metadata.rs b/substrate/frame/support/src/traits/metadata.rs
index ff4507dce9c..b13a0464b30 100644
--- a/substrate/frame/support/src/traits/metadata.rs
+++ b/substrate/frame/support/src/traits/metadata.rs
@@ -31,6 +31,16 @@ pub trait PalletInfo {
 	fn name<P: 'static>() -> Option<&'static str>;
 }
 
+/// Provides information about the pallet setup in the runtime.
+///
+/// Access the information provided by [`PalletInfo`] for a specific pallet.
+pub trait PalletInfoAccess {
+	/// Index of the pallet as configured in the runtime.
+	fn index() -> usize;
+	/// Name of the pallet as configured in the runtime.
+	fn name() -> &'static str;
+}
+
 /// The function and pallet name of the Call.
 #[derive(Clone, Eq, PartialEq, Default, RuntimeDebug)]
 pub struct CallMetadata {
diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs
index 04e8b2a8f18..8fc056a2f36 100644
--- a/substrate/frame/support/test/tests/pallet.rs
+++ b/substrate/frame/support/test/tests/pallet.rs
@@ -861,3 +861,14 @@ fn metadata() {
 
 	pretty_assertions::assert_eq!(pallet_metadata, expected_pallet_metadata);
 }
+
+#[test]
+fn test_pallet_info_access() {
+	assert_eq!(<System as frame_support::traits::PalletInfoAccess>::name(), "System");
+	assert_eq!(<Example as frame_support::traits::PalletInfoAccess>::name(), "Example");
+	assert_eq!(<Example2 as frame_support::traits::PalletInfoAccess>::name(), "Example2");
+
+	assert_eq!(<System as frame_support::traits::PalletInfoAccess>::index(), 0);
+	assert_eq!(<Example as frame_support::traits::PalletInfoAccess>::index(), 1);
+	assert_eq!(<Example2 as frame_support::traits::PalletInfoAccess>::index(), 2);
+}
diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs
index b181fe0bd6e..232a25ff5bf 100644
--- a/substrate/frame/support/test/tests/pallet_instance.rs
+++ b/substrate/frame/support/test/tests/pallet_instance.rs
@@ -712,3 +712,18 @@ fn metadata() {
 	pretty_assertions::assert_eq!(pallet_metadata, expected_pallet_metadata);
 	pretty_assertions::assert_eq!(pallet_instance1_metadata, expected_pallet_instance1_metadata);
 }
+
+#[test]
+fn test_pallet_info_access() {
+	assert_eq!(<System as frame_support::traits::PalletInfoAccess>::name(), "System");
+	assert_eq!(<Example as frame_support::traits::PalletInfoAccess>::name(), "Example");
+	assert_eq!(<Instance1Example as frame_support::traits::PalletInfoAccess>::name(), "Instance1Example");
+	assert_eq!(<Example2 as frame_support::traits::PalletInfoAccess>::name(), "Example2");
+	assert_eq!(<Instance1Example2 as frame_support::traits::PalletInfoAccess>::name(), "Instance1Example2");
+
+	assert_eq!(<System as frame_support::traits::PalletInfoAccess>::index(), 0);
+	assert_eq!(<Example as frame_support::traits::PalletInfoAccess>::index(), 1);
+	assert_eq!(<Instance1Example as frame_support::traits::PalletInfoAccess>::index(), 2);
+	assert_eq!(<Example2 as frame_support::traits::PalletInfoAccess>::index(), 3);
+	assert_eq!(<Instance1Example2 as frame_support::traits::PalletInfoAccess>::index(), 4);
+}
diff --git a/substrate/frame/support/test/tests/pallet_with_name_trait_is_valid.rs b/substrate/frame/support/test/tests/pallet_with_name_trait_is_valid.rs
index 3d96fe24d94..99c00b535fa 100644
--- a/substrate/frame/support/test/tests/pallet_with_name_trait_is_valid.rs
+++ b/substrate/frame/support/test/tests/pallet_with_name_trait_is_valid.rs
@@ -46,7 +46,7 @@ frame_support::decl_module! {
 		const Foo: u32 = u32::max_value();
 
 		#[weight = 0]
-		fn accumulate_dummy(origin, increase_by: T::Balance) {
+		fn accumulate_dummy(_origin, _increase_by: T::Balance) {
 			unimplemented!();
 		}
 
diff --git a/substrate/frame/support/test/tests/system.rs b/substrate/frame/support/test/tests/system.rs
index 19858731b3a..c4d7cf01ae2 100644
--- a/substrate/frame/support/test/tests/system.rs
+++ b/substrate/frame/support/test/tests/system.rs
@@ -36,7 +36,7 @@ pub trait Config: 'static + Eq + Clone {
 frame_support::decl_module! {
 	pub struct Module<T: Config> for enum Call where origin: T::Origin, system=self {
 		#[weight = 0]
-		fn noop(origin) {}
+		fn noop(_origin) {}
 	}
 }
 
-- 
GitLab