• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
stmt(&mut self, stmt: &Stmt, is_last: bool)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 
add_semi(expr: &Expr) -> bool82 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 
break_after(expr: &Expr) -> bool163 pub 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 
remove_semi(expr: &Expr) -> bool172 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