blob: e675baad25bbe0af61718252791f697be2c5873a [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Newtype wrappers for `syn` types implementing a different
//! `Debug` implementation that results in more concise output.
use std::fmt::Display;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::punctuated::{Pair, Punctuated};
macro_rules! minisyn_no_parse {
($syntype:ident) => {
/// Equivalent to the identically-named `syn` type except
/// that its `Debug` implementation is more concise.
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct $syntype(pub ::syn::$syntype);
impl std::fmt::Debug for $syntype {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{}", self.0.to_token_stream().to_string())
}
}
impl ToTokens for $syntype
where
::syn::$syntype: ToTokens,
{
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens)
}
fn to_token_stream(&self) -> TokenStream {
self.0.to_token_stream()
}
fn into_token_stream(self) -> TokenStream
where
Self: Sized,
{
self.0.into_token_stream()
}
}
impl std::ops::Deref for $syntype {
type Target = ::syn::$syntype;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for $syntype {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl std::convert::From<::syn::$syntype> for $syntype {
fn from(inner: ::syn::$syntype) -> Self {
Self(inner)
}
}
impl std::convert::From<$syntype> for syn::$syntype {
fn from(inner: $syntype) -> Self {
inner.0
}
}
};
}
macro_rules! minisyn {
($syntype:ident) => {
minisyn_no_parse!($syntype);
impl syn::parse::Parse for $syntype {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::parse::Result<Self> {
syn::parse::Parse::parse(input).map(Self)
}
}
};
}
minisyn!(ItemMod);
minisyn_no_parse!(Attribute);
minisyn_no_parse!(AssocConst);
minisyn_no_parse!(AssocType);
minisyn!(Expr);
minisyn!(ExprAssign);
minisyn!(ExprAwait);
minisyn!(ExprBinary);
minisyn!(ExprBlock);
minisyn!(ExprBreak);
minisyn!(ExprConst);
minisyn!(ExprCast);
minisyn!(ExprField);
minisyn_no_parse!(ExprGroup);
minisyn!(ExprLet);
minisyn!(ExprParen);
minisyn!(ExprReference);
minisyn!(ExprTry);
minisyn!(ExprUnary);
minisyn_no_parse!(Field);
minisyn_no_parse!(Fields);
minisyn!(ForeignItem);
minisyn!(FnArg);
minisyn!(GenericArgument);
minisyn!(GenericParam);
minisyn!(Ident);
minisyn!(ImplItem);
minisyn!(Item);
minisyn!(ItemConst);
minisyn!(ItemEnum);
minisyn!(ItemForeignMod);
minisyn!(ItemStruct);
minisyn!(ItemType);
minisyn!(ItemUse);
minisyn!(LitBool);
minisyn!(LitInt);
minisyn!(Macro);
minisyn_no_parse!(Pat);
minisyn_no_parse!(PatType);
minisyn_no_parse!(PatReference);
minisyn_no_parse!(PatSlice);
minisyn_no_parse!(PatTuple);
minisyn!(Path);
minisyn_no_parse!(PathArguments);
minisyn!(PathSegment);
minisyn!(Receiver);
minisyn!(ReturnType);
minisyn!(Signature);
minisyn!(Stmt);
minisyn!(TraitItem);
minisyn!(Type);
minisyn!(TypeArray);
minisyn!(TypeGroup);
minisyn!(TypeParamBound);
minisyn!(TypeParen);
minisyn!(TypePath);
minisyn!(TypePtr);
minisyn!(TypeReference);
minisyn!(TypeSlice);
minisyn!(Visibility);
/// Converts a `syn::Punctuated` from being full of `syn` types to being
/// full of `minisyn` types or vice-versa.
pub(crate) fn minisynize_punctuated<T1, T2, S>(input: Punctuated<T1, S>) -> Punctuated<T2, S>
where
T1: Into<T2>,
{
input
.into_pairs()
.map(|p| match p {
Pair::Punctuated(t, p) => Pair::Punctuated(t.into(), p),
Pair::End(t) => Pair::End(t.into()),
})
.collect()
}
/// Converts a `Vec` from being full of `syn` types to being
/// full of `minisyn` types or vice-versa.
pub(crate) fn minisynize_vec<T1, T2>(input: Vec<T1>) -> Vec<T2>
where
T1: Into<T2>,
{
input.into_iter().map(Into::into).collect()
}
impl Ident {
pub(crate) fn new(string: &str, span: proc_macro2::Span) -> Self {
Self(syn::Ident::new(string, span))
}
}
impl Display for Ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0.to_string())
}
}
impl<T> PartialEq<T> for Ident
where
T: AsRef<str> + ?Sized,
{
fn eq(&self, rhs: &T) -> bool {
self.0.eq(rhs)
}
}