decl_storage as a proc_macro (#1176)

* `decl_storage` parsing of the macro (TODO change tool crate structure)

* Start formatting, for now use inner macro.
Still missing optional formating last part (genesis ...).

* Calling extra genesis macro

* decl_storage lines parsing.

* genesis macro as quote (need some cleaning reorg)

* dirty $crate substitute

* proc crate reorg.

* PR impl : skip usage of phantom data, it only applies in test and
council (others required it).

* Remaining macro of decl_storage, warning stringify behave sometime
oddly.

* Formatting code and some cleaning.

* Include line parsing to main struct (cannot use existing macro anymore).

* Remove genesis phantom data when there is already a field with type
parameter.

* Revert wasm files

* Remove old version of `decl_storage`.

* Fix false positive for phantom trait (additional type check on config
build).

* slight changes:
- return token errors instead of panic
- do not use useless intermediate vec

* Update srml/support/procedural/tools/derive/src/lib.rs

remove indent

Co-Authored-By: cheme <emericchevalier.pro@gmail.com>

* Switch iterations to fold, remove unused import.
This commit is contained in:
cheme
2018-12-09 21:09:39 +01:00
committed by Bastian Köcher
parent 3ffb45e3c8
commit ed5b78eaf0
34 changed files with 1681 additions and 1427 deletions
+46 -14
View File
@@ -703,7 +703,7 @@ name = "failure_derive"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1597,7 +1597,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2032,7 +2032,7 @@ name = "parity-codec-derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2172,7 +2172,7 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "0.4.23"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2236,7 +2236,7 @@ name = "quote"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2602,7 +2602,7 @@ name = "serde_derive"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2712,7 +2712,7 @@ version = "0.1.0"
dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0",
@@ -3013,6 +3013,37 @@ dependencies = [
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"srml-metadata 0.1.0",
"srml-support-procedural 0.1.0",
]
[[package]]
name = "srml-support-procedural"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-api-macros 0.1.0",
"srml-support-procedural-tools 0.1.0",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "srml-support-procedural-tools"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"srml-support-procedural-tools-derive 0.1.0",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "srml-support-procedural-tools-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -3077,6 +3108,7 @@ dependencies = [
"sr-std 0.1.0",
"srml-consensus 0.1.0",
"srml-support 0.1.0",
"srml-support-procedural 0.1.0",
"srml-system 0.1.0",
"substrate-primitives 0.1.0",
]
@@ -3113,7 +3145,7 @@ name = "stdweb-derive"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3126,7 +3158,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base-x 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3173,7 +3205,7 @@ version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3759,7 +3791,7 @@ name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3769,7 +3801,7 @@ name = "syn"
version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3779,7 +3811,7 @@ name = "synstructure"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4768,7 +4800,7 @@ dependencies = [
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7"
"checksum proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "88dae56b29da695d783ea7fc5a90de281f79eb38407e77f6d674dd8befc4ac47"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "671a9cce836bd3635b40b2b0a72783481755ee988c493891f4e974b45264cc9d"
"checksum pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd695333cfae6e9dbe2703a6d040e252b57a6fc3b9a65c712615ac042b2e0c5"
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
+3
View File
@@ -40,6 +40,9 @@ members = [
"core/transaction-pool",
"core/transaction-pool/graph",
"srml/support",
"srml/support/procedural",
"srml/support/procedural/tools",
"srml/support/procedural/tools/derive",
"srml/assets",
"srml/balances",
"srml/consensus",
+43 -13
View File
@@ -395,7 +395,7 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -559,8 +559,8 @@ name = "parity-codec-derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -638,7 +638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.19"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -646,10 +646,10 @@ dependencies = [
[[package]]
name = "quote"
version = "0.6.8"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -918,6 +918,36 @@ dependencies = [
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"srml-metadata 0.1.0",
"srml-support-procedural 0.1.0",
]
[[package]]
name = "srml-support-procedural"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"srml-support-procedural-tools 0.1.0",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "srml-support-procedural-tools"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"srml-support-procedural-tools-derive 0.1.0",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "srml-support-procedural-tools-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -981,7 +1011,7 @@ dependencies = [
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0",
@@ -1098,8 +1128,8 @@ name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1108,8 +1138,8 @@ name = "syn"
version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1531,8 +1561,8 @@ dependencies = [
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
"checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
+1 -25
View File
@@ -59,7 +59,6 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
consensus: Some(ConsensusConfig {
code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), // TODO change
authorities: initial_authorities.clone(),
_genesis_phantom_data: Default::default(),
}),
system: None,
balances: Some(BalancesConfig {
@@ -70,12 +69,10 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
transfer_fee: 1 * CENTS,
creation_fee: 1 * CENTS,
reclaim_rebate: 1 * CENTS,
_genesis_phantom_data: Default::default(),
}),
session: Some(SessionConfig {
validators: initial_authorities.iter().cloned().map(Into::into).collect(),
session_length: 5 * MINUTES,
_genesis_phantom_data: Default::default(),
}),
staking: Some(StakingConfig {
current_era: 0,
@@ -89,13 +86,11 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
bonding_duration: 1 * DAYS,
offline_slash_grace: 4,
minimum_validator_count: 4,
_genesis_phantom_data: Default::default(),
}),
democracy: Some(DemocracyConfig {
launch_period: 5 * MINUTES, // 1 day per public referendum
voting_period: 5 * MINUTES, // 3 days to discuss & vote on an active referendum
minimum_deposit: 50 * DOLLARS, // 12000 as the minimum deposit for a referendum
_genesis_phantom_data: Default::default(),
}),
council_seats: Some(CouncilSeatsConfig {
active_council: vec![],
@@ -108,23 +103,19 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
term_duration: 28 * DAYS,
desired_seats: 0,
inactive_grace_period: 1, // one additional vote should go by before an inactive voter can be reaped.
_genesis_phantom_data: Default::default(),
}),
council_voting: Some(CouncilVotingConfig {
cooloff_period: 4 * DAYS,
voting_period: 1 * DAYS,
_genesis_phantom_data: Default::default(),
}),
timestamp: Some(TimestampConfig {
period: SECS_PER_BLOCK,
_genesis_phantom_data: Default::default(),
}),
treasury: Some(TreasuryConfig {
proposal_bond: Permill::from_percent(5),
proposal_bond_minimum: 1 * DOLLARS,
spend_period: 1 * DAYS,
burn: Permill::from_percent(50),
_genesis_phantom_data: Default::default(),
}),
contract: Some(ContractConfig {
contract_fee: 1 * CENTS,
@@ -134,15 +125,12 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: Default::default(),
_genesis_phantom_data: Default::default(),
}),
upgrade_key: Some(UpgradeKeyConfig {
key: endowed_accounts[0].clone(),
_genesis_phantom_data: Default::default(),
}),
grandpa: Some(GrandpaConfig {
authorities: initial_authorities.clone().into_iter().map(|k| (k, 1)).collect(),
_genesis_phantom_data: Default::default(),
})
}
}
@@ -190,7 +178,6 @@ pub fn testnet_genesis(
consensus: Some(ConsensusConfig {
code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(),
authorities: initial_authorities.clone(),
_genesis_phantom_data: Default::default(),
}),
system: None,
balances: Some(BalancesConfig {
@@ -201,12 +188,10 @@ pub fn testnet_genesis(
creation_fee: 0,
reclaim_rebate: 0,
balances: endowed_accounts.iter().map(|&k| (k.into(), (1 << 60))).collect(),
_genesis_phantom_data: Default::default(),
}),
session: Some(SessionConfig {
validators: initial_authorities.iter().cloned().map(Into::into).collect(),
session_length: 10,
_genesis_phantom_data: Default::default(),
}),
staking: Some(StakingConfig {
current_era: 0,
@@ -220,13 +205,11 @@ pub fn testnet_genesis(
current_offline_slash: 0,
current_session_reward: 0,
offline_slash_grace: 0,
_genesis_phantom_data: Default::default(),
}),
democracy: Some(DemocracyConfig {
launch_period: 9,
voting_period: 18,
minimum_deposit: 10,
_genesis_phantom_data: Default::default(),
}),
council_seats: Some(CouncilSeatsConfig {
active_council: endowed_accounts.iter()
@@ -241,23 +224,19 @@ pub fn testnet_genesis(
term_duration: 1000000,
desired_seats: (endowed_accounts.len() - initial_authorities.len()) as u32,
inactive_grace_period: 1,
_genesis_phantom_data: Default::default(),
}),
council_voting: Some(CouncilVotingConfig {
cooloff_period: 75,
voting_period: 20,
_genesis_phantom_data: Default::default(),
}),
timestamp: Some(TimestampConfig {
period: 5, // 5 second block time.
_genesis_phantom_data: Default::default(),
}),
treasury: Some(TreasuryConfig {
proposal_bond: Permill::from_percent(5),
proposal_bond_minimum: 1_000_000,
spend_period: 12 * 60 * 24,
burn: Permill::from_percent(50),
_genesis_phantom_data: Default::default(),
}),
contract: Some(ContractConfig {
contract_fee: 21,
@@ -267,15 +246,12 @@ pub fn testnet_genesis(
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: Default::default(),
_genesis_phantom_data: Default::default(),
}),
upgrade_key: Some(UpgradeKeyConfig {
key: upgrade_key,
_genesis_phantom_data: Default::default(),
}),
grandpa: Some(GrandpaConfig {
authorities: initial_authorities.clone().into_iter().map(|k| (k, 1)).collect(),
_genesis_phantom_data: Default::default(),
})
}
}
@@ -319,7 +295,7 @@ mod tests {
fn local_testnet_genesis_instant() -> GenesisConfig {
let mut genesis = local_testnet_genesis();
genesis.timestamp = Some(TimestampConfig { period: 0, _genesis_phantom_data: Default::default() });
genesis.timestamp = Some(TimestampConfig { period: 0 });
genesis
}
-4
View File
@@ -235,12 +235,10 @@ mod tests {
transfer_fee: 0,
creation_fee: 0,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}),
session: Some(SessionConfig {
session_length: 2,
validators: vec![One.to_raw_public().into(), Two.to_raw_public().into(), three],
_genesis_phantom_data: Default::default(),
}),
staking: Some(StakingConfig {
sessions_per_era: 2,
@@ -254,7 +252,6 @@ mod tests {
current_offline_slash: 0,
current_session_reward: 0,
offline_slash_grace: 0,
_genesis_phantom_data: Default::default(),
}),
democracy: Some(Default::default()),
council_seats: Some(Default::default()),
@@ -269,7 +266,6 @@ mod tests {
(Bob.to_raw_public().into(), 1),
(Charlie.to_raw_public().into(), 1),
],
_genesis_phantom_data: Default::default(),
}),
}.build_storage().unwrap().0)
}
+44 -13
View File
@@ -395,7 +395,7 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -602,8 +602,8 @@ name = "parity-codec-derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -681,7 +681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.19"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -699,10 +699,10 @@ dependencies = [
[[package]]
name = "quote"
version = "0.6.8"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1155,6 +1155,36 @@ dependencies = [
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"srml-metadata 0.1.0",
"srml-support-procedural 0.1.0",
]
[[package]]
name = "srml-support-procedural"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"srml-support-procedural-tools 0.1.0",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "srml-support-procedural-tools"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"srml-support-procedural-tools-derive 0.1.0",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "srml-support-procedural-tools-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1219,6 +1249,7 @@ dependencies = [
"sr-std 0.1.0",
"srml-consensus 0.1.0",
"srml-support 0.1.0",
"srml-support-procedural 0.1.0",
"srml-system 0.1.0",
"substrate-primitives 0.1.0",
]
@@ -1284,7 +1315,7 @@ dependencies = [
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0",
@@ -1396,8 +1427,8 @@ name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1406,8 +1437,8 @@ name = "syn"
version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1829,9 +1860,9 @@ dependencies = [
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
"checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd695333cfae6e9dbe2703a6d040e252b57a6fc3b9a65c712615ac042b2e0c5"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
-1
View File
@@ -104,7 +104,6 @@ impl ExtBuilder {
transfer_fee: self.transfer_fee,
creation_fee: self.creation_fee,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.into()
}
-1
View File
@@ -54,7 +54,6 @@ pub fn new_test_ext(authorities: Vec<u64>) -> runtime_io::TestExternalities<Blak
t.extend(GenesisConfig::<Test>{
code: vec![],
authorities,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.into()
}
-2
View File
@@ -131,7 +131,6 @@ impl ExtBuilder {
transfer_fee: self.transfer_fee,
creation_fee: self.creation_fee,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage()
.unwrap().0,
);
@@ -144,7 +143,6 @@ impl ExtBuilder {
max_depth: 100,
block_gas_limit: self.block_gas_limit,
current_schedule: Default::default(),
_genesis_phantom_data: Default::default(),
}.build_storage()
.unwrap().0,
);
-4
View File
@@ -122,13 +122,11 @@ mod tests {
transfer_fee: 0,
creation_fee: 0,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(democracy::GenesisConfig::<Test>{
launch_period: 1,
voting_period: 3,
minimum_deposit: 1,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(seats::GenesisConfig::<Test> {
candidacy_bond: 9,
@@ -145,12 +143,10 @@ mod tests {
presentation_duration: 2,
desired_seats: 2,
term_duration: 5,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(voting::GenesisConfig::<Test> {
cooloff_period: 2,
voting_period: 1,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
runtime_io::TestExternalities::new(t)
}
-1
View File
@@ -172,7 +172,6 @@ decl_storage! {
pub ProposalCount get(proposal_count): u32;
}
add_extra_genesis {
config(_marker): ::std::marker::PhantomData<T>;
build(|_, _, _| {});
}
}
-2
View File
@@ -358,13 +358,11 @@ mod tests {
transfer_fee: 0,
creation_fee: 0,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(GenesisConfig::<Test>{
launch_period: 1,
voting_period: 1,
minimum_deposit: 1,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
runtime_io::TestExternalities::new(t)
}
-1
View File
@@ -313,7 +313,6 @@ mod tests {
t.extend(GenesisConfig::<Test>{
dummy: 42,
foo: 24,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.into()
}
-1
View File
@@ -327,7 +327,6 @@ mod tests {
transfer_fee: 0,
creation_fee: 0,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2.into(), 69.into()));
let mut t = runtime_io::TestExternalities::<Blake2Hasher>::new(t);
-1
View File
@@ -69,7 +69,6 @@ impl_outer_event!{
pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> runtime_io::TestExternalities<Blake2Hasher> {
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
t.extend(GenesisConfig::<Test> {
_genesis_phantom_data: Default::default(),
authorities,
}.build_storage().unwrap().0);
t.into()
-3
View File
@@ -296,16 +296,13 @@ mod tests {
t.extend(consensus::GenesisConfig::<Test>{
code: vec![],
authorities: vec![1, 2, 3],
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(timestamp::GenesisConfig::<Test>{
period: 5,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(GenesisConfig::<Test>{
session_length: 2,
validators: vec![1, 2, 3],
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
runtime_io::TestExternalities::new(t)
}
-5
View File
@@ -88,12 +88,10 @@ pub fn new_test_ext(
t.extend(consensus::GenesisConfig::<Test>{
code: vec![],
authorities: vec![],
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(session::GenesisConfig::<Test>{
session_length,
validators: vec![10, 20],
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(balances::GenesisConfig::<Test>{
balances: if monied {
@@ -111,7 +109,6 @@ pub fn new_test_ext(
transfer_fee: 0,
creation_fee: 0,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(GenesisConfig::<Test>{
sessions_per_era,
@@ -125,11 +122,9 @@ pub fn new_test_ext(
current_session_reward: reward,
current_offline_slash: 20,
offline_slash_grace: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(timestamp::GenesisConfig::<Test>{
period: 5,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
runtime_io::TestExternalities::new(t)
}
+1
View File
@@ -12,6 +12,7 @@ srml-metadata = { path = "../metadata", default-features = false }
sr-std = { path = "../../core/sr-std", default-features = false }
sr-io = { path = "../../core/sr-io", default-features = false }
sr-primitives = { path = "../../core/sr-primitives", default-features = false }
srml-support-procedural = { path = "./procedural" }
mashup = "0.1.7"
[dev-dependencies]
@@ -0,0 +1,15 @@
[package]
name = "srml-support-procedural"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[lib]
proc-macro = true
[dependencies]
srml-support-procedural-tools = { path = "./tools" }
sr-api-macros = { path = "../../../core/sr-api-macros" }
proc-macro2 = "0.4"
quote = { version = "0.6" }
syn = { version = "0.15", features = ["full"] }
@@ -0,0 +1,59 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Proc macro of Support code for the runtime.
// end::description[]
#![recursion_limit="256"]
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate srml_support_procedural_tools;
mod storage;
use proc_macro::TokenStream;
/// Declares strongly-typed wrappers around codec-compatible types in storage.
///
/// ## Example
///
/// ```compile_fail
/// decl_storage! {
/// trait Store for Module<T: Trait> as Example {
/// Dummy get(dummy) config(): Option<T::Balance>;
/// Foo get(foo) config(): T::Balance;
/// }
/// }
/// ```
///
/// For now we implement a convenience trait with pre-specialised associated types, one for each
/// storage item. This allows you to gain access to publicly visible storage items from a
/// module type. Currently you must disambiguate by using `<Module as Store>::Item` rather than
/// the simpler `Module::Item`. Hopefully the rust guys with fix this soon.
#[proc_macro]
pub fn decl_storage(input: TokenStream) -> TokenStream {
storage::transformation::decl_storage_impl(input)
}
@@ -0,0 +1,144 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! `decl_storage` macro
// end::description[]
use srml_support_procedural_tools::syn_ext as ext;
use syn::Ident;
use syn::token::CustomKeyword;
pub mod transformation;
/// Parsing usage only
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct StorageDefinition {
pub hidden_crate: Option<SpecificHiddenCrate>,
pub visibility: syn::Visibility,
pub trait_token: Token![trait],
pub ident: Ident,
pub for_token: Token![for],
pub module_ident: Ident,
pub mod_lt_token: Token![<],
pub mod_param: syn::GenericParam,
pub mod_gt_token: Token![>],
pub as_token: Token![as],
pub crate_ident: Ident,
pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
pub extra_genesis: Option<AddExtraGenesis>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct SpecificHiddenCrate {
pub keyword: ext::CustomToken<SpecificHiddenCrate>,
pub ident: ext::Parens<Ident>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct AddExtraGenesis {
pub extragenesis_keyword: ext::CustomToken<AddExtraGenesis>,
pub content: ext::Braces<AddExtraGenesisContent>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct AddExtraGenesisContent {
pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
}
#[derive(ParseEnum, ToTokensEnum, Debug)]
enum AddExtraGenesisLineEnum {
AddExtraGenesisLine(AddExtraGenesisLine),
AddExtraGenesisBuild(DeclStorageBuild),
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct AddExtraGenesisLine {
pub attrs: ext::OuterAttributes,
pub config_keyword: ext::CustomToken<ConfigKeyword>,
pub extra_field: ext::Parens<Ident>,
pub coldot_token: Token![:],
pub extra_type: syn::Type,
// TODO use a custom ext::Option instead (syn option on '=' fails)
pub default_value: ext::Seq<DeclStorageDefault>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct DeclStorageLine {
// attrs (main use case is doc)
pub attrs: ext::OuterAttributes,
// visibility (no need to make optional
pub visibility: syn::Visibility,
// name
pub name: Ident,
pub getter: Option<DeclStorageGetter>,
pub config: Option<DeclStorageConfig>,
pub build: Option<DeclStorageBuild>,
pub coldot_token: Token![:],
pub storage_type: DeclStorageType,
// TODO use a custom ext::Option instead (syn option on '=' fails)
pub default_value: ext::Seq<DeclStorageDefault>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct DeclStorageGetter {
pub getter_keyword: ext::CustomToken<DeclStorageGetter>,
pub getfn: ext::Parens<Ident>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct DeclStorageConfig {
pub config_keyword: ext::CustomToken<DeclStorageConfig>,
pub expr: ext::Parens<Option<syn::Ident>>,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct DeclStorageBuild {
pub build_keyword: ext::CustomToken<DeclStorageBuild>,
pub expr: ext::Parens<syn::Expr>,
}
#[derive(ParseEnum, ToTokensEnum, Debug)]
enum DeclStorageType {
Map(DeclStorageMap),
Simple(syn::Type),
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct DeclStorageMap {
pub map_keyword: ext::CustomToken<MapKeyword>,
pub key: syn::Type,
pub ass_keyword: Token![=>],
pub value: syn::Type,
}
#[derive(ParseStruct, ToTokensStruct, Debug)]
struct DeclStorageDefault {
pub equal_token: Token![=],
pub expr: syn::Expr,
}
custom_keyword_impl!(SpecificHiddenCrate, "hiddencrate", "hiddencrate as keyword");
custom_keyword_impl!(DeclStorageConfig, "config", "build as keyword");
custom_keyword!(ConfigKeyword, "config", "config as keyword");
custom_keyword!(BuildKeyword, "build", "build as keyword");
custom_keyword_impl!(DeclStorageBuild, "build", "storage build config");
custom_keyword_impl!(AddExtraGenesis, "add_extra_genesis", "storage extra genesis");
custom_keyword_impl!(DeclStorageGetter, "get", "storage getter");
custom_keyword!(MapKeyword, "map", "map as keyword");
@@ -0,0 +1,636 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! `decl_storage` macro transformation
// end::description[]
use srml_support_procedural_tools::syn_ext as ext;
use srml_support_procedural_tools::{generate_crate_access, generate_hidden_includes};
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use syn::{
Ident,
GenericParam,
spanned::Spanned,
parse::{
Error,
Result,
}
};
use super::*;
// try macro but returning tokenized error
macro_rules! try_tok(( $expre : expr ) => {
match $expre {
Ok(r) => r,
Err (err) => {
return err.to_compile_error().into()
}
}
});
pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
let def = parse_macro_input!(input as StorageDefinition);
// old macro naming convention (s replaces $)
let StorageDefinition {
hidden_crate,
visibility,
ident: storetype,
module_ident,
mod_param: strait,
crate_ident: cratename,
content: ext::Braces { content: storage_lines, ..},
extra_genesis,
..
} = def;
let hidden_crate_name = hidden_crate.map(|rc| rc.ident.content).map(|i| i.to_string())
.unwrap_or_else(|| "decl_storage".to_string());
let scrate = generate_crate_access(&hidden_crate_name, "srml-support");
let scrate_decl = generate_hidden_includes(
&hidden_crate_name,
"srml-support",
"srml_support",
);
let (
traitinstance,
traittypes,
) = if let GenericParam::Type(syn::TypeParam {ident, bounds, ..}) = strait {
(ident, bounds)
} else {
return try_tok!(Err(Error::new(strait.span(), "Missing declare store generic params")));
};
let traittype = if let Some(traittype) = traittypes.first() {
traittype.into_value()
} else {
return try_tok!(Err(Error::new(traittypes.span(), "Trait bound expected")));
};
let extra_genesis = try_tok!(decl_store_extra_genesis(
&scrate,
&traitinstance,
&traittype,
&storage_lines,
&extra_genesis,
));
let decl_storage_items = decl_storage_items(
&scrate,
&traitinstance,
&traittype,
&cratename,
&storage_lines,
);
let decl_store_items = decl_store_items(
&storage_lines,
);
let impl_store_items = impl_store_items(
&traitinstance,
&storage_lines,
);
let impl_store_fns = impl_store_fns(
&scrate,
&traitinstance,
&storage_lines,
);
let store_functions_to_metadata = store_functions_to_metadata(
&scrate,
&storage_lines,
);
let cratename_string = cratename.to_string();
let expanded = quote! {
#scrate_decl
#decl_storage_items
#visibility trait #storetype {
#decl_store_items
}
impl<#traitinstance: #traittype> #storetype for #module_ident<#traitinstance> {
#impl_store_items
}
impl<#traitinstance: #traittype> #module_ident<#traitinstance> {
#impl_store_fns
pub fn store_metadata() -> #scrate::storage::generator::StorageMetadata {
#scrate::storage::generator::StorageMetadata {
prefix: #scrate::storage::generator::DecodeDifferent::Encode(#cratename_string),
functions: #store_functions_to_metadata ,
}
}
}
#extra_genesis
};
expanded.into()
}
fn decl_store_extra_genesis(
scrate: &TokenStream2,
traitinstance: &Ident,
traittype: &syn::TypeParamBound,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
extra_genesis: &Option<AddExtraGenesis>,
) -> Result<TokenStream2> {
let mut is_trait_needed = false;
let mut has_trait_field = false;
let mut config_field = TokenStream2::new();
let mut config_field_default = TokenStream2::new();
let mut builders = TokenStream2::new();
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
name,
getter,
config,
build,
storage_type,
default_value,
..
} = sline;
let is_simple = if let DeclStorageType::Simple(..) = storage_type { true } else { false };
let mut opt_build;
// need build line
if let (Some(ref getter), Some(ref config)) = (getter, config) {
let ident = if let Some(ident) = config.expr.content.as_ref() {
quote!( #ident )
} else {
let ident = &getter.getfn.content;
quote!( #ident )
};
let option_extracteed = if let DeclStorageType::Simple(ref st) = storage_type {
if ext::has_parametric_type(st, traitinstance) {
is_trait_needed = true;
has_trait_field = true;
}
ext::extract_type_option(st)
} else { None };
let is_option = option_extracteed.is_some();
let storage_type = option_extracteed.unwrap_or_else(|| quote!( #storage_type ));
config_field.extend(quote!( pub #ident: #storage_type, ));
opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b ))
.unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) )));
let fielddefault = default_value.inner.get(0).as_ref().map(|d| &d.expr).map(|d|
if is_option {
quote!( #d.unwrap_or_default() )
} else {
quote!( #d )
}).unwrap_or_else(|| quote!( Default::default() ));
config_field_default.extend(quote!( #ident: #fielddefault, ));
} else {
opt_build = build.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b ));
}
if let Some(builder) = opt_build {
is_trait_needed = true;
if is_simple {
builders.extend(quote!{{
use #scrate::codec::Encode;
let v = (#builder)(&self);
r.insert(Self::hash(<#name<#traitinstance>>::key()).to_vec(), v.encode());
}});
} else {
builders.extend(quote!{{
use #scrate::codec::Encode;
let data = (#builder)(&self);
for (k, v) in data.into_iter() {
r.insert(Self::hash(&<#name<#traitinstance>>::key_for(k)).to_vec(), v.encode());
}
}});
}
}
}
let mut has_scall = false;
let mut scall = quote!{ ( |_, _, _| {} ) };
let mut genesis_extrafields = TokenStream2::new();
let mut genesis_extrafields_default = TokenStream2::new();
// extra genesis
if let Some(eg) = extra_genesis {
for ex_content in eg.content.content.lines.inner.iter() {
match ex_content {
AddExtraGenesisLineEnum::AddExtraGenesisLine(AddExtraGenesisLine {
attrs,
extra_field,
extra_type,
default_value,
..
}) => {
if ext::has_parametric_type(&extra_type, traitinstance) {
is_trait_needed = true;
has_trait_field = true;
}
let extrafield = &extra_field.content;
genesis_extrafields.extend(quote!{
#attrs pub #extrafield: #extra_type,
});
let extra_default = default_value.inner.get(0).map(|d| &d.expr).map(|e| quote!{ #e })
.unwrap_or_else(|| quote!( Default::default() ));
genesis_extrafields_default.extend(quote!{
#extrafield: #extra_default,
});
},
AddExtraGenesisLineEnum::AddExtraGenesisBuild(DeclStorageBuild{ expr, .. }) => {
if has_scall {
return Err(Error::new(expr.span(), "Only one build expression allowed for extra genesis"));
}
let content = &expr.content;
scall = quote!( ( #content ) );
has_scall = true;
},
}
}
}
let is_extra_genesis_needed = has_scall
|| !config_field.is_empty()
|| !genesis_extrafields.is_empty()
|| !builders.is_empty();
Ok(if is_extra_genesis_needed {
let (fparam, sparam, ph_field, ph_default) = if is_trait_needed {
if has_trait_field {
// no phantom data required
(
quote!(<#traitinstance: #traittype>),
quote!(<#traitinstance>),
quote!(),
quote!(),
)
} else {
// need phantom data
(
quote!(<#traitinstance: #traittype>),
quote!(<#traitinstance>),
quote!{
#[serde(skip)]
pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<#traitinstance>,
},
quote!{
_genesis_phantom_data: Default::default(),
},
)
}
} else {
// do not even need type parameter
(quote!(), quote!(), quote!(), quote!())
};
quote!{
#[derive(Serialize, Deserialize)]
#[cfg(feature = "std")]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct GenesisConfig#fparam {
#ph_field
#config_field
#genesis_extrafields
}
#[cfg(feature = "std")]
impl#fparam Default for GenesisConfig#sparam {
fn default() -> Self {
GenesisConfig {
#ph_default
#config_field_default
#genesis_extrafields_default
}
}
}
#[cfg(feature = "std")]
impl#fparam #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam {
fn build_storage(self) -> ::std::result::Result<(#scrate::runtime_primitives::StorageMap, #scrate::runtime_primitives::ChildrenStorageMap), String> {
let mut r: #scrate::runtime_primitives::StorageMap = Default::default();
let mut c: #scrate::runtime_primitives::ChildrenStorageMap = Default::default();
#builders
#scall(&mut r, &mut c, &self);
Ok((r, c))
}
}
}
} else {
quote!()
})
}
fn decl_storage_items(
scrate: &TokenStream2,
traitinstance: &Ident,
traittype: &syn::TypeParamBound,
cratename: &Ident,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
let mut impls = TokenStream2::new();
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
name,
storage_type,
default_value,
visibility,
..
} = sline;
let (is_simple, extracted_opt, stk, gettype) = match storage_type {
DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st),
DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value),
};
let is_option = extracted_opt.is_some();
let fielddefault = default_value.inner.get(0).as_ref().map(|d| &d.expr).map(|d| quote!( #d ))
.unwrap_or_else(|| quote!{ Default::default() });
let typ = extracted_opt.unwrap_or(quote!( #gettype ));
let option_simple_1 = if !is_option {
// raw type case
quote!( unwrap_or_else )
} else {
// Option<> type case
quote!( or_else )
};
let implementation = if is_simple {
let mutate_impl = if !is_option {
quote!{
<Self as #scrate::storage::generator::StorageValue<#typ>>::put(&val, storage)
}
} else {
quote!{
match val {
Some(ref val) => <Self as #scrate::storage::generator::StorageValue<#typ>>::put(&val, storage),
None => <Self as #scrate::storage::generator::StorageValue<#typ>>::kill(storage),
}
}
};
let key_string = cratename.to_string() + " " + &name.to_string();
// generator for value
quote!{
#visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>);
impl<#traitinstance: #traittype> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance> {
type Query = #gettype;
/// Get the storage key.
fn key() -> &'static [u8] {
#key_string.as_bytes()
}
/// Load the value from the provided storage instance.
fn get<S: #scrate::GenericStorage>(storage: &S) -> Self::Query {
storage.get(<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::key())
.#option_simple_1(|| #fielddefault)
}
/// Take a value from storage, removing it afterwards.
fn take<S: #scrate::GenericStorage>(storage: &S) -> Self::Query {
storage.take(<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::key())
.#option_simple_1(|| #fielddefault)
}
/// Mutate the value under a key.
fn mutate<R, F: FnOnce(&mut Self::Query) -> R, S: #scrate::GenericStorage>(f: F, storage: &S) -> R {
let mut val = <Self as #scrate::storage::generator::StorageValue<#typ>>::get(storage);
let ret = f(&mut val);
#mutate_impl ;
ret
}
}
}
} else {
let kty = stk.expect("is not simple; qed");
let mutate_impl = if !is_option {
quote!{
<Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::insert(key, &val, storage)
}
} else {
quote!{
match val {
Some(ref val) => <Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::insert(key, &val, storage),
None => <Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::remove(key, storage),
}
}
};
let prefix_string = cratename.to_string() + " " + &name.to_string();
// generator for map
quote!{
#visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>);
impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> {
type Query = #gettype;
/// Get the prefix key in storage.
fn prefix() -> &'static [u8] {
#prefix_string.as_bytes()
}
/// Get the storage key used to fetch a value corresponding to a specific key.
fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec<u8> {
let mut key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::prefix().to_vec();
#scrate::codec::Encode::encode_to(x, &mut key);
key
}
/// Load the value associated with the given key from the map.
fn get<S: #scrate::GenericStorage>(key: &#kty, storage: &S) -> Self::Query {
let key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(key);
storage.get(&key[..]).#option_simple_1(|| #fielddefault)
}
/// Take the value, reading and removing it.
fn take<S: #scrate::GenericStorage>(key: &#kty, storage: &S) -> Self::Query {
let key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(key);
storage.take(&key[..]).#option_simple_1(|| #fielddefault)
}
/// Mutate the value under a key
fn mutate<R, F: FnOnce(&mut Self::Query) -> R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R {
let mut val = <Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::take(key, storage);
let ret = f(&mut val);
#mutate_impl ;
ret
}
}
}
};
impls.extend(implementation)
}
impls
}
fn decl_store_items(
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
storage_lines.inner.iter().map(|sline| &sline.name)
.fold(TokenStream2::new(), |mut items, name| {
items.extend(quote!(type #name;));
items
})
}
fn impl_store_items(
traitinstance: &Ident,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
storage_lines.inner.iter().map(|sline| &sline.name)
.fold(TokenStream2::new(), |mut items, name| {
items.extend(quote!(type #name = #name<#traitinstance>;));
items
})
}
fn impl_store_fns(
scrate: &TokenStream2,
traitinstance: &Ident,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
let mut items = TokenStream2::new();
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
name,
getter,
storage_type,
..
} = sline;
if let Some(getter) = getter {
let get_fn = &getter.getfn.content;
let (is_simple, extracted_opt, stk, gettype) = match storage_type {
DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st),
DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value),
};
let typ = extracted_opt.unwrap_or(quote!(#gettype));
let item = if is_simple {
quote!{
pub fn #get_fn() -> #gettype {
<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage)
}
}
} else {
let kty = stk.expect("is not simple; qed");
// map
quote!{
pub fn #get_fn<K: #scrate::storage::generator::Borrow<#kty>>(key: K) -> #gettype {
<#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage)
}
}
};
items.extend(item);
}
}
items
}
fn store_functions_to_metadata (
scrate: &TokenStream2,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
let mut items = TokenStream2::new();
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
attrs,
name,
storage_type,
..
} = sline;
let (is_simple, extracted_opt, stk, gettype) = match storage_type {
DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st),
DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value),
};
let is_option = extracted_opt.is_some();
let typ = extracted_opt.unwrap_or(quote!( #gettype ));
let stype = if is_simple {
let styp = typ.to_string().replace(" ","");
quote!{
#scrate::storage::generator::StorageFunctionType::Plain(
#scrate::storage::generator::DecodeDifferent::Encode(#styp),
)
}
} else {
let kty = stk.expect("is not simple; qed");
let kty = quote!(#kty).to_string();
let styp = typ.to_string().replace(" ","");
quote!{
#scrate::storage::generator::StorageFunctionType::Map {
key: #scrate::storage::generator::DecodeDifferent::Encode(#kty),
value: #scrate::storage::generator::DecodeDifferent::Encode(#styp),
}
}
};
let modifier = if !is_option {
quote!{
#scrate::storage::generator::StorageFunctionModifier::Default
}
} else {
quote!{
#scrate::storage::generator::StorageFunctionModifier::Optional
}
};
let mut docs = TokenStream2::new();
for attr in attrs.inner.iter().filter_map(|v| v.interpret_meta()) {
if let syn::Meta::NameValue(syn::MetaNameValue{
ref ident,
ref lit,
..
}) = attr {
if ident == "doc" {
docs.extend(quote!(#lit,));
}
}
}
let str_name = name.to_string();
let item = quote! {
#scrate::storage::generator::StorageFunctionMetadata {
name: #scrate::storage::generator::DecodeDifferent::Encode(#str_name),
modifier: #modifier,
ty: #stype,
documentation: #scrate::storage::generator::DecodeDifferent::Encode(&[ #docs ]),
},
};
items.extend(item);
}
quote!{
#scrate::storage::generator::DecodeDifferent::Encode(&[
#items
])
}
}
@@ -0,0 +1,10 @@
[package]
name = "srml-support-procedural-tools"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
srml-support-procedural-tools-derive = { path = "./derive" }
proc-macro2 = "0.4"
quote = { version = "0.6" }
syn = { version = "0.15", features = ["full"] }
@@ -0,0 +1,12 @@
[package]
name = "srml-support-procedural-tools-derive"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "0.4.24"
quote = { version = "0.6.10", features = ["proc-macro"] }
syn = { version = "0.15.21", features = ["proc-macro" ,"full", "extra-traits", "parsing"] }
@@ -0,0 +1,229 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Use to derive parsing for parsing struct.
// end::description[]
#![recursion_limit = "128"]
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro;
extern crate proc_macro2;
use proc_macro::TokenStream;
use proc_macro2::Span;
pub(crate) fn fields_idents(
fields: impl Iterator<Item = syn::Field>,
) -> impl Iterator<Item = proc_macro2::TokenStream> {
fields.enumerate().map(|(ix, field)| {
field.ident.clone().map(|i| quote!{#i}).unwrap_or_else(|| {
let f_ix: syn::Ident = syn::Ident::new(&format!("f_{}", ix), Span::call_site());
quote!( #f_ix )
})
})
}
pub(crate) fn fields_access(
fields: impl Iterator<Item = syn::Field>,
) -> impl Iterator<Item = proc_macro2::TokenStream> {
fields.enumerate().map(|(ix, field)| {
field.ident.clone().map(|i| quote!( #i )).unwrap_or_else(|| {
let f_ix: syn::Index = syn::Index {
index: ix as u32,
span: Span::call_site(),
};
quote!( #f_ix )
})
})
}
/// self defined parsing struct (use where clause on struct for it: not meant for good struct
/// design but fast parse impl).
#[proc_macro_derive(ParseStruct)]
pub fn derive_parse_struct(input: TokenStream) -> TokenStream {
let syn::ItemStruct {
ident,
generics,
fields,
..
} = parse_macro_input!(input as syn::ItemStruct);
let field_names = {
let name = fields_idents(fields.iter().map(Clone::clone));
quote!{
#(
#name,
)*
}
};
let field = fields_idents(fields.iter().map(Clone::clone));
let tokens = quote! {
impl #generics syn::parse::Parse for #ident #generics {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
#(
let #field = input.parse()?;
)*
Ok(Self {
#field_names
})
}
}
};
tokens.into()
}
#[proc_macro_derive(ToTokensStruct)]
pub fn derive_totokens_struct(input: TokenStream) -> TokenStream {
let syn::ItemStruct {
ident,
generics,
fields,
..
} = parse_macro_input!(input as syn::ItemStruct);
let fields = fields_access(fields.iter().map(Clone::clone));
let tokens = quote! {
impl #generics quote::ToTokens for #ident #generics {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
#(
self.#fields.to_tokens(tokens);
)*
}
}
};
tokens.into()
}
/// self defined parsing enum, variant are tested in order of definition.
/// Empty variant allways true.
/// Please use carefully, this will fully parse successfull variant twice.
#[proc_macro_derive(ParseEnum)]
pub fn derive_parse_enum(input: TokenStream) -> TokenStream {
let syn::ItemEnum {
ident,
generics,
variants,
..
} = parse_macro_input!(input as syn::ItemEnum);
let variants = variants.iter().map(|v| {
let variant_ident = v.ident.clone();
let fields_build = if v.fields.iter().count() > 0 {
let fields_id = fields_idents(v.fields.iter().map(Clone::clone));
quote!( (#(#fields_id), *) )
} else {
quote!()
};
let fields_procs = fields_idents(v.fields.iter().map(Clone::clone))
.map(|fident| {
quote!{
let mut #fident = match fork.parse() {
Ok(r) => r,
Err(_e) => break,
};
}
});
let fields_procs_again = fields_idents(v.fields.iter().map(Clone::clone))
.map(|fident| {
quote!{
#fident = input.parse().expect("was parsed just before");
}
});
// double parse to update input cursor position
// next syn crate version should be checked for a way
// to copy position/state from a fork
quote!{
let mut fork = input.fork();
loop {
#(#fields_procs)*
#(#fields_procs_again)*
return Ok(#ident::#variant_ident#fields_build);
}
}
});
let tokens = quote! {
impl #generics syn::parse::Parse for #ident #generics {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
#(
#variants
)*
// no early return from any variants
Err(
syn::parse::Error::new(
proc_macro2::Span::call_site(),
"derived enum no matching variants"
)
)
}
}
};
tokens.into()
}
/// only output field (empty field act as a None)
#[proc_macro_derive(ToTokensEnum)]
pub fn derive_totokens_enum(input: TokenStream) -> TokenStream {
let syn::ItemEnum {
ident,
generics,
variants,
..
} = parse_macro_input!(input as syn::ItemEnum);
let variants = variants.iter().map(|v| {
let v_ident = v.ident.clone();
let fields_build = if v.fields.iter().count() > 0 {
let fields_id = fields_idents(v.fields.iter().map(Clone::clone));
quote!( (#(#fields_id), *) )
} else {
quote!()
};
let field = fields_idents(v.fields.iter().map(Clone::clone));
quote! {
#ident::#v_ident#fields_build => {
#(
#field.to_tokens(tokens);
)*
},
}
});
let tokens = quote! {
impl #generics quote::ToTokens for #ident #generics {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
#(
#variants
)*
}
}
}
};
tokens.into()
}
@@ -0,0 +1,94 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Proc macro helpers for procedural macros
// end::description[]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro2;
extern crate proc_macro;
#[macro_use] extern crate srml_support_procedural_tools_derive;
// reexport proc macros
pub use srml_support_procedural_tools_derive::*;
pub mod syn_ext;
#[macro_export]
macro_rules! custom_keyword_impl {
($name:ident, $keyident:expr, $keydisp:expr) => {
impl CustomKeyword for $name {
fn ident() -> &'static str { $keyident }
fn display() -> &'static str { $keydisp }
}
}
}
#[macro_export]
macro_rules! custom_keyword {
($name:ident, $keyident:expr, $keydisp:expr) => {
#[derive(Debug)]
struct $name;
custom_keyword_impl!($name, $keyident, $keydisp);
}
}
// TODO following functions are copied from sr-api-macros : do a merge to get a unique procedural
// macro tooling crate (this crate path does not look good for it)
use proc_macro2::{TokenStream, Span};
use syn::Ident;
fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident {
Ident::new(&format!("sr_api_hidden_includes_{}", unique_id), Span::call_site())
}
/// Generates the access to the `subtrate_client` crate.
pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream {
if ::std::env::var("CARGO_PKG_NAME").unwrap() == def_crate {
quote!( crate )
} else {
let mod_name = generate_hidden_includes_mod_name(unique_id);
quote!( self::#mod_name::hidden_include )
}.into()
}
/// 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, crate_id: &str) -> TokenStream {
let crate_id = Ident::new(crate_id, Span::call_site());
if ::std::env::var("CARGO_PKG_NAME").unwrap() == def_crate {
TokenStream::new()
} else {
let mod_name = generate_hidden_includes_mod_name(unique_id);
quote!(
#[doc(hidden)]
mod #mod_name {
pub extern crate #crate_id as hidden_include;
}
)
}.into()
}
@@ -0,0 +1,336 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Extension to syn types, mainly for parsing
// end::description[]
use syn::parse::{
Parse,
ParseStream,
Result,
};
use syn::token::CustomKeyword;
use proc_macro2::TokenStream as T2;
use quote::ToTokens;
use std::iter::once;
use syn::Ident;
/// stop parsing here getting remaining token as content
/// Warn duplicate stream (part of)
#[derive(ParseStruct, ToTokensStruct, Debug)]
pub struct StopParse {
pub inner: T2,
}
// inner macro really dependant on syn naming convention, do not export
macro_rules! groups_impl {
($name:ident, $tok:ident, $deli:ident, $parse:ident) => {
#[derive(Debug)]
pub struct $name<P> {
pub token: syn::token::$tok,
pub content: P,
}
impl<P: Parse> Parse for $name<P> {
fn parse(input: ParseStream) -> Result<Self> {
let syn::group::$name { token, content } = syn::group::$parse(input)?;
let content = content.parse()?;
Ok($name { token, content, })
}
}
impl<P: ToTokens> ToTokens for $name<P> {
fn to_tokens(&self, tokens: &mut T2) {
let mut inner_stream = T2::new();
self.content.to_tokens(&mut inner_stream);
let token_tree: proc_macro2::TokenTree =
proc_macro2::Group::new(proc_macro2::Delimiter::$deli, inner_stream).into();
tokens.extend(once(token_tree));
}
}
}
}
groups_impl!(Braces, Brace, Brace, parse_braces);
groups_impl!(Brackets, Bracket, Bracket, parse_brackets);
groups_impl!(Parens, Paren, Parenthesis, parse_parens);
#[derive(Debug)]
pub struct CustomToken<T>(std::marker::PhantomData<T>);
impl<T: CustomKeyword> Parse for CustomToken<T> {
fn parse(input: ParseStream) -> Result<Self> {
let ident: syn::Ident = input.parse()?;
if ident.to_string().as_str() != T::ident() {
return Err(syn::parse::Error::new_spanned(ident, "expected another custom token"))
}
Ok(CustomToken(std::marker::PhantomData))
}
}
impl<T: CustomKeyword> ToTokens for CustomToken<T> {
fn to_tokens(&self, tokens: &mut T2) {
use std::str::FromStr;
tokens.extend(T2::from_str(T::ident()).expect("custom keyword should parse to ident"));
}
}
impl<T: CustomKeyword> CustomKeyword for CustomToken<T> {
fn ident() -> &'static str { <T as CustomKeyword>::ident() }
fn display() -> &'static str { <T as CustomKeyword>::display() }
}
#[derive(Debug)]
pub struct PunctuatedInner<P,T,V> {
pub inner: syn::punctuated::Punctuated<P,T>,
pub variant: V,
}
#[derive(Debug)]
pub struct NoTrailing;
#[derive(Debug)]
pub struct Trailing;
pub type Punctuated<P,T> = PunctuatedInner<P,T,NoTrailing>;
pub type PunctuatedTrailing<P,T> = PunctuatedInner<P,T,Trailing>;
impl<P: Parse, T: Parse + syn::token::Token> Parse for PunctuatedInner<P,T,Trailing> {
fn parse(input: ParseStream) -> Result<Self> {
Ok(PunctuatedInner {
inner: syn::punctuated::Punctuated::parse_separated_nonempty(input)?,
variant: Trailing,
})
}
}
impl<P: Parse, T: Parse> Parse for PunctuatedInner<P,T,NoTrailing> {
fn parse(input: ParseStream) -> Result<Self> {
Ok(PunctuatedInner {
inner: syn::punctuated::Punctuated::parse_terminated(input)?,
variant: NoTrailing,
})
}
}
impl<P: ToTokens, T: ToTokens, V> ToTokens for PunctuatedInner<P,T,V> {
fn to_tokens(&self, tokens: &mut T2) {
self.inner.to_tokens(tokens)
}
}
/// Note that syn Meta is almost fine for use case (lacks only `ToToken`)
#[derive(Debug, Clone)]
pub struct Meta {
pub inner: syn::Meta,
}
impl Parse for Meta {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Meta {
inner: syn::Meta::parse(input)?,
})
}
}
impl ToTokens for Meta {
fn to_tokens(&self, tokens: &mut T2) {
match self.inner {
syn::Meta::Word(ref ident) => {
let ident = ident.clone();
let toks = quote!{
#[#ident]
};
tokens.extend(toks);
},
syn::Meta::List(ref l) => l.to_tokens(tokens),
syn::Meta::NameValue(ref n) => n.to_tokens(tokens),
}
}
}
#[derive(Debug)]
pub struct OuterAttributes {
pub inner: Vec<syn::Attribute>,
}
impl Parse for OuterAttributes {
fn parse(input: ParseStream) -> Result<Self> {
let inner = syn::Attribute::parse_outer(input)?;
Ok(OuterAttributes {
inner,
})
}
}
impl ToTokens for OuterAttributes {
fn to_tokens(&self, tokens: &mut T2) {
for att in self.inner.iter() {
att.to_tokens(tokens);
}
}
}
#[derive(Debug)]
pub struct Seq<P> {
pub inner: Vec<P>,
}
impl<P: Parse> Parse for Seq<P> {
// Note that it cost a double parsing (same as enum derive)
fn parse(input: ParseStream) -> Result<Self> {
let mut inner = Vec::new();
loop {
let fork = input.fork();
let res: Result<P> = fork.parse();
match res {
Ok(_item) => {
// move cursor
let item: P = input.parse().expect("Same parsing ran before");
inner.push(item);
},
Err(_e) => break,
}
}
Ok(Seq { inner })
}
}
impl<P: ToTokens> ToTokens for Seq<P> {
fn to_tokens(&self, tokens: &mut T2) {
for p in self.inner.iter() {
p.to_tokens(tokens);
}
}
}
pub fn extract_type_option(typ: &syn::Type) -> Option<T2> {
if let syn::Type::Path(ref path) = typ {
path.path.segments.last().and_then(|v| {
if v.value().ident == "Option" {
if let syn::PathArguments::AngleBracketed(ref a) = v.value().arguments {
let args = &a.args;
Some(quote!{ #args })
} else {
None
}
} else {
None
}
})
} else {
None
}
}
pub fn is_parametric_type_def(typ: &syn::Type, default: bool) -> bool {
match *typ {
syn::Type::Path(ref path) => {
path.path.segments.iter().any(|v| {
if let syn::PathArguments::AngleBracketed(..) = v.arguments {
true
} else {
false
}
})
},
syn::Type::Slice(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Array(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Ptr(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Reference(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::BareFn(ref inner) => inner.variadic.is_some(),
syn::Type::Never(..) => false,
syn::Type::Tuple(ref inner) =>
inner.elems.iter().any(|t| is_parametric_type_def(t, default)),
syn::Type::TraitObject(..) => true,
syn::Type::ImplTrait(..) => true,
syn::Type::Paren(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Group(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Infer(..) => true,
syn::Type::Macro(..) => default,
syn::Type::Verbatim(..) => default,
}
}
/// check if type has any type parameter, defaults to true for some cases.
pub fn is_parametric_type(typ: &syn::Type) -> bool {
is_parametric_type_def(typ, true)
}
fn has_parametric_type_def_in_path(path: &syn::Path, ident: &Ident, default: bool) -> bool {
path.segments.iter().any(|v| {
if ident == &v.ident {
return true;
}
if let syn::PathArguments::AngleBracketed(ref a) = v.arguments {
for arg in a.args.iter() {
if let syn::GenericArgument::Type(ref typ) = arg {
if has_parametric_type_def(typ, ident, default) {
return true;
}
}
// potentially missing matches here
}
false
} else {
false
}
})
}
pub fn has_parametric_type_def(typ: &syn::Type, ident: &Ident, default: bool) -> bool {
match *typ {
syn::Type::Path(ref path) => has_parametric_type_def_in_path(&path.path, ident, default),
syn::Type::Slice(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Array(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Ptr(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Reference(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::BareFn(ref inner) => inner.variadic.is_some(),
syn::Type::Never(..) => false,
syn::Type::Tuple(ref inner) =>
inner.elems.iter().any(|t| has_parametric_type_def(t, ident, default)),
syn::Type::TraitObject(ref to) => {
to.bounds.iter().any(|bound| {
if let syn::TypeParamBound::Trait(ref t) = bound {
has_parametric_type_def_in_path(&t.path, ident, default)
} else { false }
})
},
syn::Type::ImplTrait(ref it) => {
it.bounds.iter().any(|bound| {
if let syn::TypeParamBound::Trait(ref t) = bound {
has_parametric_type_def_in_path(&t.path, ident, default)
} else { false }
})
},
syn::Type::Paren(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Group(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Infer(..) => default,
syn::Type::Macro(..) => default,
syn::Type::Verbatim(..) => default,
}
}
/// check if type has a type parameter, defaults to true for some cases.
pub fn has_parametric_type(typ: &syn::Type, ident: &Ident) -> bool {
has_parametric_type_def(typ, ident, true)
}
+6
View File
@@ -31,6 +31,9 @@ extern crate srml_metadata;
extern crate mashup;
#[macro_use]
extern crate srml_support_procedural;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
@@ -67,6 +70,9 @@ pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType};
pub use self::metadata::RuntimeMetadata;
pub use runtime_io::print;
#[doc(inline)]
pub use srml_support_procedural::decl_storage;
#[macro_export]
macro_rules! fail {
( $y:expr ) => {{
-1
View File
@@ -188,7 +188,6 @@ mod tests {
StorageMethod : Option<u32>;
}
add_extra_genesis {
config(_marker) : ::std::marker::PhantomData<T>;
build(|_, _, _| {});
}
}
File diff suppressed because it is too large Load Diff
-3
View File
@@ -207,7 +207,6 @@ mod tests {
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
t.extend(GenesisConfig::<Test> {
period: 5,
_genesis_phantom_data: Default::default()
}.build_storage().unwrap().0);
with_externalities(&mut TestExternalities::new(t), || {
@@ -223,7 +222,6 @@ mod tests {
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
t.extend(GenesisConfig::<Test> {
period: 5,
_genesis_phantom_data: Default::default()
}.build_storage().unwrap().0);
with_externalities(&mut TestExternalities::new(t), || {
@@ -239,7 +237,6 @@ mod tests {
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
t.extend(GenesisConfig::<Test> {
period: 5,
_genesis_phantom_data: Default::default()
}.build_storage().unwrap().0);
with_externalities(&mut TestExternalities::new(t), || {
-2
View File
@@ -330,14 +330,12 @@ mod tests {
creation_fee: 0,
existential_deposit: 0,
reclaim_rebate: 0,
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.extend(GenesisConfig::<Test>{
proposal_bond: Permill::from_percent(5),
proposal_bond_minimum: 1,
spend_period: 2,
burn: Permill::from_percent(50),
_genesis_phantom_data: Default::default(),
}.build_storage().unwrap().0);
t.into()
}
+1
View File
@@ -13,6 +13,7 @@ sr-std = { path = "../../core/sr-std", default-features = false }
sr-io = { path = "../../core/sr-io", default-features = false }
sr-primitives = { path = "../../core/sr-primitives", default-features = false }
srml-support = { path = "../support", default-features = false }
srml-support-procedural = { path = "../support/procedural" }
srml-system = { path = "../system", default-features = false }
srml-consensus = { path = "../consensus", default-features = false }
+1
View File
@@ -30,6 +30,7 @@ extern crate parity_codec_derive;
extern crate parity_codec as codec;
#[macro_use]
extern crate srml_support as support;
extern crate srml_system as system;
extern crate srml_consensus as consensus;