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(¶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::Verbatim(bound) => self.type_param_bound_verbatim(bound), 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 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 const_param(&mut self, const_param: &ConstParam)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 where_clause_for_body(&mut self, where_clause: &Option<WhereClause>)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 where_clause_semi(&mut self, where_clause: &Option<WhereClause>)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 where_clause_oneline(&mut self, where_clause: &Option<WhereClause>)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 where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>)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 where_clause_impl( &mut self, where_clause: &Option<WhereClause>, hardbreaks: bool, semi: bool, )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 where_predicate(&mut self, predicate: &WherePredicate)290 fn where_predicate(&mut self, predicate: &WherePredicate) { 291 match predicate { 292 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] 293 WherePredicate::Type(predicate) => self.predicate_type(predicate), 294 WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate), 295 _ => unimplemented!("unknown WherePredicate"), 296 } 297 } 298 predicate_type(&mut self, predicate: &PredicateType)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 predicate_lifetime(&mut self, predicate: &PredicateLifetime)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