1 | use crate::algorithm::Printer; |
2 | use crate::classify; |
3 | use crate::expr; |
4 | use crate::fixup::FixupContext; |
5 | use crate::mac; |
6 | use crate::INDENT; |
7 | use syn::{BinOp, Expr, Stmt}; |
8 | |
9 | impl 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 | |
82 | pub 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 | |
163 | pub fn break_after(expr: &Expr) -> bool { |
164 | if let Expr::Group(group: &ExprGroup) = expr { |
165 | if let Expr::Verbatim(verbatim: &TokenStream) = group.expr.as_ref() { |
166 | return !verbatim.is_empty(); |
167 | } |
168 | } |
169 | true |
170 | } |
171 | |
172 | fn 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 | } |
222 | |