From 415b9f16c6015420c56eafda4bcf9210d6c6ca3d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 22:20:34 +0200 Subject: [PATCH 1/6] Implement namespace statement in delegate_components! --- .../src/parse/delegate_components.rs | 28 +++++++++++++++++++ .../tests/namespace_tests/use_namespace.rs | 3 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 9df0c55e..a45577a6 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -153,6 +153,34 @@ pub fn parse_meta_delegate_entries( entries.push(entry) } + } else if keyword == "namespace" { + input.advance_to(&fork); + + let namespace_ident: Ident = input.parse()?; + let _: Semi = input.parse()?; + + let delegate_key: Type = parse2(quote! { + __Component__ + })?; + + let generics: ImplGenerics = parse2(quote! { + <__Component__: #namespace_ident< #target_type >> + })?; + + let delegate_value: Type = parse2(quote! { + < __Component__ as #namespace_ident< #target_type >>::Provider + })?; + + let entry = DelegateEntry { + keys: Punctuated::from_iter([DelegateKey { + ty: delegate_key, + generics, + }]), + mode: DelegateMode::Provider(Colon(Span::call_site())), + value: DelegateValue::Type(delegate_value), + }; + + entries.push(entry) } else { break; } diff --git a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs index 27531959..550ee18b 100644 --- a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs @@ -13,8 +13,9 @@ pub trait Foo { pub struct App; delegate_components! { - #[use_namespace] App { + namespace DefaultNamespace; + @cgp.core.error.ErrorTypeProviderComponent: UseType, @cgp.core.error.ErrorRaiserComponent.String: From 197bec321c004cd3f368da45e85e69a3b2b90320 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 22:29:57 +0200 Subject: [PATCH 2/6] Special case on default namespace --- .../src/parse/delegate_components.rs | 8 ++++- .../namespace_tests/namespace_macro/basic.rs | 3 +- .../namespace_macro/extended_namespace.rs | 3 +- .../namespace_macro/multi_namespace.rs | 6 ++-- .../namespace_macro/symbol_path.rs | 3 +- .../namespace_macro/type_path.rs | 3 +- .../cgp-tests/tests/namespace_tests/open.rs | 36 ++++++++++++++----- .../tests/namespace_tests/use_namespace.rs | 2 +- 8 files changed, 48 insertions(+), 16 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index a45577a6..0b65b293 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -156,9 +156,15 @@ pub fn parse_meta_delegate_entries( } else if keyword == "namespace" { input.advance_to(&fork); - let namespace_ident: Ident = input.parse()?; + let ident: Ident = input.parse()?; let _: Semi = input.parse()?; + let namespace_ident = if ident == "default" { + Ident::new("DefaultNamespace", ident.span()) + } else { + ident + }; + let delegate_key: Type = parse2(quote! { __Component__ })?; 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 fc9291fc..24eaf4d0 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -34,8 +34,9 @@ impl BarProvider { pub struct App; delegate_components! { - #[use_namespace(MyNamespace)] App { + namespace MyNamespace; + @MyFooComponent: DummyFoo, @MyBarComponent: diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs index 54f19ae0..7e10c72f 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs @@ -7,8 +7,9 @@ use cgp_tests::namespaces::ExtendedNamespace; pub struct App; delegate_components! { - #[use_namespace(ExtendedNamespace)] App { + namespace ExtendedNamespace; + @app.ErrorTypeProviderComponent: UseType, @app.{ 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 index 54d10124..e2d1856f 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -45,8 +45,9 @@ impl BarProvider { pub struct App; delegate_components! { - #[use_namespace(MyNamespace)] App { + namespace MyNamespace; + @MyApp.MyFooComponent: DummyFoo, @MyApp.MyBarComponent: @@ -64,8 +65,9 @@ check_components! { pub struct OtherApp; delegate_components! { - #[use_namespace(OtherNamespace)] OtherApp { + namespace OtherNamespace; + @my_app.MyFooComponent: DummyFoo, @my_app.MyBarComponent: 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 index e5899dfc..35a114d8 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -35,8 +35,9 @@ impl BarProvider { pub struct App; delegate_components! { - #[use_namespace(MyNamespace)] App { + namespace MyNamespace; + @my_app.MyFooComponent: DummyFoo, @my_app.MyBarComponent: 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 index b23fc646..c8d01822 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -37,8 +37,9 @@ impl BarProvider { pub struct App; delegate_components! { - #[use_namespace(MyNamespace)] App { + namespace MyNamespace; + @MyApp.MyFooComponent: DummyFoo, @MyApp.MyBarComponent: diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index fff4e71b..316e4d85 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -1,23 +1,43 @@ -use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; -use cgp::extra::error::ReturnError; use cgp::prelude::*; pub struct App; +#[cgp_component(FooProvider)] +pub trait Foo { + fn foo(&self, value: &T); +} + +#[cgp_component(BarProvider)] +pub trait Bar { + fn bar(&self, value: &T); +} + +#[cgp_impl(new DummyFoo)] +impl FooProvider { + fn foo(&self, _value: &T) {} +} + +#[cgp_impl(new DummyBar)] +impl BarProvider { + fn bar(&self, _value: &T) {} +} + delegate_components! { App { - open ErrorRaiserComponent; + open FooProviderComponent, BarProviderComponent; - ErrorTypeProviderComponent: - UseType, - @ErrorRaiserComponent.String: - ReturnError, + @FooProviderComponent.String: + DummyFoo, + @BarProviderComponent.u32: + DummyBar, } } check_components! { App { - ErrorRaiserComponent: + FooProviderComponent: String, + // BarProviderComponent: + // u32, } } diff --git a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs index 550ee18b..4f2ed515 100644 --- a/crates/cgp-tests/tests/namespace_tests/use_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/use_namespace.rs @@ -14,7 +14,7 @@ pub struct App; delegate_components! { App { - namespace DefaultNamespace; + namespace default; @cgp.core.error.ErrorTypeProviderComponent: UseType, From 72c4468b6136c5122afdb43d19d65232d31d2c63 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 22:44:06 +0200 Subject: [PATCH 3/6] Fix primitives with lowercase converted into path --- crates/cgp-macro-lib/src/parse/path.rs | 15 +++++++++++++++ crates/cgp-tests/tests/namespace_tests/open.rs | 8 +++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index ee8119f6..9068c84c 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -137,6 +137,7 @@ pub fn path_type_as_ident(path_type: &Type) -> Option { let path_str = path_ident.to_string(); if let Some(path_char) = path_str.chars().next() && path_char.is_ascii_lowercase() + && !is_primitive_type(&path_str) { return Some(path_ident); } @@ -166,3 +167,17 @@ impl Parse for PathType { } } } + +pub fn is_primitive_type( + ident: &str, +) -> bool { + if ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f") { + if (&ident[1..]).chars().all(|c| c.is_numeric()) { + return true + } + } else if ident == "char" || ident == "bool" { + return true + } + + false +} diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index 316e4d85..2bfbb68d 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -28,7 +28,7 @@ delegate_components! { @FooProviderComponent.String: DummyFoo, - @BarProviderComponent.u32: + @BarProviderComponent.{u32, u64}: DummyBar, } } @@ -37,7 +37,9 @@ check_components! { App { FooProviderComponent: String, - // BarProviderComponent: - // u32, + BarProviderComponent: [ + u32, + u64, + ], } } From 5c35b13e20ee8ae15816ebaeaee80f8f1405227b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 22:47:49 +0200 Subject: [PATCH 4/6] Remove #[use_namespace] attribute in delegate_components! --- .../src/delegate_components/attributes.rs | 48 ------------------ .../delegate_components/derive_namespace.rs | 49 ------------------- .../src/delegate_components/mod.rs | 4 -- .../src/entrypoints/delegate_components.rs | 14 +----- .../src/parse/delegate_components.rs | 12 +---- crates/cgp-macro-lib/src/parse/path.rs | 8 ++- .../tests/namespace_tests/redirect.rs | 3 +- 7 files changed, 8 insertions(+), 130 deletions(-) delete mode 100644 crates/cgp-macro-lib/src/delegate_components/attributes.rs delete mode 100644 crates/cgp-macro-lib/src/delegate_components/derive_namespace.rs diff --git a/crates/cgp-macro-lib/src/delegate_components/attributes.rs b/crates/cgp-macro-lib/src/delegate_components/attributes.rs deleted file mode 100644 index f5174e89..00000000 --- a/crates/cgp-macro-lib/src/delegate_components/attributes.rs +++ /dev/null @@ -1,48 +0,0 @@ -use syn::{Attribute, Ident, Meta}; - -pub fn parse_delegate_attributes(attributes: Vec) -> syn::Result { - let mut parsed_attributes = DelegateAttributes::default(); - - for attribute in attributes.iter() { - if let Some(ident) = attribute.path().get_ident() { - if ident == "use_namespace" { - if parsed_attributes.use_namespace.is_some() { - return Err(syn::Error::new_spanned( - attribute, - "Multiple #[use_namespace] attributes are not allowed", - )); - } - - if let Meta::Path(_) = attribute.meta { - parsed_attributes.use_namespace = - Some(DelegateNamespaceAttribute { namespace: None }); - } else { - let namespace = attribute.parse_args::>()?; - parsed_attributes.use_namespace = - Some(DelegateNamespaceAttribute { namespace }); - } - } else { - return Err(syn::Error::new_spanned( - attribute, - format!("Unknown attribute {} for delegate_components", ident), - )); - } - } else { - return Err(syn::Error::new_spanned( - attribute, - "Unexpected attribute format for delegate_components", - )); - } - } - - Ok(parsed_attributes) -} - -#[derive(Default)] -pub struct DelegateAttributes { - pub use_namespace: Option, -} - -pub struct DelegateNamespaceAttribute { - pub namespace: Option, -} diff --git a/crates/cgp-macro-lib/src/delegate_components/derive_namespace.rs b/crates/cgp-macro-lib/src/delegate_components/derive_namespace.rs deleted file mode 100644 index 071dc720..00000000 --- a/crates/cgp-macro-lib/src/delegate_components/derive_namespace.rs +++ /dev/null @@ -1,49 +0,0 @@ -use proc_macro2::{Span, TokenStream}; -use quote::quote; -use syn::{Generics, Ident, Type, parse2}; - -pub fn derive_namespace_delegate( - namespace: Option, - target_type: &Type, - target_generics: &Generics, -) -> syn::Result { - let namespace = namespace.unwrap_or_else(|| Ident::new("DefaultNamespace", Span::call_site())); - - let mut generics = target_generics.clone(); - generics.params.push(parse2(quote! { __Component__ })?); - - let impl_generics = generics.split_for_impl().0; - - let namespace_impl = quote! { - impl #impl_generics - DelegateComponent<__Component__> - for #target_type - where - __Component__: #namespace< #target_type >, - { - type Delegate = < __Component__ as #namespace< #target_type >>::Provider; - } - }; - - let mut generics = generics.clone(); - generics.params.push(parse2(quote! { __Context__ })?); - generics.params.push(parse2(quote! { __Params__ })?); - - let impl_generics = generics.split_for_impl().0; - - let is_provider_for_impl = quote! { - impl #impl_generics - IsProviderFor<__Component__, __Context__, __Params__> - for #target_type - where - __Component__: #namespace< #target_type >, - < __Component__ as #namespace< #target_type >>::Provider: IsProviderFor<__Component__, __Context__, __Params__>, - { - } - }; - - Ok(quote! { - #namespace_impl - #is_provider_for_impl - }) -} diff --git a/crates/cgp-macro-lib/src/delegate_components/mod.rs b/crates/cgp-macro-lib/src/delegate_components/mod.rs index 3d9674c5..6a725623 100644 --- a/crates/cgp-macro-lib/src/delegate_components/mod.rs +++ b/crates/cgp-macro-lib/src/delegate_components/mod.rs @@ -1,10 +1,6 @@ -mod attributes; mod define_struct; -mod derive_namespace; mod impl_delegate; mod merge_generics; -pub use attributes::*; pub use define_struct::*; -pub use derive_namespace::*; pub use impl_delegate::*; diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs index f43a873f..5dea004f 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs @@ -2,10 +2,7 @@ use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; -use crate::delegate_components::{ - DelegateNamespaceAttribute, define_struct, derive_namespace_delegate, impl_delegate_components, - parse_delegate_attributes, -}; +use crate::delegate_components::{define_struct, impl_delegate_components}; use crate::parse::{DelegateComponents, SimpleType, TypeGenerics}; pub fn delegate_components(body: TokenStream) -> syn::Result { @@ -26,15 +23,6 @@ pub fn delegate_components(body: TokenStream) -> syn::Result { output.extend(component_struct.to_token_stream()); } - let attributes = parse_delegate_attributes(spec.attributes)?; - - if let Some(DelegateNamespaceAttribute { namespace }) = attributes.use_namespace { - let namespace_impl = - derive_namespace_delegate(namespace, target_type, &target_generics.generics)?; - - output.extend(namespace_impl); - } - let impl_items = impl_delegate_components(target_type, target_generics, &spec.entries)?; output.extend(impl_items); diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 0b65b293..a34c4d47 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -5,13 +5,12 @@ use quote::{ToTokens, TokenStreamExt, quote}; use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, Pound, RArrow, Semi}; -use syn::{Attribute, Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote, parse2}; +use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, RArrow, Semi}; +use syn::{Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote, parse2}; use crate::parse::{ComponentPaths, ImplGenerics, SimpleType, TypeGenerics}; pub struct DelegateComponents { - pub attributes: Vec, pub new_struct: bool, pub target_type: Type, pub target_generics: ImplGenerics, @@ -73,12 +72,6 @@ impl DelegateValue { impl Parse for DelegateComponents { fn parse(input: ParseStream) -> syn::Result { - let attributes = if input.peek(Pound) { - input.call(Attribute::parse_outer)? - } else { - Vec::new() - }; - let target_generics = if input.peek(Lt) { input.parse()? } else { @@ -110,7 +103,6 @@ impl Parse for DelegateComponents { let entries = meta_entries.into_iter().chain(delegate_entries).collect(); Ok(Self { - attributes, new_struct, target_type, target_generics, diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 9068c84c..bedc661e 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -168,15 +168,13 @@ impl Parse for PathType { } } -pub fn is_primitive_type( - ident: &str, -) -> bool { +pub fn is_primitive_type(ident: &str) -> bool { if ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f") { if (&ident[1..]).chars().all(|c| c.is_numeric()) { - return true + return true; } } else if ident == "char" || ident == "bool" { - return true + return true; } false diff --git a/crates/cgp-tests/tests/namespace_tests/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index 5ef22d2d..03ed0aaf 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -18,8 +18,9 @@ impl FooProvider { pub struct App; delegate_components! { - #[use_namespace] App { + namespace default; + // @bar: TestProvider, @bar.baz: TestProvider, From 2235fda8eb40d741110f2ae54b53c02c97d07381 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 22:54:27 +0200 Subject: [PATCH 5/6] Include usize and isize in primitive ident matching --- crates/cgp-macro-lib/src/parse/path.rs | 4 +++- crates/cgp-tests/tests/namespace_tests/open.rs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index bedc661e..05b4557c 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -173,7 +173,9 @@ pub fn is_primitive_type(ident: &str) -> bool { if (&ident[1..]).chars().all(|c| c.is_numeric()) { return true; } - } else if ident == "char" || ident == "bool" { + } + + if ["char", "bool", "usize", "isize", "str"].contains(&ident) { return true; } diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index 2bfbb68d..61b6aa2c 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -28,7 +28,7 @@ delegate_components! { @FooProviderComponent.String: DummyFoo, - @BarProviderComponent.{u32, u64}: + @BarProviderComponent.{u32, u64, bool, usize, isize}: DummyBar, } } @@ -40,6 +40,9 @@ check_components! { BarProviderComponent: [ u32, u64, + bool, + usize, + isize, ], } } From 3753e00c9b62158ab6127b19a831b4b51cd49afe Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 4 May 2026 23:05:53 +0200 Subject: [PATCH 6/6] Fix clippy --- crates/cgp-macro-lib/src/parse/path.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 05b4557c..78d91694 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -169,10 +169,10 @@ impl Parse for PathType { } pub fn is_primitive_type(ident: &str) -> bool { - if ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f") { - if (&ident[1..]).chars().all(|c| c.is_numeric()) { - return true; - } + if (ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f")) + && ident[1..].chars().all(|c| c.is_numeric()) + { + return true; } if ["char", "bool", "usize", "isize", "str"].contains(&ident) {