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