1pub mod range;
5
6pub use self::range::RangePattern;
8
9use {
11 crate::{attr, util::FmtSingleOrIndent},
12 super::{
13 attr::WithOuterAttributes,
14 expr::{
15 MacroInvocation,
16 PathExpression,
17 without_block::{TupleIndex, path::PathInExpression},
18 },
19 token,
20 util::{Braced, Bracketed, Parenthesized},
21 },
22 core::fmt::Debug,
23 rustidy_ast_literal::{ByteLiteral, ByteStringLiteral, LiteralExpression},
24 rustidy_ast_util::{
25 AtLeast1,
26 Identifier,
27 Punctuated,
28 PunctuatedTrailing,
29 at_least,
30 delimited,
31 punct,
32 },
33 rustidy_format::{Format, Formattable, WhitespaceFormat},
34 rustidy_parse::{Parse, ParsePeeked, ParserError},
35 rustidy_print::Print,
36 rustidy_util::Whitespace,
37};
38
39#[derive(PartialEq, Eq, Clone, Debug)]
41#[derive(serde::Serialize, serde::Deserialize)]
42#[derive(Parse, Formattable, Format, Print)]
43#[parse(name = "a pattern")]
44pub struct Pattern {
45 pub top_alt: Option<token::Or>,
46 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.top_alt.is_some()))]
47 #[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::SINGLE))]
48 pub inner: Punctuated<PatternNoTopAlt, token::Or>,
49}
50
51#[derive(PartialEq, Eq, Clone, Debug)]
53#[derive(serde::Serialize, serde::Deserialize)]
54#[derive(Parse, Formattable, Format, Print)]
55pub enum PatternNoTopAlt {
56 Range(RangePattern),
57 WithoutRange(PatternWithoutRange),
58}
59
60#[derive(PartialEq, Eq, Clone, Debug)]
62#[derive(serde::Serialize, serde::Deserialize)]
63#[derive(Parse, Formattable, Format, Print)]
64pub enum PatternWithoutRange {
65 Struct(StructPattern),
66 TupleStruct(TupleStructPattern),
67 Path(PathPattern),
68
69 #[parse(peek = ByteLiteral)]
70 #[parse(peek = ByteStringLiteral)]
71 Literal(LiteralPattern),
72 #[parse(peek = (Option::<token::Ref>, Option::<token::Mut>, Identifier, token::At))]
74 Ident(IdentifierPattern),
75 Wildcard(WildcardPattern),
76 Rest(RestPattern),
77 Reference(ReferencePattern),
78 Tuple(TuplePattern),
79 Grouped(GroupedPattern),
80 Slice(SlicePattern),
81
82 #[parse(peek = MacroInvocation)]
83 Macro(MacroInvocation),
84}
85
86#[derive(PartialEq, Eq, Clone, Debug)]
88#[derive(serde::Serialize, serde::Deserialize)]
89#[derive(Parse, Formattable, Format, Print)]
90pub struct WildcardPattern(token::Underscore);
91
92#[derive(PartialEq, Eq, Clone, Debug)]
94#[derive(serde::Serialize, serde::Deserialize)]
95#[derive(Parse, Formattable, Format, Print)]
96pub struct RestPattern(token::DotDot);
97
98#[derive(PartialEq, Eq, Clone, Debug)]
100#[derive(serde::Serialize, serde::Deserialize)]
101#[derive(Parse, Formattable, Format, Print)]
102pub struct GroupedPattern(#[format(args = delimited::FmtRemove)] Parenthesized<Box<Pattern>>);
103
104#[derive(PartialEq, Eq, Clone, Debug)]
106#[derive(serde::Serialize, serde::Deserialize)]
107#[derive(Parse, Formattable, Format, Print)]
108pub struct SlicePattern(#[format(args = delimited::FmtRemove)] Bracketed<Option<SlicePatternItems>>);
109
110#[derive(PartialEq, Eq, Clone, Debug)]
112#[derive(serde::Serialize, serde::Deserialize)]
113#[derive(Parse, Formattable, Format, Print)]
114pub struct SlicePatternItems(
115 #[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::REMOVE))]
116 PunctuatedTrailing<Box<Pattern>, token::Comma>,
117);
118
119#[derive(PartialEq, Eq, Clone, Debug)]
121#[derive(serde::Serialize, serde::Deserialize)]
122#[derive(Parse, Formattable, Format, Print)]
123pub struct PathPattern(PathExpression);
124
125#[derive(PartialEq, Eq, Clone, Debug)]
127#[derive(serde::Serialize, serde::Deserialize)]
128#[derive(Parse, Formattable, Format, Print)]
129pub struct ReferencePattern {
130 pub ref_: ReferencePatternRef,
131 #[format(prefix_ws = Whitespace::REMOVE)]
132 pub mut_: Option<token::Mut>,
133 #[format(prefix_ws = match self.mut_.is_some() {
134 true => Whitespace::SINGLE,
135 false => Whitespace::REMOVE,
136 })]
137 pub pat: Box<PatternWithoutRange>,
138}
139
140#[derive(PartialEq, Eq, Clone, Debug)]
141#[derive(serde::Serialize, serde::Deserialize)]
142#[derive(Parse, Formattable, Format, Print)]
143pub enum ReferencePatternRef {
144 And(token::And),
145 AndAnd(token::AndAnd),
146}
147
148#[derive(PartialEq, Eq, Clone, Debug)]
150#[derive(serde::Serialize, serde::Deserialize)]
151#[derive(Parse, Formattable, Format, Print)]
152pub struct StructPattern {
153 pub top: PathInExpression,
154 #[format(prefix_ws = Whitespace::SINGLE)]
155 #[format(args = delimited::fmt_single_or_indent_if_non_blank(
156 50,
157 FmtSingleOrIndent::Single,
158 FmtSingleOrIndent::Indent
159 ))]
160 pub items: Braced<Option<StructPatternElements>>,
161}
162
163#[derive(PartialEq, Eq, Clone, Debug)]
165#[derive(serde::Serialize, serde::Deserialize)]
166#[derive(Parse, Formattable, Format, Print)]
167#[format(args(ty = "FmtSingleOrIndent"))]
168pub enum StructPatternElements {
169 #[format(args = args)]
170 Fields(StructPatternElementsFields),
171 EtCetera(StructPatternEtCetera),
172}
173
174#[derive(PartialEq, Eq, Clone, Debug)]
175#[derive(serde::Serialize, serde::Deserialize)]
176#[derive(Parse, Formattable, Format, Print)]
177#[format(args(ty = "FmtSingleOrIndent"))]
178pub struct StructPatternElementsFields {
179 #[format(args = args)]
180 pub fields: StructPatternFields,
181 #[format(prefix_ws = Whitespace::REMOVE)]
182 #[format(args = args)]
183 pub et_cetera: Option<StructPatternElementsFieldsEtCetera>,
184}
185
186#[derive(PartialEq, Eq, Clone, Debug)]
187#[derive(serde::Serialize, serde::Deserialize)]
188#[derive(Parse, Formattable, Format, Print)]
189#[format(args(ty = "FmtSingleOrIndent"))]
190pub struct StructPatternElementsFieldsEtCetera {
191 pub comma: token::Comma,
192 #[format(prefix_ws = args.prefix_ws())]
193 pub et_cetera: Option<StructPatternEtCetera>,
194}
195
196#[derive(PartialEq, Eq, Clone, Debug)]
198#[derive(serde::Serialize, serde::Deserialize)]
199#[derive(Parse, Formattable, Format, Print)]
200#[format(args(ty = "FmtSingleOrIndent"))]
201pub struct StructPatternFields(
202 #[format(args = punct::fmt(args.prefix_ws(), Whitespace::REMOVE))]
203 Punctuated<StructPatternField, token::Comma>,
204);
205
206#[derive(PartialEq, Eq, Clone, Debug)]
208#[derive(serde::Serialize, serde::Deserialize)]
209#[derive(Parse, Formattable, Format, Print)]
210pub struct StructPatternField(
211 #[format(args = attr::with::fmt(Whitespace::INDENT))]
212 pub WithOuterAttributes<StructPatternFieldInner>,
213);
214
215#[derive(PartialEq, Eq, Clone, Debug)]
216#[derive(serde::Serialize, serde::Deserialize)]
217#[derive(Parse, Formattable, Format, Print)]
218pub enum StructPatternFieldInner {
219 TuplePat(StructPatternFieldTuplePat),
220 IdentPat(StructPatternFieldIdentPat),
221 Ident(StructPatternFieldIdent),
222}
223
224#[derive(PartialEq, Eq, Clone, Debug)]
225#[derive(serde::Serialize, serde::Deserialize)]
226#[derive(Parse, Formattable, Format, Print)]
227pub struct StructPatternFieldTuplePat {
228 pub idx: TupleIndex,
229 #[format(prefix_ws = Whitespace::REMOVE)]
230 pub dot: token::Colon,
231 #[format(prefix_ws = Whitespace::SINGLE)]
232 pub pat: Box<Pattern>,
233}
234
235#[derive(PartialEq, Eq, Clone, Debug)]
236#[derive(serde::Serialize, serde::Deserialize)]
237#[derive(Parse, Formattable, Format, Print)]
238pub struct StructPatternFieldIdentPat {
239 pub ident: Identifier,
240 #[format(prefix_ws = Whitespace::REMOVE)]
241 pub dot: token::Colon,
242 #[format(prefix_ws = Whitespace::SINGLE)]
243 pub pat: Box<Pattern>,
244}
245
246#[derive(PartialEq, Eq, Clone, Debug)]
247#[derive(serde::Serialize, serde::Deserialize)]
248#[derive(Parse, Formattable, Format, Print)]
249pub struct StructPatternFieldIdent {
250 pub ref_: Option<token::Ref>,
251 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.ref_.is_some()))]
252 pub mut_: Option<token::Mut>,
253 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.ref_.is_some() || self.mut_.is_some()))]
254 pub ident: Identifier,
255}
256
257#[derive(PartialEq, Eq, Clone, Debug)]
259#[derive(serde::Serialize, serde::Deserialize)]
260#[derive(Parse, Formattable, Format, Print)]
261pub struct StructPatternEtCetera(token::DotDot);
262
263#[derive(PartialEq, Eq, Clone, Debug)]
265#[derive(serde::Serialize, serde::Deserialize)]
266#[derive(Parse, Formattable, Format, Print)]
267pub struct TupleStructPattern {
268 pub top: PathInExpression,
269 #[format(prefix_ws = Whitespace::REMOVE)]
270 #[format(args = delimited::FmtRemove)]
271 pub items: Parenthesized<Option<TupleStructItems>>,
272}
273
274#[derive(PartialEq, Eq, Clone, Debug)]
276#[derive(serde::Serialize, serde::Deserialize)]
277#[derive(Parse, Formattable, Format, Print)]
278pub struct TupleStructItems(
279 #[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::REMOVE))]
280 pub PunctuatedTrailing<Box<Pattern>, token::Comma>,
281);
282
283#[derive(PartialEq, Eq, Clone, Debug)]
285#[derive(serde::Serialize, serde::Deserialize)]
286#[derive(Parse, Formattable, Format, Print)]
287pub struct TuplePattern(
288 #[format(args = delimited::FmtRemove)]
289 Parenthesized<Option<TuplePatternItems>>,
290);
291
292#[derive(PartialEq, Eq, Clone, Debug)]
294#[derive(serde::Serialize, serde::Deserialize)]
295#[derive(Parse, Formattable, Format, Print)]
296pub enum TuplePatternItems {
297 Pats(TupleItemsPats),
298 Pat(TupleItemsPat),
299 Rest(RestPattern),
300}
301
302#[derive(PartialEq, Eq, Clone, Debug)]
303#[derive(serde::Serialize, serde::Deserialize)]
304#[derive(Parse, Formattable, Format, Print)]
305pub struct TupleItemsPat {
306 pub pat: Box<Pattern>,
307 #[format(prefix_ws = Whitespace::REMOVE)]
308 pub comma: token::Comma,
309}
310
311#[derive(PartialEq, Eq, Clone, Debug)]
312#[derive(serde::Serialize, serde::Deserialize)]
313#[derive(Parse, Formattable, Format, Print)]
314pub struct TupleItemsPats {
315 pub first: Box<Pattern>,
316 #[format(prefix_ws = Whitespace::REMOVE)]
317 #[format(args = at_least::fmt_prefix_ws(Whitespace::REMOVE))]
318 pub rest: AtLeast1<TupleItemsPatsPat>,
319 #[format(prefix_ws = Whitespace::REMOVE)]
320 pub trailing_comma: Option<token::Comma>,
321}
322
323#[derive(PartialEq, Eq, Clone, Debug)]
324#[derive(serde::Serialize, serde::Deserialize)]
325#[derive(Parse, Formattable, Format, Print)]
326pub struct TupleItemsPatsPat {
327 pub comma: token::Comma,
328 #[format(prefix_ws = Whitespace::SINGLE)]
329 pub pat: Box<Pattern>,
330}
331
332#[derive(PartialEq, Eq, Clone, Debug)]
334#[derive(serde::Serialize, serde::Deserialize)]
335#[derive(Parse, Formattable, Format, Print)]
336pub struct LiteralPattern {
337 pub minus: Option<token::Minus>,
338 pub literal: LiteralExpression,
339}
340
341impl ParsePeeked<ByteLiteral> for LiteralPattern {
342 fn parse_from_with_peeked(_parser: &mut rustidy_parse::Parser, parsed: ByteLiteral) -> Result<Self, Self::Error> {
343 Ok(Self {
344 minus: None,
345 literal: LiteralExpression::Byte(parsed),
346 })
347 }
348}
349
350impl ParsePeeked<ByteStringLiteral> for LiteralPattern {
351 fn parse_from_with_peeked(
352 _parser: &mut rustidy_parse::Parser,
353 parsed: ByteStringLiteral
354 ) -> Result<Self, Self::Error> {
355 Ok(Self {
356 minus: None,
357 literal: LiteralExpression::ByteString(parsed),
358 })
359 }
360}
361
362#[derive(PartialEq, Eq, Clone, Debug)]
364#[derive(serde::Serialize, serde::Deserialize)]
365#[derive(Parse, Formattable, Format, Print)]
366#[parse(error(name = Pat(ParserError::<PatternNoTopAlt>), transparent))]
367pub struct IdentifierPattern {
368 pub ref_: Option<token::Ref>,
369 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.ref_.is_some()))]
370 pub mut_: Option<token::Mut>,
371 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.ref_.is_some() || self.mut_.is_some()))]
372 pub ident: Identifier,
373 #[format(prefix_ws = Whitespace::SINGLE)]
374 pub rest: Option<IdentifierPatternRest>,
375}
376
377impl ParsePeeked<(Option<token::Ref>, Option<token::Mut>, Identifier, token::At)> for IdentifierPattern {
378 fn parse_from_with_peeked(
379 parser: &mut rustidy_parse::Parser,
380 (ref_, mut_, ident, at): (Option<token::Ref>, Option<token::Mut>, Identifier, token::At),
381 ) -> Result<Self, Self::Error> {
382 let pat = parser
383 .parse::<PatternNoTopAlt>()
384 .map_err(Self::Error::Pat)?;
385 Ok(Self {
386 ref_,
387 mut_,
388 ident,
389 rest: Some(IdentifierPatternRest { at, pat: Box::new(pat) }),
390 })
391 }
392}
393
394#[derive(PartialEq, Eq, Clone, Debug)]
395#[derive(serde::Serialize, serde::Deserialize)]
396#[derive(Parse, Formattable, Format, Print)]
397pub struct IdentifierPatternRest {
398 pub at: token::At,
399 #[format(prefix_ws = Whitespace::SINGLE)]
400 pub pat: Box<PatternNoTopAlt>,
401}