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