From c48271aef7e6b0819c497f302127c161845a83d7 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 18 Mar 2023 17:14:42 +0100 Subject: refactor: rewrite the mock macro as a procedural macro --- macros/src/syn_ext.rs | 372 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 macros/src/syn_ext.rs (limited to 'macros/src/syn_ext.rs') diff --git a/macros/src/syn_ext.rs b/macros/src/syn_ext.rs new file mode 100644 index 0000000..7a3e9ae --- /dev/null +++ b/macros/src/syn_ext.rs @@ -0,0 +1,372 @@ +use proc_macro2::{Ident, Span, TokenStream}; +use quote::format_ident; +use syn::token::{Bracket, Paren}; +use syn::{ + AngleBracketedGenericArguments, + AttrStyle, + Attribute, + BareFnArg, + FnArg, + GenericArgument, + GenericParam, + Generics, + Lifetime, + Path, + PathArguments, + PathSegment, + ReturnType, + Signature, + Token, + Type, + TypeBareFn, + TypePath, + TypeReference, + VisRestricted, + Visibility, +}; + +pub trait GenericsExt: Sized +{ + fn without_where_clause(self) -> Self; +} + +impl GenericsExt for Generics +{ + fn without_where_clause(mut self) -> Self + { + self.where_clause = None; + + self + } +} + +pub trait AttributeExt: Sized +{ + fn new(style: AttributeStyle, path: Path, token_stream: TokenStream) -> Self; +} + +impl AttributeExt for Attribute +{ + fn new(style: AttributeStyle, path: Path, token_stream: TokenStream) -> Self + { + Self { + pound_token: ::default(), + style: style.into(), + bracket_token: Bracket::default(), + path, + tokens: token_stream, + } + } +} + +pub enum AttributeStyle +{ + /// A outer attribute. For example like `#[repr(C)]`. + Outer, + + /// A inner attribute. For example like `#![deny(clippy::all)]`. + Inner, +} + +impl From for AttrStyle +{ + fn from(style: AttributeStyle) -> Self + { + match style { + AttributeStyle::Outer => Self::Outer, + AttributeStyle::Inner => Self::Inner(::default()), + } + } +} + +pub trait VisibilityExt: Sized +{ + /// Returns a new `pub(crate)` visibility. + fn new_pub_crate() -> Self; +} + +impl VisibilityExt for Visibility +{ + fn new_pub_crate() -> Self + { + Self::Restricted(VisRestricted { + pub_token: ::default(), + paren_token: Paren::default(), + in_token: None, + path: Box::new(Path::new( + WithLeadingColons::No, + [PathSegment::new(format_ident!("crate"), None)], + )), + }) + } +} + +pub trait PathExt: Sized +{ + fn new( + with_leading_colons: WithLeadingColons, + segments: impl IntoIterator, + ) -> Self; +} + +impl PathExt for Path +{ + fn new( + with_leading_colons: WithLeadingColons, + segments: impl IntoIterator, + ) -> Self + { + Self { + leading_colon: match with_leading_colons { + WithLeadingColons::Yes => Some(::default()), + WithLeadingColons::No => None, + }, + segments: segments.into_iter().collect(), + } + } +} + +pub enum WithLeadingColons +{ + Yes, + No, +} + +pub trait PathSegmentExt: Sized +{ + fn new(ident: Ident, args: Option) -> Self; +} + +impl PathSegmentExt for PathSegment +{ + fn new(ident: Ident, args: Option) -> Self + { + Self { + ident, + arguments: args + .map_or_else(|| PathArguments::None, PathArguments::AngleBracketed), + } + } +} + +pub trait AngleBracketedGenericArgumentsExt: Sized +{ + fn new( + with_colons: WithColons, + generic_args: impl IntoIterator, + ) -> Self; +} + +impl AngleBracketedGenericArgumentsExt for AngleBracketedGenericArguments +{ + fn new( + with_colons: WithColons, + generic_args: impl IntoIterator, + ) -> Self + { + Self { + colon2_token: match with_colons { + WithColons::Yes => Some(::default()), + WithColons::No => None, + }, + lt_token: ::default(), + args: generic_args.into_iter().collect(), + gt_token: <::syn::Token![>]>::default(), + } + } +} + +pub enum WithColons +{ + Yes, + No, +} + +pub trait TypeReferenceExt: Sized +{ + fn new(lifetime: Option, is_mut: IsMut, inner_type: Type) -> Self; +} + +impl TypeReferenceExt for TypeReference +{ + fn new(lifetime: Option, is_mut: IsMut, inner_type: Type) -> Self + { + Self { + and_token: ::default(), + lifetime, + mutability: is_mut.into(), + elem: Box::new(inner_type), + } + } +} + +pub enum IsMut +{ + Yes, + No, +} + +impl From> for IsMut +{ + fn from(opt_mut: Option) -> Self + { + match opt_mut { + Some(_) => Self::Yes, + None => Self::No, + } + } +} + +impl From for Option +{ + fn from(is_mut: IsMut) -> Self + { + match is_mut { + IsMut::Yes => Some(Self::None.unwrap_or_default()), + IsMut::No => None, + } + } +} + +pub trait SignatureExt: Sized +{ + fn new( + ident: Ident, + generics: Generics, + inputs: impl IntoIterator, + output: ReturnType, + ) -> Self; +} + +impl SignatureExt for Signature +{ + fn new( + ident: Ident, + generics: Generics, + inputs: impl IntoIterator, + output: ReturnType, + ) -> Self + { + Self { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: ::default(), + ident, + generics, + paren_token: Paren::default(), + inputs: inputs.into_iter().collect(), + variadic: None, + output, + } + } +} + +pub trait ReturnTypeExt: Sized +{ + /// Returns a new `ReturnType::Type`. + fn new(ty: Type) -> Self; +} + +impl ReturnTypeExt for ReturnType +{ + fn new(ty: Type) -> Self + { + Self::Type(]>::default(), Box::new(ty)) + } +} + +pub trait GenericArgumentExt: Sized +{ + fn from_generic_param(generic_param: GenericParam) -> Self; +} + +impl GenericArgumentExt for GenericArgument +{ + fn from_generic_param(generic_param: GenericParam) -> Self + { + match generic_param { + GenericParam::Type(type_param) => { + GenericArgument::Type(Type::Path(TypePath::new(Path::new( + WithLeadingColons::No, + [PathSegment::new(type_param.ident, None)], + )))) + } + GenericParam::Lifetime(lifetime_param) => { + GenericArgument::Lifetime(lifetime_param.lifetime) + } + GenericParam::Const(_) => { + todo!(); + } + } + } +} + +pub trait TypePathExt: Sized +{ + fn new(path: Path) -> Self; +} + +impl TypePathExt for TypePath +{ + fn new(path: Path) -> Self + { + Self { qself: None, path } + } +} + +pub trait TypeBareFnExt: Sized +{ + fn new(inputs: impl IntoIterator, output: ReturnType) -> Self; +} + +impl TypeBareFnExt for TypeBareFn +{ + fn new(inputs: impl IntoIterator, output: ReturnType) -> Self + { + Self { + lifetimes: None, + unsafety: None, + abi: None, + fn_token: ::default(), + paren_token: Paren::default(), + inputs: inputs.into_iter().collect(), + variadic: None, + output, + } + } +} + +pub trait LifetimeExt: Sized +{ + fn create(ident: Ident) -> Self; +} + +impl LifetimeExt for Lifetime +{ + fn create(ident: Ident) -> Self + { + Self { + apostrophe: Span::call_site(), + ident, + } + } +} + +pub trait BareFnArgExt: Sized +{ + fn new(ty: Type) -> Self; +} + +impl BareFnArgExt for BareFnArg +{ + fn new(ty: Type) -> Self + { + Self { + attrs: vec![], + name: None, + ty, + } + } +} -- cgit v1.2.3-18-g5258