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
3 changes: 3 additions & 0 deletions crates/macros/cgp-macro-core/src/functions/getter/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod parse;

pub use parse::*;
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
use alloc::vec::Vec;

use cgp_macro_core::functions::{parse_field_type, parse_single_segment_type_path};
use cgp_macro_core::visitors::ReplaceSelfTypeVisitor;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::{Comma, Mut};
Expand All @@ -11,8 +7,9 @@ use syn::{
Signature, TraitItem, TraitItemFn, TraitItemType, Type, parse_quote,
};

use crate::derive_getter::ReceiverMode;
use crate::derive_getter::getter_field::GetterField;
use crate::functions::{parse_field_type, parse_single_segment_type_path};
use crate::types::cgp_getter::{GetterField, ReceiverMode};
use crate::visitors::ReplaceSelfTypeVisitor;

pub fn parse_getter_fields(
context_type: &Ident,
Expand Down Expand Up @@ -91,7 +88,7 @@ pub fn parse_getter_fields(
Ok((fields, field_assoc_type))
}

pub fn parse_getter_method(
fn parse_getter_method(
context_type: &Ident,
method: &TraitItemFn,
field_assoc_type: &Option<Ident>,
Expand Down Expand Up @@ -121,7 +118,7 @@ pub fn parse_getter_method(
})
}

pub fn validate_getter_method_signature(signature: &Signature) -> syn::Result<()> {
fn validate_getter_method_signature(signature: &Signature) -> syn::Result<()> {
if signature.constness.is_some() {
return Err(Error::new(
signature.constness.span(),
Expand Down
2 changes: 2 additions & 0 deletions crates/macros/cgp-macro-core/src/functions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
mod delegated_impls;
mod field;
mod generics;
mod getter;
mod implicits;
mod is_provider_params;
mod snake_case;

pub use delegated_impls::*;
pub use field::*;
pub use generics::*;
pub use getter::*;
pub use implicits::*;
pub use is_provider_params::*;
pub use snake_case::*;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::mem;
use syn::parse::Parse;
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::{Attribute, TypeParamBound};
use syn::{Attribute, ItemTrait, TypeParamBound};

use crate::types::attributes::{PrefixAttribute, UseTypeAttribute, UseTypeAttributes};

Expand All @@ -15,6 +15,18 @@ pub struct CgpComponentAttributes {
}

impl CgpComponentAttributes {
pub fn preprocess(item_trait: &ItemTrait) -> syn::Result<(Self, ItemTrait)> {
let mut item_trait = item_trait.clone();

let attributes = Self::parse(&mut item_trait.attrs)?;

item_trait.supertraits.extend(attributes.extend.clone());

attributes.use_type.transform_item_trait(&mut item_trait)?;

Ok((attributes, item_trait))
}

pub fn parse(attributes: &mut Vec<Attribute>) -> syn::Result<Self> {
let mut parsed_attributes = CgpComponentAttributes::default();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use cgp_macro_core::types::field::{FieldName, HasFieldBound};
use proc_macro2::TokenStream;
use quote::{ToTokens, quote};
use syn::{Ident, ItemImpl, ItemTrait, TraitItemType, parse_quote, parse2};
use syn::{Ident, ImplItem, ItemImpl, ItemTrait, TraitItemType, parse_quote, parse2};

use crate::derive_getter::getter_field::GetterField;
use crate::derive_getter::{ContextArg, ReceiverMode, derive_getter_method};
use crate::type_component::get_bounds_and_replace_self_assoc_type;
use crate::types::cgp_getter::{GetterField, ReceiverMode};
use crate::types::field::{FieldName, HasFieldBound};
use crate::types::getter::{ContextArg, derive_getter_method};
use crate::visitors::get_bounds_and_replace_self_assoc_type;

pub fn derive_blanket_impl(
context_type: &Ident,
Expand All @@ -17,7 +16,7 @@ pub fn derive_blanket_impl(

let supertrait_constraints = consumer_trait.supertraits.clone();

let mut items: TokenStream = TokenStream::new();
let mut items: Vec<ImplItem> = Vec::new();

let mut generics = consumer_trait.generics.clone();

Expand All @@ -32,9 +31,9 @@ pub fn derive_blanket_impl(
.params
.push(parse2(field_assoc_type_ident.to_token_stream())?);

items.extend(quote! {
items.push(parse2(quote! {
type #field_assoc_type_ident = #field_assoc_type_ident;
});
})?);

let field_constraints = get_bounds_and_replace_self_assoc_type(field_assoc_type);

Expand All @@ -54,23 +53,15 @@ pub fn derive_blanket_impl(
for field in fields {
let (receiver_type, context_arg) = match &field.receiver_mode {
ReceiverMode::SelfReceiver => (context_type.to_token_stream(), ContextArg::SelfArg),
ReceiverMode::Type(ty) => (
ty.to_token_stream(),
ContextArg::Ident(ty.to_token_stream()),
),
ReceiverMode::Type(ty) => (ty.to_token_stream(), ContextArg::Type(ty.clone())),
};

let field_name = FieldName::from(field.field_name.clone());
let tag_type = parse_quote!(#field_name);

let method = derive_getter_method(
&context_arg,
field,
Some(quote! { ::< #field_name > }),
None,
);
let method = derive_getter_method(&context_arg, field, &tag_type, None)?;

items.extend(method);
items.push(method.into());

let field_type = if let Some(trait_item) = &field_assoc_type {
let trait_item_ident = &trait_item.ident;
Expand Down Expand Up @@ -98,7 +89,7 @@ pub fn derive_blanket_impl(
impl #impl_generics #consumer_name #type_generics for #context_type
#where_clause
{
#items
#( #items )*
}
})?;

Expand Down
35 changes: 35 additions & 0 deletions crates/macros/cgp-macro-core/src/types/cgp_auto_getter/item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use proc_macro2::Span;
use syn::{Ident, Item, ItemImpl, ItemTrait};

use crate::functions::parse_getter_fields;
use crate::types::attributes::CgpComponentAttributes;
use crate::types::cgp_auto_getter::derive_blanket_impl;

pub struct ItemCgpAutoGetter {
pub item_trait: ItemTrait,
}

impl ItemCgpAutoGetter {
pub fn preprocess(item_trait: &ItemTrait) -> syn::Result<Self> {
let (_attributes, item_trait) = CgpComponentAttributes::preprocess(item_trait)?;
Ok(Self { item_trait })
}

pub fn to_items(&self) -> syn::Result<Vec<Item>> {
let item_trait = self.item_trait.clone().into();
let item_impl = self.to_blanket_impl()?.into();

Ok(vec![item_trait, item_impl])
}

pub fn to_blanket_impl(&self) -> syn::Result<ItemImpl> {
let context_type = Ident::new("__Context__", Span::call_site());

let (fields, field_type) = parse_getter_fields(&context_type, &self.item_trait)?;

let blanket_impl =
derive_blanket_impl(&context_type, &self.item_trait, &fields, &field_type)?;

Ok(blanket_impl)
}
}
5 changes: 5 additions & 0 deletions crates/macros/cgp-macro-core/src/types/cgp_auto_getter/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod blanket;
mod item;

pub use blanket::*;
pub use item::*;
8 changes: 1 addition & 7 deletions crates/macros/cgp-macro-core/src/types/cgp_component/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,7 @@ pub struct ItemCgpComponent {

impl ItemCgpComponent {
pub fn preprocess(&self) -> syn::Result<PreprocessedCgpComponent> {
let mut item_trait = self.item_trait.clone();

let attributes = CgpComponentAttributes::parse(&mut item_trait.attrs)?;

item_trait.supertraits.extend(attributes.extend.clone());

attributes.use_type.transform_item_trait(&mut item_trait)?;
let (attributes, item_trait) = CgpComponentAttributes::preprocess(&self.item_trait)?;

Ok(PreprocessedCgpComponent {
args: self.args.clone(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use cgp_macro_core::types::getter::FieldMode;
use syn::token::Mut;
use syn::{Ident, Type};

use crate::types::getter::FieldMode;

#[derive(Clone)]
pub struct GetterField {
pub field_name: Ident,
pub field_type: Type,
Expand All @@ -12,6 +14,7 @@ pub struct GetterField {
pub receiver_mode: ReceiverMode,
}

#[derive(Clone)]
pub enum ReceiverMode {
SelfReceiver,
Type(Box<Type>),
Expand Down
49 changes: 49 additions & 0 deletions crates/macros/cgp-macro-core/src/types/cgp_getter/item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use syn::{Error, Item, TraitItemType};

use crate::functions::parse_getter_fields;
use crate::types::cgp_component::EvaluatedCgpComponent;
use crate::types::cgp_getter::GetterField;
use crate::types::provider_impl::ItemProviderImpls;

pub struct ItemCgpGetter {
pub item_component: EvaluatedCgpComponent,
pub fields: Vec<GetterField>,
pub field_assoc_type: Option<TraitItemType>,
}

impl ItemCgpGetter {
pub fn to_items(&self) -> syn::Result<Vec<Item>> {
let mut items = self.item_component.to_items()?;

let item_impls = self.to_item_provider_impls()?.to_item_impls()?;
items.extend(item_impls.into_iter().map(Item::Impl));

Ok(items)
}

pub fn to_item_provider_impls(&self) -> syn::Result<ItemProviderImpls> {
let mut items = ItemProviderImpls::default();

items.items.push(self.to_use_fields_impl()?);
items.items.extend(self.to_use_field_impl()?);
items.items.extend(self.to_with_provider_impl()?);

Ok(items)
}
}

impl TryFrom<EvaluatedCgpComponent> for ItemCgpGetter {
type Error = Error;

fn try_from(item_component: EvaluatedCgpComponent) -> Result<Self, Self::Error> {
let (fields, field_assoc_type) = parse_getter_fields(
&item_component.args.context_ident,
&item_component.consumer_trait,
)?;
Ok(Self {
item_component,
fields,
field_assoc_type,
})
}
}
8 changes: 8 additions & 0 deletions crates/macros/cgp-macro-core/src/types/cgp_getter/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod getter_field;
mod item;
mod to_use_fields_impl;
mod use_field;
mod with_provider;

pub use getter_field::*;
pub use item::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use quote::{ToTokens, quote};
use syn::{ImplItem, ItemImpl, Type, parse_quote, parse2};

use crate::types::cgp_getter::{ItemCgpGetter, ReceiverMode};
use crate::types::field::{HasFieldBound, Symbol};
use crate::types::getter::{ContextArg, derive_getter_method};
use crate::types::provider_impl::ItemProviderImpl;
use crate::visitors::get_bounds_and_replace_self_assoc_type;

impl ItemCgpGetter {
pub fn to_use_fields_impl(&self) -> syn::Result<ItemProviderImpl> {
let provider_trait = &self.item_component.provider_trait;

let context_type = &self.item_component.args.context_ident;

let provider_name = &self.item_component.args.provider_ident;

let component_name = &self.item_component.args.component_name;

let field_assoc_type = &self.field_assoc_type;

let mut items: Vec<ImplItem> = Vec::new();

let mut provider_generics = provider_trait.generics.clone();

if let Some(field_assoc_type) = &field_assoc_type {
let field_assoc_type_ident = &field_assoc_type.ident;

provider_generics
.params
.push(parse2(field_assoc_type_ident.to_token_stream())?);

items.push(parse2(quote! {
type #field_assoc_type_ident = #field_assoc_type_ident;
})?);

let field_constraints = get_bounds_and_replace_self_assoc_type(field_assoc_type);

provider_generics
.make_where_clause()
.predicates
.push(parse2(quote! {
#field_assoc_type_ident: #field_constraints
})?);
}

let where_clause = provider_generics.make_where_clause();

for field in &self.fields {
let receiver_type = match &field.receiver_mode {
ReceiverMode::SelfReceiver => parse_quote!(#context_type),
ReceiverMode::Type(ty) => ty.clone(),
};

let field_name = Symbol::new(field.field_name.clone());
let tag_type: Type = parse_quote!(#field_name);

let method = derive_getter_method(
&ContextArg::Type(receiver_type.clone()),
field,
&tag_type,
None,
)?;

items.push(method.into());

let field_type = if let Some(trait_item) = &field_assoc_type {
let trait_item_ident = &trait_item.ident;
parse_quote!(#trait_item_ident)
} else {
field.field_type.clone()
};

let constraint = HasFieldBound {
field_type,
field_mut: field.receiver_mut,
field_mode: field.field_mode.clone(),
tag_type: tag_type.clone(),
};

where_clause
.predicates
.push(parse2(quote! { #receiver_type: #constraint })?);
}

let (_, type_generics, _) = provider_trait.generics.split_for_impl();
let (impl_generics, _, where_clause) = provider_generics.split_for_impl();

let item_impl: ItemImpl = parse2(quote! {
impl #impl_generics #provider_name #type_generics for UseFields
#where_clause
{
#( #items )*
}
})?;

Ok(ItemProviderImpl {
component_type: component_name.to_type(),
item_impl,
})
}
}
Loading
Loading