Skip to content

Commit 245b214

Browse files
authored
Implement ItemCgpFn (#234)
1 parent 602d001 commit 245b214

18 files changed

Lines changed: 207 additions & 185 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/macros/cgp-extra-macro-lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ default = []
1818
syn = { version = "2.0.95", features = [ "full", "extra-traits" ] }
1919
quote = "1.0.38"
2020
proc-macro2 = "1.0.92"
21-
cgp-macro-lib = { workspace = true }
21+
cgp-macro-core = { workspace = true }

crates/macros/cgp-extra-macro-lib/src/entrypoints/cgp_auto_dispatch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::BTreeSet;
22

3-
use cgp_macro_lib::utils::to_camel_case_str;
3+
use cgp_macro_core::functions::to_camel_case_str;
44
use proc_macro2::{Span, TokenStream};
55
use quote::quote;
66
use syn::punctuated::Punctuated;

crates/macros/cgp-extra-macro-lib/src/entrypoints/cgp_computer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use cgp_macro_lib::utils::to_camel_case_str;
1+
use cgp_macro_core::functions::to_camel_case_str;
22
use proc_macro2::TokenStream;
33
use quote::{ToTokens, quote};
44
use syn::punctuated::Punctuated;

crates/macros/cgp-extra-macro-lib/src/entrypoints/cgp_producer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use cgp_macro_lib::utils::to_camel_case_str;
1+
use cgp_macro_core::functions::to_camel_case_str;
22
use proc_macro2::TokenStream;
33
use quote::quote;
44
use syn::spanned::Spanned;
File renamed without changes.

crates/macros/cgp-macro-core/src/functions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod camel_case;
12
mod delegated_impls;
23
mod field;
34
mod generics;
@@ -6,6 +7,7 @@ mod implicits;
67
mod is_provider_params;
78
mod snake_case;
89

10+
pub use camel_case::*;
911
pub use delegated_impls::*;
1012
pub use field::*;
1113
pub use generics::*;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use syn::{Ident, ItemFn, Visibility};
2+
3+
use crate::functions::{extract_and_parse_implicit_args, to_camel_case_str};
4+
use crate::types::attributes::FunctionAttributes;
5+
use crate::types::cgp_fn::PreprocessedItemCgpFn;
6+
7+
pub struct ItemCgpFn {
8+
pub ident: Option<Ident>,
9+
pub item_fn: ItemFn,
10+
}
11+
12+
impl ItemCgpFn {
13+
pub fn preprocess(&self) -> syn::Result<PreprocessedItemCgpFn> {
14+
let mut item_fn = self.item_fn.clone();
15+
16+
let ident = self.ident.clone().unwrap_or_else(|| {
17+
Ident::new(
18+
&to_camel_case_str(&item_fn.sig.ident.to_string()),
19+
item_fn.sig.ident.span(),
20+
)
21+
});
22+
23+
let visibility = item_fn.vis.clone();
24+
item_fn.vis = Visibility::Inherited;
25+
26+
let implicit_args = extract_and_parse_implicit_args(&mut item_fn.sig.inputs)?;
27+
implicit_args.prepend_to_block(&mut item_fn.block)?;
28+
29+
let attributes = FunctionAttributes::parse(core::mem::take(&mut item_fn.attrs))?;
30+
31+
let generics = core::mem::take(&mut item_fn.sig.generics);
32+
33+
Ok(PreprocessedItemCgpFn {
34+
ident,
35+
item_fn,
36+
implicit_args,
37+
attributes,
38+
visibility,
39+
generics,
40+
})
41+
}
42+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod item;
2+
mod preprocessed;
3+
4+
pub use item::*;
5+
pub use preprocessed::*;
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use quote::quote;
2+
use syn::punctuated::Punctuated;
3+
use syn::token::Plus;
4+
use syn::{
5+
Generics, Ident, Item, ItemFn, ItemImpl, ItemTrait, TraitItemFn, Type, TypeParamBound,
6+
Visibility, parse_quote, parse2,
7+
};
8+
9+
use crate::traits::AddTypeParamBounds;
10+
use crate::types::attributes::FunctionAttributes;
11+
use crate::types::implicits::ImplicitArgFields;
12+
13+
pub struct PreprocessedItemCgpFn {
14+
pub ident: Ident,
15+
pub item_fn: ItemFn,
16+
pub implicit_args: ImplicitArgFields,
17+
pub attributes: FunctionAttributes,
18+
pub visibility: Visibility,
19+
pub generics: Generics,
20+
}
21+
22+
impl PreprocessedItemCgpFn {
23+
pub fn to_items(&self) -> syn::Result<Vec<Item>> {
24+
let item_trait = self.to_item_trait()?;
25+
let item_impl = self.to_item_impl()?;
26+
27+
Ok(vec![item_trait.into(), item_impl.into()])
28+
}
29+
30+
pub fn to_item_trait(&self) -> syn::Result<ItemTrait> {
31+
let Self {
32+
ident,
33+
item_fn,
34+
attributes,
35+
generics,
36+
visibility,
37+
..
38+
} = self;
39+
40+
let trait_item_fn = TraitItemFn {
41+
attrs: item_fn.attrs.clone(),
42+
sig: item_fn.sig.clone(),
43+
default: None,
44+
semi_token: None,
45+
};
46+
47+
let mut item_trait: ItemTrait = parse2(quote! {
48+
pub trait #ident {
49+
#trait_item_fn
50+
}
51+
})?;
52+
53+
item_trait.generics = generics.clone();
54+
item_trait.generics.where_clause = None;
55+
56+
item_trait.supertraits.extend(attributes.extend.clone());
57+
58+
if !attributes.extend_where.is_empty() {
59+
item_trait
60+
.generics
61+
.make_where_clause()
62+
.predicates
63+
.extend(attributes.extend_where.clone());
64+
}
65+
66+
attributes.use_type.transform_item_trait(&mut item_trait)?;
67+
68+
item_trait.attrs.extend(attributes.raw_attributes.clone());
69+
item_trait.vis = visibility.clone();
70+
71+
Ok(item_trait)
72+
}
73+
74+
pub fn to_item_impl(&self) -> syn::Result<ItemImpl> {
75+
let Self {
76+
ident,
77+
item_fn,
78+
implicit_args,
79+
attributes,
80+
generics,
81+
..
82+
} = self;
83+
84+
let type_generics = generics.split_for_impl().1;
85+
86+
let self_type: Type = parse_quote!(Self);
87+
88+
let mut item_impl: ItemImpl = parse2(quote! {
89+
impl #ident #type_generics for __Context__ {
90+
#item_fn
91+
}
92+
})?;
93+
94+
item_impl.generics = generics.clone();
95+
item_impl
96+
.generics
97+
.params
98+
.insert(0, parse_quote!(__Context__));
99+
100+
item_impl
101+
.generics
102+
.params
103+
.extend(attributes.impl_generics.clone());
104+
105+
{
106+
let mut bounds: Punctuated<TypeParamBound, Plus> = Punctuated::default();
107+
bounds.extend(attributes.extend.clone());
108+
109+
for import in attributes.uses.iter() {
110+
bounds.push(parse2(quote! { #import })?);
111+
}
112+
113+
if !bounds.is_empty() {
114+
item_impl
115+
.generics
116+
.make_where_clause()
117+
.predicates
118+
.push(parse2(quote! {
119+
Self: #bounds
120+
})?);
121+
}
122+
}
123+
124+
if !attributes.extend_where.is_empty() {
125+
item_impl
126+
.generics
127+
.make_where_clause()
128+
.predicates
129+
.extend(attributes.extend_where.clone());
130+
}
131+
132+
implicit_args.add_type_param_bounds(&self_type, &mut item_impl.generics)?;
133+
134+
attributes.use_type.transform_item_impl(&mut item_impl)?;
135+
attributes
136+
.use_provider
137+
.add_type_param_bounds(&self_type, &mut item_impl.generics)?;
138+
139+
item_impl.attrs.extend(attributes.raw_attributes.clone());
140+
141+
Ok(item_impl)
142+
}
143+
}

0 commit comments

Comments
 (0)