Skip to content

Commit 3b8befa

Browse files
authored
Introduce #[cgp_inherit] for inheriting from presets (#176)
* Draft implement #[cgp_inherit] * Test use of #[cgp_inherit]
1 parent 1a26ff4 commit 3b8befa

File tree

10 files changed

+79
-32
lines changed

10 files changed

+79
-32
lines changed

crates/cgp-core/src/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use cgp_field::types::{
1919
pub use cgp_macro::{
2020
BuildField, CgpData, CgpRecord, CgpVariant, ExtractField, FromVariant, HasField, HasFields,
2121
Product, Sum, Symbol, cgp_auto_getter, cgp_component, cgp_context, cgp_getter, cgp_impl,
22-
cgp_new_provider, cgp_preset, cgp_provider, cgp_type, check_components,
22+
cgp_inherit, cgp_new_provider, cgp_preset, cgp_provider, cgp_type, check_components,
2323
delegate_and_check_components, delegate_components, product, re_export_imports, replace_with,
2424
};
2525
pub use cgp_type::{HasType, ProvideType, UseType};

crates/cgp-macro-lib/src/derive_context/derive.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use quote::quote;
2-
use syn::{AngleBracketedGenericArguments, Ident, ItemImpl, ItemStruct, parse_quote, parse2};
2+
use syn::{Ident, ItemImpl, ItemStruct, parse_quote, parse2};
33

4-
use crate::parse::TypeGenerics;
4+
use crate::parse::{SimpleType, TypeGenerics};
55

66
pub fn derive_has_components(
77
provider_name: &Ident,
@@ -28,9 +28,11 @@ pub fn derive_has_components(
2828
pub fn derive_delegate_preset(
2929
provider_name: &Ident,
3030
provider_generics: &Option<TypeGenerics>,
31-
preset_name: &Ident,
32-
preset_generics: &Option<AngleBracketedGenericArguments>,
31+
preset: &SimpleType,
3332
) -> syn::Result<(ItemImpl, ItemImpl)> {
33+
let preset_name = &preset.name;
34+
let preset_generics = &preset.generics;
35+
3436
let provider_params = match provider_generics {
3537
Some(generics) => {
3638
let params = &generics.generics.params;

crates/cgp-macro-lib/src/entrypoints/cgp_context.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,9 @@ pub fn cgp_context(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStr
4949
};
5050

5151
match &context_spec.preset {
52-
Some((preset_path, preset_generics)) => {
53-
let (delegate_impl, is_provider_impl) = derive_delegate_preset(
54-
provider_name,
55-
provider_generics,
56-
preset_path,
57-
preset_generics,
58-
)?;
52+
Some(preset) => {
53+
let (delegate_impl, is_provider_impl) =
54+
derive_delegate_preset(provider_name, provider_generics, preset)?;
5955

6056
Ok(quote! {
6157
#base_derived
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote;
3+
use syn::{ItemStruct, parse2};
4+
5+
use crate::derive_context::derive_delegate_preset;
6+
use crate::parse::{SimpleType, TypeGenerics};
7+
8+
pub fn cgp_inherit(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream> {
9+
let context_struct: ItemStruct = parse2(body)?;
10+
11+
let preset: SimpleType = parse2(attr)?;
12+
13+
let type_generics = TypeGenerics::try_from(&context_struct.generics)?;
14+
15+
let (delegate_impl, is_provider_impl) =
16+
derive_delegate_preset(&context_struct.ident, &Some(type_generics), &preset)?;
17+
18+
Ok(quote! {
19+
#context_struct
20+
21+
#delegate_impl
22+
23+
#is_provider_impl
24+
})
25+
}

crates/cgp-macro-lib/src/entrypoints/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod cgp_context;
55
mod cgp_data;
66
mod cgp_getter;
77
mod cgp_impl;
8+
mod cgp_inherit;
89
mod cgp_new_provider;
910
mod cgp_preset;
1011
mod cgp_provider;
@@ -28,6 +29,7 @@ pub use cgp_context::*;
2829
pub use cgp_data::*;
2930
pub use cgp_getter::*;
3031
pub use cgp_impl::*;
32+
pub use cgp_inherit::*;
3133
pub use cgp_new_provider::*;
3234
pub use cgp_preset::*;
3335
pub use cgp_provider::*;

crates/cgp-macro-lib/src/parse/context_spec.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
use syn::Ident;
12
use syn::parse::{Parse, ParseStream};
23
use syn::token::{Colon, Lt};
3-
use syn::{AngleBracketedGenericArguments, Ident};
44

5-
use crate::parse::TypeGenerics;
5+
use crate::parse::{SimpleType, TypeGenerics};
66

77
pub struct ContextSpec {
88
pub provider_name: Ident,
99
pub provider_generics: Option<TypeGenerics>,
10-
pub preset: Option<(Ident, Option<AngleBracketedGenericArguments>)>,
10+
pub preset: Option<SimpleType>,
1111
}
1212

1313
impl Parse for ContextSpec {
@@ -24,15 +24,8 @@ impl Parse for ContextSpec {
2424

2525
let preset = match colon {
2626
Some(_) => {
27-
let path = input.parse()?;
28-
29-
let generics = if input.peek(Lt) {
30-
Some(input.parse()?)
31-
} else {
32-
None
33-
};
34-
35-
Some((path, generics))
27+
let preset = input.parse()?;
28+
Some(preset)
3629
}
3730
None => None,
3831
};

crates/cgp-macro/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,13 @@ pub fn cgp_context(attr: TokenStream, item: TokenStream) -> TokenStream {
790790
.into()
791791
}
792792

793+
#[proc_macro_attribute]
794+
pub fn cgp_inherit(attr: TokenStream, item: TokenStream) -> TokenStream {
795+
cgp_macro_lib::cgp_inherit(attr.into(), item.into())
796+
.unwrap_or_else(syn::Error::into_compile_error)
797+
.into()
798+
}
799+
793800
/**
794801
The `#[blanket_trait]` macro can be used to define trait aliases that contain
795802
empty body and trivial blanket implementations.

crates/cgp-tests/tests/preset_tests/basic/consumer_delegate.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@ use crate::preset_tests::basic::components::{
55
};
66
use crate::preset_tests::basic::preset::{CheckDelegatesForMyPreset, MyPreset};
77

8+
#[cgp_inherit(MyPreset)]
89
#[derive(HasField)]
910
pub struct MyContext {
1011
pub foo: (),
1112
pub bar: (),
1213
}
1314

14-
impl<__Name__> DelegateComponent<__Name__> for MyContext
15-
where
16-
Self: MyPreset::IsPreset<__Name__>,
17-
MyPreset::Components: DelegateComponent<__Name__>,
18-
{
19-
type Delegate = <MyPreset::Components as DelegateComponent<__Name__>>::Delegate;
20-
}
21-
2215
impl HasBar for MyContext {
2316
fn bar(&self) -> &Self::Bar {
2417
&self.bar
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use cgp::prelude::*;
2+
3+
use crate::preset_tests::generics::components::{
4+
BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent,
5+
};
6+
use crate::preset_tests::generics::preset::MyGenericPreset;
7+
8+
#[cgp_inherit(MyGenericPreset<T>)]
9+
#[derive(HasField)]
10+
pub struct MyContext<T> {
11+
pub foo: T,
12+
pub bar: T,
13+
}
14+
15+
check_components! {
16+
<T> CanUseMyContext for MyContext<T> {
17+
FooTypeProviderComponent,
18+
BarTypeProviderComponent,
19+
BarGetterComponent,
20+
}
21+
}
22+
23+
check_components! {
24+
<const I: usize, T>
25+
CanUseFooGetter for MyContext<T> {
26+
FooGetterComponent<Index<I>>: Index<I>,
27+
}
28+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod components;
2+
pub mod consumer_delegate;
23
pub mod contexts;
34
pub mod preset;

0 commit comments

Comments
 (0)