prettyplease/
pat.rs
1use crate::algorithm::Printer;
2use crate::fixup::FixupContext;
3use crate::iter::IterDelimited;
4use crate::path::PathKind;
5use crate::INDENT;
6use proc_macro2::TokenStream;
7use syn::{
8 FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple,
9 PatTupleStruct, PatType, PatWild,
10};
11
12impl Printer {
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
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
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
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
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
95 fn pat_rest(&mut self, pat: &PatRest) {
96 self.outer_attrs(&pat.attrs);
97 self.word("..");
98 }
99
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
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
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
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
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"))]
173 fn pat_verbatim(&mut self, pat: &TokenStream) {
174 unimplemented!("Pat::Verbatim `{}`", pat);
175 }
176
177 #[cfg(feature = "verbatim")]
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
241 fn pat_wild(&mut self, pat: &PatWild) {
242 self.outer_attrs(&pat.attrs);
243 self.word("_");
244 }
245
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}