Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/cgp-macro-lib/src/check_components/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use syn::token::Comma;
use syn::{ItemImpl, ItemTrait, Type, parse2};

use crate::check_components::override_span;
use crate::delegate_components::merge_generics;
use crate::parse::{CheckComponents, CheckEntry};

pub fn derive_check_components(spec: &CheckComponents) -> syn::Result<(ItemTrait, Vec<ItemImpl>)> {
Expand All @@ -27,6 +28,7 @@ pub fn derive_check_components(spec: &CheckComponents) -> syn::Result<(ItemTrait
component_type,
component_params,
span,
generics: check_generics,
} in spec.check_entries.entries.iter()
{
// Override the span of the context type so that any unsatisfied constraint
Expand All @@ -35,8 +37,10 @@ pub fn derive_check_components(spec: &CheckComponents) -> syn::Result<(ItemTrait

let component_param = component_params.as_ref().unwrap_or(&unit);

let generics = merge_generics(&check_generics.generics, &impl_generics.generics);

let item_impl: ItemImpl = parse2(quote! {
impl #impl_generics
impl #generics
#trait_name < #component_type, #component_param >
for #context_type
#where_clause
Expand Down
1 change: 1 addition & 0 deletions crates/cgp-macro-lib/src/delegate_components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ mod merge_generics;

pub use define_struct::*;
pub use impl_delegate::*;
pub use merge_generics::*;
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ pub fn delegate_and_check_components(body: TokenStream) -> syn::Result<TokenStre
component_type: component_type.clone(),
component_params: Some(generic.clone()),
span,
generics: ImplGenerics::default(),
})
.collect::<Vec<_>>(),
None => vec![CheckEntry {
component_type: component_type.clone(),
component_params: None,
span,
generics: ImplGenerics::default(),
}],
}
})
Expand Down
34 changes: 30 additions & 4 deletions crates/cgp-macro-lib/src/parse/check_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct CheckEntry {
pub component_type: Type,
pub component_params: Option<Type>,
pub span: Span,
pub generics: ImplGenerics,
}

struct ParseCheckEntries {
Expand Down Expand Up @@ -155,14 +156,15 @@ impl Parse for ParseCheckEntries {
vec![component_type]
};

let component_params: Vec<Type> = if input.peek(Colon) {
let component_params: Vec<TypeWithGenerics> = if input.peek(Colon) {
let _: Colon = input.parse()?;

if input.peek(Bracket) {
let content;
bracketed!(content in input);

let types: Punctuated<Type, Comma> = Punctuated::parse_terminated(&content)?;
let types: Punctuated<TypeWithGenerics, Comma> =
Punctuated::parse_terminated(&content)?;
types.into_iter().collect()
} else {
vec![input.parse()?]
Expand All @@ -181,21 +183,26 @@ impl Parse for ParseCheckEntries {
component_type: component_type.clone(),
component_params: None,
span: component_type.span(),
generics: ImplGenerics::default(),
})
} else {
let component_params_count = component_params.len();

for component_param in component_params.iter() {
let component_param_type = &component_param.ty;
let component_param_generics = &component_param.generics;

let span = if component_types_count >= component_params_count {
component_type.span()
} else {
component_param.span()
component_param_type.span()
};

entries.push(CheckEntry {
component_type: component_type.clone(),
component_params: Some(component_param.clone()),
component_params: Some(component_param_type.clone()),
span,
generics: component_param_generics.clone(),
})
}
}
Expand All @@ -204,3 +211,22 @@ impl Parse for ParseCheckEntries {
Ok(Self { entries })
}
}

pub struct TypeWithGenerics {
pub ty: Type,
pub generics: ImplGenerics,
}

impl Parse for TypeWithGenerics {
fn parse(input: ParseStream) -> syn::Result<Self> {
let generics = if input.peek(Lt) {
input.parse()?
} else {
ImplGenerics::default()
};

let ty = input.parse()?;

Ok(Self { ty, generics })
}
}
55 changes: 40 additions & 15 deletions crates/cgp-macro-lib/src/parse/delegate_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use syn::punctuated::Punctuated;
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::delegate_components::merge_generics;
use crate::parse::{ComponentPaths, ImplGenerics, SimpleType, TypeGenerics};

pub struct DelegateComponents {
Expand Down Expand Up @@ -193,26 +194,50 @@ impl Parse for DelegateEntry<Type> {
let components_body;
bracketed!(components_body in input);
components_body.parse_terminated(DelegateKey::parse, Token![,])?
} else if input.peek(At) {
let _: At = input.parse()?;
} else {
let impl_generics: Option<ImplGenerics> = if input.peek(Lt) {
Some(input.parse()?)
} else {
None
};

let path: ComponentPaths = input.parse()?;
if input.peek(At) {
let _: At = input.parse()?;

let mut keys = Punctuated::new();
let path: ComponentPaths = input.parse()?;

for path in path.paths {
let key = DelegateKey {
ty: path.path_type,
generics: path.generics,
};
let mut keys = Punctuated::new();

keys.push(key);
}
for path in path.paths {
let generics = if let Some(impl_generics) = &impl_generics {
ImplGenerics {
generics: merge_generics(
&impl_generics.generics,
&path.generics.generics,
),
}
} else {
path.generics
};

keys
} else {
let component: DelegateKey<Type> = input.parse()?;
Punctuated::from_iter(iter::once(component))
let key = DelegateKey {
ty: path.path_type,
generics,
};

keys.push(key);
}

keys
} else {
let mut key: DelegateKey<Type> = input.parse()?;

if let Some(impl_generics) = impl_generics {
key.generics = impl_generics;
}

Punctuated::from_iter(iter::once(key))
}
};

let mode = input.parse()?;
Expand Down
1 change: 1 addition & 0 deletions crates/cgp-tests/tests/namespace_tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod multi_param;
pub mod namespace_macro;
pub mod open;
pub mod redirect;
Expand Down
58 changes: 58 additions & 0 deletions crates/cgp-tests/tests/namespace_tests/multi_param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use cgp::prelude::*;

#[cgp_component(FooProvider)]
#[use_namespace(@app.FooProviderComponent)]
pub trait Foo<'a, T, U> {
fn foo(&self, first: &'a T, second: U);
}

#[cgp_impl(new DummyFoo)]
impl<'a, T, U> FooProvider<'a, T, U> {
fn foo(&self, _first: &'a T, _second: U) {}
}

pub struct AppA;

delegate_components! {
AppA {
open FooProviderComponent;

@FooProviderComponent.String.u32:
DummyFoo,
<T> @FooProviderComponent.bool.T:
DummyFoo,
}
}

check_components! {
AppA {
FooProviderComponent: [
<'a> (Life<'a>, String, u32),
<'a> (Life<'a>, bool, String),
],
FooProviderComponent:
<'a> (Life<'a>, bool, bool),
}
}

pub struct AppB;

delegate_components! {
AppB {
namespace default;

@app.FooProviderComponent.String.u64:
DummyFoo,
@app.FooProviderComponent.bool.<T> T:
DummyFoo,
}
}

check_components! {
<'a> AppB {
FooProviderComponent: [
(Life<'a>, String, u64),
(Life<'a>, bool, String),
],
}
}
Loading