1use crate::algorithm::Printer;
2use crate::INDENT;
3use syn::{BinOp, Expr, Stmt};
4
5impl 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
83pub fn add_semi(expr: &Expr) -> bool {
84 match expr {
85 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
86 Expr::Assign(_) | Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) | Expr::Yield(_) => {
87 true
88 }
89 Expr::Binary(expr) =>
90 {
91 match expr.op {
92 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
93 BinOp::AddAssign(_)
94 | BinOp::SubAssign(_)
95 | BinOp::MulAssign(_)
96 | BinOp::DivAssign(_)
97 | BinOp::RemAssign(_)
98 | BinOp::BitXorAssign(_)
99 | BinOp::BitAndAssign(_)
100 | BinOp::BitOrAssign(_)
101 | BinOp::ShlAssign(_)
102 | BinOp::ShrAssign(_) => true,
103 BinOp::Add(_)
104 | BinOp::Sub(_)
105 | BinOp::Mul(_)
106 | BinOp::Div(_)
107 | BinOp::Rem(_)
108 | BinOp::And(_)
109 | BinOp::Or(_)
110 | BinOp::BitXor(_)
111 | BinOp::BitAnd(_)
112 | BinOp::BitOr(_)
113 | BinOp::Shl(_)
114 | BinOp::Shr(_)
115 | BinOp::Eq(_)
116 | BinOp::Lt(_)
117 | BinOp::Le(_)
118 | BinOp::Ne(_)
119 | BinOp::Ge(_)
120 | BinOp::Gt(_) => false,
121 _ => unimplemented!("unknown BinOp"),
122 }
123 }
124 Expr::Group(group) => add_semi(&group.expr),
125
126 Expr::Array(_)
127 | Expr::Async(_)
128 | Expr::Await(_)
129 | Expr::Block(_)
130 | Expr::Call(_)
131 | Expr::Cast(_)
132 | Expr::Closure(_)
133 | Expr::Const(_)
134 | Expr::Field(_)
135 | Expr::ForLoop(_)
136 | Expr::If(_)
137 | Expr::Index(_)
138 | Expr::Infer(_)
139 | Expr::Let(_)
140 | Expr::Lit(_)
141 | Expr::Loop(_)
142 | Expr::Macro(_)
143 | Expr::Match(_)
144 | Expr::MethodCall(_)
145 | Expr::Paren(_)
146 | Expr::Path(_)
147 | Expr::Range(_)
148 | Expr::RawAddr(_)
149 | Expr::Reference(_)
150 | Expr::Repeat(_)
151 | Expr::Struct(_)
152 | Expr::Try(_)
153 | Expr::TryBlock(_)
154 | Expr::Tuple(_)
155 | Expr::Unary(_)
156 | Expr::Unsafe(_)
157 | Expr::Verbatim(_)
158 | Expr::While(_) => false,
159
160 _ => false,
161 }
162}
163
164pub fn break_after(expr: &Expr) -> bool {
165 if let Expr::Group(group) = expr {
166 if let Expr::Verbatim(verbatim) = group.expr.as_ref() {
167 return !verbatim.is_empty();
168 }
169 }
170 true
171}
172
173fn remove_semi(expr: &Expr) -> bool {
174 match expr {
175 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
176 Expr::ForLoop(_) | Expr::While(_) => true,
177 Expr::Group(group) => remove_semi(&group.expr),
178 Expr::If(expr) => match &expr.else_branch {
179 Some((_else_token, else_branch)) => remove_semi(else_branch),
180 None => true,
181 },
182
183 Expr::Array(_)
184 | Expr::Assign(_)
185 | Expr::Async(_)
186 | Expr::Await(_)
187 | Expr::Binary(_)
188 | Expr::Block(_)
189 | Expr::Break(_)
190 | Expr::Call(_)
191 | Expr::Cast(_)
192 | Expr::Closure(_)
193 | Expr::Continue(_)
194 | Expr::Const(_)
195 | Expr::Field(_)
196 | Expr::Index(_)
197 | Expr::Infer(_)
198 | Expr::Let(_)
199 | Expr::Lit(_)
200 | Expr::Loop(_)
201 | Expr::Macro(_)
202 | Expr::Match(_)
203 | Expr::MethodCall(_)
204 | Expr::Paren(_)
205 | Expr::Path(_)
206 | Expr::Range(_)
207 | Expr::RawAddr(_)
208 | Expr::Reference(_)
209 | Expr::Repeat(_)
210 | Expr::Return(_)
211 | Expr::Struct(_)
212 | Expr::Try(_)
213 | Expr::TryBlock(_)
214 | Expr::Tuple(_)
215 | Expr::Unary(_)
216 | Expr::Unsafe(_)
217 | Expr::Verbatim(_)
218 | Expr::Yield(_) => false,
219
220 _ => false,
221 }
222}