• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::internals::respan::respan;
2 use proc_macro2::Span;
3 use quote::ToTokens;
4 use std::mem;
5 use syn::{
6     parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
7     Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
8 };
9 
replace_receiver(input: &mut DeriveInput)10 pub fn replace_receiver(input: &mut DeriveInput) {
11     let self_ty = {
12         let ident = &input.ident;
13         let ty_generics = input.generics.split_for_impl().1;
14         parse_quote!(#ident #ty_generics)
15     };
16     let mut visitor = ReplaceReceiver(&self_ty);
17     visitor.visit_generics_mut(&mut input.generics);
18     visitor.visit_data_mut(&mut input.data);
19 }
20 
21 struct ReplaceReceiver<'a>(&'a TypePath);
22 
23 impl ReplaceReceiver<'_> {
self_ty(&self, span: Span) -> TypePath24     fn self_ty(&self, span: Span) -> TypePath {
25         let tokens = self.0.to_token_stream();
26         let respanned = respan(tokens, span);
27         syn::parse2(respanned).unwrap()
28     }
29 
self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path)30     fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
31         if path.leading_colon.is_some() || path.segments[0].ident != "Self" {
32             return;
33         }
34 
35         if path.segments.len() == 1 {
36             self.self_to_expr_path(path);
37             return;
38         }
39 
40         let span = path.segments[0].ident.span();
41         *qself = Some(QSelf {
42             lt_token: Token![<](span),
43             ty: Box::new(Type::Path(self.self_ty(span))),
44             position: 0,
45             as_token: None,
46             gt_token: Token![>](span),
47         });
48 
49         path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
50 
51         let segments = mem::take(&mut path.segments);
52         path.segments = segments.into_pairs().skip(1).collect();
53     }
54 
self_to_expr_path(&self, path: &mut Path)55     fn self_to_expr_path(&self, path: &mut Path) {
56         let self_ty = self.self_ty(path.segments[0].ident.span());
57         let variant = mem::replace(path, self_ty.path);
58         for segment in &mut path.segments {
59             if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
60                 if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
61                     bracketed.colon2_token = Some(<Token![::]>::default());
62                 }
63             }
64         }
65         if variant.segments.len() > 1 {
66             path.segments.push_punct(<Token![::]>::default());
67             path.segments.extend(variant.segments.into_pairs().skip(1));
68         }
69     }
70 }
71 
72 impl ReplaceReceiver<'_> {
73     // `Self` -> `Receiver`
visit_type_mut(&mut self, ty: &mut Type)74     fn visit_type_mut(&mut self, ty: &mut Type) {
75         let span = if let Type::Path(node) = ty {
76             if node.qself.is_none() && node.path.is_ident("Self") {
77                 node.path.segments[0].ident.span()
78             } else {
79                 self.visit_type_path_mut(node);
80                 return;
81             }
82         } else {
83             self.visit_type_mut_impl(ty);
84             return;
85         };
86         *ty = Type::Path(self.self_ty(span));
87     }
88 
89     // `Self::Assoc` -> `<Receiver>::Assoc`
visit_type_path_mut(&mut self, ty: &mut TypePath)90     fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
91         if ty.qself.is_none() {
92             self.self_to_qself(&mut ty.qself, &mut ty.path);
93         }
94         self.visit_type_path_mut_impl(ty);
95     }
96 
97     // `Self::method` -> `<Receiver>::method`
visit_expr_path_mut(&mut self, expr: &mut ExprPath)98     fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
99         if expr.qself.is_none() {
100             self.self_to_qself(&mut expr.qself, &mut expr.path);
101         }
102         self.visit_expr_path_mut_impl(expr);
103     }
104 
105     // Everything below is simply traversing the syntax tree.
106 
visit_type_mut_impl(&mut self, ty: &mut Type)107     fn visit_type_mut_impl(&mut self, ty: &mut Type) {
108         match ty {
109             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
110             Type::Array(ty) => {
111                 self.visit_type_mut(&mut ty.elem);
112                 self.visit_expr_mut(&mut ty.len);
113             }
114             Type::BareFn(ty) => {
115                 for arg in &mut ty.inputs {
116                     self.visit_type_mut(&mut arg.ty);
117                 }
118                 self.visit_return_type_mut(&mut ty.output);
119             }
120             Type::Group(ty) => self.visit_type_mut(&mut ty.elem),
121             Type::ImplTrait(ty) => {
122                 for bound in &mut ty.bounds {
123                     self.visit_type_param_bound_mut(bound);
124                 }
125             }
126             Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac),
127             Type::Paren(ty) => self.visit_type_mut(&mut ty.elem),
128             Type::Path(ty) => {
129                 if let Some(qself) = &mut ty.qself {
130                     self.visit_type_mut(&mut qself.ty);
131                 }
132                 self.visit_path_mut(&mut ty.path);
133             }
134             Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem),
135             Type::Reference(ty) => self.visit_type_mut(&mut ty.elem),
136             Type::Slice(ty) => self.visit_type_mut(&mut ty.elem),
137             Type::TraitObject(ty) => {
138                 for bound in &mut ty.bounds {
139                     self.visit_type_param_bound_mut(bound);
140                 }
141             }
142             Type::Tuple(ty) => {
143                 for elem in &mut ty.elems {
144                     self.visit_type_mut(elem);
145                 }
146             }
147 
148             Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
149 
150             _ => {}
151         }
152     }
153 
visit_type_path_mut_impl(&mut self, ty: &mut TypePath)154     fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) {
155         if let Some(qself) = &mut ty.qself {
156             self.visit_type_mut(&mut qself.ty);
157         }
158         self.visit_path_mut(&mut ty.path);
159     }
160 
visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath)161     fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) {
162         if let Some(qself) = &mut expr.qself {
163             self.visit_type_mut(&mut qself.ty);
164         }
165         self.visit_path_mut(&mut expr.path);
166     }
167 
visit_path_mut(&mut self, path: &mut Path)168     fn visit_path_mut(&mut self, path: &mut Path) {
169         for segment in &mut path.segments {
170             self.visit_path_arguments_mut(&mut segment.arguments);
171         }
172     }
173 
visit_path_arguments_mut(&mut self, arguments: &mut PathArguments)174     fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) {
175         match arguments {
176             PathArguments::None => {}
177             PathArguments::AngleBracketed(arguments) => {
178                 for arg in &mut arguments.args {
179                     match arg {
180                         #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
181                         GenericArgument::Type(arg) => self.visit_type_mut(arg),
182                         GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
183                         GenericArgument::Lifetime(_)
184                         | GenericArgument::Const(_)
185                         | GenericArgument::AssocConst(_)
186                         | GenericArgument::Constraint(_) => {}
187                         _ => {}
188                     }
189                 }
190             }
191             PathArguments::Parenthesized(arguments) => {
192                 for argument in &mut arguments.inputs {
193                     self.visit_type_mut(argument);
194                 }
195                 self.visit_return_type_mut(&mut arguments.output);
196             }
197         }
198     }
199 
visit_return_type_mut(&mut self, return_type: &mut ReturnType)200     fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) {
201         match return_type {
202             ReturnType::Default => {}
203             ReturnType::Type(_, output) => self.visit_type_mut(output),
204         }
205     }
206 
visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound)207     fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
208         match bound {
209             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
210             TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
211             TypeParamBound::Lifetime(_)
212             | TypeParamBound::PreciseCapture(_)
213             | TypeParamBound::Verbatim(_) => {}
214             _ => {}
215         }
216     }
217 
visit_generics_mut(&mut self, generics: &mut Generics)218     fn visit_generics_mut(&mut self, generics: &mut Generics) {
219         for param in &mut generics.params {
220             match param {
221                 GenericParam::Type(param) => {
222                     for bound in &mut param.bounds {
223                         self.visit_type_param_bound_mut(bound);
224                     }
225                 }
226                 GenericParam::Lifetime(_) | GenericParam::Const(_) => {}
227             }
228         }
229         if let Some(where_clause) = &mut generics.where_clause {
230             for predicate in &mut where_clause.predicates {
231                 match predicate {
232                     #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
233                     WherePredicate::Type(predicate) => {
234                         self.visit_type_mut(&mut predicate.bounded_ty);
235                         for bound in &mut predicate.bounds {
236                             self.visit_type_param_bound_mut(bound);
237                         }
238                     }
239                     WherePredicate::Lifetime(_) => {}
240                     _ => {}
241                 }
242             }
243         }
244     }
245 
visit_data_mut(&mut self, data: &mut Data)246     fn visit_data_mut(&mut self, data: &mut Data) {
247         match data {
248             Data::Struct(data) => {
249                 for field in &mut data.fields {
250                     self.visit_type_mut(&mut field.ty);
251                 }
252             }
253             Data::Enum(data) => {
254                 for variant in &mut data.variants {
255                     for field in &mut variant.fields {
256                         self.visit_type_mut(&mut field.ty);
257                     }
258                 }
259             }
260             Data::Union(_) => {}
261         }
262     }
263 
visit_expr_mut(&mut self, expr: &mut Expr)264     fn visit_expr_mut(&mut self, expr: &mut Expr) {
265         match expr {
266             Expr::Binary(expr) => {
267                 self.visit_expr_mut(&mut expr.left);
268                 self.visit_expr_mut(&mut expr.right);
269             }
270             Expr::Call(expr) => {
271                 self.visit_expr_mut(&mut expr.func);
272                 for arg in &mut expr.args {
273                     self.visit_expr_mut(arg);
274                 }
275             }
276             Expr::Cast(expr) => {
277                 self.visit_expr_mut(&mut expr.expr);
278                 self.visit_type_mut(&mut expr.ty);
279             }
280             Expr::Field(expr) => self.visit_expr_mut(&mut expr.base),
281             Expr::Index(expr) => {
282                 self.visit_expr_mut(&mut expr.expr);
283                 self.visit_expr_mut(&mut expr.index);
284             }
285             Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr),
286             Expr::Path(expr) => self.visit_expr_path_mut(expr),
287             Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr),
288             _ => {}
289         }
290     }
291 
visit_macro_mut(&mut self, _mac: &mut Macro)292     fn visit_macro_mut(&mut self, _mac: &mut Macro) {}
293 }
294