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