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 // 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
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(&param);
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 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
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, 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
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
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
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
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
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
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
290 fn where_predicate(&mut self, predicate: &WherePredicate) {
291 match predicate {
292 WherePredicate::Type(predicate) => self.predicate_type(predicate),
293 WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
294 #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
295 _ => unimplemented!("unknown WherePredicate"),
296 }
297 }
298
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
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