prettyplease/
stmt.rs
1use crate::algorithm::Printer;
2use crate::classify;
3use crate::expr;
4use crate::fixup::FixupContext;
5use crate::mac;
6use crate::INDENT;
7use syn::{BinOp, Expr, Stmt};
8
9impl Printer {
10 pub fn stmt(&mut self, stmt: &Stmt, is_last: bool) {
11 match stmt {
12 Stmt::Local(local) => {
13 self.outer_attrs(&local.attrs);
14 self.ibox(0);
15 self.word("let ");
16 self.pat(&local.pat);
17 if let Some(local_init) = &local.init {
18 self.word(" = ");
19 self.neverbreak();
20 self.subexpr(
21 &local_init.expr,
22 local_init.diverge.is_some()
23 && classify::expr_trailing_brace(&local_init.expr),
24 FixupContext::NONE,
25 );
26 if let Some((_else, diverge)) = &local_init.diverge {
27 self.space();
28 self.word("else ");
29 self.end();
30 self.neverbreak();
31 self.cbox(INDENT);
32 if let Some(expr) = expr::simple_block(diverge) {
33 self.small_block(&expr.block, &[]);
34 } else {
35 self.expr_as_small_block(diverge, INDENT);
36 }
37 }
38 }
39 self.end();
40 self.word(";");
41 self.hardbreak();
42 }
43 Stmt::Item(item) => self.item(item),
44 Stmt::Expr(expr, None) => {
45 if break_after(expr) {
46 self.ibox(0);
47 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
48 if add_semi(expr) {
49 self.word(";");
50 }
51 self.end();
52 self.hardbreak();
53 } else {
54 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
55 }
56 }
57 Stmt::Expr(expr, Some(_semi)) => {
58 if let Expr::Verbatim(tokens) = expr {
59 if tokens.is_empty() {
60 return;
61 }
62 }
63 self.ibox(0);
64 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
65 if !remove_semi(expr) {
66 self.word(";");
67 }
68 self.end();
69 self.hardbreak();
70 }
71 Stmt::Macro(stmt) => {
72 self.outer_attrs(&stmt.attrs);
73 let semicolon = stmt.semi_token.is_some()
74 || !is_last && mac::requires_semi(&stmt.mac.delimiter);
75 self.mac(&stmt.mac, None, semicolon);
76 self.hardbreak();
77 }
78 }
79 }
80}
81
82pub fn add_semi(expr: &Expr) -> bool {
83 match expr {
84 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
85 Expr::Assign(_) | Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) | Expr::Yield(_) => {
86 true
87 }
88 Expr::Binary(expr) =>
89 {
90 match expr.op {
91 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
92 BinOp::AddAssign(_)
93 | BinOp::SubAssign(_)
94 | BinOp::MulAssign(_)
95 | BinOp::DivAssign(_)
96 | BinOp::RemAssign(_)
97 | BinOp::BitXorAssign(_)
98 | BinOp::BitAndAssign(_)
99 | BinOp::BitOrAssign(_)
100 | BinOp::ShlAssign(_)
101 | BinOp::ShrAssign(_) => true,
102 BinOp::Add(_)
103 | BinOp::Sub(_)
104 | BinOp::Mul(_)
105 | BinOp::Div(_)
106 | BinOp::Rem(_)
107 | BinOp::And(_)
108 | BinOp::Or(_)
109 | BinOp::BitXor(_)
110 | BinOp::BitAnd(_)
111 | BinOp::BitOr(_)
112 | BinOp::Shl(_)
113 | BinOp::Shr(_)
114 | BinOp::Eq(_)
115 | BinOp::Lt(_)
116 | BinOp::Le(_)
117 | BinOp::Ne(_)
118 | BinOp::Ge(_)
119 | BinOp::Gt(_) => false,
120 _ => unimplemented!("unknown BinOp"),
121 }
122 }
123 Expr::Group(group) => add_semi(&group.expr),
124
125 Expr::Array(_)
126 | Expr::Async(_)
127 | Expr::Await(_)
128 | Expr::Block(_)
129 | Expr::Call(_)
130 | Expr::Cast(_)
131 | Expr::Closure(_)
132 | Expr::Const(_)
133 | Expr::Field(_)
134 | Expr::ForLoop(_)
135 | Expr::If(_)
136 | Expr::Index(_)
137 | Expr::Infer(_)
138 | Expr::Let(_)
139 | Expr::Lit(_)
140 | Expr::Loop(_)
141 | Expr::Macro(_)
142 | Expr::Match(_)
143 | Expr::MethodCall(_)
144 | Expr::Paren(_)
145 | Expr::Path(_)
146 | Expr::Range(_)
147 | Expr::RawAddr(_)
148 | Expr::Reference(_)
149 | Expr::Repeat(_)
150 | Expr::Struct(_)
151 | Expr::Try(_)
152 | Expr::TryBlock(_)
153 | Expr::Tuple(_)
154 | Expr::Unary(_)
155 | Expr::Unsafe(_)
156 | Expr::Verbatim(_)
157 | Expr::While(_) => false,
158
159 _ => false,
160 }
161}
162
163pub fn break_after(expr: &Expr) -> bool {
164 if let Expr::Group(group) = expr {
165 if let Expr::Verbatim(verbatim) = group.expr.as_ref() {
166 return !verbatim.is_empty();
167 }
168 }
169 true
170}
171
172fn remove_semi(expr: &Expr) -> bool {
173 match expr {
174 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
175 Expr::ForLoop(_) | Expr::While(_) => true,
176 Expr::Group(group) => remove_semi(&group.expr),
177 Expr::If(expr) => match &expr.else_branch {
178 Some((_else_token, else_branch)) => remove_semi(else_branch),
179 None => true,
180 },
181
182 Expr::Array(_)
183 | Expr::Assign(_)
184 | Expr::Async(_)
185 | Expr::Await(_)
186 | Expr::Binary(_)
187 | Expr::Block(_)
188 | Expr::Break(_)
189 | Expr::Call(_)
190 | Expr::Cast(_)
191 | Expr::Closure(_)
192 | Expr::Continue(_)
193 | Expr::Const(_)
194 | Expr::Field(_)
195 | Expr::Index(_)
196 | Expr::Infer(_)
197 | Expr::Let(_)
198 | Expr::Lit(_)
199 | Expr::Loop(_)
200 | Expr::Macro(_)
201 | Expr::Match(_)
202 | Expr::MethodCall(_)
203 | Expr::Paren(_)
204 | Expr::Path(_)
205 | Expr::Range(_)
206 | Expr::RawAddr(_)
207 | Expr::Reference(_)
208 | Expr::Repeat(_)
209 | Expr::Return(_)
210 | Expr::Struct(_)
211 | Expr::Try(_)
212 | Expr::TryBlock(_)
213 | Expr::Tuple(_)
214 | Expr::Unary(_)
215 | Expr::Unsafe(_)
216 | Expr::Verbatim(_)
217 | Expr::Yield(_) => false,
218
219 _ => false,
220 }
221}