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(¶m); 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