Skip to content

Commit fffdbdd

Browse files
authored
Fix component generics inside derivation of WithProvider for #[cgp_getter] (#80)
* Fix component generics inside derivation of WithProvider for cgp_getter * Add test for getter component generics
1 parent bd315a3 commit fffdbdd

File tree

2 files changed

+120
-2
lines changed

2 files changed

+120
-2
lines changed

crates/cgp-component-macro-lib/src/getter_component/with_provider.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub fn derive_with_provider_impl(
1010
field: &GetterField,
1111
) -> syn::Result<ItemImpl> {
1212
let component_name = &spec.component_name;
13+
let component_params = &spec.component_params;
14+
1315
let context_type = &spec.context_type;
1416
let provider_name = &spec.provider_name;
1517

@@ -20,11 +22,11 @@ pub fn derive_with_provider_impl(
2022

2123
let provider_constraint = if field.field_mut.is_none() {
2224
quote! {
23-
FieldGetter< #context_type, #component_name, Value = #provider_type >
25+
FieldGetter< #context_type, #component_name < #component_params > , Value = #provider_type >
2426
}
2527
} else {
2628
quote! {
27-
MutFieldGetter< #context_type, #component_name, Value = #provider_type >
29+
MutFieldGetter< #context_type, #component_name < #component_params >, Value = #provider_type >
2830
}
2931
};
3032

crates/cgp-component-macro-lib/src/tests/derive_getter.rs

+116
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,119 @@ fn test_derive_getter_with_generics() {
242242

243243
assert_equal_token_stream(&derived, &expected);
244244
}
245+
246+
#[test]
247+
fn test_derive_getter_with_component_generics() {
248+
let derived = cgp_getter(
249+
quote! {
250+
name: NameGetterComponent<App>,
251+
provider: NameGetter,
252+
},
253+
quote! {
254+
pub trait HasName<App>
255+
where
256+
App: HasNameType,
257+
{
258+
fn name(&self) -> &App::Name;
259+
}
260+
},
261+
)
262+
.unwrap();
263+
264+
let expected = quote! {
265+
pub struct NameGetterComponent<App>(pub core::marker::PhantomData<(App)>);
266+
pub trait HasName<App>
267+
where
268+
App: HasNameType,
269+
{
270+
fn name(&self) -> &App::Name;
271+
}
272+
pub trait NameGetter<Context, App>:
273+
IsProviderFor<NameGetterComponent<App>, Context, (App)>
274+
where
275+
App: HasNameType,
276+
{
277+
fn name(context: &Context) -> &App::Name;
278+
}
279+
impl<Context, App> HasName<App> for Context
280+
where
281+
App: HasNameType,
282+
Context: HasProvider,
283+
Context::Provider: NameGetter<Context, App>,
284+
{
285+
fn name(&self) -> &App::Name {
286+
Context::Provider::name(self)
287+
}
288+
}
289+
impl<Component, Context, App> NameGetter<Context, App> for Component
290+
where
291+
App: HasNameType,
292+
Component: DelegateComponent<NameGetterComponent<App>>
293+
+ IsProviderFor<NameGetterComponent<App>, Context, (App)>,
294+
Component::Delegate: NameGetter<Context, App>,
295+
{
296+
fn name(context: &Context) -> &App::Name {
297+
Component::Delegate::name(context)
298+
}
299+
}
300+
impl<Context, App> NameGetter<Context, App> for UseFields
301+
where
302+
App: HasNameType,
303+
Context: HasField<
304+
Cons<Char<'n'>, Cons<Char<'a'>, Cons<Char<'m'>, Cons<Char<'e'>, Nil>>>>,
305+
Value = App::Name,
306+
>,
307+
{
308+
fn name(context: &Context) -> &App::Name {
309+
context.get_field(
310+
::core::marker::PhantomData::<
311+
Cons<Char<'n'>, Cons<Char<'a'>, Cons<Char<'m'>, Cons<Char<'e'>, Nil>>>>,
312+
>,
313+
)
314+
}
315+
}
316+
impl<Context, App> IsProviderFor<NameGetterComponent<App>, Context, (App)> for UseFields
317+
where
318+
App: HasNameType,
319+
Context: HasField<
320+
Cons<Char<'n'>, Cons<Char<'a'>, Cons<Char<'m'>, Cons<Char<'e'>, Nil>>>>,
321+
Value = App::Name,
322+
>,
323+
{
324+
}
325+
impl<Context, App, __Tag__> NameGetter<Context, App> for UseField<__Tag__>
326+
where
327+
App: HasNameType,
328+
Context: HasField<__Tag__, Value = App::Name>,
329+
{
330+
fn name(context: &Context) -> &App::Name {
331+
context.get_field(::core::marker::PhantomData)
332+
}
333+
}
334+
impl<Context, App, __Tag__> IsProviderFor<NameGetterComponent<App>, Context, (App)>
335+
for UseField<__Tag__>
336+
where
337+
App: HasNameType,
338+
Context: HasField<__Tag__, Value = App::Name>,
339+
{
340+
}
341+
impl<Context, App, __Provider__> NameGetter<Context, App> for WithProvider<__Provider__>
342+
where
343+
App: HasNameType,
344+
__Provider__: FieldGetter<Context, NameGetterComponent<App>, Value = App::Name>,
345+
{
346+
fn name(context: &Context) -> &App::Name {
347+
__Provider__::get_field(context, ::core::marker::PhantomData)
348+
}
349+
}
350+
impl<Context, App, __Provider__> IsProviderFor<NameGetterComponent<App>, Context, (App)>
351+
for WithProvider<__Provider__>
352+
where
353+
App: HasNameType,
354+
__Provider__: FieldGetter<Context, NameGetterComponent<App>, Value = App::Name>,
355+
{
356+
}
357+
};
358+
359+
assert_equal_token_stream(&derived, &expected);
360+
}

0 commit comments

Comments
 (0)