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))
}