diff --git a/typegen/src/tests/mod.rs b/typegen/src/tests/mod.rs index 405b510..a954ff1 100644 --- a/typegen/src/tests/mod.rs +++ b/typegen/src/tests/mod.rs @@ -20,6 +20,158 @@ use crate::{ mod utils; +#[test] +fn more_than_1_generic_parameters() { + #[allow(unused)] + #[derive(TypeInfo)] + struct Foo { + a: T, + b: U, + c: V, + d: W, + } + + #[allow(unused)] + #[derive(TypeInfo)] + struct Bar { + p: Foo, + q: Foo, + } + + let generated = Testgen::new() + .with::() + .gen_tests_mod(Default::default()); + + #[rustfmt::skip] + let expected = quote!( + pub mod tests { + use super::types; + pub struct Bar { + pub p: types::scale_typegen::tests::Foo< + ::core::primitive::u32, + ::core::primitive::u32, + ::core::primitive::u64, + ::core::primitive::u128 + >, + pub q: types::scale_typegen::tests::Foo< + ::core::primitive::u8, + ::core::primitive::u8, + ::core::primitive::u8, + ::core::primitive::u8 + >, + } + pub struct Foo<_0, _1, _2, _3> { + pub a: _0, + pub b: _1, + pub c: _2, + pub d: _3, + } + } + ); + + assert_eq!(generated.to_string(), expected.to_string()); +} + +#[test] +fn dupe_types_do_not_overwrite_each_other() { + enum Foo {} + impl TypeInfo for Foo { + type Identity = Self; + fn type_info() -> scale_info::Type { + scale_info::Type::builder() + .path(scale_info::Path::new("DuplicateType", "dupe_mod")) + .variant( + scale_info::build::Variants::new() + .variant("FirstDupeTypeVariant", |builder| builder.index(0)), + ) + } + } + enum Bar {} + impl TypeInfo for Bar { + type Identity = Self; + fn type_info() -> scale_info::Type { + scale_info::Type::builder() + .path(scale_info::Path::new("DuplicateType", "dupe_mod")) + .variant( + scale_info::build::Variants::new() + .variant("SecondDupeTypeVariant", |builder| builder.index(0)), + ) + } + } + + let generated = Testgen::new() + .with::() + .with::() + .gen(Default::default()) + .to_string(); + + let expected = quote!( + pub mod types { + use super::types; + pub mod dupe_mod { + use super::types; + pub enum DuplicateType1 { + FirstDupeTypeVariant, + } + pub enum DuplicateType2 { + SecondDupeTypeVariant, + } + } + } + ); + + assert_eq!(generated.to_string(), expected.to_string()); +} + +#[test] +fn generic_types_overwrite_each_other() { + use scale_info::meta_type; + + // If we have two types mentioned in the registry that have generic params, + // only one type will be output (the codegen assumes that the generic param will disambiguate) + enum Foo {} + impl TypeInfo for Foo { + type Identity = Self; + fn type_info() -> scale_info::Type { + scale_info::Type::builder() + .path(scale_info::Path::new("DuplicateType", "dupe_mod")) + .type_params([scale_info::TypeParameter::new("T", Some(meta_type::()))]) + .variant(scale_info::build::Variants::new()) + } + } + enum Bar {} + impl TypeInfo for Bar { + type Identity = Self; + fn type_info() -> scale_info::Type { + scale_info::Type::builder() + .path(scale_info::Path::new("DuplicateType", "dupe_mod")) + .type_params([scale_info::TypeParameter::new("T", Some(meta_type::()))]) + .variant(scale_info::build::Variants::new()) + } + } + + let generated = Testgen::new() + .with::() + .with::() + .gen(Default::default()) + .to_string(); + + // Since a generic is present on the type, we do _not_ expect two types to be generated: + let expected = quote!( + pub mod types { + use super::types; + pub mod dupe_mod { + use super::types; + pub enum DuplicateType<_0> { + __Ignore(::core::marker::PhantomData<_0>), + } + } + } + ); + + assert_eq!(generated.to_string(), expected.to_string()); +} + #[test] fn substitutes_with_generics() { #[allow(unused)] diff --git a/typegen/src/tests/utils.rs b/typegen/src/tests/utils.rs index 4c35e93..9dc3666 100644 --- a/typegen/src/tests/utils.rs +++ b/typegen/src/tests/utils.rs @@ -6,6 +6,7 @@ use scale_info::{PortableRegistry, TypeInfo}; use syn::parse_quote; use crate::typegen::ir::module_ir::ModuleIR; +use crate::utils::ensure_unique_type_paths; use crate::{ typegen::settings::substitutes::absolute_path, DerivesRegistry, TypeGenerator, TypeGeneratorSettings, TypeSubstitutes, @@ -33,7 +34,8 @@ impl Testgen { } pub fn gen(self, settings: TypeGeneratorSettings) -> TokenStream { - let registry: PortableRegistry = self.registry.into(); + let mut registry: PortableRegistry = self.registry.into(); + ensure_unique_type_paths(&mut registry); let type_gen = TypeGenerator::new(®istry, &settings); let module = type_gen.generate_types_mod().unwrap(); module.to_token_stream()