diff --git a/crates/cgp-core/src/prelude.rs b/crates/cgp-core/src/prelude.rs index cc2321ab..41063b28 100644 --- a/crates/cgp-core/src/prelude.rs +++ b/crates/cgp-core/src/prelude.rs @@ -19,7 +19,8 @@ pub use cgp_field::types::{ pub use cgp_macro::{ BuildField, CgpData, CgpRecord, CgpVariant, ExtractField, FromVariant, HasField, HasFields, Product, Sum, Symbol, cgp_auto_getter, cgp_component, cgp_fn, cgp_getter, cgp_impl, - cgp_inherit, cgp_new_provider, cgp_preset, cgp_provider, cgp_type, check_components, - delegate_and_check_components, delegate_components, product, re_export_imports, replace_with, + cgp_inherit, cgp_namespace, cgp_new_provider, cgp_preset, cgp_provider, cgp_type, + check_components, delegate_and_check_components, delegate_components, product, + re_export_imports, replace_with, }; pub use cgp_type::{HasType, TypeProvider, UseType}; diff --git a/crates/cgp-error/src/traits/can_raise_error.rs b/crates/cgp-error/src/traits/can_raise_error.rs index 4fbbd1a8..3be6da8f 100644 --- a/crates/cgp-error/src/traits/can_raise_error.rs +++ b/crates/cgp-error/src/traits/can_raise_error.rs @@ -12,7 +12,7 @@ use crate::traits::has_error_type::HasErrorType; provider: ErrorRaiser, derive_delegate: UseDelegate, }] -#[use_namespace(cgp.core.error)] +#[use_namespace(@cgp.core.error.ErrorRaiserComponent)] pub trait CanRaiseError: HasErrorType { fn raise_error(error: SourceError) -> Self::Error; } diff --git a/crates/cgp-error/src/traits/can_wrap_error.rs b/crates/cgp-error/src/traits/can_wrap_error.rs index a28b03a0..c8defb99 100644 --- a/crates/cgp-error/src/traits/can_wrap_error.rs +++ b/crates/cgp-error/src/traits/can_wrap_error.rs @@ -1,4 +1,5 @@ use cgp_component::*; +use cgp_field::types::*; use cgp_macro::cgp_component; use crate::traits::HasErrorType; @@ -7,6 +8,7 @@ use crate::traits::HasErrorType; provider: ErrorWrapper, derive_delegate: UseDelegate, }] +#[use_namespace(@cgp.core.error.ErrorWrapperComponent)] pub trait CanWrapError: HasErrorType { fn wrap_error(error: Self::Error, detail: Detail) -> Self::Error; } diff --git a/crates/cgp-error/src/traits/has_error_type.rs b/crates/cgp-error/src/traits/has_error_type.rs index c02beb4a..4cec7151 100644 --- a/crates/cgp-error/src/traits/has_error_type.rs +++ b/crates/cgp-error/src/traits/has_error_type.rs @@ -28,7 +28,7 @@ use cgp_type::{TypeProvider, UseType}; */ #[cgp_type] -#[use_namespace(cgp.core.error)] +#[use_namespace(@cgp.core.error.ErrorTypeProviderComponent)] pub trait HasErrorType { type Error: Debug; } diff --git a/crates/cgp-macro-lib/src/attributes/use_namespace.rs b/crates/cgp-macro-lib/src/attributes/use_namespace.rs index 35199567..ef142a5d 100644 --- a/crates/cgp-macro-lib/src/attributes/use_namespace.rs +++ b/crates/cgp-macro-lib/src/attributes/use_namespace.rs @@ -1,13 +1,14 @@ -use syn::Ident; +use quote::quote; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{Colon, Dot}; +use syn::token::{At, Colon, Dot}; +use syn::{Ident, Type, parse2}; use crate::parse::PathType; pub struct UseNamespaceAttribute { pub namespace: Ident, - pub path: Punctuated, + pub path: Type, } impl Parse for UseNamespaceAttribute { @@ -20,7 +21,17 @@ impl Parse for UseNamespaceAttribute { Ident::new("DefaultNamespace", input.span()) }; - let path = Punctuated::parse_separated_nonempty(input)?; + let _: At = input.parse()?; + + let paths: Punctuated = Punctuated::parse_separated_nonempty(input)?; + + let raw_path_type = paths.into_iter().rev().fold( + quote!(PathNil), + |tail, PathType { path_type }| quote!(PathCons<#path_type, #tail>), + ); + + let path: Type = parse2(raw_path_type)?; + Ok(UseNamespaceAttribute { namespace, path }) } } diff --git a/crates/cgp-macro-lib/src/cgp_namespace/mod.rs b/crates/cgp-macro-lib/src/cgp_namespace/mod.rs new file mode 100644 index 00000000..cc05df3b --- /dev/null +++ b/crates/cgp-macro-lib/src/cgp_namespace/mod.rs @@ -0,0 +1 @@ +pub mod spec; diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs new file mode 100644 index 00000000..837b7766 --- /dev/null +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -0,0 +1,83 @@ +use quote::quote; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::{At, Colon, Comma, Dot, Lt}; +use syn::{Ident, Type, braced, parse2}; + +use crate::parse::{ComponentPath, ComponentPaths, ImplGenerics, PathType}; + +pub struct NamespaceSpec { + pub namespace_ident: Ident, + pub parent_namespace_ident: Option, + pub entries: Punctuated, +} + +pub struct NamespaceEntry { + pub keys: ComponentPaths, + pub value: Type, +} + +impl Parse for NamespaceSpec { + fn parse(input: ParseStream) -> syn::Result { + let namespace_ident: Ident = input.parse()?; + + let parent_namespace_ident: Option = if input.peek(Colon) { + let _: Colon = input.parse()?; + let ident = input.parse()?; + Some(ident) + } else { + None + }; + + let content; + braced!(content in input); + + let entries = Punctuated::parse_terminated(&content)?; + + Ok(NamespaceSpec { + namespace_ident, + parent_namespace_ident, + entries, + }) + } +} + +impl Parse for NamespaceEntry { + fn parse(input: ParseStream) -> syn::Result { + let keys: ComponentPaths = if input.peek(At) { + let _: At = input.parse()?; + + input.parse()? + } else { + let generics: ImplGenerics = if input.peek(Lt) { + input.parse()? + } else { + Default::default() + }; + + let path_type: Type = input.parse()?; + + let path = ComponentPath { + generics, + path_type, + }; + + ComponentPaths { paths: vec![path] } + }; + + let _: Colon = input.parse()?; + + let _: At = input.parse()?; + + let value_path: Punctuated = Punctuated::parse_separated_nonempty(input)?; + + let value = value_path.into_iter().rev().fold( + quote!(PathNil), + |tail, PathType { path_type }| quote!( PathCons< #path_type, #tail > ), + ); + + let value: Type = parse2(value)?; + + Ok(Self { keys, value }) + } +} diff --git a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs index 6229f5af..e3dde545 100644 --- a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs +++ b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs @@ -1,5 +1,5 @@ -use quote::{ToTokens, quote}; -use syn::{Ident, ItemImpl, Type, parse2}; +use quote::quote; +use syn::{Ident, ItemImpl, parse2}; use crate::attributes::UseNamespaceAttribute; @@ -21,10 +21,7 @@ pub fn derive_namespace_impl( component_name: &Ident, ) -> syn::Result { let namespace = &attribute.namespace; - let mut paths = Vec::from_iter(attribute.path.iter().map(|path| path.path_type.clone())); - paths.push(parse2(component_name.to_token_stream())?); - - let path = path_to_product(&paths)?; + let path = &attribute.path; let out = quote! { impl<__Components__> #namespace < __Components__ > for #component_name @@ -35,15 +32,3 @@ pub fn derive_namespace_impl( parse2(out) } - -pub fn path_to_product(paths: &[Type]) -> syn::Result { - let mut out = quote! { PathNil }; - - for path in paths.iter().rev() { - out = quote! { - PathCons< #path , #out > - }; - } - - parse2(out) -} diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs new file mode 100644 index 00000000..7b39a741 --- /dev/null +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -0,0 +1,82 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse2}; + +use crate::cgp_namespace::spec::NamespaceSpec; + +pub fn cgp_namespace(body: TokenStream) -> syn::Result { + let spec: NamespaceSpec = parse2(body)?; + + let mut out = TokenStream::new(); + + let namespace_ident = &spec.namespace_ident; + + let namespace_trait: ItemTrait = parse2(quote! { + pub trait #namespace_ident< __Components__ > { + type Provider; + } + })?; + + out.extend(quote! { + #namespace_trait + }); + + if let Some(parent_namespace_ident) = spec.parent_namespace_ident { + let namespace_struct_ident = Ident::new( + &format!("__{}Components", namespace_ident), + namespace_ident.span(), + ); + + let namespace_struct: ItemStruct = parse2(quote! { + pub struct #namespace_struct_ident; + })?; + + let item_impl: ItemImpl = parse2(quote! { + impl<__Context__, __Components__, __Provider__> + #namespace_ident< __Components__ > + for __Context__ + where + __Context__: #parent_namespace_ident< __Components__, Provider = __Provider__ > + + #parent_namespace_ident< #namespace_struct_ident >, + { + type Provider = __Provider__; + } + })?; + + out.extend(quote! { + #namespace_struct + + #item_impl + }) + } + + for entry in spec.entries.into_iter() { + let value = entry.value; + for path in entry.keys.paths.into_iter() { + let path_type = path.path_type; + + let mut generics = path.generics.generics; + generics.params.push(parse2(quote!(__Components__))?); + + let impl_generics = generics.split_for_impl().0; + + let item_impl: ItemImpl = parse2(quote! { + impl #impl_generics + #namespace_ident< __Components__ > + for #path_type + { + type Provider = RedirectLookup< + __Components__, + #value, + >; + } + })?; + + out.extend(quote! { + #item_impl + }) + } + } + + Ok(out) +} diff --git a/crates/cgp-macro-lib/src/entrypoints/mod.rs b/crates/cgp-macro-lib/src/entrypoints/mod.rs index 958186cf..ee117d9c 100644 --- a/crates/cgp-macro-lib/src/entrypoints/mod.rs +++ b/crates/cgp-macro-lib/src/entrypoints/mod.rs @@ -6,6 +6,7 @@ mod cgp_fn; mod cgp_getter; mod cgp_impl; mod cgp_inherit; +mod cgp_namespace; mod cgp_new_provider; mod cgp_preset; mod cgp_provider; @@ -30,6 +31,7 @@ pub use cgp_fn::*; pub use cgp_getter::*; pub use cgp_impl::*; pub use cgp_inherit::*; +pub use cgp_namespace::*; pub use cgp_new_provider::*; pub use cgp_preset::*; pub use cgp_provider::*; diff --git a/crates/cgp-macro-lib/src/lib.rs b/crates/cgp-macro-lib/src/lib.rs index 2b322b95..23501b7a 100644 --- a/crates/cgp-macro-lib/src/lib.rs +++ b/crates/cgp-macro-lib/src/lib.rs @@ -11,6 +11,7 @@ pub(crate) mod attributes; pub(crate) mod blanket_trait; pub(crate) mod cgp_fn; pub(crate) mod cgp_impl; +pub(crate) mod cgp_namespace; pub(crate) mod check_components; pub(crate) mod delegate_components; pub(crate) mod derive_builder; diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index ebc09cd4..ee8119f6 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -2,7 +2,7 @@ use proc_macro2::{TokenStream, TokenTree}; use quote::{ToTokens, quote}; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{Brace, Comma, Dot, Lt, Star}; +use syn::token::{Brace, Comma, Dot, Lt}; use syn::{Ident, Type, braced, parse_quote, parse2}; use crate::parse::ImplGenerics; @@ -16,7 +16,7 @@ impl Parse for ComponentPaths { fn parse(input: ParseStream) -> syn::Result { let path_head = PathHead::parse(input)?; - if let PathHead::Nil = path_head { + if let PathHead::Wildcard = path_head { return Err(syn::Error::new( input.span(), "Expected at least one path element", @@ -43,11 +43,9 @@ pub struct ComponentPath { } pub enum PathHead { - Type(Option, Type, Box), - Symbol(Option, Ident, Box), + Type(Option, Box, Box), Group(Punctuated), Wildcard, - Nil, } impl PathHead { @@ -56,14 +54,11 @@ impl PathHead { Self::Type(generics, path_type, rest) => { let rest_types = rest.to_paths(); - prepend_path(path_type.to_token_stream(), generics.clone(), rest_types) - } - Self::Symbol(generics, ident, rest) => { - let ident_str = ident.to_string(); - let path_type = symbol_from_string_spanned(ident.span(), &ident_str); - - let rest_types = rest.to_paths(); - prepend_path(path_type, generics.clone(), rest_types) + prepend_path( + path_type.path_type.to_token_stream(), + generics.clone(), + rest_types, + ) } Self::Group(paths) => paths.iter().flat_map(|path| path.to_paths()).collect(), Self::Wildcard => { @@ -72,12 +67,6 @@ impl PathHead { generics: parse_quote! { <__Wildcard__> }, }] } - Self::Nil => { - vec![ComponentPath { - path_type: quote! { PathNil }, - generics: Default::default(), - }] - } } } } @@ -111,9 +100,6 @@ pub fn prepend_path( impl Parse for PathHead { fn parse(input: ParseStream) -> syn::Result { if input.is_empty() { - Ok(Self::Nil) - } else if input.peek(Star) { - let _: Star = input.parse()?; Ok(Self::Wildcard) } else if input.peek(Brace) { let body; @@ -129,20 +115,16 @@ impl Parse for PathHead { None }; - let path_type: Type = input.parse()?; + let path_type: PathType = input.parse()?; let rest_path = if input.peek(Dot) { let _: Dot = input.parse()?; Box::new(Self::parse(input)?) } else { - Box::new(Self::Nil) + Box::new(Self::Wildcard) }; - if let Some(path_ident) = path_type_as_ident(&path_type) { - Ok(Self::Symbol(generics, path_ident, rest_path)) - } else { - Ok(Self::Type(generics, path_type, rest_path)) - } + Ok(Self::Type(generics, Box::new(path_type), rest_path)) } } } diff --git a/crates/cgp-macro/src/lib.rs b/crates/cgp-macro/src/lib.rs index e70c0cd1..acc29b0f 100644 --- a/crates/cgp-macro/src/lib.rs +++ b/crates/cgp-macro/src/lib.rs @@ -541,6 +541,13 @@ pub fn delegate_components(body: TokenStream) -> TokenStream { .into() } +#[proc_macro] +pub fn cgp_namespace(body: TokenStream) -> TokenStream { + cgp_macro_lib::cgp_namespace(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + /** The `check_components!` macro allows users to write compile-time tests to check for the correctness of component wiring for a CGP context. diff --git a/crates/cgp-tests/src/namespaces/extend.rs b/crates/cgp-tests/src/namespaces/extend.rs deleted file mode 100644 index 3d19b6a2..00000000 --- a/crates/cgp-tests/src/namespaces/extend.rs +++ /dev/null @@ -1,47 +0,0 @@ -use cgp::core::component::RedirectLookup; -use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; -use cgp::prelude::*; - -pub trait ExtendedNamespace { - type Provider; -} - -pub struct ExtendedNamespaceComponents; - -impl ExtendedNamespace for Component -where - Component: DefaultNamespace - + DefaultNamespace, -{ - type Provider = Provider; -} - -impl ExtendedNamespace - for PathCons< - Symbol!("cgp"), - PathCons< - Symbol!("core"), - PathCons>>, - >, - > -{ - type Provider = RedirectLookup< - Components, - PathCons>, - >; -} - -impl ExtendedNamespace - for PathCons< - Symbol!("cgp"), - PathCons< - Symbol!("core"), - PathCons>, - >, - > -{ - type Provider = RedirectLookup< - Components, - PathCons>, - >; -} diff --git a/crates/cgp-tests/src/namespaces/extended.rs b/crates/cgp-tests/src/namespaces/extended.rs new file mode 100644 index 00000000..3c4699e0 --- /dev/null +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -0,0 +1,12 @@ +use cgp::core::component::RedirectLookup; +use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; +use cgp::prelude::*; + +cgp_namespace! { + ExtendedNamespace: DefaultNamespace { + @cgp.core.error.ErrorRaiserComponent: + @app.ErrorRaiserComponent, + @cgp.core.error.ErrorTypeProviderComponent: + @app.ErrorTypeProviderComponent, + } +} diff --git a/crates/cgp-tests/src/namespaces/mod.rs b/crates/cgp-tests/src/namespaces/mod.rs index d5e97d22..34d3c6b8 100644 --- a/crates/cgp-tests/src/namespaces/mod.rs +++ b/crates/cgp-tests/src/namespaces/mod.rs @@ -1,3 +1,3 @@ -mod extend; +mod extended; -pub use extend::*; +pub use extended::*; diff --git a/crates/cgp-tests/tests/namespace_tests/mod.rs b/crates/cgp-tests/tests/namespace_tests/mod.rs index 05efb2a4..149e8657 100644 --- a/crates/cgp-tests/tests/namespace_tests/mod.rs +++ b/crates/cgp-tests/tests/namespace_tests/mod.rs @@ -1,4 +1,4 @@ -pub mod extend_namespace; +pub mod namespace_macro; pub mod open; pub mod redirect; pub mod use_namespace; diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs new file mode 100644 index 00000000..fc9291fc --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -0,0 +1,51 @@ +use cgp::prelude::*; + +#[cgp_component(FooProvider)] +pub trait Foo { + fn foo(&self); +} + +cgp_namespace! { + MyNamespace { + FooProviderComponent: + @MyFooComponent, + } +} + +#[cgp_component(BarProvider)] +#[use_namespace(MyNamespace: @MyBarComponent)] +pub trait Bar { + fn bar(&self); +} + +pub struct MyFooComponent; +pub struct MyBarComponent; + +#[cgp_impl(new DummyFoo)] +impl FooProvider { + fn foo(&self) {} +} + +#[cgp_impl(new DummyBar)] +impl BarProvider { + fn bar(&self) {} +} + +pub struct App; + +delegate_components! { + #[use_namespace(MyNamespace)] + App { + @MyFooComponent: + DummyFoo, + @MyBarComponent: + DummyBar, + } +} + +check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } +} diff --git a/crates/cgp-tests/tests/namespace_tests/extend_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs similarity index 95% rename from crates/cgp-tests/tests/namespace_tests/extend_namespace.rs rename to crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs index b0b90a97..54f19ae0 100644 --- a/crates/cgp-tests/tests/namespace_tests/extend_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs @@ -13,7 +13,7 @@ delegate_components! { UseType, @app.{ ErrorRaiserComponent.{&'static str, String}, - ErrorWrapperComponent.*, + ErrorWrapperComponent, }: RaiseFrom, TryComputerComponent: diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs new file mode 100644 index 00000000..dbd2d282 --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs @@ -0,0 +1,5 @@ +pub mod basic; +pub mod extended_namespace; +pub mod multi_namespace; +pub mod symbol_path; +pub mod type_path; diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs new file mode 100644 index 00000000..54d10124 --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -0,0 +1,81 @@ +use cgp::prelude::*; + +pub struct MyApp; + +#[cgp_component(FooProvider)] +pub trait Foo { + fn foo(&self); +} + +cgp_namespace! { + MyNamespace { + FooProviderComponent: + @MyApp.MyFooComponent, + } +} + +cgp_namespace! { + OtherNamespace { + FooProviderComponent: + @my_app.MyFooComponent, + } +} + +#[cgp_component(BarProvider)] +#[use_namespace(MyNamespace: @MyApp.MyBarComponent)] +#[use_namespace(OtherNamespace: @my_app.MyBarComponent)] +pub trait Bar { + fn bar(&self); +} + +pub struct MyFooComponent; + +pub struct MyBarComponent; + +#[cgp_impl(new DummyFoo)] +impl FooProvider { + fn foo(&self) {} +} + +#[cgp_impl(new DummyBar)] +impl BarProvider { + fn bar(&self) {} +} + +pub struct App; + +delegate_components! { + #[use_namespace(MyNamespace)] + App { + @MyApp.MyFooComponent: + DummyFoo, + @MyApp.MyBarComponent: + DummyBar, + } +} + +check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } +} + +pub struct OtherApp; + +delegate_components! { + #[use_namespace(OtherNamespace)] + OtherApp { + @my_app.MyFooComponent: + DummyFoo, + @my_app.MyBarComponent: + DummyBar, + } +} + +check_components! { + OtherApp { + FooProviderComponent, + BarProviderComponent, + } +} diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs new file mode 100644 index 00000000..e5899dfc --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -0,0 +1,52 @@ +use cgp::prelude::*; + +#[cgp_component(FooProvider)] +pub trait Foo { + fn foo(&self); +} + +cgp_namespace! { + MyNamespace { + FooProviderComponent: + @my_app.MyFooComponent, + } +} + +#[cgp_component(BarProvider)] +#[use_namespace(MyNamespace: @my_app.MyBarComponent)] +pub trait Bar { + fn bar(&self); +} + +pub struct MyFooComponent; + +pub struct MyBarComponent; + +#[cgp_impl(new DummyFoo)] +impl FooProvider { + fn foo(&self) {} +} + +#[cgp_impl(new DummyBar)] +impl BarProvider { + fn bar(&self) {} +} + +pub struct App; + +delegate_components! { + #[use_namespace(MyNamespace)] + App { + @my_app.MyFooComponent: + DummyFoo, + @my_app.MyBarComponent: + DummyBar, + } +} + +check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } +} diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs new file mode 100644 index 00000000..b23fc646 --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -0,0 +1,54 @@ +use cgp::prelude::*; + +pub struct MyApp; + +#[cgp_component(FooProvider)] +pub trait Foo { + fn foo(&self); +} + +cgp_namespace! { + MyNamespace { + FooProviderComponent: + @MyApp.MyFooComponent, + } +} + +#[cgp_component(BarProvider)] +#[use_namespace(MyNamespace: @MyApp.MyBarComponent)] +pub trait Bar { + fn bar(&self); +} + +pub struct MyFooComponent; + +pub struct MyBarComponent; + +#[cgp_impl(new DummyFoo)] +impl FooProvider { + fn foo(&self) {} +} + +#[cgp_impl(new DummyBar)] +impl BarProvider { + fn bar(&self) {} +} + +pub struct App; + +delegate_components! { + #[use_namespace(MyNamespace)] + App { + @MyApp.MyFooComponent: + DummyFoo, + @MyApp.MyBarComponent: + DummyBar, + } +} + +check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } +} diff --git a/crates/cgp-tests/tests/namespace_tests/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index b42f959a..5ef22d2d 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -1,7 +1,7 @@ use cgp::prelude::*; #[cgp_component(FooProvider)] -#[use_namespace(bar.baz)] +#[use_namespace(@bar.baz.FooProviderComponent)] pub trait CanDoFoo { fn foo(); } @@ -20,9 +20,9 @@ pub struct App; delegate_components! { #[use_namespace] App { - // @bar.*: TestProvider, + // @bar: TestProvider, - @bar.baz.*: TestProvider, + @bar.baz: TestProvider, // @bar.baz.FooProviderComponent: TestProvider, } diff --git a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs index 6b8e16c3..27531959 100644 --- a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs @@ -5,8 +5,8 @@ use cgp::prelude::*; pub struct MyComponents; #[cgp_component(FooProvider)] -#[use_namespace(DefaultNamespace: app.MyComponents)] -pub trait CanDoFoo { +#[use_namespace(DefaultNamespace: @app.MyComponents.FooProviderComponent)] +pub trait Foo { fn foo(&self); }