1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
use rustc_ast::ast; use rustc_span::Span; use crate::comment::recover_comment_removed; use crate::config::Version; use crate::expr::{format_expr, ExprType}; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; use crate::spanned::Spanned; use crate::utils::semicolon_for_stmt; pub(crate) struct Stmt<'a> { inner: &'a ast::Stmt, is_last: bool, } impl<'a> Spanned for Stmt<'a> { fn span(&self) -> Span { self.inner.span() } } impl<'a> Stmt<'a> { pub(crate) fn as_ast_node(&self) -> &ast::Stmt { self.inner } pub(crate) fn to_item(&self) -> Option<&ast::Item> { match self.inner.kind { ast::StmtKind::Item(ref item) => Some(&**item), _ => None, } } pub(crate) fn from_ast_node(inner: &'a ast::Stmt, is_last: bool) -> Self { Stmt { inner, is_last } } pub(crate) fn from_ast_nodes<I>(iter: I) -> Vec<Self> where I: Iterator<Item = &'a ast::Stmt>, { let mut result = vec![]; let mut iter = iter.peekable(); while iter.peek().is_some() { result.push(Stmt { inner: iter.next().unwrap(), is_last: iter.peek().is_none(), }) } result } pub(crate) fn is_empty(&self) -> bool { matches!(self.inner.kind, ast::StmtKind::Empty) } fn is_last_expr(&self) -> bool { if !self.is_last { return false; } match self.as_ast_node().kind { ast::StmtKind::Expr(ref expr) => match expr.kind { ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { false } _ => true, }, _ => false, } } } impl<'a> Rewrite for Stmt<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { let expr_type = if context.config.version() == Version::Two && self.is_last_expr() { ExprType::SubExpression } else { ExprType::Statement }; format_stmt(context, shape, self.as_ast_node(), expr_type) } } impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { format_stmt(context, shape, self, ExprType::Statement) } } fn format_stmt( context: &RewriteContext<'_>, shape: Shape, stmt: &ast::Stmt, expr_type: ExprType, ) -> Option<String> { skip_out_of_file_lines_range!(context, stmt.span()); let result = match stmt.kind { ast::StmtKind::Local(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt) { ";" } else { "" }; let shape = shape.sub_width(suffix.len())?; format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, }; result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) }