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
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use syn::parse::{Parse, ParseStream};
use syn::token::In;
use syn::{Generics, ItemImpl, Type, parse_quote};

use crate::types::ident::IdentWithTypeArgs;
use crate::types::path::UniPathOrType;

pub struct DefaultImplAttribute {
pub key_type: UniPathOrType,
pub in_token: In,
pub namespace: IdentWithTypeArgs,
}

impl DefaultImplAttribute {
pub fn to_item_impl(
&self,
provider_generics: &Generics,
provider_type: &Type,
) -> syn::Result<ItemImpl> {
let key_type = &self.key_type;
let mut namespace_trait_path = self.namespace.clone();

namespace_trait_path
.type_args
.make_args()
.push(parse_quote!(__Components__));

let mut generics = provider_generics.clone();
generics.params.push(parse_quote!(__Components__));

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

let item_impl = parse_quote! {
impl #impl_generics #namespace_trait_path for #key_type
#where_clause
{
type Delegate = #provider_type;
}
};

Ok(item_impl)
}
}

impl Parse for DefaultImplAttribute {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key_type = input.parse()?;
let in_token = input.parse()?;
let namespace = input.parse()?;

Ok(Self {
key_type,
in_token,
namespace,
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use syn::{Generics, ItemImpl, Type};

use crate::types::attributes::DefaultImplAttribute;

#[derive(Default)]
pub struct DefaultImplAttributes {
pub attributes: Vec<DefaultImplAttribute>,
}

impl DefaultImplAttributes {
pub fn to_item_impls(
&self,
provider_generics: &Generics,
provider_type: &Type,
) -> syn::Result<Vec<ItemImpl>> {
let mut item_impls = Vec::new();

for attribute in &self.attributes {
let item_impl = attribute.to_item_impl(provider_generics, provider_type)?;
item_impls.push(item_impl);
}

Ok(item_impls)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod attribute;
mod attributes;

pub use attribute::*;
pub use attributes::*;
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use syn::Attribute;
use syn::parse::Parse;
use syn::punctuated::Punctuated;
use syn::token::Comma;

use crate::types::attributes::{
UseProviderAttribute, UseProviderAttributes, UseTypeAttribute, UseTypeAttributes,
UsesAttributes,
DefaultImplAttribute, DefaultImplAttributes, UseProviderAttribute, UseProviderAttributes,
UseTypeAttribute, UseTypeAttributes, UsesAttributes,
};
use crate::types::ident::IdentWithTypeArgs;

Expand All @@ -13,6 +14,7 @@ pub struct ImplAttributes {
pub uses: UsesAttributes,
pub use_type: UseTypeAttributes,
pub use_provider: UseProviderAttributes,
pub default_impls: DefaultImplAttributes,
pub raw_attributes: Vec<Attribute>,
}

Expand Down Expand Up @@ -47,6 +49,15 @@ impl ImplAttributes {
.attributes
.extend(use_provider);
}
"default_impl" => {
let default_impl =
attribute.parse_args_with(DefaultImplAttribute::parse)?;

parsed_attributes
.default_impls
.attributes
.push(default_impl);
}
_ => {
parsed_attributes.raw_attributes.push(attribute.clone());
}
Expand Down
2 changes: 2 additions & 0 deletions crates/macros/cgp-macro-core/src/types/attributes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod default_impl;
mod function;
mod impl_attributes;
mod use_provider;
mod use_type;
mod uses;

pub use default_impl::*;
pub use function::*;
pub use impl_attributes::*;
pub use use_provider::*;
Expand Down
17 changes: 11 additions & 6 deletions crates/macros/cgp-macro-core/src/types/cgp_impl/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,35 @@ impl ItemCgpImpl {
.use_provider
.add_type_param_bounds(&self_type, &mut item_impl.generics)?;

let (consumer_trait_path, context_type) = match &item_impl.trait_ {
let default_impls = attributes
.default_impls
.to_item_impls(&item_impl.generics, &self.args.provider_type)?;

let (provider_trait_path, context_type) = match &item_impl.trait_ {
Some((_, path, _)) => {
let consumer_trait_path = parse2(path.to_token_stream())?;
let provider_trait_path = parse2(path.to_token_stream())?;
let context_type = item_impl.self_ty.as_ref().clone();
(consumer_trait_path, context_type)
(provider_trait_path, context_type)
}
None => {
let consumer_trait_path = parse2(item_impl.self_ty.to_token_stream())?;
let provider_trait_path = parse2(item_impl.self_ty.to_token_stream())?;
let context_type = parse_quote! { __Context__ };

item_impl
.generics
.params
.insert(0, parse_quote! { #context_type });

(consumer_trait_path, context_type)
(provider_trait_path, context_type)
}
};

Ok(LoweredCgpImpl {
args: self.args.clone(),
item_impl,
context_type,
consumer_trait_path,
provider_trait_path,
default_impls,
})
}
}
7 changes: 3 additions & 4 deletions crates/macros/cgp-macro-core/src/types/cgp_impl/lowered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ pub struct LoweredCgpImpl {
pub args: ImplArgs,
pub item_impl: ItemImpl,
pub context_type: Type,
pub consumer_trait_path: IdentWithTypeArgs,
pub provider_trait_path: IdentWithTypeArgs,
pub default_impls: Vec<ItemImpl>,
}

impl LoweredCgpImpl {
Expand Down Expand Up @@ -53,7 +54,7 @@ impl LoweredCgpImpl {
pub fn to_raw_item_impl(&self) -> syn::Result<ItemImpl> {
let item_impl = &self.item_impl;
let context_type = &self.context_type;
let consumer_trait_path = &self.consumer_trait_path;
let mut provider_trait_path = self.provider_trait_path.clone();
let provider_type = &self.args.provider_type;

let context_ident = if let Ok(ident) = parse2::<Ident>(context_type.to_token_stream()) {
Expand All @@ -78,8 +79,6 @@ impl LoweredCgpImpl {

out_impl.self_ty = Box::new(provider_type.clone());

let mut provider_trait_path = consumer_trait_path.clone();

provider_trait_path
.type_args
.make_args()
Expand Down
2 changes: 2 additions & 0 deletions crates/macros/cgp-macro-core/src/types/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ mod path_head;
mod path_head_or_type;
mod prefix;
mod unipath;
mod unipath_or_type;

pub use path_element::*;
pub use path_head::*;
pub use path_head_or_type::*;
pub use prefix::*;
pub use unipath::*;
pub use unipath_or_type::*;
33 changes: 33 additions & 0 deletions crates/macros/cgp-macro-core/src/types/path/unipath_or_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::Type;
use syn::parse::{Parse, ParseStream};
use syn::token::At;

use crate::types::path::UniPath;

pub enum UniPathOrType {
Type(Type),
Path(UniPath),
}

impl Parse for UniPathOrType {
fn parse(input: ParseStream) -> syn::Result<Self> {
if input.peek(At) {
let path = input.parse()?;
Ok(Self::Path(path))
} else {
let ty = input.parse()?;
Ok(Self::Type(ty))
}
}
}

impl ToTokens for UniPathOrType {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
UniPathOrType::Type(ty) => ty.to_tokens(tokens),
UniPathOrType::Path(path) => path.to_tokens(tokens),
}
}
}
12 changes: 9 additions & 3 deletions crates/macros/cgp-macro-lib/src/entrypoints/cgp_impl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cgp_macro_core::types::cgp_impl::{ImplArgs, ItemCgpImpl};
use proc_macro2::TokenStream;
use quote::ToTokens;
use quote::quote;
use syn::{ItemImpl, parse2};

pub fn cgp_impl(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream> {
Expand All @@ -10,7 +10,13 @@ pub fn cgp_impl(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream
let item_cgp_impl = ItemCgpImpl { args, item_impl };

let lowered = item_cgp_impl.lower()?;
let lowered = lowered.lower()?;

Ok(lowered.to_token_stream())
let default_impls = &lowered.default_impls;

let bare_impls = lowered.lower()?;

Ok(quote! {
#bare_impls
#(#default_impls)*
})
}
48 changes: 48 additions & 0 deletions crates/tests/cgp-tests/src/namespaces/default_impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use core::fmt::Display;

use cgp::core::component::DefaultImpls1;
use cgp::prelude::*;

#[cgp_component(ShowImpl)]
#[prefix(@test)]
pub trait Show<T> {
fn show(&self, value: &T) -> String;
}

#[cgp_impl(new ShowString)]
#[default_impl(String in DefaultImpls1<ShowImplComponent>)]
impl ShowImpl<String> {
fn show(&self, value: &String) -> String {
value.clone()
}
}

#[cgp_impl(new ShowWithDisplay)]
impl<T: Display> ShowImpl<T> {
fn show(&self, value: &T) -> String {
value.to_string()
}
}

cgp_namespace! {
new DefaultShowComponents {
[
String,
u64,
]:
ShowWithDisplay,
}
}

cgp_namespace! {
new ExtendedNamespace: DefaultNamespace {
}
}

#[cgp_impl(new ShowU32)]
#[default_impl(@test.ShowImplComponent.u32 in ExtendedNamespace)]
impl ShowImpl<u32> {
fn show(&self, value: &u32) -> String {
value.to_string()
}
}
38 changes: 0 additions & 38 deletions crates/tests/cgp-tests/src/namespaces/generics.rs

This file was deleted.

2 changes: 1 addition & 1 deletion crates/tests/cgp-tests/src/namespaces/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub mod default_impls;
pub mod extended;
pub mod generics;
Loading
Loading