Austin Schuh | 6ea9bfa | 2023-08-06 19:05:10 -0700 | [diff] [blame^] | 1 | // Copyright 2023 Google LLC |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 4 | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 5 | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your |
| 6 | // option. This file may not be copied, modified, or distributed |
| 7 | // except according to those terms. |
| 8 | |
| 9 | //! Newtype wrappers for `syn` types implementing a different |
| 10 | //! `Debug` implementation that results in more concise output. |
| 11 | |
| 12 | use std::fmt::Display; |
| 13 | |
| 14 | use proc_macro2::TokenStream; |
| 15 | use quote::ToTokens; |
| 16 | use syn::punctuated::{Pair, Punctuated}; |
| 17 | |
| 18 | macro_rules! minisyn_no_parse { |
| 19 | ($syntype:ident) => { |
| 20 | /// Equivalent to the identically-named `syn` type except |
| 21 | /// that its `Debug` implementation is more concise. |
| 22 | #[derive(Clone, Hash, Eq, PartialEq)] |
| 23 | pub struct $syntype(pub ::syn::$syntype); |
| 24 | impl std::fmt::Debug for $syntype { |
| 25 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { |
| 26 | write!(f, "{}", self.0.to_token_stream().to_string()) |
| 27 | } |
| 28 | } |
| 29 | impl ToTokens for $syntype |
| 30 | where |
| 31 | ::syn::$syntype: ToTokens, |
| 32 | { |
| 33 | fn to_tokens(&self, tokens: &mut TokenStream) { |
| 34 | self.0.to_tokens(tokens) |
| 35 | } |
| 36 | |
| 37 | fn to_token_stream(&self) -> TokenStream { |
| 38 | self.0.to_token_stream() |
| 39 | } |
| 40 | fn into_token_stream(self) -> TokenStream |
| 41 | where |
| 42 | Self: Sized, |
| 43 | { |
| 44 | self.0.into_token_stream() |
| 45 | } |
| 46 | } |
| 47 | impl std::ops::Deref for $syntype { |
| 48 | type Target = ::syn::$syntype; |
| 49 | fn deref(&self) -> &Self::Target { |
| 50 | &self.0 |
| 51 | } |
| 52 | } |
| 53 | impl std::ops::DerefMut for $syntype { |
| 54 | fn deref_mut(&mut self) -> &mut Self::Target { |
| 55 | &mut self.0 |
| 56 | } |
| 57 | } |
| 58 | impl std::convert::From<::syn::$syntype> for $syntype { |
| 59 | fn from(inner: ::syn::$syntype) -> Self { |
| 60 | Self(inner) |
| 61 | } |
| 62 | } |
| 63 | impl std::convert::From<$syntype> for syn::$syntype { |
| 64 | fn from(inner: $syntype) -> Self { |
| 65 | inner.0 |
| 66 | } |
| 67 | } |
| 68 | }; |
| 69 | } |
| 70 | |
| 71 | macro_rules! minisyn { |
| 72 | ($syntype:ident) => { |
| 73 | minisyn_no_parse!($syntype); |
| 74 | |
| 75 | impl syn::parse::Parse for $syntype { |
| 76 | fn parse(input: syn::parse::ParseStream<'_>) -> syn::parse::Result<Self> { |
| 77 | syn::parse::Parse::parse(input).map(Self) |
| 78 | } |
| 79 | } |
| 80 | }; |
| 81 | } |
| 82 | |
| 83 | minisyn!(ItemMod); |
| 84 | minisyn_no_parse!(Attribute); |
| 85 | minisyn_no_parse!(AssocConst); |
| 86 | minisyn_no_parse!(AssocType); |
| 87 | minisyn!(Expr); |
| 88 | minisyn!(ExprAssign); |
| 89 | minisyn!(ExprAwait); |
| 90 | minisyn!(ExprBinary); |
| 91 | minisyn!(ExprBlock); |
| 92 | minisyn!(ExprBreak); |
| 93 | minisyn!(ExprConst); |
| 94 | minisyn!(ExprCast); |
| 95 | minisyn!(ExprField); |
| 96 | minisyn_no_parse!(ExprGroup); |
| 97 | minisyn!(ExprLet); |
| 98 | minisyn!(ExprParen); |
| 99 | minisyn!(ExprReference); |
| 100 | minisyn!(ExprTry); |
| 101 | minisyn!(ExprUnary); |
| 102 | minisyn_no_parse!(Field); |
| 103 | minisyn_no_parse!(Fields); |
| 104 | minisyn!(ForeignItem); |
| 105 | minisyn!(FnArg); |
| 106 | minisyn!(GenericArgument); |
| 107 | minisyn!(GenericParam); |
| 108 | minisyn!(Ident); |
| 109 | minisyn!(ImplItem); |
| 110 | minisyn!(Item); |
| 111 | minisyn!(ItemConst); |
| 112 | minisyn!(ItemEnum); |
| 113 | minisyn!(ItemForeignMod); |
| 114 | minisyn!(ItemStruct); |
| 115 | minisyn!(ItemType); |
| 116 | minisyn!(ItemUse); |
| 117 | minisyn!(LitBool); |
| 118 | minisyn!(LitInt); |
| 119 | minisyn!(Macro); |
| 120 | minisyn_no_parse!(Pat); |
| 121 | minisyn_no_parse!(PatType); |
| 122 | minisyn_no_parse!(PatReference); |
| 123 | minisyn_no_parse!(PatSlice); |
| 124 | minisyn_no_parse!(PatTuple); |
| 125 | minisyn!(Path); |
| 126 | minisyn_no_parse!(PathArguments); |
| 127 | minisyn!(PathSegment); |
| 128 | minisyn!(Receiver); |
| 129 | minisyn!(ReturnType); |
| 130 | minisyn!(Signature); |
| 131 | minisyn!(Stmt); |
| 132 | minisyn!(TraitItem); |
| 133 | minisyn!(Type); |
| 134 | minisyn!(TypeArray); |
| 135 | minisyn!(TypeGroup); |
| 136 | minisyn!(TypeParamBound); |
| 137 | minisyn!(TypeParen); |
| 138 | minisyn!(TypePath); |
| 139 | minisyn!(TypePtr); |
| 140 | minisyn!(TypeReference); |
| 141 | minisyn!(TypeSlice); |
| 142 | minisyn!(Visibility); |
| 143 | |
| 144 | /// Converts a `syn::Punctuated` from being full of `syn` types to being |
| 145 | /// full of `minisyn` types or vice-versa. |
| 146 | pub(crate) fn minisynize_punctuated<T1, T2, S>(input: Punctuated<T1, S>) -> Punctuated<T2, S> |
| 147 | where |
| 148 | T1: Into<T2>, |
| 149 | { |
| 150 | input |
| 151 | .into_pairs() |
| 152 | .map(|p| match p { |
| 153 | Pair::Punctuated(t, p) => Pair::Punctuated(t.into(), p), |
| 154 | Pair::End(t) => Pair::End(t.into()), |
| 155 | }) |
| 156 | .collect() |
| 157 | } |
| 158 | |
| 159 | /// Converts a `Vec` from being full of `syn` types to being |
| 160 | /// full of `minisyn` types or vice-versa. |
| 161 | pub(crate) fn minisynize_vec<T1, T2>(input: Vec<T1>) -> Vec<T2> |
| 162 | where |
| 163 | T1: Into<T2>, |
| 164 | { |
| 165 | input.into_iter().map(Into::into).collect() |
| 166 | } |
| 167 | |
| 168 | impl Ident { |
| 169 | pub(crate) fn new(string: &str, span: proc_macro2::Span) -> Self { |
| 170 | Self(syn::Ident::new(string, span)) |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | impl Display for Ident { |
| 175 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 176 | f.write_str(&self.0.to_string()) |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | impl<T> PartialEq<T> for Ident |
| 181 | where |
| 182 | T: AsRef<str> + ?Sized, |
| 183 | { |
| 184 | fn eq(&self, rhs: &T) -> bool { |
| 185 | self.0.eq(rhs) |
| 186 | } |
| 187 | } |