Skip to main content

rustidy_ast/expr/
with_block.rs

1//! Expressions with a block
2
3// Modules
4pub mod block;
5pub mod match_;
6
7// Exports
8pub use self::{block::BlockExpression, match_::{MatchExpression, Scrutinee}};
9
10// Imports
11use {
12	crate::{
13		attr::{self, WithOuterAttributes},
14		lifetime::LifetimeOrLabel,
15		pat::Pattern,
16		token,
17	},
18	super::Expression,
19	rustidy_ast_util::{Longest, Punctuated, punct},
20	rustidy_format::{Format, Formattable, WhitespaceFormat},
21	rustidy_parse::{ParsableFrom, Parse, ParserTag},
22	rustidy_print::Print,
23	rustidy_util::Whitespace,
24};
25
26/// `ExpressionWithBlock`
27#[derive(PartialEq, Eq, Clone, Debug)]
28#[derive(serde::Serialize, serde::Deserialize)]
29#[derive(Parse, Formattable, Format, Print)]
30pub struct ExpressionWithBlock(
31	// TODO: Should this ever be SINGLE?
32	#[format(args = attr::with::fmt(Whitespace::INDENT))]
33	pub WithOuterAttributes<ExpressionWithBlockInner>,
34);
35
36#[derive(PartialEq, Eq, Clone, Debug)]
37#[derive(serde::Serialize, serde::Deserialize)]
38#[derive(Parse, Formattable, Format, Print)]
39pub enum ExpressionWithBlockInner {
40	Block(BlockExpression),
41	ConstBlock(ConstBlockExpression),
42	UnsafeBlock(UnsafeBlockExpression),
43	TryBlock(TryBlockExpression),
44	Loop(LoopExpression),
45	If(IfExpression),
46	Match(MatchExpression),
47}
48
49/// `ConstBlockExpression`
50#[derive(PartialEq, Eq, Clone, Debug)]
51#[derive(serde::Serialize, serde::Deserialize)]
52#[derive(Parse, Formattable, Format, Print)]
53pub struct ConstBlockExpression {
54	pub const_: token::Const,
55	#[format(prefix_ws = Whitespace::SINGLE)]
56	pub expr:   BlockExpression,
57}
58
59/// `UnsafeBlockExpression`
60#[derive(PartialEq, Eq, Clone, Debug)]
61#[derive(serde::Serialize, serde::Deserialize)]
62#[derive(Parse, Formattable, Format, Print)]
63pub struct UnsafeBlockExpression {
64	pub unsafe_: token::Unsafe,
65	#[format(prefix_ws = Whitespace::SINGLE)]
66	pub expr:    BlockExpression,
67}
68
69// Note: Nightly-only
70#[derive(PartialEq, Eq, Clone, Debug)]
71#[derive(serde::Serialize, serde::Deserialize)]
72#[derive(Parse, Formattable, Format, Print)]
73pub struct TryBlockExpression {
74	pub try_: token::Try,
75	#[parse(fatal)]
76	#[format(prefix_ws = Whitespace::SINGLE)]
77	pub expr: BlockExpression,
78}
79
80/// `IfExpression`
81#[derive(PartialEq, Eq, Clone, Debug)]
82#[derive(serde::Serialize, serde::Deserialize)]
83#[derive(Parse, Formattable, Format, Print)]
84#[parse(name = "an if expression")]
85pub struct IfExpression {
86	pub if_:        token::If,
87	#[parse(fatal)]
88	#[format(prefix_ws = Whitespace::SINGLE)]
89	pub conditions: Conditions,
90	#[format(prefix_ws = Whitespace::SINGLE)]
91	pub expr:       BlockExpression,
92	#[format(prefix_ws = Whitespace::SINGLE)]
93	pub else_:      Option<IfExpressionElse>,
94}
95
96#[derive(PartialEq, Eq, Clone, Debug)]
97#[derive(serde::Serialize, serde::Deserialize)]
98#[derive(Parse, Formattable, Format, Print)]
99pub struct IfExpressionElse {
100	pub else_: token::Else,
101	#[parse(fatal)]
102	#[format(prefix_ws = Whitespace::SINGLE)]
103	pub inner: IfExpressionElseInner,
104}
105
106#[derive(PartialEq, Eq, Clone, Debug)]
107#[derive(serde::Serialize, serde::Deserialize)]
108#[derive(Parse, Formattable, Format, Print)]
109pub enum IfExpressionElseInner {
110	Block(BlockExpression),
111	If(Box<IfExpression>),
112}
113
114/// `Conditions`
115#[derive(PartialEq, Eq, Clone, Debug)]
116#[derive(serde::Serialize, serde::Deserialize)]
117#[derive(Parse, Formattable, Format, Print)]
118#[parse(from = Longest::<LetChain, ConditionsExpr>)]
119pub enum Conditions {
120	Let(LetChain),
121	Expr(ConditionsExpr)
122}
123
124impl ParsableFrom<Longest<LetChain, ConditionsExpr>> for Conditions {
125	fn from_parsable(value: Longest<LetChain, ConditionsExpr>) -> Self {
126		match value {
127			Longest::Left(let_chain) => Self::Let(let_chain),
128			Longest::Right(expr) => Self::Expr(expr),
129		}
130	}
131}
132
133#[derive(PartialEq, Eq, Clone, Debug)]
134#[derive(serde::Serialize, serde::Deserialize)]
135#[derive(Parse, Formattable, Format, Print)]
136pub struct ConditionsExpr(
137	#[parse(with_tag = ParserTag::SkipStructExpression)]
138	#[parse(with_tag = ParserTag::SkipOptionalTrailingBlockExpression)]
139	Expression,
140);
141
142/// `LetChain`
143#[derive(PartialEq, Eq, Clone, Debug)]
144#[derive(serde::Serialize, serde::Deserialize)]
145#[derive(Parse, Formattable, Format, Print)]
146pub struct LetChain(
147	#[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::SINGLE))]
148	pub Punctuated<LetChainCondition, token::AndAnd>,
149);
150
151/// `LetChainCondition`
152#[derive(PartialEq, Eq, Clone, Debug)]
153#[derive(serde::Serialize, serde::Deserialize)]
154#[derive(Parse, Formattable, Format, Print)]
155pub enum LetChainCondition {
156	#[format(args = attr::with::fmt(Whitespace::SINGLE))]
157	Let(WithOuterAttributes<LetChainConditionLet>),
158	#[parse(with_tag = ParserTag::SkipStructExpression)]
159	#[parse(with_tag = ParserTag::SkipLazyBooleanExpression)]
160	#[parse(with_tag = ParserTag::SkipRangeExpr)]
161	#[parse(with_tag = ParserTag::SkipRangeFromExpr)]
162	#[parse(with_tag = ParserTag::SkipRangeInclusiveExpr)]
163	#[parse(with_tag = ParserTag::SkipAssignmentExpression)]
164	#[parse(with_tag = ParserTag::SkipCompoundAssignmentExpression)]
165	#[parse(with_tag = ParserTag::SkipOptionalTrailingBlockExpression)]
166	Expr(Expression),
167}
168
169#[derive(PartialEq, Eq, Clone, Debug)]
170#[derive(serde::Serialize, serde::Deserialize)]
171#[derive(Parse, Formattable, Format, Print)]
172pub struct LetChainConditionLet {
173	pub let_:      token::Let,
174	#[parse(fatal)]
175	#[format(prefix_ws = Whitespace::SINGLE)]
176	pub pat:       Pattern,
177	#[format(prefix_ws = Whitespace::SINGLE)]
178	pub eq:        token::Eq,
179	#[parse(with_tag = ParserTag::SkipStructExpression)]
180	#[parse(with_tag = ParserTag::SkipLazyBooleanExpression)]
181	#[parse(with_tag = ParserTag::SkipRangeExpr)]
182	#[parse(with_tag = ParserTag::SkipRangeFromExpr)]
183	#[parse(with_tag = ParserTag::SkipRangeInclusiveExpr)]
184	#[parse(with_tag = ParserTag::SkipAssignmentExpression)]
185	#[parse(with_tag = ParserTag::SkipCompoundAssignmentExpression)]
186	#[parse(with_tag = ParserTag::SkipOptionalTrailingBlockExpression)]
187	#[format(prefix_ws = Whitespace::SINGLE)]
188	pub scrutinee: Box<Scrutinee>,
189}
190
191/// `LoopExpression`
192#[derive(PartialEq, Eq, Clone, Debug)]
193#[derive(serde::Serialize, serde::Deserialize)]
194#[derive(Parse, Formattable, Format, Print)]
195pub struct LoopExpression {
196	pub label: Option<LoopLabel>,
197	#[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.label.is_some()))]
198	pub inner: LoopExpressionInner,
199}
200
201/// `LoopLabel`
202#[derive(PartialEq, Eq, Clone, Debug)]
203#[derive(serde::Serialize, serde::Deserialize)]
204#[derive(Parse, Formattable, Format, Print)]
205pub struct LoopLabel {
206	pub lifetime: LifetimeOrLabel,
207	#[format(prefix_ws = Whitespace::REMOVE)]
208	pub colon:    token::Colon,
209}
210
211#[derive(PartialEq, Eq, Clone, Debug)]
212#[derive(serde::Serialize, serde::Deserialize)]
213#[derive(Parse, Formattable, Format, Print)]
214pub enum LoopExpressionInner {
215	Infinite(InfiniteLoopExpression),
216	Predicate(PredicateLoopExpression),
217	Iterator(IteratorLoopExpression),
218	LabelBlock(LabelBlockExpression),
219}
220
221/// `IteratorLoopExpression`
222#[derive(PartialEq, Eq, Clone, Debug)]
223#[derive(serde::Serialize, serde::Deserialize)]
224#[derive(Parse, Formattable, Format, Print)]
225pub struct IteratorLoopExpression {
226	pub for_: token::For,
227	#[format(prefix_ws = Whitespace::SINGLE)]
228	pub pat:  Pattern,
229	#[format(prefix_ws = Whitespace::SINGLE)]
230	pub in_:  token::In,
231	#[parse(with_tag = ParserTag::SkipStructExpression)]
232	#[parse(with_tag = ParserTag::SkipOptionalTrailingBlockExpression)]
233	#[format(prefix_ws = Whitespace::SINGLE)]
234	pub expr: Expression,
235	#[format(prefix_ws = Whitespace::SINGLE)]
236	pub body: BlockExpression,
237}
238
239/// `PredicateLoopExpression`
240#[derive(PartialEq, Eq, Clone, Debug)]
241#[derive(serde::Serialize, serde::Deserialize)]
242#[derive(Parse, Formattable, Format, Print)]
243pub struct PredicateLoopExpression {
244	pub for_: token::While,
245	#[format(prefix_ws = Whitespace::SINGLE)]
246	pub cond: Conditions,
247	#[format(prefix_ws = Whitespace::SINGLE)]
248	pub body: BlockExpression,
249}
250
251/// `InfiniteLoopExpression`
252#[derive(PartialEq, Eq, Clone, Debug)]
253#[derive(serde::Serialize, serde::Deserialize)]
254#[derive(Parse, Formattable, Format, Print)]
255pub struct InfiniteLoopExpression {
256	pub loop_: token::Loop,
257	#[format(prefix_ws = Whitespace::SINGLE)]
258	pub body:  BlockExpression,
259}
260
261/// `LabelBlockExpression`
262#[derive(PartialEq, Eq, Clone, Debug)]
263#[derive(serde::Serialize, serde::Deserialize)]
264#[derive(Parse, Formattable, Format, Print)]
265pub struct LabelBlockExpression(BlockExpression);