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 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