17e2e9c0cSopenharmony_ciuse crate::internals::respan::respan;
27e2e9c0cSopenharmony_ciuse proc_macro2::Span;
37e2e9c0cSopenharmony_ciuse quote::ToTokens;
47e2e9c0cSopenharmony_ciuse std::mem;
57e2e9c0cSopenharmony_ciuse syn::punctuated::Punctuated;
67e2e9c0cSopenharmony_ciuse syn::{
77e2e9c0cSopenharmony_ci    parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
87e2e9c0cSopenharmony_ci    Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
97e2e9c0cSopenharmony_ci};
107e2e9c0cSopenharmony_ci
117e2e9c0cSopenharmony_cipub fn replace_receiver(input: &mut DeriveInput) {
127e2e9c0cSopenharmony_ci    let self_ty = {
137e2e9c0cSopenharmony_ci        let ident = &input.ident;
147e2e9c0cSopenharmony_ci        let ty_generics = input.generics.split_for_impl().1;
157e2e9c0cSopenharmony_ci        parse_quote!(#ident #ty_generics)
167e2e9c0cSopenharmony_ci    };
177e2e9c0cSopenharmony_ci    let mut visitor = ReplaceReceiver(&self_ty);
187e2e9c0cSopenharmony_ci    visitor.visit_generics_mut(&mut input.generics);
197e2e9c0cSopenharmony_ci    visitor.visit_data_mut(&mut input.data);
207e2e9c0cSopenharmony_ci}
217e2e9c0cSopenharmony_ci
227e2e9c0cSopenharmony_cistruct ReplaceReceiver<'a>(&'a TypePath);
237e2e9c0cSopenharmony_ci
247e2e9c0cSopenharmony_ciimpl ReplaceReceiver<'_> {
257e2e9c0cSopenharmony_ci    fn self_ty(&self, span: Span) -> TypePath {
267e2e9c0cSopenharmony_ci        let tokens = self.0.to_token_stream();
277e2e9c0cSopenharmony_ci        let respanned = respan(tokens, span);
287e2e9c0cSopenharmony_ci        syn::parse2(respanned).unwrap()
297e2e9c0cSopenharmony_ci    }
307e2e9c0cSopenharmony_ci
317e2e9c0cSopenharmony_ci    fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
327e2e9c0cSopenharmony_ci        if path.leading_colon.is_some() || path.segments[0].ident != "Self" {
337e2e9c0cSopenharmony_ci            return;
347e2e9c0cSopenharmony_ci        }
357e2e9c0cSopenharmony_ci
367e2e9c0cSopenharmony_ci        if path.segments.len() == 1 {
377e2e9c0cSopenharmony_ci            self.self_to_expr_path(path);
387e2e9c0cSopenharmony_ci            return;
397e2e9c0cSopenharmony_ci        }
407e2e9c0cSopenharmony_ci
417e2e9c0cSopenharmony_ci        let span = path.segments[0].ident.span();
427e2e9c0cSopenharmony_ci        *qself = Some(QSelf {
437e2e9c0cSopenharmony_ci            lt_token: Token![<](span),
447e2e9c0cSopenharmony_ci            ty: Box::new(Type::Path(self.self_ty(span))),
457e2e9c0cSopenharmony_ci            position: 0,
467e2e9c0cSopenharmony_ci            as_token: None,
477e2e9c0cSopenharmony_ci            gt_token: Token![>](span),
487e2e9c0cSopenharmony_ci        });
497e2e9c0cSopenharmony_ci
507e2e9c0cSopenharmony_ci        path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
517e2e9c0cSopenharmony_ci
527e2e9c0cSopenharmony_ci        let segments = mem::replace(&mut path.segments, Punctuated::new());
537e2e9c0cSopenharmony_ci        path.segments = segments.into_pairs().skip(1).collect();
547e2e9c0cSopenharmony_ci    }
557e2e9c0cSopenharmony_ci
567e2e9c0cSopenharmony_ci    fn self_to_expr_path(&self, path: &mut Path) {
577e2e9c0cSopenharmony_ci        let self_ty = self.self_ty(path.segments[0].ident.span());
587e2e9c0cSopenharmony_ci        let variant = mem::replace(path, self_ty.path);
597e2e9c0cSopenharmony_ci        for segment in &mut path.segments {
607e2e9c0cSopenharmony_ci            if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
617e2e9c0cSopenharmony_ci                if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
627e2e9c0cSopenharmony_ci                    bracketed.colon2_token = Some(<Token![::]>::default());
637e2e9c0cSopenharmony_ci                }
647e2e9c0cSopenharmony_ci            }
657e2e9c0cSopenharmony_ci        }
667e2e9c0cSopenharmony_ci        if variant.segments.len() > 1 {
677e2e9c0cSopenharmony_ci            path.segments.push_punct(<Token![::]>::default());
687e2e9c0cSopenharmony_ci            path.segments.extend(variant.segments.into_pairs().skip(1));
697e2e9c0cSopenharmony_ci        }
707e2e9c0cSopenharmony_ci    }
717e2e9c0cSopenharmony_ci}
727e2e9c0cSopenharmony_ci
737e2e9c0cSopenharmony_ciimpl ReplaceReceiver<'_> {
747e2e9c0cSopenharmony_ci    // `Self` -> `Receiver`
757e2e9c0cSopenharmony_ci    fn visit_type_mut(&mut self, ty: &mut Type) {
767e2e9c0cSopenharmony_ci        let span = if let Type::Path(node) = ty {
777e2e9c0cSopenharmony_ci            if node.qself.is_none() && node.path.is_ident("Self") {
787e2e9c0cSopenharmony_ci                node.path.segments[0].ident.span()
797e2e9c0cSopenharmony_ci            } else {
807e2e9c0cSopenharmony_ci                self.visit_type_path_mut(node);
817e2e9c0cSopenharmony_ci                return;
827e2e9c0cSopenharmony_ci            }
837e2e9c0cSopenharmony_ci        } else {
847e2e9c0cSopenharmony_ci            self.visit_type_mut_impl(ty);
857e2e9c0cSopenharmony_ci            return;
867e2e9c0cSopenharmony_ci        };
877e2e9c0cSopenharmony_ci        *ty = self.self_ty(span).into();
887e2e9c0cSopenharmony_ci    }
897e2e9c0cSopenharmony_ci
907e2e9c0cSopenharmony_ci    // `Self::Assoc` -> `<Receiver>::Assoc`
917e2e9c0cSopenharmony_ci    fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
927e2e9c0cSopenharmony_ci        if ty.qself.is_none() {
937e2e9c0cSopenharmony_ci            self.self_to_qself(&mut ty.qself, &mut ty.path);
947e2e9c0cSopenharmony_ci        }
957e2e9c0cSopenharmony_ci        self.visit_type_path_mut_impl(ty);
967e2e9c0cSopenharmony_ci    }
977e2e9c0cSopenharmony_ci
987e2e9c0cSopenharmony_ci    // `Self::method` -> `<Receiver>::method`
997e2e9c0cSopenharmony_ci    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
1007e2e9c0cSopenharmony_ci        if expr.qself.is_none() {
1017e2e9c0cSopenharmony_ci            self.self_to_qself(&mut expr.qself, &mut expr.path);
1027e2e9c0cSopenharmony_ci        }
1037e2e9c0cSopenharmony_ci        self.visit_expr_path_mut_impl(expr);
1047e2e9c0cSopenharmony_ci    }
1057e2e9c0cSopenharmony_ci
1067e2e9c0cSopenharmony_ci    // Everything below is simply traversing the syntax tree.
1077e2e9c0cSopenharmony_ci
1087e2e9c0cSopenharmony_ci    fn visit_type_mut_impl(&mut self, ty: &mut Type) {
1097e2e9c0cSopenharmony_ci        match ty {
1107e2e9c0cSopenharmony_ci            #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1117e2e9c0cSopenharmony_ci            Type::Array(ty) => {
1127e2e9c0cSopenharmony_ci                self.visit_type_mut(&mut ty.elem);
1137e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut ty.len);
1147e2e9c0cSopenharmony_ci            }
1157e2e9c0cSopenharmony_ci            Type::BareFn(ty) => {
1167e2e9c0cSopenharmony_ci                for arg in &mut ty.inputs {
1177e2e9c0cSopenharmony_ci                    self.visit_type_mut(&mut arg.ty);
1187e2e9c0cSopenharmony_ci                }
1197e2e9c0cSopenharmony_ci                self.visit_return_type_mut(&mut ty.output);
1207e2e9c0cSopenharmony_ci            }
1217e2e9c0cSopenharmony_ci            Type::Group(ty) => self.visit_type_mut(&mut ty.elem),
1227e2e9c0cSopenharmony_ci            Type::ImplTrait(ty) => {
1237e2e9c0cSopenharmony_ci                for bound in &mut ty.bounds {
1247e2e9c0cSopenharmony_ci                    self.visit_type_param_bound_mut(bound);
1257e2e9c0cSopenharmony_ci                }
1267e2e9c0cSopenharmony_ci            }
1277e2e9c0cSopenharmony_ci            Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac),
1287e2e9c0cSopenharmony_ci            Type::Paren(ty) => self.visit_type_mut(&mut ty.elem),
1297e2e9c0cSopenharmony_ci            Type::Path(ty) => {
1307e2e9c0cSopenharmony_ci                if let Some(qself) = &mut ty.qself {
1317e2e9c0cSopenharmony_ci                    self.visit_type_mut(&mut qself.ty);
1327e2e9c0cSopenharmony_ci                }
1337e2e9c0cSopenharmony_ci                self.visit_path_mut(&mut ty.path);
1347e2e9c0cSopenharmony_ci            }
1357e2e9c0cSopenharmony_ci            Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem),
1367e2e9c0cSopenharmony_ci            Type::Reference(ty) => self.visit_type_mut(&mut ty.elem),
1377e2e9c0cSopenharmony_ci            Type::Slice(ty) => self.visit_type_mut(&mut ty.elem),
1387e2e9c0cSopenharmony_ci            Type::TraitObject(ty) => {
1397e2e9c0cSopenharmony_ci                for bound in &mut ty.bounds {
1407e2e9c0cSopenharmony_ci                    self.visit_type_param_bound_mut(bound);
1417e2e9c0cSopenharmony_ci                }
1427e2e9c0cSopenharmony_ci            }
1437e2e9c0cSopenharmony_ci            Type::Tuple(ty) => {
1447e2e9c0cSopenharmony_ci                for elem in &mut ty.elems {
1457e2e9c0cSopenharmony_ci                    self.visit_type_mut(elem);
1467e2e9c0cSopenharmony_ci                }
1477e2e9c0cSopenharmony_ci            }
1487e2e9c0cSopenharmony_ci
1497e2e9c0cSopenharmony_ci            Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
1507e2e9c0cSopenharmony_ci
1517e2e9c0cSopenharmony_ci            _ => {}
1527e2e9c0cSopenharmony_ci        }
1537e2e9c0cSopenharmony_ci    }
1547e2e9c0cSopenharmony_ci
1557e2e9c0cSopenharmony_ci    fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) {
1567e2e9c0cSopenharmony_ci        if let Some(qself) = &mut ty.qself {
1577e2e9c0cSopenharmony_ci            self.visit_type_mut(&mut qself.ty);
1587e2e9c0cSopenharmony_ci        }
1597e2e9c0cSopenharmony_ci        self.visit_path_mut(&mut ty.path);
1607e2e9c0cSopenharmony_ci    }
1617e2e9c0cSopenharmony_ci
1627e2e9c0cSopenharmony_ci    fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) {
1637e2e9c0cSopenharmony_ci        if let Some(qself) = &mut expr.qself {
1647e2e9c0cSopenharmony_ci            self.visit_type_mut(&mut qself.ty);
1657e2e9c0cSopenharmony_ci        }
1667e2e9c0cSopenharmony_ci        self.visit_path_mut(&mut expr.path);
1677e2e9c0cSopenharmony_ci    }
1687e2e9c0cSopenharmony_ci
1697e2e9c0cSopenharmony_ci    fn visit_path_mut(&mut self, path: &mut Path) {
1707e2e9c0cSopenharmony_ci        for segment in &mut path.segments {
1717e2e9c0cSopenharmony_ci            self.visit_path_arguments_mut(&mut segment.arguments);
1727e2e9c0cSopenharmony_ci        }
1737e2e9c0cSopenharmony_ci    }
1747e2e9c0cSopenharmony_ci
1757e2e9c0cSopenharmony_ci    fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) {
1767e2e9c0cSopenharmony_ci        match arguments {
1777e2e9c0cSopenharmony_ci            PathArguments::None => {}
1787e2e9c0cSopenharmony_ci            PathArguments::AngleBracketed(arguments) => {
1797e2e9c0cSopenharmony_ci                for arg in &mut arguments.args {
1807e2e9c0cSopenharmony_ci                    match arg {
1817e2e9c0cSopenharmony_ci                        #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1827e2e9c0cSopenharmony_ci                        GenericArgument::Type(arg) => self.visit_type_mut(arg),
1837e2e9c0cSopenharmony_ci                        GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
1847e2e9c0cSopenharmony_ci                        GenericArgument::Lifetime(_)
1857e2e9c0cSopenharmony_ci                        | GenericArgument::Const(_)
1867e2e9c0cSopenharmony_ci                        | GenericArgument::AssocConst(_)
1877e2e9c0cSopenharmony_ci                        | GenericArgument::Constraint(_) => {}
1887e2e9c0cSopenharmony_ci                        _ => {}
1897e2e9c0cSopenharmony_ci                    }
1907e2e9c0cSopenharmony_ci                }
1917e2e9c0cSopenharmony_ci            }
1927e2e9c0cSopenharmony_ci            PathArguments::Parenthesized(arguments) => {
1937e2e9c0cSopenharmony_ci                for argument in &mut arguments.inputs {
1947e2e9c0cSopenharmony_ci                    self.visit_type_mut(argument);
1957e2e9c0cSopenharmony_ci                }
1967e2e9c0cSopenharmony_ci                self.visit_return_type_mut(&mut arguments.output);
1977e2e9c0cSopenharmony_ci            }
1987e2e9c0cSopenharmony_ci        }
1997e2e9c0cSopenharmony_ci    }
2007e2e9c0cSopenharmony_ci
2017e2e9c0cSopenharmony_ci    fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) {
2027e2e9c0cSopenharmony_ci        match return_type {
2037e2e9c0cSopenharmony_ci            ReturnType::Default => {}
2047e2e9c0cSopenharmony_ci            ReturnType::Type(_, output) => self.visit_type_mut(output),
2057e2e9c0cSopenharmony_ci        }
2067e2e9c0cSopenharmony_ci    }
2077e2e9c0cSopenharmony_ci
2087e2e9c0cSopenharmony_ci    fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
2097e2e9c0cSopenharmony_ci        match bound {
2107e2e9c0cSopenharmony_ci            #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
2117e2e9c0cSopenharmony_ci            TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
2127e2e9c0cSopenharmony_ci            TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {}
2137e2e9c0cSopenharmony_ci            _ => {}
2147e2e9c0cSopenharmony_ci        }
2157e2e9c0cSopenharmony_ci    }
2167e2e9c0cSopenharmony_ci
2177e2e9c0cSopenharmony_ci    fn visit_generics_mut(&mut self, generics: &mut Generics) {
2187e2e9c0cSopenharmony_ci        for param in &mut generics.params {
2197e2e9c0cSopenharmony_ci            match param {
2207e2e9c0cSopenharmony_ci                GenericParam::Type(param) => {
2217e2e9c0cSopenharmony_ci                    for bound in &mut param.bounds {
2227e2e9c0cSopenharmony_ci                        self.visit_type_param_bound_mut(bound);
2237e2e9c0cSopenharmony_ci                    }
2247e2e9c0cSopenharmony_ci                }
2257e2e9c0cSopenharmony_ci                GenericParam::Lifetime(_) | GenericParam::Const(_) => {}
2267e2e9c0cSopenharmony_ci            }
2277e2e9c0cSopenharmony_ci        }
2287e2e9c0cSopenharmony_ci        if let Some(where_clause) = &mut generics.where_clause {
2297e2e9c0cSopenharmony_ci            for predicate in &mut where_clause.predicates {
2307e2e9c0cSopenharmony_ci                match predicate {
2317e2e9c0cSopenharmony_ci                    #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
2327e2e9c0cSopenharmony_ci                    WherePredicate::Type(predicate) => {
2337e2e9c0cSopenharmony_ci                        self.visit_type_mut(&mut predicate.bounded_ty);
2347e2e9c0cSopenharmony_ci                        for bound in &mut predicate.bounds {
2357e2e9c0cSopenharmony_ci                            self.visit_type_param_bound_mut(bound);
2367e2e9c0cSopenharmony_ci                        }
2377e2e9c0cSopenharmony_ci                    }
2387e2e9c0cSopenharmony_ci                    WherePredicate::Lifetime(_) => {}
2397e2e9c0cSopenharmony_ci                    _ => {}
2407e2e9c0cSopenharmony_ci                }
2417e2e9c0cSopenharmony_ci            }
2427e2e9c0cSopenharmony_ci        }
2437e2e9c0cSopenharmony_ci    }
2447e2e9c0cSopenharmony_ci
2457e2e9c0cSopenharmony_ci    fn visit_data_mut(&mut self, data: &mut Data) {
2467e2e9c0cSopenharmony_ci        match data {
2477e2e9c0cSopenharmony_ci            Data::Struct(data) => {
2487e2e9c0cSopenharmony_ci                for field in &mut data.fields {
2497e2e9c0cSopenharmony_ci                    self.visit_type_mut(&mut field.ty);
2507e2e9c0cSopenharmony_ci                }
2517e2e9c0cSopenharmony_ci            }
2527e2e9c0cSopenharmony_ci            Data::Enum(data) => {
2537e2e9c0cSopenharmony_ci                for variant in &mut data.variants {
2547e2e9c0cSopenharmony_ci                    for field in &mut variant.fields {
2557e2e9c0cSopenharmony_ci                        self.visit_type_mut(&mut field.ty);
2567e2e9c0cSopenharmony_ci                    }
2577e2e9c0cSopenharmony_ci                }
2587e2e9c0cSopenharmony_ci            }
2597e2e9c0cSopenharmony_ci            Data::Union(_) => {}
2607e2e9c0cSopenharmony_ci        }
2617e2e9c0cSopenharmony_ci    }
2627e2e9c0cSopenharmony_ci
2637e2e9c0cSopenharmony_ci    fn visit_expr_mut(&mut self, expr: &mut Expr) {
2647e2e9c0cSopenharmony_ci        match expr {
2657e2e9c0cSopenharmony_ci            Expr::Binary(expr) => {
2667e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut expr.left);
2677e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut expr.right);
2687e2e9c0cSopenharmony_ci            }
2697e2e9c0cSopenharmony_ci            Expr::Call(expr) => {
2707e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut expr.func);
2717e2e9c0cSopenharmony_ci                for arg in &mut expr.args {
2727e2e9c0cSopenharmony_ci                    self.visit_expr_mut(arg);
2737e2e9c0cSopenharmony_ci                }
2747e2e9c0cSopenharmony_ci            }
2757e2e9c0cSopenharmony_ci            Expr::Cast(expr) => {
2767e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut expr.expr);
2777e2e9c0cSopenharmony_ci                self.visit_type_mut(&mut expr.ty);
2787e2e9c0cSopenharmony_ci            }
2797e2e9c0cSopenharmony_ci            Expr::Field(expr) => self.visit_expr_mut(&mut expr.base),
2807e2e9c0cSopenharmony_ci            Expr::Index(expr) => {
2817e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut expr.expr);
2827e2e9c0cSopenharmony_ci                self.visit_expr_mut(&mut expr.index);
2837e2e9c0cSopenharmony_ci            }
2847e2e9c0cSopenharmony_ci            Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr),
2857e2e9c0cSopenharmony_ci            Expr::Path(expr) => self.visit_expr_path_mut(expr),
2867e2e9c0cSopenharmony_ci            Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr),
2877e2e9c0cSopenharmony_ci            _ => {}
2887e2e9c0cSopenharmony_ci        }
2897e2e9c0cSopenharmony_ci    }
2907e2e9c0cSopenharmony_ci
2917e2e9c0cSopenharmony_ci    fn visit_macro_mut(&mut self, _mac: &mut Macro) {}
2927e2e9c0cSopenharmony_ci}
293