From 7d23f932d3d233ca15ee80028568fc0160bb4d14 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Fri, 17 Oct 2025 20:48:30 +0000 Subject: [PATCH 1/2] Draft implement #[cgp_inherit] --- crates/cgp-core/src/prelude.rs | 2 +- .../src/derive_context/derive.rs | 10 ++++---- .../src/entrypoints/cgp_context.rs | 10 +++----- .../src/entrypoints/cgp_inherit.rs | 24 +++++++++++++++++++ crates/cgp-macro-lib/src/entrypoints/mod.rs | 2 ++ .../cgp-macro-lib/src/parse/context_spec.rs | 17 ++++--------- crates/cgp-macro/src/lib.rs | 7 ++++++ 7 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs diff --git a/crates/cgp-core/src/prelude.rs b/crates/cgp-core/src/prelude.rs index c44714b9..657590f7 100644 --- a/crates/cgp-core/src/prelude.rs +++ b/crates/cgp-core/src/prelude.rs @@ -19,7 +19,7 @@ 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_context, cgp_getter, cgp_impl, - cgp_new_provider, cgp_preset, cgp_provider, cgp_type, check_components, + 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, }; pub use cgp_type::{HasType, ProvideType, UseType}; diff --git a/crates/cgp-macro-lib/src/derive_context/derive.rs b/crates/cgp-macro-lib/src/derive_context/derive.rs index efd615ca..0652fb11 100644 --- a/crates/cgp-macro-lib/src/derive_context/derive.rs +++ b/crates/cgp-macro-lib/src/derive_context/derive.rs @@ -1,7 +1,7 @@ use quote::quote; -use syn::{AngleBracketedGenericArguments, Ident, ItemImpl, ItemStruct, parse_quote, parse2}; +use syn::{Ident, ItemImpl, ItemStruct, parse_quote, parse2}; -use crate::parse::TypeGenerics; +use crate::parse::{SimpleType, TypeGenerics}; pub fn derive_has_components( provider_name: &Ident, @@ -28,9 +28,11 @@ pub fn derive_has_components( pub fn derive_delegate_preset( provider_name: &Ident, provider_generics: &Option, - preset_name: &Ident, - preset_generics: &Option, + preset: &SimpleType, ) -> syn::Result<(ItemImpl, ItemImpl)> { + let preset_name = &preset.name; + let preset_generics = &preset.generics; + let provider_params = match provider_generics { Some(generics) => { let params = &generics.generics.params; diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_context.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_context.rs index 7ff7ebf8..a09dcbde 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_context.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_context.rs @@ -49,13 +49,9 @@ pub fn cgp_context(attr: TokenStream, body: TokenStream) -> syn::Result { - let (delegate_impl, is_provider_impl) = derive_delegate_preset( - provider_name, - provider_generics, - preset_path, - preset_generics, - )?; + Some(preset) => { + let (delegate_impl, is_provider_impl) = + derive_delegate_preset(provider_name, provider_generics, preset)?; Ok(quote! { #base_derived diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs new file mode 100644 index 00000000..5abfb69a --- /dev/null +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs @@ -0,0 +1,24 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{ItemStruct, parse2}; + +use crate::derive_context::derive_delegate_preset; +use crate::parse::{SimpleType, TypeGenerics}; + +pub fn cgp_inherit(attr: TokenStream, body: TokenStream) -> syn::Result { + let context_struct: ItemStruct = parse2(body)?; + + let preset: SimpleType = parse2(attr)?; + + let type_generics = TypeGenerics::try_from(&context_struct.generics)?; + + let (delegate_impl, is_provider_impl) = + derive_delegate_preset(&context_struct.ident, &Some(type_generics), &preset)?; + + Ok(quote! { + + #delegate_impl + + #is_provider_impl + }) +} diff --git a/crates/cgp-macro-lib/src/entrypoints/mod.rs b/crates/cgp-macro-lib/src/entrypoints/mod.rs index 16aa4233..6b030b89 100644 --- a/crates/cgp-macro-lib/src/entrypoints/mod.rs +++ b/crates/cgp-macro-lib/src/entrypoints/mod.rs @@ -5,6 +5,7 @@ mod cgp_context; mod cgp_data; mod cgp_getter; mod cgp_impl; +mod cgp_inherit; mod cgp_new_provider; mod cgp_preset; mod cgp_provider; @@ -28,6 +29,7 @@ pub use cgp_context::*; pub use cgp_data::*; pub use cgp_getter::*; pub use cgp_impl::*; +pub use cgp_inherit::*; pub use cgp_new_provider::*; pub use cgp_preset::*; pub use cgp_provider::*; diff --git a/crates/cgp-macro-lib/src/parse/context_spec.rs b/crates/cgp-macro-lib/src/parse/context_spec.rs index 4d241c89..e4d325bc 100644 --- a/crates/cgp-macro-lib/src/parse/context_spec.rs +++ b/crates/cgp-macro-lib/src/parse/context_spec.rs @@ -1,13 +1,13 @@ +use syn::Ident; use syn::parse::{Parse, ParseStream}; use syn::token::{Colon, Lt}; -use syn::{AngleBracketedGenericArguments, Ident}; -use crate::parse::TypeGenerics; +use crate::parse::{SimpleType, TypeGenerics}; pub struct ContextSpec { pub provider_name: Ident, pub provider_generics: Option, - pub preset: Option<(Ident, Option)>, + pub preset: Option, } impl Parse for ContextSpec { @@ -24,15 +24,8 @@ impl Parse for ContextSpec { let preset = match colon { Some(_) => { - let path = input.parse()?; - - let generics = if input.peek(Lt) { - Some(input.parse()?) - } else { - None - }; - - Some((path, generics)) + let preset = input.parse()?; + Some(preset) } None => None, }; diff --git a/crates/cgp-macro/src/lib.rs b/crates/cgp-macro/src/lib.rs index cf0a1aee..dc5be0ed 100644 --- a/crates/cgp-macro/src/lib.rs +++ b/crates/cgp-macro/src/lib.rs @@ -790,6 +790,13 @@ pub fn cgp_context(attr: TokenStream, item: TokenStream) -> TokenStream { .into() } +#[proc_macro_attribute] +pub fn cgp_inherit(attr: TokenStream, item: TokenStream) -> TokenStream { + cgp_macro_lib::cgp_inherit(attr.into(), item.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + /** The `#[blanket_trait]` macro can be used to define trait aliases that contain empty body and trivial blanket implementations. From 5342430ddcc93c77dfd2100db6327d7ba194cff4 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Fri, 17 Oct 2025 20:52:22 +0000 Subject: [PATCH 2/2] Test use of #[cgp_inherit] --- .../src/entrypoints/cgp_inherit.rs | 1 + .../preset_tests/basic/consumer_delegate.rs | 9 +----- .../generics/consumer_delegate.rs | 28 +++++++++++++++++++ .../tests/preset_tests/generics/mod.rs | 1 + 4 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 crates/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs index 5abfb69a..1d5cd71d 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs @@ -16,6 +16,7 @@ pub fn cgp_inherit(attr: TokenStream, body: TokenStream) -> syn::Result DelegateComponent<__Name__> for MyContext -where - Self: MyPreset::IsPreset<__Name__>, - MyPreset::Components: DelegateComponent<__Name__>, -{ - type Delegate = >::Delegate; -} - impl HasBar for MyContext { fn bar(&self) -> &Self::Bar { &self.bar diff --git a/crates/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs b/crates/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs new file mode 100644 index 00000000..06eae6e4 --- /dev/null +++ b/crates/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs @@ -0,0 +1,28 @@ +use cgp::prelude::*; + +use crate::preset_tests::generics::components::{ + BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, +}; +use crate::preset_tests::generics::preset::MyGenericPreset; + +#[cgp_inherit(MyGenericPreset)] +#[derive(HasField)] +pub struct MyContext { + pub foo: T, + pub bar: T, +} + +check_components! { + CanUseMyContext for MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + BarGetterComponent, + } +} + +check_components! { + + CanUseFooGetter for MyContext { + FooGetterComponent>: Index, + } +} diff --git a/crates/cgp-tests/tests/preset_tests/generics/mod.rs b/crates/cgp-tests/tests/preset_tests/generics/mod.rs index 6960be78..9f6ff9b2 100644 --- a/crates/cgp-tests/tests/preset_tests/generics/mod.rs +++ b/crates/cgp-tests/tests/preset_tests/generics/mod.rs @@ -1,3 +1,4 @@ pub mod components; +pub mod consumer_delegate; pub mod contexts; pub mod preset;