derive/src/utils.rs
use proc_macro2::*;
use quote::*;
use syn::{visit_mut::*, *};
pub fn expr_strip(ty: &Type) -> TokenStream {
let stripped = strip_lifetimes(ty);
if let Type::Path(TypePath { qself: None, path }) = &stripped {
let mut path = path.clone();
for seg in path.segments.iter_mut() {
if let PathArguments::AngleBracketed(args) = &mut seg.arguments {
args.colon2_token = Some(syn::token::PathSep::default());
}
}
quote!(#path)
} else {
quote!(#stripped)
}
}
pub fn strip_lifetimes(ty: &Type) -> Type {
let mut ty = ty.clone();
StripLifetimes.visit_type_mut(&mut ty);
ty
}
struct StripLifetimes;
impl VisitMut for StripLifetimes {
fn visit_type_reference_mut(&mut self, node: &mut TypeReference) {
node.lifetime = None;
syn::visit_mut::visit_type_reference_mut(self, node);
}
fn visit_path_arguments_mut(&mut self, node: &mut PathArguments) {
if let PathArguments::AngleBracketed(args) = node {
let filtered: syn::punctuated::Punctuated<GenericArgument, Token![,]> = args
.args
.iter()
.filter(|arg| !matches!(arg, GenericArgument::Lifetime(_)))
.cloned()
.collect();
if filtered.is_empty() {
*node = PathArguments::None;
return;
} else {
args.args = filtered;
}
}
syn::visit_mut::visit_path_arguments_mut(self, node);
}
}