use crate::algorithm::Printer;
use crate::INDENT;
use syn::{BinOp, Expr, Stmt};
impl Printer {
pub fn stmt(&mut self, stmt: &Stmt) {
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.expr(&local_init.expr);
if let Some((_else, diverge)) = &local_init.diverge {
self.space();
self.word("else ");
self.end();
self.neverbreak();
if let Expr::Block(expr) = diverge.as_ref() {
self.cbox(INDENT);
self.small_block(&expr.block, &[]);
self.end();
} else {
self.word("{");
self.space();
self.ibox(INDENT);
self.expr(diverge);
self.end();
self.space();
self.offset(-INDENT);
self.word("}");
}
} else {
self.end();
}
} else {
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, true);
if add_semi(expr) {
self.word(";");
}
self.end();
self.hardbreak();
} else {
self.expr_beginning_of_line(expr, true);
}
}
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, true);
if !remove_semi(expr) {
self.word(";");
}
self.end();
self.hardbreak();
}
Stmt::Macro(stmt) => {
self.outer_attrs(&stmt.attrs);
let semicolon = true;
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::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::Reference(_)
| Expr::Repeat(_)
| Expr::Return(_)
| Expr::Struct(_)
| Expr::Try(_)
| Expr::TryBlock(_)
| Expr::Tuple(_)
| Expr::Unary(_)
| Expr::Unsafe(_)
| Expr::Verbatim(_)
| Expr::Yield(_) => false,
_ => false,
}
}