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 syn::{ 7 FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, 8 PatTupleStruct, PatType, PatWild, 9 }; 10 11 impl Printer { pat(&mut self, pat: &Pat)12 pub fn pat(&mut self, pat: &Pat) { 13 match pat { 14 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] 15 Pat::Const(pat) => self.expr_const(pat), 16 Pat::Ident(pat) => self.pat_ident(pat), 17 Pat::Lit(pat) => self.expr_lit(pat), 18 Pat::Macro(pat) => self.expr_macro(pat), 19 Pat::Or(pat) => self.pat_or(pat), 20 Pat::Paren(pat) => self.pat_paren(pat), 21 Pat::Path(pat) => self.expr_path(pat), 22 Pat::Range(pat) => self.expr_range(pat), 23 Pat::Reference(pat) => self.pat_reference(pat), 24 Pat::Rest(pat) => self.pat_rest(pat), 25 Pat::Slice(pat) => self.pat_slice(pat), 26 Pat::Struct(pat) => self.pat_struct(pat), 27 Pat::Tuple(pat) => self.pat_tuple(pat), 28 Pat::TupleStruct(pat) => self.pat_tuple_struct(pat), 29 Pat::Type(pat) => self.pat_type(pat), 30 Pat::Verbatim(pat) => self.pat_verbatim(pat), 31 Pat::Wild(pat) => self.pat_wild(pat), 32 _ => unimplemented!("unknown Pat"), 33 } 34 } 35 pat_ident(&mut self, pat: &PatIdent)36 fn pat_ident(&mut self, pat: &PatIdent) { 37 self.outer_attrs(&pat.attrs); 38 if pat.by_ref.is_some() { 39 self.word("ref "); 40 } 41 if pat.mutability.is_some() { 42 self.word("mut "); 43 } 44 self.ident(&pat.ident); 45 if let Some((_at_token, subpat)) = &pat.subpat { 46 self.word(" @ "); 47 self.pat(subpat); 48 } 49 } 50 pat_or(&mut self, pat: &PatOr)51 fn pat_or(&mut self, pat: &PatOr) { 52 self.outer_attrs(&pat.attrs); 53 let mut consistent_break = false; 54 for case in &pat.cases { 55 match case { 56 Pat::Lit(_) | Pat::Wild(_) => {} 57 _ => { 58 consistent_break = true; 59 break; 60 } 61 } 62 } 63 if consistent_break { 64 self.cbox(0); 65 } else { 66 self.ibox(0); 67 } 68 for case in pat.cases.iter().delimited() { 69 if !case.is_first { 70 self.space(); 71 self.word("| "); 72 } 73 self.pat(&case); 74 } 75 self.end(); 76 } 77 pat_paren(&mut self, pat: &PatParen)78 fn pat_paren(&mut self, pat: &PatParen) { 79 self.outer_attrs(&pat.attrs); 80 self.word("("); 81 self.pat(&pat.pat); 82 self.word(")"); 83 } 84 pat_reference(&mut self, pat: &PatReference)85 fn pat_reference(&mut self, pat: &PatReference) { 86 self.outer_attrs(&pat.attrs); 87 self.word("&"); 88 if pat.mutability.is_some() { 89 self.word("mut "); 90 } 91 self.pat(&pat.pat); 92 } 93 pat_rest(&mut self, pat: &PatRest)94 fn pat_rest(&mut self, pat: &PatRest) { 95 self.outer_attrs(&pat.attrs); 96 self.word(".."); 97 } 98 pat_slice(&mut self, pat: &PatSlice)99 fn pat_slice(&mut self, pat: &PatSlice) { 100 self.outer_attrs(&pat.attrs); 101 self.word("["); 102 for elem in pat.elems.iter().delimited() { 103 self.pat(&elem); 104 self.trailing_comma(elem.is_last); 105 } 106 self.word("]"); 107 } 108 pat_struct(&mut self, pat: &PatStruct)109 fn pat_struct(&mut self, pat: &PatStruct) { 110 self.outer_attrs(&pat.attrs); 111 self.cbox(INDENT); 112 self.path(&pat.path, PathKind::Expr); 113 self.word(" {"); 114 self.space_if_nonempty(); 115 for field in pat.fields.iter().delimited() { 116 self.field_pat(&field); 117 self.trailing_comma_or_space(field.is_last && pat.rest.is_none()); 118 } 119 if let Some(rest) = &pat.rest { 120 self.pat_rest(rest); 121 self.space(); 122 } 123 self.offset(-INDENT); 124 self.end(); 125 self.word("}"); 126 } 127 pat_tuple(&mut self, pat: &PatTuple)128 fn pat_tuple(&mut self, pat: &PatTuple) { 129 self.outer_attrs(&pat.attrs); 130 self.word("("); 131 self.cbox(INDENT); 132 self.zerobreak(); 133 for elem in pat.elems.iter().delimited() { 134 self.pat(&elem); 135 if pat.elems.len() == 1 { 136 if pat.elems.trailing_punct() { 137 self.word(","); 138 } 139 self.zerobreak(); 140 } else { 141 self.trailing_comma(elem.is_last); 142 } 143 } 144 self.offset(-INDENT); 145 self.end(); 146 self.word(")"); 147 } 148 pat_tuple_struct(&mut self, pat: &PatTupleStruct)149 fn pat_tuple_struct(&mut self, pat: &PatTupleStruct) { 150 self.outer_attrs(&pat.attrs); 151 self.path(&pat.path, PathKind::Expr); 152 self.word("("); 153 self.cbox(INDENT); 154 self.zerobreak(); 155 for elem in pat.elems.iter().delimited() { 156 self.pat(&elem); 157 self.trailing_comma(elem.is_last); 158 } 159 self.offset(-INDENT); 160 self.end(); 161 self.word(")"); 162 } 163 pat_type(&mut self, pat: &PatType)164 pub fn pat_type(&mut self, pat: &PatType) { 165 self.outer_attrs(&pat.attrs); 166 self.pat(&pat.pat); 167 self.word(": "); 168 self.ty(&pat.ty); 169 } 170 171 #[cfg(not(feature = "verbatim"))] pat_verbatim(&mut self, pat: &TokenStream)172 fn pat_verbatim(&mut self, pat: &TokenStream) { 173 unimplemented!("Pat::Verbatim `{}`", pat); 174 } 175 176 #[cfg(feature = "verbatim")] pat_verbatim(&mut self, tokens: &TokenStream)177 fn pat_verbatim(&mut self, tokens: &TokenStream) { 178 use syn::parse::{Parse, ParseStream, Result}; 179 use syn::{braced, Attribute, Block, Token}; 180 181 enum PatVerbatim { 182 Ellipsis, 183 Box(Pat), 184 Const(PatConst), 185 } 186 187 struct PatConst { 188 attrs: Vec<Attribute>, 189 block: Block, 190 } 191 192 impl Parse for PatVerbatim { 193 fn parse(input: ParseStream) -> Result<Self> { 194 let lookahead = input.lookahead1(); 195 if lookahead.peek(Token![box]) { 196 input.parse::<Token![box]>()?; 197 let inner = Pat::parse_single(input)?; 198 Ok(PatVerbatim::Box(inner)) 199 } else if lookahead.peek(Token![const]) { 200 input.parse::<Token![const]>()?; 201 let content; 202 let brace_token = braced!(content in input); 203 let attrs = content.call(Attribute::parse_inner)?; 204 let stmts = content.call(Block::parse_within)?; 205 Ok(PatVerbatim::Const(PatConst { 206 attrs, 207 block: Block { brace_token, stmts }, 208 })) 209 } else if lookahead.peek(Token![...]) { 210 input.parse::<Token![...]>()?; 211 Ok(PatVerbatim::Ellipsis) 212 } else { 213 Err(lookahead.error()) 214 } 215 } 216 } 217 218 let pat: PatVerbatim = match syn::parse2(tokens.clone()) { 219 Ok(pat) => pat, 220 Err(_) => unimplemented!("Pat::Verbatim `{}`", tokens), 221 }; 222 223 match pat { 224 PatVerbatim::Ellipsis => { 225 self.word("..."); 226 } 227 PatVerbatim::Box(pat) => { 228 self.word("box "); 229 self.pat(&pat); 230 } 231 PatVerbatim::Const(pat) => { 232 self.word("const "); 233 self.cbox(INDENT); 234 self.small_block(&pat.block, &pat.attrs); 235 self.end(); 236 } 237 } 238 } 239 pat_wild(&mut self, pat: &PatWild)240 fn pat_wild(&mut self, pat: &PatWild) { 241 self.outer_attrs(&pat.attrs); 242 self.word("_"); 243 } 244 field_pat(&mut self, field_pat: &FieldPat)245 fn field_pat(&mut self, field_pat: &FieldPat) { 246 self.outer_attrs(&field_pat.attrs); 247 if field_pat.colon_token.is_some() { 248 self.member(&field_pat.member); 249 self.word(": "); 250 } 251 self.pat(&field_pat.pat); 252 } 253 } 254