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
@@ -1,14 +1,15 @@
use syn::{ImplItem, ItemTrait, Type, parse_quote};
use syn::{ImplItem, ItemTrait, Type};

use crate::functions::trait_items_to_delegated_impl_items;
use crate::parse_internal;

pub fn provider_trait_to_impl_items(
item_trait: &ItemTrait,
delegate_type: &Type,
) -> syn::Result<Vec<ImplItem>> {
let provider_name = &item_trait.ident;
let provider_type_generics = item_trait.generics.split_for_impl().1;
let provider_trait_path: Type = parse_quote!(#provider_name #provider_type_generics);
let provider_trait_path: Type = parse_internal!(#provider_name #provider_type_generics);

trait_items_to_delegated_impl_items(&item_trait.items, delegate_type, &provider_trait_path)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, quote};
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::{FnArg, Ident, ImplItemFn, Signature, Type, Visibility, parse2};
use syn::{FnArg, Ident, ImplItemFn, Signature, Type, Visibility};

use crate::functions::parse_internal;

pub fn signature_to_delegated_impl_item_fn(
signature: &Signature,
Expand All @@ -18,11 +20,11 @@ pub fn signature_to_delegated_impl_item_fn(
TokenStream::new()
};

let body = parse2(quote!({
let body = parse_internal!({
#delegate_type :: #fn_name (
#args
) #await_expr
}))?;
});

let item = ImplItemFn {
attrs: Vec::new(),
Expand All @@ -42,7 +44,7 @@ fn signature_to_idents(sig: &Signature) -> syn::Result<Punctuated<Ident, Comma>>
fn arg_to_ident(arg: &FnArg) -> syn::Result<Ident> {
let ident = match arg {
FnArg::Receiver(_) => Ident::new("self", Span::call_site()),
FnArg::Typed(pat) => parse2(pat.pat.to_token_stream())?,
FnArg::Typed(pat) => parse_internal(pat.pat.to_token_stream())?,
};

Ok(ident)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use proc_macro2::Span;
use quote::quote;
use syn::spanned::Spanned;
use syn::token::Eq;
use syn::{Error, ImplItem, ImplItemConst, TraitItem, Type, Visibility, parse2};
use syn::{Error, ImplItem, ImplItemConst, TraitItem, Type, Visibility};

use crate::functions::{signature_to_delegated_impl_item_fn, trait_to_impl_item_type};
use crate::functions::{
parse_internal, signature_to_delegated_impl_item_fn, trait_to_impl_item_type,
};

pub fn trait_items_to_delegated_impl_items(
trait_items: &[TraitItem],
Expand Down Expand Up @@ -33,9 +34,9 @@ pub fn trait_item_to_delegated_impl_items(
TraitItem::Type(trait_type) => {
let type_name = &trait_type.ident;
let type_generics = trait_type.generics.split_for_impl().1;
let delegate_type = parse2(quote!(
let delegate_type = parse_internal! {
< #delegate_type as #provider_trait_path > :: #type_name #type_generics
))?;
};

let impl_type = trait_to_impl_item_type(trait_type, delegate_type);

Expand All @@ -45,9 +46,9 @@ pub fn trait_item_to_delegated_impl_items(
let const_ident = &trait_item_const.ident;
let type_generics = trait_item_const.generics.split_for_impl().1;

let impl_expr = parse2(quote! {
let impl_expr = parse_internal! {
< #delegate_type as #provider_trait_path > :: #const_ident #type_generics
})?;
};

let impl_item_const = ImplItemConst {
attrs: trait_item_const.attrs.clone(),
Expand Down
13 changes: 6 additions & 7 deletions crates/macros/cgp-macro-core/src/functions/field/parse.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use quote::{ToTokens, quote};
use quote::ToTokens;
use syn::spanned::Spanned;
use syn::token::Mut;
use syn::{
Error, GenericArgument, PathArguments, PathSegment, Type, TypePath, parse_quote, parse2,
};
use syn::{Error, GenericArgument, PathArguments, PathSegment, Type, TypePath};

use crate::functions::parse_internal;
use crate::types::getter::FieldMode;

pub fn parse_field_type(
Expand All @@ -23,10 +22,10 @@ pub fn parse_field_type(
));
}

if type_ref.elem.as_ref() == &parse_quote! { str } {
if type_ref.elem.as_ref() == &parse_internal! { str } {
// Special case to handle &str as String field

let field_type: Type = parse_quote! { String };
let field_type: Type = parse_internal! { String };

Ok((field_type, FieldMode::Str))
} else if let (Type::Slice(slice), None) = (type_ref.elem.as_ref(), receiver_mut) {
Expand All @@ -42,7 +41,7 @@ pub fn parse_field_type(
Type::Path(type_path) => {
if let Some(field_type) = try_parse_option_ref(type_path) {
Ok((
parse2(quote! { Option< #field_type > })?,
parse_internal! { Option< #field_type > },
FieldMode::OptionRef,
))
} else if let (Some(field_type), None) = (try_parse_mref(type_path), receiver_mut) {
Expand Down
11 changes: 6 additions & 5 deletions crates/macros/cgp-macro-core/src/functions/getter/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use syn::token::{Comma, Mut};
use syn::visit_mut::VisitMut;
use syn::{
Error, FnArg, GenericArgument, Ident, ItemTrait, PathArguments, PathSegment, ReturnType,
Signature, TraitItem, TraitItemFn, TraitItemType, Type, parse_quote,
Signature, TraitItem, TraitItemFn, TraitItemType, Type,
};

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

Expand Down Expand Up @@ -68,8 +69,8 @@ pub fn parse_getter_fields(
let field_assoc_type_ident = &field_assoc_type.ident;
let field_type = &field.field_type;

if field_type != &parse_quote! { Self :: #field_assoc_type_ident }
&& field_type != &parse_quote! { #context_type :: #field_assoc_type_ident }
if field_type != &parse_internal! { Self :: #field_assoc_type_ident }
&& field_type != &parse_internal! { #context_type :: #field_assoc_type_ident }
{
return Err(Error::new(
field.field_type.span(),
Expand Down Expand Up @@ -229,7 +230,7 @@ fn parse_receiver(context_ident: &Ident, arg: &FnArg) -> syn::Result<(ReceiverMo
let mut receiver = ty.elem.clone();

ReplaceSelfTypeVisitor {
replaced_type: &parse_quote!(#context_ident),
replaced_type: &parse_internal!(#context_ident),
skip_assoc_types: &Vec::new(),
}
.visit_type_mut(&mut receiver);
Expand All @@ -254,7 +255,7 @@ fn parse_return_type(
let mut replaced_type = ty.as_ref().clone();

ReplaceSelfTypeVisitor {
replaced_type: &parse_quote!(#context_type),
replaced_type: &parse_internal!(#context_type),
skip_assoc_types: &Vec::from_iter(field_assoc_type.clone()),
}
.visit_type_mut(&mut replaced_type);
Expand Down
20 changes: 12 additions & 8 deletions crates/macros/cgp-macro-core/src/functions/is_provider_params.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::{GenericParam, Generics, Type, parse_quote};
use syn::{GenericParam, Generics, Type};

use crate::parse_internal;
use crate::types::generics::TypeGenerics;

pub fn parse_is_provider_params(generics: &Generics) -> syn::Result<Punctuated<Type, Comma>> {
let params = TypeGenerics::try_from(generics)?.generics.params;

let params = params.into_iter().map(|param| -> Type {
match param {
let mut res = Punctuated::new();

for param in params {
let out = match param {
GenericParam::Type(type_param) => {
let ident = type_param.ident;
parse_quote! { #ident }
parse_internal! { #ident }
}
GenericParam::Lifetime(life_param) => {
let life = &life_param.lifetime;
parse_quote! { Life<#life> }
parse_internal! { Life<#life> }
}
GenericParam::Const(_) => {
unimplemented!("const generic parameters are not yet supported in CGP traits")
}
}
});
};
res.push(out)
}

Ok(Punctuated::from_iter(params))
Ok(res)
}
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
Expand Up @@ -5,6 +5,7 @@ mod generics;
mod getter;
mod implicits;
mod is_provider_params;
mod parse_internal;
mod snake_case;

pub use camel_case::*;
Expand All @@ -14,4 +15,5 @@ pub use generics::*;
pub use getter::*;
pub use implicits::*;
pub use is_provider_params::*;
pub use parse_internal::*;
pub use snake_case::*;
79 changes: 79 additions & 0 deletions crates/macros/cgp-macro-core/src/functions/parse_internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use core::any::type_name;

use proc_macro2::{Group, TokenStream, TokenTree};
use syn::parse::Parse;
use syn::spanned::Spanned;
use syn::{Error, parse2};

pub use crate::macros::parse_internal;

pub fn parse_internal<T>(body: TokenStream) -> Result<T, Error>
where
T: Parse,
{
parse2(body.clone()).map_err(|mut e| {
e.combine(Error::new(
body.span(),
format!(
"failed to parse internal tokens to type `{}`:\n{}",
type_name::<T>(),
strip_macro_prelude(body.clone()),
),
));
e
})
}

/// Strips the `::cgp::macro_prelude::` prefix from the [`TokenStream`] so the
/// error message shows the more readable, unqualified paths. The replacement is
/// done at the token level, recursing into nested groups.
fn strip_macro_prelude(body: TokenStream) -> TokenStream {
// The prefix `::cgp::macro_prelude::` is made up of the following tokens.
fn is_prefix(tokens: &[TokenTree]) -> bool {
matches!(
tokens,
[
TokenTree::Punct(p1),
TokenTree::Punct(p2),
TokenTree::Ident(cgp),
TokenTree::Punct(p3),
TokenTree::Punct(p4),
TokenTree::Ident(prelude),
TokenTree::Punct(p5),
TokenTree::Punct(p6),
] if p1.as_char() == ':'
&& p2.as_char() == ':'
&& cgp == "cgp"
&& p3.as_char() == ':'
&& p4.as_char() == ':'
&& prelude == "macro_prelude"
&& p5.as_char() == ':'
&& p6.as_char() == ':'
)
}

const PREFIX_LEN: usize = 8;

let tokens: Vec<TokenTree> = body.into_iter().collect();
let mut output = Vec::with_capacity(tokens.len());
let mut i = 0;

while i < tokens.len() {
if is_prefix(&tokens[i..(i + PREFIX_LEN).min(tokens.len())]) {
i += PREFIX_LEN;
} else {
match &tokens[i] {
TokenTree::Group(group) => {
let inner = strip_macro_prelude(group.stream());
let mut new_group = Group::new(group.delimiter(), inner);
new_group.set_span(group.span());
output.push(TokenTree::Group(new_group));
}
other => output.push(other.clone()),
}
i += 1;
}
}

output.into_iter().collect()
}
1 change: 1 addition & 0 deletions crates/macros/cgp-macro-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ pub mod functions;
pub mod macros;
pub mod traits;
pub mod types;
pub mod vendor;
pub mod visitors;
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,3 @@ macro_rules! export_constructs {
$( $crate::export_construct! { $from $( => $to )* } )*
};
}

#[macro_export]
macro_rules! define_keyword {
( $struct_ident:ident, $value:literal ) => {
pub struct $struct_ident;

impl $crate::traits::IsKeyword for $struct_ident {
const IDENT: &'static str = $value;
}
};
}
10 changes: 10 additions & 0 deletions crates/macros/cgp-macro-core/src/macros/keyword.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[macro_export]
macro_rules! define_keyword {
( $struct_ident:ident, $value:literal ) => {
pub struct $struct_ident;

impl $crate::traits::IsKeyword for $struct_ident {
const IDENT: &'static str = $value;
}
};
}
5 changes: 5 additions & 0 deletions crates/macros/cgp-macro-core/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod export;
mod keyword;
mod parse;

pub use parse::*;
9 changes: 9 additions & 0 deletions crates/macros/cgp-macro-core/src/macros/parse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[macro_export]
macro_rules! parse_internal {
( $($body:tt)* ) => {
$crate::functions::parse_internal(
$crate::vendor::quote!( $( $body )* ))?
}
}

pub use parse_internal;
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use syn::parse::{Parse, ParseStream};
use syn::token::In;
use syn::{Generics, ItemImpl, Type, parse_quote};
use syn::{Generics, ItemImpl, Type};

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

Expand All @@ -23,14 +24,14 @@ impl DefaultImplAttribute {
namespace_trait_path
.type_args
.make_args()
.push(parse_quote!(__Components__));
.push(parse_internal!(__Components__));

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

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

let item_impl = parse_quote! {
let item_impl = parse_internal! {
impl #impl_generics #namespace_trait_path for #key_type
#where_clause
{
Expand Down
Loading
Loading