From 172d126397f3a0f48947f769ce636c656df0aa19 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 13:22:09 +0200 Subject: [PATCH 01/12] Make paths always wildcard --- crates/cgp-macro-lib/src/cgp_namespace/mod.rs | 1 + .../cgp-macro-lib/src/cgp_namespace/spec.rs | 60 +++++++++++++++++++ .../src/entrypoints/cgp_namespace.rs | 6 ++ crates/cgp-macro-lib/src/entrypoints/mod.rs | 1 + crates/cgp-macro-lib/src/lib.rs | 1 + crates/cgp-macro-lib/src/parse/path.rs | 14 +---- crates/cgp-tests/src/namespaces/extend.rs | 9 +++ .../tests/namespace_tests/extend_namespace.rs | 2 +- .../tests/namespace_tests/redirect.rs | 4 +- 9 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 crates/cgp-macro-lib/src/cgp_namespace/mod.rs create mode 100644 crates/cgp-macro-lib/src/cgp_namespace/spec.rs create mode 100644 crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs 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..b8b43717 --- /dev/null +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -0,0 +1,60 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::{At, Colon}; +use syn::{Ident, Type, braced}; + +use crate::parse::ComponentPaths; + +pub struct NamespaceSpec { + pub namespace_ident: Ident, + pub parent_namespace_ident: Option, + pub entries: Vec, +} + +pub struct NamespaceEntry { + pub source: Type, + pub target: 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 = parse_namespace_entries(&content)?; + + Ok(NamespaceSpec { + namespace_ident, + parent_namespace_ident, + entries, + }) + } +} + +fn parse_namespace_entries(input: ParseStream) -> syn::Result> { + let mut entries = Vec::new(); + + while !input.is_empty() { + if input.peek(At) { + let _: At = input.parse()?; + + let paths: ComponentPaths = input.parse()?; + + let _: Colon = input.parse()?; + + if input.peek(At) {} + } else { + } + } + + Ok(entries) +} 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..3227cc8c --- /dev/null +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -0,0 +1,6 @@ +use proc_macro2::TokenStream; +use syn::Ident; + +pub fn cgp_namespace(body: TokenStream) -> syn::Result { + todo!() +} diff --git a/crates/cgp-macro-lib/src/entrypoints/mod.rs b/crates/cgp-macro-lib/src/entrypoints/mod.rs index 958186cf..85a1e62f 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; 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..158cd6aa 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -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", @@ -47,7 +47,6 @@ pub enum PathHead { Symbol(Option, Ident, Box), Group(Punctuated), Wildcard, - Nil, } impl PathHead { @@ -72,12 +71,6 @@ impl PathHead { generics: parse_quote! { <__Wildcard__> }, }] } - Self::Nil => { - vec![ComponentPath { - path_type: quote! { PathNil }, - generics: Default::default(), - }] - } } } } @@ -111,9 +104,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; @@ -135,7 +125,7 @@ impl Parse for PathHead { 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) { diff --git a/crates/cgp-tests/src/namespaces/extend.rs b/crates/cgp-tests/src/namespaces/extend.rs index 3d19b6a2..beb775f2 100644 --- a/crates/cgp-tests/src/namespaces/extend.rs +++ b/crates/cgp-tests/src/namespaces/extend.rs @@ -2,6 +2,15 @@ use cgp::core::component::RedirectLookup; use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; use cgp::prelude::*; +/* + cgp_namespace! { + ExtendedNamespace: DefaultNamespace { + @cgp.core.error.{ErrorRaiserComponent, ErrorTypeProviderComponent}: + @app, + } + } +*/ + pub trait ExtendedNamespace { type Provider; } diff --git a/crates/cgp-tests/tests/namespace_tests/extend_namespace.rs b/crates/cgp-tests/tests/namespace_tests/extend_namespace.rs index b0b90a97..54f19ae0 100644 --- a/crates/cgp-tests/tests/namespace_tests/extend_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/extend_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/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index b42f959a..eb5e7abc 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -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, } From 3cba53f0943caa76dcf361e95f2adf0860b13a08 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 13:25:22 +0200 Subject: [PATCH 02/12] Simplify PathType parsing --- crates/cgp-macro-lib/src/parse/path.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 158cd6aa..7b53da04 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; @@ -43,8 +43,7 @@ pub struct ComponentPath { } pub enum PathHead { - Type(Option, Type, Box), - Symbol(Option, Ident, Box), + Type(Option, PathType, Box), Group(Punctuated), Wildcard, } @@ -55,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 => { @@ -119,7 +115,7 @@ 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()?; @@ -128,11 +124,7 @@ impl Parse for PathHead { 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, path_type, rest_path)) } } } From e979c703e79329802189823281bf9022e4970530 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 13:42:18 +0200 Subject: [PATCH 03/12] Implement Parse for NamespaceSpec --- .../cgp-macro-lib/src/cgp_namespace/spec.rs | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index b8b43717..01cd6017 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -1,18 +1,20 @@ +use quote::quote; use syn::parse::{Parse, ParseStream}; -use syn::token::{At, Colon}; -use syn::{Ident, Type, braced}; +use syn::punctuated::Punctuated; +use syn::token::{At, Colon, Comma, Dot, Lt}; +use syn::{Ident, Type, braced, parse2}; -use crate::parse::ComponentPaths; +use crate::parse::{ComponentPath, ComponentPaths, ImplGenerics, PathType}; pub struct NamespaceSpec { pub namespace_ident: Ident, pub parent_namespace_ident: Option, - pub entries: Vec, + pub entries: Punctuated, } pub struct NamespaceEntry { - pub source: Type, - pub target: Type, + pub keys: ComponentPaths, + pub value: Type, } impl Parse for NamespaceSpec { @@ -30,7 +32,7 @@ impl Parse for NamespaceSpec { let content; braced!(content in input); - let entries = parse_namespace_entries(&content)?; + let entries = Punctuated::parse_terminated(&content)?; Ok(NamespaceSpec { namespace_ident, @@ -40,21 +42,45 @@ impl Parse for NamespaceSpec { } } -fn parse_namespace_entries(input: ParseStream) -> syn::Result> { - let mut entries = Vec::new(); - - while !input.is_empty() { - if input.peek(At) { +impl Parse for NamespaceEntry { + fn parse(input: ParseStream) -> syn::Result { + let keys: ComponentPaths = if input.peek(At) { let _: At = input.parse()?; - let paths: ComponentPaths = input.parse()?; + input.parse()? + } else { + let generics: ImplGenerics = if input.peek(Lt) { + input.parse()? + } else { + Default::default() + }; - let _: Colon = input.parse()?; + let path_type: Type = input.parse()?; + + let path = ComponentPath { + generics, + path_type, + }; + + ComponentPaths { paths: vec![] } + }; - if input.peek(At) {} + let _: Colon = input.parse()?; + + let value: Type = if input.peek(At) { + 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 > ), + ); + + parse2(value)? } else { - } - } + input.parse()? + }; - Ok(entries) + Ok(Self { keys, value }) + } } From d8db34d7fb1cb1c8a26db6f909296b9078107149 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 14:01:30 +0200 Subject: [PATCH 04/12] Implement cgp_namespace proc macro --- .../src/entrypoints/cgp_namespace.rs | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 3227cc8c..862949ed 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -1,6 +1,78 @@ use proc_macro2::TokenStream; -use syn::Ident; +use quote::{ToTokens, quote}; +use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse2}; + +use crate::cgp_namespace::spec::NamespaceSpec; pub fn cgp_namespace(body: TokenStream) -> syn::Result { - todo!() + 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, + >; + } + })?; + } + } + + Ok(out) } From e596eaa8dfead41a845e099d1fcfbeb19cf50587 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 14:05:24 +0200 Subject: [PATCH 05/12] Wire up proc macro --- crates/cgp-macro-lib/src/cgp_namespace/spec.rs | 2 +- crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs | 6 +++++- crates/cgp-macro-lib/src/entrypoints/mod.rs | 1 + crates/cgp-macro/src/lib.rs | 7 +++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index 01cd6017..ca398ec1 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -62,7 +62,7 @@ impl Parse for NamespaceEntry { path_type, }; - ComponentPaths { paths: vec![] } + ComponentPaths { paths: vec![path] } }; let _: Colon = input.parse()?; diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 862949ed..7b39a741 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -1,5 +1,5 @@ use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::quote; use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse2}; use crate::cgp_namespace::spec::NamespaceSpec; @@ -71,6 +71,10 @@ pub fn cgp_namespace(body: TokenStream) -> syn::Result { >; } })?; + + out.extend(quote! { + #item_impl + }) } } diff --git a/crates/cgp-macro-lib/src/entrypoints/mod.rs b/crates/cgp-macro-lib/src/entrypoints/mod.rs index 85a1e62f..ee117d9c 100644 --- a/crates/cgp-macro-lib/src/entrypoints/mod.rs +++ b/crates/cgp-macro-lib/src/entrypoints/mod.rs @@ -31,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/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. From be9da49b454de244b731244d49307455d98c8fd0 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 14:16:05 +0200 Subject: [PATCH 06/12] Namespace macro is now working --- .../cgp-macro-lib/src/cgp_namespace/spec.rs | 4 +- crates/cgp-tests/src/namespaces/extend.rs | 57 +++---------------- 2 files changed, 10 insertions(+), 51 deletions(-) diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index ca398ec1..5210d482 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -68,12 +68,14 @@ impl Parse for NamespaceEntry { let _: Colon = input.parse()?; let value: Type = if input.peek(At) { + 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 > ), + |tail, PathType { path_type }| quote!( PathCons< #path_type, #tail > ), ); parse2(value)? diff --git a/crates/cgp-tests/src/namespaces/extend.rs b/crates/cgp-tests/src/namespaces/extend.rs index beb775f2..408e859a 100644 --- a/crates/cgp-tests/src/namespaces/extend.rs +++ b/crates/cgp-tests/src/namespaces/extend.rs @@ -1,56 +1,13 @@ use cgp::core::component::RedirectLookup; use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; +use cgp::core::macros::cgp_namespace; use cgp::prelude::*; -/* - cgp_namespace! { - ExtendedNamespace: DefaultNamespace { - @cgp.core.error.{ErrorRaiserComponent, ErrorTypeProviderComponent}: - @app, - } +cgp_namespace! { + ExtendedNamespace: DefaultNamespace { + @cgp.core.error.ErrorRaiserComponent: + @app.ErrorRaiserComponent, + @cgp.core.error.ErrorTypeProviderComponent: + @app.ErrorTypeProviderComponent, } -*/ - -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>, - >; } From 2a1b91c2ea9d59c9afb1a3c5bfb59762dea7bdcf Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 14:55:57 +0200 Subject: [PATCH 07/12] Add basic namespace test --- crates/cgp-core/src/prelude.rs | 5 +- .../src/namespaces/{extend.rs => extended.rs} | 1 - crates/cgp-tests/src/namespaces/mod.rs | 4 +- crates/cgp-tests/tests/namespace_tests/mod.rs | 2 +- .../namespace_tests/namespace_macro/basic.rs | 51 +++++++++++++++++++ .../extended_namespace.rs} | 0 .../namespace_tests/namespace_macro/mod.rs | 2 + 7 files changed, 59 insertions(+), 6 deletions(-) rename crates/cgp-tests/src/namespaces/{extend.rs => extended.rs} (91%) create mode 100644 crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs rename crates/cgp-tests/tests/namespace_tests/{extend_namespace.rs => namespace_macro/extended_namespace.rs} (100%) create mode 100644 crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs 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-tests/src/namespaces/extend.rs b/crates/cgp-tests/src/namespaces/extended.rs similarity index 91% rename from crates/cgp-tests/src/namespaces/extend.rs rename to crates/cgp-tests/src/namespaces/extended.rs index 408e859a..3c4699e0 100644 --- a/crates/cgp-tests/src/namespaces/extend.rs +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -1,6 +1,5 @@ use cgp::core::component::RedirectLookup; use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; -use cgp::core::macros::cgp_namespace; use cgp::prelude::*; cgp_namespace! { 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..66083129 --- /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.BarProviderComponent: + 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 100% rename from crates/cgp-tests/tests/namespace_tests/extend_namespace.rs rename to crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs 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..f04b0191 --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs @@ -0,0 +1,2 @@ +pub mod basic; +pub mod extended_namespace; From dad7f10e5bc1229a90be2aa21c7ba7be76f56a6d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 15:05:13 +0200 Subject: [PATCH 08/12] Always list full redirected component path explicitly --- crates/cgp-error/src/traits/can_raise_error.rs | 2 +- crates/cgp-error/src/traits/can_wrap_error.rs | 2 ++ crates/cgp-error/src/traits/has_error_type.rs | 2 +- .../cgp-macro-lib/src/derive_component/derive_namespace.rs | 5 ++--- .../cgp-tests/tests/namespace_tests/namespace_macro/basic.rs | 2 +- crates/cgp-tests/tests/namespace_tests/use_namespace.rs | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/cgp-error/src/traits/can_raise_error.rs b/crates/cgp-error/src/traits/can_raise_error.rs index 4fbbd1a8..ad6c3a16 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..54ce4ca5 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..5907a722 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/derive_component/derive_namespace.rs b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs index 6229f5af..4737cb72 100644 --- a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs +++ b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs @@ -1,4 +1,4 @@ -use quote::{ToTokens, quote}; +use quote::quote; use syn::{Ident, ItemImpl, Type, parse2}; use crate::attributes::UseNamespaceAttribute; @@ -21,8 +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 paths = Vec::from_iter(attribute.path.iter().map(|path| path.path_type.clone())); let path = path_to_product(&paths)?; diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 66083129..3a7398d2 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -38,7 +38,7 @@ delegate_components! { App { MyFooComponent: DummyFoo, - @MyBarComponent.BarProviderComponent: + @MyBarComponent: DummyBar, } } diff --git a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs index 6b8e16c3..8c8fbe2a 100644 --- a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs @@ -6,7 +6,7 @@ pub struct MyComponents; #[cgp_component(FooProvider)] #[use_namespace(DefaultNamespace: app.MyComponents)] -pub trait CanDoFoo { +pub trait Foo { fn foo(&self); } From ec341923a9ebfcb70acd83f985a8f976004b5778 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 15:18:17 +0200 Subject: [PATCH 09/12] Use path notation in #[use_namespace] --- .../cgp-error/src/traits/can_raise_error.rs | 2 +- crates/cgp-error/src/traits/can_wrap_error.rs | 2 +- crates/cgp-error/src/traits/has_error_type.rs | 2 +- .../src/attributes/use_namespace.rs | 23 ++++++-- .../src/derive_component/derive_namespace.rs | 18 +------ .../namespace_tests/namespace_macro/basic.rs | 2 +- .../namespace_tests/namespace_macro/mod.rs | 2 + .../namespace_macro/symbol_path.rs | 52 ++++++++++++++++++ .../namespace_macro/type_path.rs | 54 +++++++++++++++++++ .../tests/namespace_tests/redirect.rs | 2 +- .../tests/namespace_tests/use_namespace.rs | 2 +- 11 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs create mode 100644 crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs diff --git a/crates/cgp-error/src/traits/can_raise_error.rs b/crates/cgp-error/src/traits/can_raise_error.rs index ad6c3a16..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.ErrorRaiserComponent)] +#[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 54ce4ca5..c8defb99 100644 --- a/crates/cgp-error/src/traits/can_wrap_error.rs +++ b/crates/cgp-error/src/traits/can_wrap_error.rs @@ -8,7 +8,7 @@ use crate::traits::HasErrorType; provider: ErrorWrapper, derive_delegate: UseDelegate, }] -#[use_namespace(cgp.core.error.ErrorWrapperComponent)] +#[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 5907a722..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.ErrorTypeProviderComponent)] +#[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..c0b24dc1 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,21 @@ impl Parse for UseNamespaceAttribute { Ident::new("DefaultNamespace", input.span()) }; - let path = Punctuated::parse_separated_nonempty(input)?; + let path: Type = if input.peek(At) { + 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>), + ); + + parse2(raw_path_type)? + } else { + input.parse()? + }; + Ok(UseNamespaceAttribute { namespace, path }) } } 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 4737cb72..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::quote; -use syn::{Ident, ItemImpl, Type, parse2}; +use syn::{Ident, ItemImpl, parse2}; use crate::attributes::UseNamespaceAttribute; @@ -21,9 +21,7 @@ pub fn derive_namespace_impl( component_name: &Ident, ) -> syn::Result { let namespace = &attribute.namespace; - let paths = Vec::from_iter(attribute.path.iter().map(|path| path.path_type.clone())); - - let path = path_to_product(&paths)?; + let path = &attribute.path; let out = quote! { impl<__Components__> #namespace < __Components__ > for #component_name @@ -34,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-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 3a7398d2..306f1684 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -38,7 +38,7 @@ delegate_components! { App { MyFooComponent: DummyFoo, - @MyBarComponent: + MyBarComponent: DummyBar, } } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs index f04b0191..44e41da9 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs @@ -1,2 +1,4 @@ pub mod basic; pub mod extended_namespace; +pub mod symbol_path; +pub mod type_path; 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 eb5e7abc..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(); } diff --git a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs index 8c8fbe2a..27531959 100644 --- a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs @@ -5,7 +5,7 @@ use cgp::prelude::*; pub struct MyComponents; #[cgp_component(FooProvider)] -#[use_namespace(DefaultNamespace: app.MyComponents)] +#[use_namespace(DefaultNamespace: @app.MyComponents.FooProviderComponent)] pub trait Foo { fn foo(&self); } From 7e4221614e04682a7f1824c76ebb7d0664629a20 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 21:28:32 +0200 Subject: [PATCH 10/12] Always use path in namespace values --- .../src/attributes/use_namespace.rs | 18 +++++++----------- .../cgp-macro-lib/src/cgp_namespace/spec.rs | 19 +++++++------------ .../namespace_tests/namespace_macro/basic.rs | 8 ++++---- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/crates/cgp-macro-lib/src/attributes/use_namespace.rs b/crates/cgp-macro-lib/src/attributes/use_namespace.rs index c0b24dc1..ef142a5d 100644 --- a/crates/cgp-macro-lib/src/attributes/use_namespace.rs +++ b/crates/cgp-macro-lib/src/attributes/use_namespace.rs @@ -21,20 +21,16 @@ impl Parse for UseNamespaceAttribute { Ident::new("DefaultNamespace", input.span()) }; - let path: Type = if input.peek(At) { - let _: At = input.parse()?; + let _: At = input.parse()?; - let paths: Punctuated = Punctuated::parse_separated_nonempty(input)?; + 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 raw_path_type = paths.into_iter().rev().fold( + quote!(PathNil), + |tail, PathType { path_type }| quote!(PathCons<#path_type, #tail>), + ); - parse2(raw_path_type)? - } else { - input.parse()? - }; + let path: Type = parse2(raw_path_type)?; Ok(UseNamespaceAttribute { namespace, path }) } diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index 5210d482..837b7766 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -67,21 +67,16 @@ impl Parse for NamespaceEntry { let _: Colon = input.parse()?; - let value: Type = if input.peek(At) { - let _: At = input.parse()?; + let _: At = input.parse()?; - let value_path: Punctuated = - Punctuated::parse_separated_nonempty(input)?; + 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 = value_path.into_iter().rev().fold( + quote!(PathNil), + |tail, PathType { path_type }| quote!( PathCons< #path_type, #tail > ), + ); - parse2(value)? - } else { - input.parse()? - }; + let value: Type = parse2(value)?; Ok(Self { keys, value }) } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 306f1684..fc9291fc 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -8,12 +8,12 @@ pub trait Foo { cgp_namespace! { MyNamespace { FooProviderComponent: - MyFooComponent, + @MyFooComponent, } } #[cgp_component(BarProvider)] -#[use_namespace(MyNamespace: MyBarComponent)] +#[use_namespace(MyNamespace: @MyBarComponent)] pub trait Bar { fn bar(&self); } @@ -36,9 +36,9 @@ pub struct App; delegate_components! { #[use_namespace(MyNamespace)] App { - MyFooComponent: + @MyFooComponent: DummyFoo, - MyBarComponent: + @MyBarComponent: DummyBar, } } From bcdb7058f6508f798e2b68c34b19d98990ee0bae Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 21:31:23 +0200 Subject: [PATCH 11/12] Add test for multi namespace --- .../namespace_tests/namespace_macro/mod.rs | 1 + .../namespace_macro/multi_namespace.rs | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs index 44e41da9..dbd2d282 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs @@ -1,4 +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, + } +} From a7bab038830574e019fcdbea42a1cef37845181c Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 21:35:53 +0200 Subject: [PATCH 12/12] Fix clippy --- crates/cgp-macro-lib/src/parse/path.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 7b53da04..ee8119f6 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -43,7 +43,7 @@ pub struct ComponentPath { } pub enum PathHead { - Type(Option, PathType, Box), + Type(Option, Box, Box), Group(Punctuated), Wildcard, } @@ -124,7 +124,7 @@ impl Parse for PathHead { Box::new(Self::Wildcard) }; - Ok(Self::Type(generics, path_type, rest_path)) + Ok(Self::Type(generics, Box::new(path_type), rest_path)) } } }