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

Commit 6e83db0

Browse files
authored
decl_storage! check for duplicate config()/get() (#3936)
* `decl_storage!` check for duplicate `config()`/`get()` * Fix tests
1 parent 07f6bdc commit 6e83db0

File tree

13 files changed

+244
-65
lines changed

13 files changed

+244
-65
lines changed

Cargo.lock

Lines changed: 38 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

srml/support/procedural/src/storage/parse.rs

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! Parsing of decl_storage input.
1818
1919
use srml_support_procedural_tools::{ToTokens, Parse, syn_ext as ext};
20-
use syn::{Ident, Token};
20+
use syn::{Ident, Token, spanned::Spanned};
2121

2222
mod keyword {
2323
syn::custom_keyword!(hiddencrate);
@@ -265,7 +265,6 @@ fn get_module_instance(
265265

266266
pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDef> {
267267
use syn::parse::Parse;
268-
use syn::spanned::Spanned;
269268

270269
let def = StorageDefinition::parse(input)?;
271270

@@ -303,9 +302,31 @@ pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDe
303302
}
304303
}
305304

306-
let mut storage_lines = vec![];
305+
let storage_lines = parse_storage_line_defs(def.content.content.inner.into_iter())?;
307306

308-
for line in def.content.content.inner.into_iter() {
307+
Ok(super::DeclStorageDef {
308+
hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content),
309+
visibility: def.visibility,
310+
module_name: def.module_ident,
311+
store_trait: def.ident,
312+
module_runtime_generic: def.mod_param_generic,
313+
module_runtime_trait: def.mod_param_bound,
314+
where_clause: def.where_clause,
315+
crate_name: def.crate_ident,
316+
module_instance,
317+
extra_genesis_build,
318+
extra_genesis_config_lines,
319+
storage_lines,
320+
})
321+
}
322+
323+
/// Parse the `DeclStorageLine` into `StorageLineDef`.
324+
fn parse_storage_line_defs(
325+
defs: impl Iterator<Item = DeclStorageLine>,
326+
) -> syn::Result<Vec<super::StorageLineDef>> {
327+
let mut storage_lines = Vec::<super::StorageLineDef>::new();
328+
329+
for line in defs {
309330
let getter = line.getter.inner.map(|o| o.getfn.content.ident);
310331
let config = if let Some(config) = line.config.inner {
311332
if let Some(ident) = config.expr.content {
@@ -315,14 +336,28 @@ pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDe
315336
} else {
316337
return Err(syn::Error::new(
317338
config.span(),
318-
"Invalid storage definiton, couldn't find config identifier: storage must either have a get \
319-
identifier `get(fn ident)` or a defined config identifier `config(ident)`"
339+
"Invalid storage definition, couldn't find config identifier: storage must \
340+
either have a get identifier `get(fn ident)` or a defined config identifier \
341+
`config(ident)`",
320342
))
321343
}
322344
} else {
323345
None
324346
};
325347

348+
if let Some(ref config) = config {
349+
storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(|other_config| {
350+
if other_config == config {
351+
Err(syn::Error::new(
352+
config.span(),
353+
"`config()`/`get()` with the same name already defined.",
354+
))
355+
} else {
356+
Ok(())
357+
}
358+
})?;
359+
}
360+
326361
let storage_type = match line.storage_type {
327362
DeclStorageType::Map(map) => super::StorageLineTypeDef::Map(
328363
super::MapDef {
@@ -365,18 +400,5 @@ pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDe
365400
})
366401
}
367402

368-
Ok(super::DeclStorageDef {
369-
hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content),
370-
visibility: def.visibility,
371-
module_name: def.module_ident,
372-
store_trait: def.ident,
373-
module_runtime_generic: def.mod_param_generic,
374-
module_runtime_trait: def.mod_param_bound,
375-
where_clause: def.where_clause,
376-
crate_name: def.crate_ident,
377-
module_instance,
378-
extra_genesis_build,
379-
extra_genesis_config_lines,
380-
storage_lines,
381-
})
403+
Ok(storage_lines)
382404
}

srml/support/test/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ support = { package = "srml-support", version = "2", path = "../", default-featu
1212
inherents = { package = "substrate-inherents", path = "../../../core/inherents", default-features = false }
1313
sr-primitives = { package = "sr-primitives", path = "../../../core/sr-primitives", default-features = false }
1414
primitives = { package = "substrate-primitives", path = "../../../core/primitives", default-features = false }
15-
trybuild = "1.0.14"
15+
trybuild = "1.0.17"
1616
pretty_assertions = "0.6.1"
1717

1818
[features]

srml/support/test/src/lib.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,3 @@
1616

1717
//! Test crate for srml_support. Allow to make use of `support::decl_storage`.
1818
//! See tests directory.
19-
20-
#[test]
21-
fn reserved_keyword() {
22-
let t = trybuild::TestCases::new();
23-
t.compile_fail("tests/reserved_keyword/*.rs");
24-
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2019 Parity Technologies (UK) Ltd.
2+
// This file is part of Substrate.
3+
4+
// Substrate is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Substrate is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
16+
17+
#[test]
18+
fn decl_storage_ui() {
19+
// As trybuild is using `cargo check`, we don't need the real WASM binaries.
20+
std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1");
21+
22+
let t = trybuild::TestCases::new();
23+
t.compile_fail("tests/decl_storage_ui/*.rs");
24+
}

0 commit comments

Comments
 (0)