Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Automatic pallet parts in construct_runtime #9681

Merged
merged 53 commits into from
Oct 31, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5c8e299
implement automatic parts
gui1117 Jul 15, 2021
62afa97
ui tests
gui1117 Sep 2, 2021
2dc4412
rename
gui1117 Sep 2, 2021
a790517
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
gui1117 Sep 2, 2021
5bec9dd
remove unnecessary exclude
gui1117 Sep 2, 2021
8c9c19b
better doc
gui1117 Sep 6, 2021
4b405a3
better doc
gui1117 Sep 6, 2021
afde346
fix genesis config
gui1117 Sep 6, 2021
eebea7b
fix UI tests
gui1117 Sep 6, 2021
a910351
fix UI test
gui1117 Sep 6, 2021
ea68d3a
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
gui1117 Sep 6, 2021
6352dfd
Revert "fix UI test"
gui1117 Sep 6, 2021
480af69
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
gui1117 Sep 13, 2021
4127c1e
implemented used_parts
gui1117 Sep 13, 2021
aaac25a
Update frame/support/procedural/src/construct_runtime/mod.rs
gui1117 Sep 15, 2021
4fb77ab
doc + fmt
gui1117 Sep 15, 2021
a2442a4
Update frame/support/procedural/src/construct_runtime/parse.rs
gui1117 Sep 15, 2021
534f293
add doc in the macro
gui1117 Sep 15, 2021
0c72e96
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
gui1117 Sep 15, 2021
6871c71
remove yet some more parts
gui1117 Sep 15, 2021
3d463f5
fix ui test
gui1117 Sep 15, 2021
62a34d5
more determnistic error message + fix ui tests
gui1117 Sep 16, 2021
32ab5a4
fix ui test
gui1117 Sep 16, 2021
318c26c
Apply suggestions from code review
gui1117 Sep 20, 2021
4b1b178
do refactor + fix ui tests
gui1117 Sep 20, 2021
134b8df
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
gui1117 Sep 20, 2021
e571e9e
fmt
gui1117 Sep 20, 2021
ebb14fb
fix test
gui1117 Sep 20, 2021
5ea0535
fix test
gui1117 Sep 20, 2021
5787ad6
fix ui test
gui1117 Sep 20, 2021
03cb587
Apply suggestions from code review
gui1117 Sep 28, 2021
89cf841
refactor
gui1117 Sep 29, 2021
871b8bf
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
gui1117 Sep 30, 2021
25811d7
remove even more part in node-runtime
gui1117 Sep 30, 2021
cdb7151
fix test
gui1117 Oct 7, 2021
8b39dc0
Add flow chart for the construct_runtime! execution flow
KiChjang Oct 8, 2021
41baa40
Fix typo
KiChjang Oct 8, 2021
b9ade81
Ignore snippets that don't contain code
KiChjang Oct 9, 2021
e5e6adc
Merge remote-tracking branch 'origin/master' into gui-construct_runti…
KiChjang Oct 9, 2021
3c34573
Refactor some code in expand_after
KiChjang Oct 9, 2021
a22cf5b
Rename expand_after to match_and_insert
KiChjang Oct 9, 2021
b381c21
cargo fmt
KiChjang Oct 9, 2021
8dc3dab
Fix rename
KiChjang Oct 9, 2021
ffc053f
Remove frame_support argument to construct_runtime_parts
KiChjang Oct 10, 2021
d7e14b4
Make use of tt-call to simplify intermediate expansions
KiChjang Oct 10, 2021
eda408b
cargo fmt
KiChjang Oct 10, 2021
67d9cfa
Update match_and_insert documentation
KiChjang Oct 10, 2021
2584262
Reset cursor to 0 when no matching patterns are found
KiChjang Oct 12, 2021
c10400f
Reorder struct fields on MatchAndInsertDef
KiChjang Oct 12, 2021
cfe4d54
Add test for dependency renames and fix frame-support import
KiChjang Oct 13, 2021
8964094
Add more doc comments
KiChjang Oct 14, 2021
9681c77
Update frame/support/test/compile_pass/src/lib.rs
KiChjang Oct 18, 2021
b032085
Merge branch 'master' into gui-construct_runtime-auto
shawntabrizi Oct 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 31 additions & 31 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,46 +1189,46 @@ construct_runtime!(
NodeBlock = node_primitives::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Utility: pallet_utility::{Pallet, Call, Event},
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Authorship: pallet_authorship::{Pallet, Call, Storage, Inherent},
Indices: pallet_indices::{Pallet, Call, Storage, Config<T>, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event<T>, ValidateUnsigned},
Staking: pallet_staking::{Pallet, Call, Config<T>, Storage, Event<T>},
System: frame_system,
Utility: pallet_utility,
Babe: pallet_babe,
Timestamp: pallet_timestamp,
Authorship: pallet_authorship,
Indices: pallet_indices,
Balances: pallet_balances,
TransactionPayment: pallet_transaction_payment,
ElectionProviderMultiPhase: pallet_election_provider_multi_phase,
Staking: pallet_staking,
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The <T> generic here still makes me a bit sad, but that's really what #8743 aims to solve.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but I expect nobody to use this syntax anymore once all pallet use pallet macro.
maybe we can explicit whitelist syntax like use_parts as well.

Democracy: pallet_democracy::{Pallet, Call, Storage, Config<T>, Event<T>},
Democracy: pallet_democracy,
Council: pallet_collective::<Instance1>::{Pallet, Call, Storage, Origin<T>, Event<T>, Config<T>},
TechnicalCommittee: pallet_collective::<Instance2>::{Pallet, Call, Storage, Origin<T>, Event<T>, Config<T>},
Elections: pallet_elections_phragmen::{Pallet, Call, Storage, Event<T>, Config<T>},
Elections: pallet_elections_phragmen,
TechnicalMembership: pallet_membership::<Instance1>::{Pallet, Call, Storage, Event<T>, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned},
Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>},
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config},
Offences: pallet_offences::{Pallet, Storage, Event},
Grandpa: pallet_grandpa,
Treasury: pallet_treasury,
Contracts: pallet_contracts,
Sudo: pallet_sudo,
ImOnline: pallet_im_online,
AuthorityDiscovery: pallet_authority_discovery,
Offences: pallet_offences,
Historical: pallet_session_historical::{Pallet},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
Identity: pallet_identity::{Pallet, Call, Storage, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip,
Identity: pallet_identity,
Society: pallet_society::{Pallet, Call, Storage, Event<T>, Config<T>},
Recovery: pallet_recovery::{Pallet, Call, Storage, Event<T>},
Vesting: pallet_vesting::{Pallet, Call, Storage, Event<T>, Config<T>},
Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>},
Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>},
Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>},
Recovery: pallet_recovery,
Vesting: pallet_vesting,
Scheduler: pallet_scheduler,
Proxy: pallet_proxy,
Multisig: pallet_multisig,
Bounties: pallet_bounties::{Pallet, Call, Storage, Event<T>},
Tips: pallet_tips::{Pallet, Call, Storage, Event<T>},
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>},
Assets: pallet_assets,
Mmr: pallet_mmr::{Pallet, Storage},
Lottery: pallet_lottery::{Pallet, Call, Storage, Event<T>},
Gilt: pallet_gilt::{Pallet, Call, Storage, Event<T>, Config},
Uniques: pallet_uniques::{Pallet, Call, Storage, Event<T>},
TransactionStorage: pallet_transaction_storage::{Pallet, Call, Storage, Inherent, Config<T>, Event<T>},
Lottery: pallet_lottery,
Gilt: pallet_gilt,
Uniques: pallet_uniques,
TransactionStorage: pallet_transaction_storage,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ This looks a lot cleaner.

}
);

Expand Down
129 changes: 43 additions & 86 deletions frame/support/procedural/src/construct_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,111 +19,68 @@ mod expand;
mod parse;

use frame_support_procedural_tools::{
generate_crate_access, generate_hidden_includes, syn_ext as ext,
generate_crate_access, generate_crate_access_2018, generate_hidden_includes,
};
use parse::{
ExplicitRuntimeDeclaration, ImplicitRuntimeDeclaration, Pallet, RuntimeDeclaration,
WhereSection,
};
use parse::{PalletDeclaration, PalletPart, PalletPath, RuntimeDefinition, WhereSection};
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use std::collections::HashMap;
use syn::{Ident, Result};

/// The fixed name of the system pallet.
const SYSTEM_PALLET_NAME: &str = "System";

/// The complete definition of a pallet with the resulting fixed index.
#[derive(Debug, Clone)]
pub struct Pallet {
pub name: Ident,
pub index: u8,
pub path: PalletPath,
pub instance: Option<Ident>,
pub pallet_parts: Vec<PalletPart>,
}

impl Pallet {
/// Get resolved pallet parts
fn pallet_parts(&self) -> &[PalletPart] {
&self.pallet_parts
}
pub fn construct_runtime(input: TokenStream) -> TokenStream {
let input_copy = input.clone();
let definition = syn::parse_macro_input!(input as RuntimeDeclaration);

/// Find matching parts
fn find_part(&self, name: &str) -> Option<&PalletPart> {
self.pallet_parts.iter().find(|part| part.name() == name)
}
let res = match definition {
RuntimeDeclaration::Implicit(implicit_def) =>
construct_runtime_intermediary_expansion(input_copy.into(), implicit_def),
RuntimeDeclaration::Explicit(explicit_decl) =>
construct_runtime_final_expansion(explicit_decl),
};

/// Return whether pallet contains part
fn exists_part(&self, name: &str) -> bool {
self.find_part(name).is_some()
}
res.unwrap_or_else(|e| e.to_compile_error()).into()
}

/// Convert from the parsed pallet to their final information.
/// Assign index to each pallet using same rules as rust for fieldless enum.
/// I.e. implicit are assigned number incrementedly from last explicit or 0.
fn complete_pallets(decl: impl Iterator<Item = PalletDeclaration>) -> syn::Result<Vec<Pallet>> {
let mut indices = HashMap::new();
let mut last_index: Option<u8> = None;
let mut names = HashMap::new();

decl.map(|pallet| {
let final_index = match pallet.index {
Some(i) => i,
None => last_index.map_or(Some(0), |i| i.checked_add(1)).ok_or_else(|| {
let msg = "Pallet index doesn't fit into u8, index is 256";
syn::Error::new(pallet.name.span(), msg)
})?,
};

last_index = Some(final_index);

if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) {
let msg = format!(
"Pallet indices are conflicting: Both pallets {} and {} are at index {}",
used_pallet, pallet.name, final_index,
);
let mut err = syn::Error::new(used_pallet.span(), &msg);
err.combine(syn::Error::new(pallet.name.span(), msg));
return Err(err)
}

if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) {
let msg = "Two pallets with the same name!";

let mut err = syn::Error::new(used_pallet, &msg);
err.combine(syn::Error::new(pallet.name.span(), &msg));
return Err(err)
}

Ok(Pallet {
name: pallet.name,
index: final_index,
path: pallet.path,
instance: pallet.instance,
pallet_parts: pallet.pallet_parts,
})
})
.collect()
}
fn construct_runtime_intermediary_expansion(
input: TokenStream2,
definition: ImplicitRuntimeDeclaration,
) -> Result<TokenStream2> {
let frame_support = generate_crate_access_2018("frame-support")?;
let mut expansion = quote::quote!(
#frame_support::construct_runtime! { #input }
);
for pallet in definition.pallets.iter().filter(|pallet| pallet.pallet_parts.is_none()) {
let pallet_path = &pallet.path;
let pallet_name = &pallet.name;
let pallet_instance = pallet.instance.as_ref().map(|instance| quote::quote!(::<#instance>));
expansion = quote::quote!(
#pallet_path::construct_runtime_parts! {
{ #frame_support }
{ #pallet_name: #pallet_path #pallet_instance }
#expansion
}
);
}

pub fn construct_runtime(input: TokenStream) -> TokenStream {
let definition = syn::parse_macro_input!(input as RuntimeDefinition);
construct_runtime_parsed(definition)
.unwrap_or_else(|e| e.to_compile_error())
.into()
Ok(expansion.into())
}

fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream2> {
let RuntimeDefinition {
fn construct_runtime_final_expansion(
definition: ExplicitRuntimeDeclaration,
) -> Result<TokenStream2> {
let ExplicitRuntimeDeclaration {
name,
where_section: WhereSection { block, node_block, unchecked_extrinsic, .. },
pallets:
ext::Braces { content: ext::Punctuated { inner: pallets, .. }, token: pallets_token },
..
where_section: WhereSection { block, node_block, unchecked_extrinsic },
pallets,
pallets_token,
} = definition;

let pallets = complete_pallets(pallets.into_iter())?;

let hidden_crate_name = "construct_runtime";
let scrate = generate_crate_access(&hidden_crate_name, "frame-support");
let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support");
Expand Down
Loading