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 Pat::Const(pat) => self.expr_const(pat), 15 Pat::Ident(pat) => self.pat_ident(pat), 16 Pat::Lit(pat) => self.expr_lit(pat), 17 Pat::Macro(pat) => self.expr_macro(pat), 18 Pat::Or(pat) => self.pat_or(pat), 19 Pat::Paren(pat) => self.pat_paren(pat), 20 Pat::Path(pat) => self.expr_path(pat), 21 Pat::Range(pat) => self.expr_range(pat), 22 Pat::Reference(pat) => self.pat_reference(pat), 23 Pat::Rest(pat) => self.pat_rest(pat), 24 Pat::Slice(pat) => self.pat_slice(pat), 25 Pat::Struct(pat) => self.pat_struct(pat), 26 Pat::Tuple(pat) => self.pat_tuple(pat), 27 Pat::TupleStruct(pat) => self.pat_tuple_struct(pat), 28 Pat::Type(pat) => self.pat_type(pat), 29 Pat::Verbatim(pat) => self.pat_verbatim(pat), 30 Pat::Wild(pat) => self.pat_wild(pat), 31 #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] 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 Box(Pat), 183 Const(PatConst), 184 } 185 186 struct PatConst { 187 attrs: Vec<Attribute>, 188 block: Block, 189 } 190 191 impl Parse for PatVerbatim { 192 fn parse(input: ParseStream) -> Result<Self> { 193 let lookahead = input.lookahead1(); 194 if lookahead.peek(Token![box]) { 195 input.parse::<Token![box]>()?; 196 let inner = Pat::parse_single(input)?; 197 Ok(PatVerbatim::Box(inner)) 198 } else if lookahead.peek(Token![const]) { 199 input.parse::<Token![const]>()?; 200 let content; 201 let brace_token = braced!(content in input); 202 let attrs = content.call(Attribute::parse_inner)?; 203 let stmts = content.call(Block::parse_within)?; 204 Ok(PatVerbatim::Const(PatConst { 205 attrs, 206 block: Block { brace_token, stmts }, 207 })) 208 } else { 209 Err(lookahead.error()) 210 } 211 } 212 } 213 214 let pat: PatVerbatim = match syn::parse2(tokens.clone()) { 215 Ok(pat) => pat, 216 Err(_) => unimplemented!("Pat::Verbatim `{}`", tokens), 217 }; 218 219 match pat { 220 PatVerbatim::Box(pat) => { 221 self.word("box "); 222 self.pat(&pat); 223 } 224 PatVerbatim::Const(pat) => { 225 self.word("const "); 226 self.cbox(INDENT); 227 self.small_block(&pat.block, &pat.attrs); 228 self.end(); 229 } 230 } 231 } 232 pat_wild(&mut self, pat: &PatWild)233 fn pat_wild(&mut self, pat: &PatWild) { 234 self.outer_attrs(&pat.attrs); 235 self.word("_"); 236 } 237 field_pat(&mut self, field_pat: &FieldPat)238 fn field_pat(&mut self, field_pat: &FieldPat) { 239 self.outer_attrs(&field_pat.attrs); 240 if field_pat.colon_token.is_some() { 241 self.member(&field_pat.member); 242 self.word(": "); 243 } 244 self.pat(&field_pat.pat); 245 } 246 } 247