• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, CapturedParam, ConstParam, Expr, GenericParam, Generics, LifetimeParam,
9     PreciseCapture, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam,
10     TypeParamBound, WhereClause, 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::PreciseCapture(precise_capture) => {
113                 self.precise_capture(precise_capture);
114             }
115             TypeParamBound::Verbatim(bound) => self.type_param_bound_verbatim(bound),
116             _ => unimplemented!("unknown TypeParamBound"),
117         }
118     }
119 
trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool)120     fn trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool) {
121         if trait_bound.paren_token.is_some() {
122             self.word("(");
123         }
124         if tilde_const {
125             self.word("~const ");
126         }
127         self.trait_bound_modifier(&trait_bound.modifier);
128         if let Some(bound_lifetimes) = &trait_bound.lifetimes {
129             self.bound_lifetimes(bound_lifetimes);
130         }
131         for segment in trait_bound.path.segments.iter().delimited() {
132             if !segment.is_first || trait_bound.path.leading_colon.is_some() {
133                 self.word("::");
134             }
135             self.path_segment(&segment, PathKind::Type);
136         }
137         if trait_bound.paren_token.is_some() {
138             self.word(")");
139         }
140     }
141 
trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier)142     fn trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier) {
143         match trait_bound_modifier {
144             TraitBoundModifier::None => {}
145             TraitBoundModifier::Maybe(_question_mark) => self.word("?"),
146         }
147     }
148 
149     #[cfg(not(feature = "verbatim"))]
type_param_bound_verbatim(&mut self, bound: &TokenStream)150     fn type_param_bound_verbatim(&mut self, bound: &TokenStream) {
151         unimplemented!("TypeParamBound::Verbatim `{}`", bound);
152     }
153 
154     #[cfg(feature = "verbatim")]
type_param_bound_verbatim(&mut self, tokens: &TokenStream)155     fn type_param_bound_verbatim(&mut self, tokens: &TokenStream) {
156         use syn::parse::{Parse, ParseStream, Result};
157         use syn::{parenthesized, token, Token};
158 
159         enum TypeParamBoundVerbatim {
160             Ellipsis,
161             TildeConst(TraitBound),
162         }
163 
164         impl Parse for TypeParamBoundVerbatim {
165             fn parse(input: ParseStream) -> Result<Self> {
166                 let content;
167                 let (paren_token, content) = if input.peek(token::Paren) {
168                     (Some(parenthesized!(content in input)), &content)
169                 } else {
170                     (None, input)
171                 };
172                 let lookahead = content.lookahead1();
173                 if lookahead.peek(Token![~]) {
174                     content.parse::<Token![~]>()?;
175                     content.parse::<Token![const]>()?;
176                     let mut bound: TraitBound = content.parse()?;
177                     bound.paren_token = paren_token;
178                     Ok(TypeParamBoundVerbatim::TildeConst(bound))
179                 } else if lookahead.peek(Token![...]) {
180                     content.parse::<Token![...]>()?;
181                     Ok(TypeParamBoundVerbatim::Ellipsis)
182                 } else {
183                     Err(lookahead.error())
184                 }
185             }
186         }
187 
188         let bound: TypeParamBoundVerbatim = match syn::parse2(tokens.clone()) {
189             Ok(bound) => bound,
190             Err(_) => unimplemented!("TypeParamBound::Verbatim `{}`", tokens),
191         };
192 
193         match bound {
194             TypeParamBoundVerbatim::Ellipsis => {
195                 self.word("...");
196             }
197             TypeParamBoundVerbatim::TildeConst(trait_bound) => {
198                 let tilde_const = true;
199                 self.trait_bound(&trait_bound, tilde_const);
200             }
201         }
202     }
203 
const_param(&mut self, const_param: &ConstParam)204     fn const_param(&mut self, const_param: &ConstParam) {
205         self.outer_attrs(&const_param.attrs);
206         self.word("const ");
207         self.ident(&const_param.ident);
208         self.word(": ");
209         self.ty(&const_param.ty);
210         if let Some(default) = &const_param.default {
211             self.word(" = ");
212             self.const_argument(default);
213         }
214     }
215 
where_clause_for_body(&mut self, where_clause: &Option<WhereClause>)216     pub fn where_clause_for_body(&mut self, where_clause: &Option<WhereClause>) {
217         let hardbreaks = true;
218         let semi = false;
219         self.where_clause_impl(where_clause, hardbreaks, semi);
220     }
221 
where_clause_semi(&mut self, where_clause: &Option<WhereClause>)222     pub fn where_clause_semi(&mut self, where_clause: &Option<WhereClause>) {
223         let hardbreaks = true;
224         let semi = true;
225         self.where_clause_impl(where_clause, hardbreaks, semi);
226     }
227 
where_clause_oneline(&mut self, where_clause: &Option<WhereClause>)228     pub fn where_clause_oneline(&mut self, where_clause: &Option<WhereClause>) {
229         let hardbreaks = false;
230         let semi = false;
231         self.where_clause_impl(where_clause, hardbreaks, semi);
232     }
233 
where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>)234     pub fn where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>) {
235         let hardbreaks = false;
236         let semi = true;
237         self.where_clause_impl(where_clause, hardbreaks, semi);
238     }
239 
where_clause_impl( &mut self, where_clause: &Option<WhereClause>, hardbreaks: bool, semi: bool, )240     fn where_clause_impl(
241         &mut self,
242         where_clause: &Option<WhereClause>,
243         hardbreaks: bool,
244         semi: bool,
245     ) {
246         let where_clause = match where_clause {
247             Some(where_clause) if !where_clause.predicates.is_empty() => where_clause,
248             _ => {
249                 if semi {
250                     self.word(";");
251                 } else {
252                     self.nbsp();
253                 }
254                 return;
255             }
256         };
257         if hardbreaks {
258             self.hardbreak();
259             self.offset(-INDENT);
260             self.word("where");
261             self.hardbreak();
262             for predicate in where_clause.predicates.iter().delimited() {
263                 self.where_predicate(&predicate);
264                 if predicate.is_last && semi {
265                     self.word(";");
266                 } else {
267                     self.word(",");
268                     self.hardbreak();
269                 }
270             }
271             if !semi {
272                 self.offset(-INDENT);
273             }
274         } else {
275             self.space();
276             self.offset(-INDENT);
277             self.word("where");
278             self.space();
279             for predicate in where_clause.predicates.iter().delimited() {
280                 self.where_predicate(&predicate);
281                 if predicate.is_last && semi {
282                     self.word(";");
283                 } else {
284                     self.trailing_comma_or_space(predicate.is_last);
285                 }
286             }
287             if !semi {
288                 self.offset(-INDENT);
289             }
290         }
291     }
292 
where_predicate(&mut self, predicate: &WherePredicate)293     fn where_predicate(&mut self, predicate: &WherePredicate) {
294         match predicate {
295             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
296             WherePredicate::Type(predicate) => self.predicate_type(predicate),
297             WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
298             _ => unimplemented!("unknown WherePredicate"),
299         }
300     }
301 
predicate_type(&mut self, predicate: &PredicateType)302     fn predicate_type(&mut self, predicate: &PredicateType) {
303         if let Some(bound_lifetimes) = &predicate.lifetimes {
304             self.bound_lifetimes(bound_lifetimes);
305         }
306         self.ty(&predicate.bounded_ty);
307         self.word(":");
308         if predicate.bounds.len() == 1 {
309             self.ibox(0);
310         } else {
311             self.ibox(INDENT);
312         }
313         for type_param_bound in predicate.bounds.iter().delimited() {
314             if type_param_bound.is_first {
315                 self.nbsp();
316             } else {
317                 self.space();
318                 self.word("+ ");
319             }
320             self.type_param_bound(&type_param_bound);
321         }
322         self.end();
323     }
324 
predicate_lifetime(&mut self, predicate: &PredicateLifetime)325     fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) {
326         self.lifetime(&predicate.lifetime);
327         self.word(":");
328         self.ibox(INDENT);
329         for lifetime in predicate.bounds.iter().delimited() {
330             if lifetime.is_first {
331                 self.nbsp();
332             } else {
333                 self.space();
334                 self.word("+ ");
335             }
336             self.lifetime(&lifetime);
337         }
338         self.end();
339     }
340 
precise_capture(&mut self, precise_capture: &PreciseCapture)341     fn precise_capture(&mut self, precise_capture: &PreciseCapture) {
342         self.word("use<");
343         for capture in precise_capture.params.iter().delimited() {
344             self.captured_param(&capture);
345             if !capture.is_last {
346                 self.word(", ");
347             }
348         }
349         self.word(">");
350     }
351 
captured_param(&mut self, capture: &CapturedParam)352     fn captured_param(&mut self, capture: &CapturedParam) {
353         match capture {
354             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
355             CapturedParam::Lifetime(lifetime) => self.lifetime(lifetime),
356             CapturedParam::Ident(ident) => self.ident(ident),
357             _ => unimplemented!("unknown CapturedParam"),
358         }
359     }
360 
const_argument(&mut self, expr: &Expr)361     pub fn const_argument(&mut self, expr: &Expr) {
362         match expr {
363             #![cfg_attr(all(test, exhaustive), allow(non_exhaustive_omitted_patterns))]
364             Expr::Lit(expr) => self.expr_lit(expr),
365 
366             Expr::Path(expr)
367                 if expr.attrs.is_empty()
368                     && expr.qself.is_none()
369                     && expr.path.get_ident().is_some() =>
370             {
371                 self.expr_path(expr);
372             }
373 
374             Expr::Block(expr) => self.expr_block(expr),
375 
376             _ => {
377                 self.cbox(INDENT);
378                 self.expr_as_small_block(expr, 0);
379                 self.end();
380             }
381         }
382     }
383 }
384