| 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 { |
| 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 | |
| 82 | 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 | |
| 163 | pub fn break_after(expr: &Expr) -> bool { |
| 164 | if let Expr::Group(group: &ExprGroup) = expr { |
| 165 | if let Expr::Verbatim(verbatim: &TokenStream) = group.expr.as_ref() { |
| 166 | return !verbatim.is_empty(); |
| 167 | } |
| 168 | } |
| 169 | true |
| 170 | } |
| 171 | |
| 172 | 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 | |