use crate::algorithm::Printer; use crate::classify; use crate::expr; use crate::fixup::FixupContext; use crate::mac; use crate::INDENT; use syn::{BinOp, Expr, Stmt}; impl Printer { pub fn stmt(&mut self, stmt: &Stmt, is_last: bool) { match stmt { Stmt::Local(local) => { self.outer_attrs(&local.attrs); self.ibox(0); self.word("let "); self.pat(&local.pat); if let Some(local_init) = &local.init { self.word(" = "); self.neverbreak(); self.subexpr( &local_init.expr, local_init.diverge.is_some() && classify::expr_trailing_brace(&local_init.expr), FixupContext::NONE, ); if let Some((_else, diverge)) = &local_init.diverge { self.space(); self.word("else "); self.end(); self.neverbreak(); self.cbox(INDENT); if let Some(expr) = expr::simple_block(diverge) { self.small_block(&expr.block, &[]); } else { self.expr_as_small_block(diverge, INDENT); } } } self.end(); self.word(";"); self.hardbreak(); } Stmt::Item(item) => self.item(item), Stmt::Expr(expr, None) => { if break_after(expr) { self.ibox(0); self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt()); if add_semi(expr) { self.word(";"); } self.end(); self.hardbreak(); } else { self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt()); } } Stmt::Expr(expr, Some(_semi)) => { if let Expr::Verbatim(tokens) = expr { if tokens.is_empty() { return; } } self.ibox(0); self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt()); if !remove_semi(expr) { self.word(";"); } self.end(); self.hardbreak(); } Stmt::Macro(stmt) => { self.outer_attrs(&stmt.attrs); let semicolon = stmt.semi_token.is_some() || !is_last && mac::requires_semi(&stmt.mac.delimiter); self.mac(&stmt.mac, None, semicolon); self.hardbreak(); } } } } pub fn add_semi(expr: &Expr) -> bool { match expr { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Expr::Assign(_) | Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) | Expr::Yield(_) => { true } Expr::Binary(expr) => { match expr.op { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] BinOp::AddAssign(_) | BinOp::SubAssign(_) | BinOp::MulAssign(_) | BinOp::DivAssign(_) | BinOp::RemAssign(_) | BinOp::BitXorAssign(_) | BinOp::BitAndAssign(_) | BinOp::BitOrAssign(_) | BinOp::ShlAssign(_) | BinOp::ShrAssign(_) => true, BinOp::Add(_) | BinOp::Sub(_) | BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) | BinOp::And(_) | BinOp::Or(_) | BinOp::BitXor(_) | BinOp::BitAnd(_) | BinOp::BitOr(_) | BinOp::Shl(_) | BinOp::Shr(_) | BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => false, _ => unimplemented!("unknown BinOp"), } } Expr::Group(group) => add_semi(&group.expr), Expr::Array(_) | Expr::Async(_) | Expr::Await(_) | Expr::Block(_) | Expr::Call(_) | Expr::Cast(_) | Expr::Closure(_) | Expr::Const(_) | Expr::Field(_) | Expr::ForLoop(_) | Expr::If(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) | Expr::RawAddr(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Struct(_) | Expr::Try(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unary(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::While(_) => false, _ => false, } } pub fn break_after(expr: &Expr) -> bool { if let Expr::Group(group) = expr { if let Expr::Verbatim(verbatim) = group.expr.as_ref() { return !verbatim.is_empty(); } } true } fn remove_semi(expr: &Expr) -> bool { match expr { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Expr::ForLoop(_) | Expr::While(_) => true, Expr::Group(group) => remove_semi(&group.expr), Expr::If(expr) => match &expr.else_branch { Some((_else_token, else_branch)) => remove_semi(else_branch), None => true, }, Expr::Array(_) | Expr::Assign(_) | Expr::Async(_) | Expr::Await(_) | Expr::Binary(_) | Expr::Block(_) | Expr::Break(_) | Expr::Call(_) | Expr::Cast(_) | Expr::Closure(_) | Expr::Continue(_) | Expr::Const(_) | Expr::Field(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) | Expr::RawAddr(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Struct(_) | Expr::Try(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unary(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::Yield(_) => false, _ => false, } }