• 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, 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             TypeParamBound::Trait(trait_bound) => {
107                 let tilde_const = false;
108                 self.trait_bound(trait_bound, tilde_const);
109             }
110             TypeParamBound::Lifetime(lifetime) => self.lifetime(lifetime),
111             TypeParamBound::Verbatim(bound) => self.type_param_bound_verbatim(bound),
112             #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
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             TildeConst(TraitBound),
158         }
159 
160         impl Parse for TypeParamBoundVerbatim {
161             fn parse(input: ParseStream) -> Result<Self> {
162                 let content;
163                 let (paren_token, content) = if input.peek(token::Paren) {
164                     (Some(parenthesized!(content in input)), &content)
165                 } else {
166                     (None, input)
167                 };
168                 content.parse::<Token![~]>()?;
169                 content.parse::<Token![const]>()?;
170                 let mut bound: TraitBound = content.parse()?;
171                 bound.paren_token = paren_token;
172                 Ok(TypeParamBoundVerbatim::TildeConst(bound))
173             }
174         }
175 
176         let bound: TypeParamBoundVerbatim = match syn::parse2(tokens.clone()) {
177             Ok(bound) => bound,
178             Err(_) => unimplemented!("TypeParamBound::Verbatim `{}`", tokens),
179         };
180 
181         match bound {
182             TypeParamBoundVerbatim::TildeConst(trait_bound) => {
183                 let tilde_const = true;
184                 self.trait_bound(&trait_bound, tilde_const);
185             }
186         }
187     }
188 
const_param(&mut self, const_param: &ConstParam)189     fn const_param(&mut self, const_param: &ConstParam) {
190         self.outer_attrs(&const_param.attrs);
191         self.word("const ");
192         self.ident(&const_param.ident);
193         self.word(": ");
194         self.ty(&const_param.ty);
195         if let Some(default) = &const_param.default {
196             self.word(" = ");
197             self.expr(default);
198         }
199     }
200 
where_clause_for_body(&mut self, where_clause: &Option<WhereClause>)201     pub fn where_clause_for_body(&mut self, where_clause: &Option<WhereClause>) {
202         let hardbreaks = true;
203         let semi = false;
204         self.where_clause_impl(where_clause, hardbreaks, semi);
205     }
206 
where_clause_semi(&mut self, where_clause: &Option<WhereClause>)207     pub fn where_clause_semi(&mut self, where_clause: &Option<WhereClause>) {
208         let hardbreaks = true;
209         let semi = true;
210         self.where_clause_impl(where_clause, hardbreaks, semi);
211     }
212 
where_clause_oneline(&mut self, where_clause: &Option<WhereClause>)213     pub fn where_clause_oneline(&mut self, where_clause: &Option<WhereClause>) {
214         let hardbreaks = false;
215         let semi = false;
216         self.where_clause_impl(where_clause, hardbreaks, semi);
217     }
218 
where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>)219     pub fn where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>) {
220         let hardbreaks = false;
221         let semi = true;
222         self.where_clause_impl(where_clause, hardbreaks, semi);
223     }
224 
where_clause_impl( &mut self, where_clause: &Option<WhereClause>, hardbreaks: bool, semi: bool, )225     fn where_clause_impl(
226         &mut self,
227         where_clause: &Option<WhereClause>,
228         hardbreaks: bool,
229         semi: bool,
230     ) {
231         let where_clause = match where_clause {
232             Some(where_clause) if !where_clause.predicates.is_empty() => where_clause,
233             _ => {
234                 if semi {
235                     self.word(";");
236                 } else {
237                     self.nbsp();
238                 }
239                 return;
240             }
241         };
242         if hardbreaks {
243             self.hardbreak();
244             self.offset(-INDENT);
245             self.word("where");
246             self.hardbreak();
247             for predicate in where_clause.predicates.iter().delimited() {
248                 self.where_predicate(&predicate);
249                 if predicate.is_last && semi {
250                     self.word(";");
251                 } else {
252                     self.word(",");
253                     self.hardbreak();
254                 }
255             }
256             if !semi {
257                 self.offset(-INDENT);
258             }
259         } else {
260             self.space();
261             self.offset(-INDENT);
262             self.word("where");
263             self.space();
264             for predicate in where_clause.predicates.iter().delimited() {
265                 self.where_predicate(&predicate);
266                 if predicate.is_last && semi {
267                     self.word(";");
268                 } else {
269                     self.trailing_comma_or_space(predicate.is_last);
270                 }
271             }
272             if !semi {
273                 self.offset(-INDENT);
274             }
275         }
276     }
277 
where_predicate(&mut self, predicate: &WherePredicate)278     fn where_predicate(&mut self, predicate: &WherePredicate) {
279         match predicate {
280             WherePredicate::Type(predicate) => self.predicate_type(predicate),
281             WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
282             #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
283             _ => unimplemented!("unknown WherePredicate"),
284         }
285     }
286 
predicate_type(&mut self, predicate: &PredicateType)287     fn predicate_type(&mut self, predicate: &PredicateType) {
288         if let Some(bound_lifetimes) = &predicate.lifetimes {
289             self.bound_lifetimes(bound_lifetimes);
290         }
291         self.ty(&predicate.bounded_ty);
292         self.word(":");
293         if predicate.bounds.len() == 1 {
294             self.ibox(0);
295         } else {
296             self.ibox(INDENT);
297         }
298         for type_param_bound in predicate.bounds.iter().delimited() {
299             if type_param_bound.is_first {
300                 self.nbsp();
301             } else {
302                 self.space();
303                 self.word("+ ");
304             }
305             self.type_param_bound(&type_param_bound);
306         }
307         self.end();
308     }
309 
predicate_lifetime(&mut self, predicate: &PredicateLifetime)310     fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) {
311         self.lifetime(&predicate.lifetime);
312         self.word(":");
313         self.ibox(INDENT);
314         for lifetime in predicate.bounds.iter().delimited() {
315             if lifetime.is_first {
316                 self.nbsp();
317             } else {
318                 self.space();
319                 self.word("+ ");
320             }
321             self.lifetime(&lifetime);
322         }
323         self.end();
324     }
325 }
326