1 use crate::algorithm::Printer;
2 use crate::iter::IterDelimited;
3 use crate::INDENT;
4 use std::ptr;
5 use syn::{
6     AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, Expr, GenericArgument,
7     ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
8 };
9 
10 #[derive(Copy, Clone, PartialEq)]
11 pub enum PathKind {
12     // a::B
13     Simple,
14     // a::B<T>
15     Type,
16     // a::B::<T>
17     Expr,
18 }
19 
20 impl Printer {
path(&mut self, path: &Path, kind: PathKind)21     pub fn path(&mut self, path: &Path, kind: PathKind) {
22         assert!(!path.segments.is_empty());
23         for segment in path.segments.iter().delimited() {
24             if !segment.is_first || path.leading_colon.is_some() {
25                 self.word("::");
26             }
27             self.path_segment(&segment, kind);
28         }
29     }
30 
path_segment(&mut self, segment: &PathSegment, kind: PathKind)31     pub fn path_segment(&mut self, segment: &PathSegment, kind: PathKind) {
32         self.ident(&segment.ident);
33         self.path_arguments(&segment.arguments, kind);
34     }
35 
path_arguments(&mut self, arguments: &PathArguments, kind: PathKind)36     fn path_arguments(&mut self, arguments: &PathArguments, kind: PathKind) {
37         match arguments {
38             PathArguments::None => {}
39             PathArguments::AngleBracketed(arguments) => {
40                 self.angle_bracketed_generic_arguments(arguments, kind);
41             }
42             PathArguments::Parenthesized(arguments) => {
43                 self.parenthesized_generic_arguments(arguments);
44             }
45         }
46     }
47 
generic_argument(&mut self, arg: &GenericArgument)48     fn generic_argument(&mut self, arg: &GenericArgument) {
49         match arg {
50             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
51             GenericArgument::Lifetime(lifetime) => self.lifetime(lifetime),
52             GenericArgument::Type(ty) => self.ty(ty),
53             GenericArgument::Const(expr) => {
54                 match expr {
55                     #![cfg_attr(all(test, exhaustive), allow(non_exhaustive_omitted_patterns))]
56                     Expr::Lit(expr) => self.expr_lit(expr),
57                     Expr::Block(expr) => self.expr_block(expr),
58                     // ERROR CORRECTION: Add braces to make sure that the
59                     // generated code is valid.
60                     _ => {
61                         self.word("{");
62                         self.expr(expr);
63                         self.word("}");
64                     }
65                 }
66             }
67             GenericArgument::AssocType(assoc) => self.assoc_type(assoc),
68             GenericArgument::AssocConst(assoc) => self.assoc_const(assoc),
69             GenericArgument::Constraint(constraint) => self.constraint(constraint),
70             _ => unimplemented!("unknown GenericArgument"),
71         }
72     }
73 
angle_bracketed_generic_arguments( &mut self, generic: &AngleBracketedGenericArguments, path_kind: PathKind, )74     pub fn angle_bracketed_generic_arguments(
75         &mut self,
76         generic: &AngleBracketedGenericArguments,
77         path_kind: PathKind,
78     ) {
79         if generic.args.is_empty() || path_kind == PathKind::Simple {
80             return;
81         }
82 
83         if path_kind == PathKind::Expr {
84             self.word("::");
85         }
86         self.word("<");
87         self.cbox(INDENT);
88         self.zerobreak();
89 
90         // Print lifetimes before types/consts/bindings, regardless of their
91         // order in self.args.
92         #[derive(Ord, PartialOrd, Eq, PartialEq)]
93         enum Group {
94             First,
95             Second,
96         }
97         fn group(arg: &GenericArgument) -> Group {
98             match arg {
99                 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
100                 GenericArgument::Lifetime(_) => Group::First,
101                 GenericArgument::Type(_)
102                 | GenericArgument::Const(_)
103                 | GenericArgument::AssocType(_)
104                 | GenericArgument::AssocConst(_)
105                 | GenericArgument::Constraint(_) => Group::Second,
106                 _ => Group::Second,
107             }
108         }
109         let last = generic.args.iter().max_by_key(|param| group(param));
110         for current_group in [Group::First, Group::Second] {
111             for arg in &generic.args {
112                 if group(arg) == current_group {
113                     self.generic_argument(arg);
114                     self.trailing_comma(ptr::eq(arg, last.unwrap()));
115                 }
116             }
117         }
118 
119         self.offset(-INDENT);
120         self.end();
121         self.word(">");
122     }
123 
assoc_type(&mut self, assoc: &AssocType)124     fn assoc_type(&mut self, assoc: &AssocType) {
125         self.ident(&assoc.ident);
126         if let Some(generics) = &assoc.generics {
127             self.angle_bracketed_generic_arguments(generics, PathKind::Type);
128         }
129         self.word(" = ");
130         self.ty(&assoc.ty);
131     }
132 
assoc_const(&mut self, assoc: &AssocConst)133     fn assoc_const(&mut self, assoc: &AssocConst) {
134         self.ident(&assoc.ident);
135         if let Some(generics) = &assoc.generics {
136             self.angle_bracketed_generic_arguments(generics, PathKind::Type);
137         }
138         self.word(" = ");
139         self.expr(&assoc.value);
140     }
141 
constraint(&mut self, constraint: &Constraint)142     fn constraint(&mut self, constraint: &Constraint) {
143         self.ident(&constraint.ident);
144         if let Some(generics) = &constraint.generics {
145             self.angle_bracketed_generic_arguments(generics, PathKind::Type);
146         }
147         self.ibox(INDENT);
148         for bound in constraint.bounds.iter().delimited() {
149             if bound.is_first {
150                 self.word(": ");
151             } else {
152                 self.space();
153                 self.word("+ ");
154             }
155             self.type_param_bound(&bound);
156         }
157         self.end();
158     }
159 
parenthesized_generic_arguments(&mut self, arguments: &ParenthesizedGenericArguments)160     fn parenthesized_generic_arguments(&mut self, arguments: &ParenthesizedGenericArguments) {
161         self.cbox(INDENT);
162         self.word("(");
163         self.zerobreak();
164         for ty in arguments.inputs.iter().delimited() {
165             self.ty(&ty);
166             self.trailing_comma(ty.is_last);
167         }
168         self.offset(-INDENT);
169         self.word(")");
170         self.return_type(&arguments.output);
171         self.end();
172     }
173 
qpath(&mut self, qself: &Option<QSelf>, path: &Path, kind: PathKind)174     pub fn qpath(&mut self, qself: &Option<QSelf>, path: &Path, kind: PathKind) {
175         let qself = match qself {
176             Some(qself) => qself,
177             None => {
178                 self.path(path, kind);
179                 return;
180             }
181         };
182 
183         assert!(qself.position < path.segments.len());
184 
185         self.word("<");
186         self.ty(&qself.ty);
187 
188         let mut segments = path.segments.iter();
189         if qself.position > 0 {
190             self.word(" as ");
191             for segment in segments.by_ref().take(qself.position).delimited() {
192                 if !segment.is_first || path.leading_colon.is_some() {
193                     self.word("::");
194                 }
195                 self.path_segment(&segment, PathKind::Type);
196                 if segment.is_last {
197                     self.word(">");
198                 }
199             }
200         } else {
201             self.word(">");
202         }
203         for segment in segments {
204             self.word("::");
205             self.path_segment(segment, kind);
206         }
207     }
208 }
209