• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use proc_macro2::Span;
2 use syn::visit_mut::{self, VisitMut};
3 use syn::{GenericArgument, Lifetime, Receiver, TypeReference};
4 
5 pub struct CollectLifetimes {
6     pub elided: Vec<Lifetime>,
7     pub explicit: Vec<Lifetime>,
8     pub name: &'static str,
9     pub default_span: Span,
10 }
11 
12 impl CollectLifetimes {
new(name: &'static str, default_span: Span) -> Self13     pub fn new(name: &'static str, default_span: Span) -> Self {
14         CollectLifetimes {
15             elided: Vec::new(),
16             explicit: Vec::new(),
17             name,
18             default_span,
19         }
20     }
21 
visit_opt_lifetime(&mut self, lifetime: &mut Option<Lifetime>)22     fn visit_opt_lifetime(&mut self, lifetime: &mut Option<Lifetime>) {
23         match lifetime {
24             None => *lifetime = Some(self.next_lifetime(None)),
25             Some(lifetime) => self.visit_lifetime(lifetime),
26         }
27     }
28 
visit_lifetime(&mut self, lifetime: &mut Lifetime)29     fn visit_lifetime(&mut self, lifetime: &mut Lifetime) {
30         if lifetime.ident == "_" {
31             *lifetime = self.next_lifetime(lifetime.span());
32         } else {
33             self.explicit.push(lifetime.clone());
34         }
35     }
36 
next_lifetime<S: Into<Option<Span>>>(&mut self, span: S) -> Lifetime37     fn next_lifetime<S: Into<Option<Span>>>(&mut self, span: S) -> Lifetime {
38         let name = format!("{}{}", self.name, self.elided.len());
39         let span = span.into().unwrap_or(self.default_span);
40         let life = Lifetime::new(&name, span);
41         self.elided.push(life.clone());
42         life
43     }
44 }
45 
46 impl VisitMut for CollectLifetimes {
visit_receiver_mut(&mut self, arg: &mut Receiver)47     fn visit_receiver_mut(&mut self, arg: &mut Receiver) {
48         if let Some((_, lifetime)) = &mut arg.reference {
49             self.visit_opt_lifetime(lifetime);
50         }
51     }
52 
visit_type_reference_mut(&mut self, ty: &mut TypeReference)53     fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
54         self.visit_opt_lifetime(&mut ty.lifetime);
55         visit_mut::visit_type_reference_mut(self, ty);
56     }
57 
visit_generic_argument_mut(&mut self, gen: &mut GenericArgument)58     fn visit_generic_argument_mut(&mut self, gen: &mut GenericArgument) {
59         if let GenericArgument::Lifetime(lifetime) = gen {
60             self.visit_lifetime(lifetime);
61         }
62         visit_mut::visit_generic_argument_mut(self, gen);
63     }
64 }
65