1 use crate::algorithm::Printer;
2 use crate::iter::IterDelimited;
3 use crate::path::PathKind;
4 use crate::INDENT;
5 use proc_macro2::TokenStream;
6 use std::ptr;
7 use syn::{
8     BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
9     PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
10     WherePredicate,
11 };
12 
13 impl Printer {
generics(&mut self, generics: &Generics)14     pub fn generics(&mut self, generics: &Generics) {
15         if generics.params.is_empty() {
16             return;
17         }
18 
19         self.word("<");
20         self.cbox(0);
21         self.zerobreak();
22 
23         // Print lifetimes before types and consts, regardless of their
24         // order in self.params.
25         #[derive(Ord, PartialOrd, Eq, PartialEq)]
26         enum Group {
27             First,
28             Second,
29         }
30         fn group(param: &GenericParam) -> Group {
31             match param {
32                 GenericParam::Lifetime(_) => Group::First,
33                 GenericParam::Type(_) | GenericParam::Const(_) => Group::Second,
34             }
35         }
36         let last = generics.params.iter().max_by_key(|param| group(param));
37         for current_group in [Group::First, Group::Second] {
38             for param in &generics.params {
39                 if group(param) == current_group {
40                     self.generic_param(param);
41                     self.trailing_comma(ptr::eq(param, last.unwrap()));
42                 }
43             }
44         }
45 
46         self.offset(-INDENT);
47         self.end();
48         self.word(">");
49     }
50 
generic_param(&mut self, generic_param: &GenericParam)51     fn generic_param(&mut self, generic_param: &GenericParam) {
52         match generic_param {
53             GenericParam::Type(type_param) => self.type_param(type_param),
54             GenericParam::Lifetime(lifetime_param) => self.lifetime_param(lifetime_param),
55             GenericParam::Const(const_param) => self.const_param(const_param),
56         }
57     }
58 
bound_lifetimes(&mut self, bound_lifetimes: &BoundLifetimes)59     pub fn bound_lifetimes(&mut self, bound_lifetimes: &BoundLifetimes) {
60         self.word("for<");
61         for param in bound_lifetimes.lifetimes.iter().delimited() {
62             self.generic_param(&param);
63             if !param.is_last {
64                 self.word(", ");
65             }
66         }
67         self.word("> ");
68     }
69 
lifetime_param(&mut self, lifetime_param: &LifetimeParam)70     fn lifetime_param(&mut self, lifetime_param: &LifetimeParam) {
71         self.outer_attrs(&lifetime_param.attrs);
72         self.lifetime(&lifetime_param.lifetime);
73         for lifetime in lifetime_param.bounds.iter().delimited() {
74             if lifetime.is_first {
75                 self.word(": ");
76             } else {
77                 self.word(" + ");
78             }
79             self.lifetime(&lifetime);
80         }
81     }
82 
type_param(&mut self, type_param: &TypeParam)83     fn type_param(&mut self, type_param: &TypeParam) {
84         self.outer_attrs(&type_param.attrs);
85         self.ident(&type_param.ident);
86         self.ibox(INDENT);
87         for type_param_bound in type_param.bounds.iter().delimited() {
88             if type_param_bound.is_first {
89                 self.word(": ");
90             } else {
91                 self.space();
92                 self.word("+ ");
93             }
94             self.type_param_bound(&type_param_bound);
95         }
96         if let Some(default) = &type_param.default {
97             self.space();
98             self.word("= ");
99             self.ty(default);
100         }
101         self.end();
102     }
103 
type_param_bound(&mut self, type_param_bound: &TypeParamBound)104     pub fn type_param_bound(&mut self, type_param_bound: &TypeParamBound) {
105         match type_param_bound {
106             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
107             TypeParamBound::Trait(trait_bound) => {
108                 let tilde_const = false;
109                 self.trait_bound(trait_bound, tilde_const);
110             }
111             TypeParamBound::Lifetime(lifetime) => self.lifetime(lifetime),
112             TypeParamBound::Verbatim(bound) => self.type_param_bound_verbatim(bound),
113             _ => unimplemented!("unknown TypeParamBound"),
114         }
115     }
116 
trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool)117     fn trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool) {
118         if trait_bound.paren_token.is_some() {
119             self.word("(");
120         }
121         if tilde_const {
122             self.word("~const ");
123         }
124         self.trait_bound_modifier(&trait_bound.modifier);
125         if let Some(bound_lifetimes) = &trait_bound.lifetimes {
126             self.bound_lifetimes(bound_lifetimes);
127         }
128         for segment in trait_bound.path.segments.iter().delimited() {
129             if !segment.is_first || trait_bound.path.leading_colon.is_some() {
130                 self.word("::");
131             }
132             self.path_segment(&segment, PathKind::Type);
133         }
134         if trait_bound.paren_token.is_some() {
135             self.word(")");
136         }
137     }
138 
trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier)139     fn trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier) {
140         match trait_bound_modifier {
141             TraitBoundModifier::None => {}
142             TraitBoundModifier::Maybe(_question_mark) => self.word("?"),
143         }
144     }
145 
146     #[cfg(not(feature = "verbatim"))]
type_param_bound_verbatim(&mut self, bound: &TokenStream)147     fn type_param_bound_verbatim(&mut self, bound: &TokenStream) {
148         unimplemented!("TypeParamBound::Verbatim `{}`", bound);
149     }
150 
151     #[cfg(feature = "verbatim")]
type_param_bound_verbatim(&mut self, tokens: &TokenStream)152     fn type_param_bound_verbatim(&mut self, tokens: &TokenStream) {
153         use syn::parse::{Parse, ParseStream, Result};
154         use syn::{parenthesized, token, Token};
155 
156         enum TypeParamBoundVerbatim {
157             Ellipsis,
158             TildeConst(TraitBound),
159         }
160 
161         impl Parse for TypeParamBoundVerbatim {
162             fn parse(input: ParseStream) -> Result<Self> {
163                 let content;
164                 let (paren_token, content) = if input.peek(token::Paren) {
165                     (Some(parenthesized!(content in input)), &content)
166                 } else {
167                     (None, input)
168                 };
169                 let lookahead = content.lookahead1();
170                 if lookahead.peek(Token![~]) {
171                     content.parse::<Token![~]>()?;
172                     content.parse::<Token![const]>()?;
173                     let mut bound: TraitBound = content.parse()?;
174                     bound.paren_token = paren_token;
175                     Ok(TypeParamBoundVerbatim::TildeConst(bound))
176                 } else if lookahead.peek(Token![...]) {
177                     content.parse::<Token![...]>()?;
178                     Ok(TypeParamBoundVerbatim::Ellipsis)
179                 } else {
180                     Err(lookahead.error())
181                 }
182             }
183         }
184 
185         let bound: TypeParamBoundVerbatim = match syn::parse2(tokens.clone()) {
186             Ok(bound) => bound,
187             Err(_) => unimplemented!("TypeParamBound::Verbatim `{}`", tokens),
188         };
189 
190         match bound {
191             TypeParamBoundVerbatim::Ellipsis => {
192                 self.word("...");
193             }
194             TypeParamBoundVerbatim::TildeConst(trait_bound) => {
195                 let tilde_const = true;
196                 self.trait_bound(&trait_bound, tilde_const);
197             }
198         }
199     }
200 
const_param(&mut self, const_param: &ConstParam)201     fn const_param(&mut self, const_param: &ConstParam) {
202         self.outer_attrs(&const_param.attrs);
203         self.word("const ");
204         self.ident(&const_param.ident);
205         self.word(": ");
206         self.ty(&const_param.ty);
207         if let Some(default) = &const_param.default {
208             self.word(" = ");
209             self.expr(default);
210         }
211     }
212 
where_clause_for_body(&mut self, where_clause: &Option<WhereClause>)213     pub fn where_clause_for_body(&mut self, where_clause: &Option<WhereClause>) {
214         let hardbreaks = true;
215         let semi = false;
216         self.where_clause_impl(where_clause, hardbreaks, semi);
217     }
218 
where_clause_semi(&mut self, where_clause: &Option<WhereClause>)219     pub fn where_clause_semi(&mut self, where_clause: &Option<WhereClause>) {
220         let hardbreaks = true;
221         let semi = true;
222         self.where_clause_impl(where_clause, hardbreaks, semi);
223     }
224 
where_clause_oneline(&mut self, where_clause: &Option<WhereClause>)225     pub fn where_clause_oneline(&mut self, where_clause: &Option<WhereClause>) {
226         let hardbreaks = false;
227         let semi = false;
228         self.where_clause_impl(where_clause, hardbreaks, semi);
229     }
230 
where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>)231     pub fn where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>) {
232         let hardbreaks = false;
233         let semi = true;
234         self.where_clause_impl(where_clause, hardbreaks, semi);
235     }
236 
where_clause_impl( &mut self, where_clause: &Option<WhereClause>, hardbreaks: bool, semi: bool, )237     fn where_clause_impl(
238         &mut self,
239         where_clause: &Option<WhereClause>,
240         hardbreaks: bool,
241         semi: bool,
242     ) {
243         let where_clause = match where_clause {
244             Some(where_clause) if !where_clause.predicates.is_empty() => where_clause,
245             _ => {
246                 if semi {
247                     self.word(";");
248                 } else {
249                     self.nbsp();
250                 }
251                 return;
252             }
253         };
254         if hardbreaks {
255             self.hardbreak();
256             self.offset(-INDENT);
257             self.word("where");
258             self.hardbreak();
259             for predicate in where_clause.predicates.iter().delimited() {
260                 self.where_predicate(&predicate);
261                 if predicate.is_last && semi {
262                     self.word(";");
263                 } else {
264                     self.word(",");
265                     self.hardbreak();
266                 }
267             }
268             if !semi {
269                 self.offset(-INDENT);
270             }
271         } else {
272             self.space();
273             self.offset(-INDENT);
274             self.word("where");
275             self.space();
276             for predicate in where_clause.predicates.iter().delimited() {
277                 self.where_predicate(&predicate);
278                 if predicate.is_last && semi {
279                     self.word(";");
280                 } else {
281                     self.trailing_comma_or_space(predicate.is_last);
282                 }
283             }
284             if !semi {
285                 self.offset(-INDENT);
286             }
287         }
288     }
289 
where_predicate(&mut self, predicate: &WherePredicate)290     fn where_predicate(&mut self, predicate: &WherePredicate) {
291         match predicate {
292             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
293             WherePredicate::Type(predicate) => self.predicate_type(predicate),
294             WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
295             _ => unimplemented!("unknown WherePredicate"),
296         }
297     }
298 
predicate_type(&mut self, predicate: &PredicateType)299     fn predicate_type(&mut self, predicate: &PredicateType) {
300         if let Some(bound_lifetimes) = &predicate.lifetimes {
301             self.bound_lifetimes(bound_lifetimes);
302         }
303         self.ty(&predicate.bounded_ty);
304         self.word(":");
305         if predicate.bounds.len() == 1 {
306             self.ibox(0);
307         } else {
308             self.ibox(INDENT);
309         }
310         for type_param_bound in predicate.bounds.iter().delimited() {
311             if type_param_bound.is_first {
312                 self.nbsp();
313             } else {
314                 self.space();
315                 self.word("+ ");
316             }
317             self.type_param_bound(&type_param_bound);
318         }
319         self.end();
320     }
321 
predicate_lifetime(&mut self, predicate: &PredicateLifetime)322     fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) {
323         self.lifetime(&predicate.lifetime);
324         self.word(":");
325         self.ibox(INDENT);
326         for lifetime in predicate.bounds.iter().delimited() {
327             if lifetime.is_first {
328                 self.nbsp();
329             } else {
330                 self.space();
331                 self.word("+ ");
332             }
333             self.lifetime(&lifetime);
334         }
335         self.end();
336     }
337 }
338