1use crate::algorithm::Printer;
2use crate::iter::IterDelimited;
3use crate::path::PathKind;
4use crate::INDENT;
5use proc_macro2::TokenStream;
6use std::ptr;
7use syn::{
8 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
9 PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
10 WherePredicate,
11};
12
13impl Printer {
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 #[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
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
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(¶m);
63 if !param.is_last {
64 self.word(", ");
65 }
66 }
67 self.word("> ");
68 }
69
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
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
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
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
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"))]
147 fn type_param_bound_verbatim(&mut self, bound: &TokenStream) {
148 unimplemented!("TypeParamBound::Verbatim `{}`", bound);
149 }
150
151 #[cfg(feature = "verbatim")]
152 fn type_param_bound_verbatim(&mut self, tokens: &TokenStream) {
153 use syn::parse::{Parse, ParseStream, Result};
154 use syn::{parenthesized, token, Ident, Lifetime, Token};
155
156 enum TypeParamBoundVerbatim {
157 Ellipsis,
158 PreciseCapture(Vec<Capture>),
159 TildeConst(TraitBound),
160 }
161
162 enum Capture {
163 Lifetime(Lifetime),
164 Type(Ident),
165 }
166
167 impl Parse for TypeParamBoundVerbatim {
168 fn parse(input: ParseStream) -> Result<Self> {
169 let content;
170 let (paren_token, content) = if input.peek(token::Paren) {
171 (Some(parenthesized!(content in input)), &content)
172 } else {
173 (None, input)
174 };
175 let lookahead = content.lookahead1();
176 if lookahead.peek(Token![use]) {
177 input.parse::<Token![use]>()?;
178 input.parse::<Token![<]>()?;
179 let mut captures = Vec::new();
180 loop {
181 let lookahead = input.lookahead1();
182 captures.push(if lookahead.peek(Lifetime) {
183 input.parse().map(Capture::Lifetime)?
184 } else if lookahead.peek(Ident) {
185 input.parse().map(Capture::Type)?
186 } else if lookahead.peek(Token![>]) {
187 break;
188 } else {
189 return Err(lookahead.error());
190 });
191 let lookahead = input.lookahead1();
192 if lookahead.peek(Token![,]) {
193 input.parse::<Token![,]>()?;
194 } else if lookahead.peek(Token![>]) {
195 break;
196 } else {
197 return Err(lookahead.error());
198 }
199 }
200 input.parse::<Token![>]>()?;
201 Ok(TypeParamBoundVerbatim::PreciseCapture(captures))
202 } else if lookahead.peek(Token![~]) {
203 content.parse::<Token![~]>()?;
204 content.parse::<Token![const]>()?;
205 let mut bound: TraitBound = content.parse()?;
206 bound.paren_token = paren_token;
207 Ok(TypeParamBoundVerbatim::TildeConst(bound))
208 } else if lookahead.peek(Token![...]) {
209 content.parse::<Token![...]>()?;
210 Ok(TypeParamBoundVerbatim::Ellipsis)
211 } else {
212 Err(lookahead.error())
213 }
214 }
215 }
216
217 let bound: TypeParamBoundVerbatim = match syn::parse2(tokens.clone()) {
218 Ok(bound) => bound,
219 Err(_) => unimplemented!("TypeParamBound::Verbatim `{}`", tokens),
220 };
221
222 match bound {
223 TypeParamBoundVerbatim::Ellipsis => {
224 self.word("...");
225 }
226 TypeParamBoundVerbatim::PreciseCapture(captures) => {
227 self.word("use<");
228 for capture in captures.iter().delimited() {
229 match *capture {
230 Capture::Lifetime(lifetime) => self.lifetime(lifetime),
231 Capture::Type(ident) => self.ident(ident),
232 }
233 if !capture.is_last {
234 self.word(", ");
235 }
236 }
237 self.word(">");
238 }
239 TypeParamBoundVerbatim::TildeConst(trait_bound) => {
240 let tilde_const = true;
241 self.trait_bound(&trait_bound, tilde_const);
242 }
243 }
244 }
245
246 fn const_param(&mut self, const_param: &ConstParam) {
247 self.outer_attrs(&const_param.attrs);
248 self.word("const ");
249 self.ident(&const_param.ident);
250 self.word(": ");
251 self.ty(&const_param.ty);
252 if let Some(default) = &const_param.default {
253 self.word(" = ");
254 self.expr(default);
255 }
256 }
257
258 pub fn where_clause_for_body(&mut self, where_clause: &Option<WhereClause>) {
259 let hardbreaks = true;
260 let semi = false;
261 self.where_clause_impl(where_clause, hardbreaks, semi);
262 }
263
264 pub fn where_clause_semi(&mut self, where_clause: &Option<WhereClause>) {
265 let hardbreaks = true;
266 let semi = true;
267 self.where_clause_impl(where_clause, hardbreaks, semi);
268 }
269
270 pub fn where_clause_oneline(&mut self, where_clause: &Option<WhereClause>) {
271 let hardbreaks = false;
272 let semi = false;
273 self.where_clause_impl(where_clause, hardbreaks, semi);
274 }
275
276 pub fn where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>) {
277 let hardbreaks = false;
278 let semi = true;
279 self.where_clause_impl(where_clause, hardbreaks, semi);
280 }
281
282 fn where_clause_impl(
283 &mut self,
284 where_clause: &Option<WhereClause>,
285 hardbreaks: bool,
286 semi: bool,
287 ) {
288 let where_clause = match where_clause {
289 Some(where_clause) if !where_clause.predicates.is_empty() => where_clause,
290 _ => {
291 if semi {
292 self.word(";");
293 } else {
294 self.nbsp();
295 }
296 return;
297 }
298 };
299 if hardbreaks {
300 self.hardbreak();
301 self.offset(-INDENT);
302 self.word("where");
303 self.hardbreak();
304 for predicate in where_clause.predicates.iter().delimited() {
305 self.where_predicate(&predicate);
306 if predicate.is_last && semi {
307 self.word(";");
308 } else {
309 self.word(",");
310 self.hardbreak();
311 }
312 }
313 if !semi {
314 self.offset(-INDENT);
315 }
316 } else {
317 self.space();
318 self.offset(-INDENT);
319 self.word("where");
320 self.space();
321 for predicate in where_clause.predicates.iter().delimited() {
322 self.where_predicate(&predicate);
323 if predicate.is_last && semi {
324 self.word(";");
325 } else {
326 self.trailing_comma_or_space(predicate.is_last);
327 }
328 }
329 if !semi {
330 self.offset(-INDENT);
331 }
332 }
333 }
334
335 fn where_predicate(&mut self, predicate: &WherePredicate) {
336 match predicate {
337 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
338 WherePredicate::Type(predicate) => self.predicate_type(predicate),
339 WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
340 _ => unimplemented!("unknown WherePredicate"),
341 }
342 }
343
344 fn predicate_type(&mut self, predicate: &PredicateType) {
345 if let Some(bound_lifetimes) = &predicate.lifetimes {
346 self.bound_lifetimes(bound_lifetimes);
347 }
348 self.ty(&predicate.bounded_ty);
349 self.word(":");
350 if predicate.bounds.len() == 1 {
351 self.ibox(0);
352 } else {
353 self.ibox(INDENT);
354 }
355 for type_param_bound in predicate.bounds.iter().delimited() {
356 if type_param_bound.is_first {
357 self.nbsp();
358 } else {
359 self.space();
360 self.word("+ ");
361 }
362 self.type_param_bound(&type_param_bound);
363 }
364 self.end();
365 }
366
367 fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) {
368 self.lifetime(&predicate.lifetime);
369 self.word(":");
370 self.ibox(INDENT);
371 for lifetime in predicate.bounds.iter().delimited() {
372 if lifetime.is_first {
373 self.nbsp();
374 } else {
375 self.space();
376 self.word("+ ");
377 }
378 self.lifetime(&lifetime);
379 }
380 self.end();
381 }
382}