• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::algorithm::Printer;
2 use crate::INDENT;
3 use syn::{BinOp, Expr, Stmt};
4 
5 impl Printer {
stmt(&mut self, stmt: &Stmt)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 
add_semi(expr: &Expr) -> bool75 pub 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 
break_after(expr: &Expr) -> bool152 pub 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 
remove_semi(expr: &Expr) -> bool161 fn 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 }
210