Skip to content

Commit 979d131

Browse files
committed
Format and preserve attributes on ast::Stmt
1 parent e31a48b commit 979d131

File tree

6 files changed

+117
-83
lines changed

6 files changed

+117
-83
lines changed

src/expr.rs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,10 @@ pub fn format_expr(
130130
ExprType::Statement => {
131131
if is_unsafe_block(block) {
132132
block.rewrite(context, shape)
133-
} else {
133+
} else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) {
134134
// Rewrite block without trying to put it in a single line.
135-
if let rw @ Some(_) = rewrite_empty_block(context, block, shape) {
136-
return rw;
137-
}
135+
rw
136+
} else {
138137
let prefix = try_opt!(block_prefix(context, block, shape));
139138
rewrite_block_with_visitor(context, &prefix, block, shape)
140139
}
@@ -293,17 +292,17 @@ pub fn format_expr(
293292
shape,
294293
),
295294
ast::ExprKind::Catch(ref block) => {
296-
if let rewrite @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape)
297-
{
298-
return rewrite;
295+
if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) {
296+
rw
297+
} else {
298+
// 9 = `do catch `
299+
let budget = shape.width.checked_sub(9).unwrap_or(0);
300+
Some(format!(
301+
"{}{}",
302+
"do catch ",
303+
try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent)))
304+
))
299305
}
300-
// 9 = `do catch `
301-
let budget = shape.width.checked_sub(9).unwrap_or(0);
302-
Some(format!(
303-
"{}{}",
304-
"do catch ",
305-
try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent)))
306-
))
307306
}
308307
};
309308

@@ -883,16 +882,13 @@ impl Rewrite for ast::Stmt {
883882
""
884883
};
885884

886-
format_expr(
887-
ex,
888-
match self.node {
889-
ast::StmtKind::Expr(_) => ExprType::SubExpression,
890-
ast::StmtKind::Semi(_) => ExprType::Statement,
891-
_ => unreachable!(),
892-
},
893-
context,
894-
try_opt!(shape.sub_width(suffix.len())),
895-
).map(|s| s + suffix)
885+
let expr_type = match self.node {
886+
ast::StmtKind::Expr(_) => ExprType::SubExpression,
887+
ast::StmtKind::Semi(_) => ExprType::Statement,
888+
_ => unreachable!(),
889+
};
890+
let shape = try_opt!(shape.sub_width(suffix.len()));
891+
format_expr(ex, expr_type, context, shape).map(|s| s + suffix)
896892
}
897893
ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None,
898894
};

src/items.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,23 @@ impl Rewrite for ast::Local {
5555

5656
skip_out_of_file_lines_range!(context, self.span);
5757

58-
let mut result = "let ".to_owned();
58+
if contains_skip(&self.attrs) {
59+
return None;
60+
}
61+
62+
let attrs_str = try_opt!(self.attrs.rewrite(context, shape));
63+
let mut result = if attrs_str.is_empty() {
64+
"let ".to_owned()
65+
} else {
66+
try_opt!(combine_strs_with_missing_comments(
67+
context,
68+
&attrs_str,
69+
"let ",
70+
mk_sp(self.attrs.last().map(|a| a.span.hi).unwrap(), self.span.lo),
71+
shape,
72+
false,
73+
))
74+
};
5975

6076
// 4 = "let ".len()
6177
let pat_shape = try_opt!(shape.offset_left(4));

src/lib.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,32 +91,46 @@ macro_rules! span_with_attrs_lo_hi {
9191
}
9292
}
9393
}
94+
9495
macro_rules! span_with_attrs {
9596
($this:ident) => {
9697
span_with_attrs_lo_hi!($this, $this.span.lo, $this.span.hi)
9798
}
9899
}
99100

100-
impl Spanned for ast::Expr {
101-
fn span(&self) -> Span {
102-
span_with_attrs!(self)
101+
macro_rules! implement_spanned {
102+
($this:ty) => {
103+
impl Spanned for $this {
104+
fn span(&self) -> Span {
105+
span_with_attrs!(self)
106+
}
107+
}
103108
}
104109
}
105110

106-
impl Spanned for ast::Item {
107-
fn span(&self) -> Span {
108-
span_with_attrs!(self)
109-
}
110-
}
111+
// Implement `Spanned` for structs with `attrs` field.
112+
implement_spanned!(ast::Expr);
113+
implement_spanned!(ast::Field);
114+
implement_spanned!(ast::ForeignItem);
115+
implement_spanned!(ast::Item);
116+
implement_spanned!(ast::Local);
111117

112118
impl Spanned for ast::Stmt {
113119
fn span(&self) -> Span {
114120
match self.node {
115-
// Cover attributes
121+
ast::StmtKind::Local(ref local) => mk_sp(local.span().lo, self.span.hi),
122+
ast::StmtKind::Item(ref item) => mk_sp(item.span().lo, self.span.hi),
116123
ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
117124
mk_sp(expr.span().lo, self.span.hi)
118125
}
119-
_ => self.span,
126+
ast::StmtKind::Mac(ref mac) => {
127+
let (_, _, ref attrs) = **mac;
128+
if attrs.is_empty() {
129+
self.span
130+
} else {
131+
mk_sp(attrs[0].span.lo, self.span.hi)
132+
}
133+
}
120134
}
121135
}
122136
}
@@ -155,12 +169,6 @@ impl Spanned for ast::StructField {
155169
}
156170
}
157171

158-
impl Spanned for ast::Field {
159-
fn span(&self) -> Span {
160-
span_with_attrs!(self)
161-
}
162-
}
163-
164172
impl Spanned for ast::WherePredicate {
165173
fn span(&self) -> Span {
166174
match *self {
@@ -208,12 +216,6 @@ impl Spanned for ast::TyParamBound {
208216
}
209217
}
210218

211-
impl Spanned for ast::ForeignItem {
212-
fn span(&self) -> Span {
213-
span_with_attrs!(self)
214-
}
215-
}
216-
217219
#[derive(Copy, Clone, Debug)]
218220
pub struct Indent {
219221
// Width of the block indent, in characters. Must be a multiple of

src/visitor.rs

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, Sepa
3030
use macros::{rewrite_macro, MacroPosition};
3131
use regex::Regex;
3232
use rewrite::{Rewrite, RewriteContext};
33-
use utils::{self, contains_skip, mk_sp};
33+
use utils::{self, contains_skip, inner_attributes, mk_sp};
3434

3535
fn is_use_item(item: &ast::Item) -> bool {
3636
match item.node {
@@ -73,47 +73,23 @@ impl<'a> FmtVisitor<'a> {
7373
ast::StmtKind::Item(ref item) => {
7474
self.visit_item(item);
7575
}
76-
ast::StmtKind::Local(ref local) => {
77-
let rewrite = if contains_skip(&local.attrs) {
78-
None
79-
} else {
80-
stmt.rewrite(
81-
&self.get_context(),
82-
Shape::indented(self.block_indent, self.config),
83-
)
84-
};
85-
self.push_rewrite(stmt.span, rewrite);
76+
ast::StmtKind::Local(..) => {
77+
let rewrite = stmt.rewrite(&self.get_context(), self.shape());
78+
self.push_rewrite(stmt.span(), rewrite);
8679
}
8780
ast::StmtKind::Expr(ref expr) => {
88-
let rewrite = format_expr(
89-
expr,
90-
ExprType::Statement,
91-
&self.get_context(),
92-
Shape::indented(self.block_indent, self.config),
93-
);
94-
let span = if expr.attrs.is_empty() {
95-
stmt.span
96-
} else {
97-
mk_sp(expr.span().lo, stmt.span.hi)
98-
};
99-
self.push_rewrite(span, rewrite)
81+
let rewrite =
82+
format_expr(expr, ExprType::Statement, &self.get_context(), self.shape());
83+
self.push_rewrite(stmt.span(), rewrite)
10084
}
101-
ast::StmtKind::Semi(ref expr) => {
102-
let rewrite = stmt.rewrite(
103-
&self.get_context(),
104-
Shape::indented(self.block_indent, self.config),
105-
);
106-
let span = if expr.attrs.is_empty() {
107-
stmt.span
108-
} else {
109-
mk_sp(expr.span().lo, stmt.span.hi)
110-
};
111-
self.push_rewrite(span, rewrite)
85+
ast::StmtKind::Semi(..) => {
86+
let rewrite = stmt.rewrite(&self.get_context(), self.shape());
87+
self.push_rewrite(stmt.span(), rewrite)
11288
}
11389
ast::StmtKind::Mac(ref mac) => {
11490
let (ref mac, _macro_style, ref attrs) = **mac;
115-
if contains_skip(attrs) {
116-
self.push_rewrite(mac.span, None);
91+
if self.visit_attrs(attrs, ast::AttrStyle::Outer) {
92+
self.push_rewrite(stmt.span(), None);
11793
} else {
11894
self.visit_mac(mac, None, MacroPosition::Statement);
11995
}

tests/source/attrib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,25 @@ impl InnerAttributes() {
124124
mod InnerAttributes {
125125
#![ this_is_an_inner_attribute ( foo ) ]
126126
}
127+
128+
fn attributes_on_statements() {
129+
// Local
130+
# [ attr ( on ( local ) ) ]
131+
let x = 3;
132+
133+
// Item
134+
# [ attr ( on ( item ) ) ]
135+
use foo;
136+
137+
// Expr
138+
# [ attr ( on ( expr ) ) ]
139+
{}
140+
141+
// Semi
142+
# [ attr ( on ( semi ) ) ]
143+
foo();
144+
145+
// Mac
146+
# [ attr ( on ( mac ) ) ]
147+
foo!();
148+
}

tests/target/attrib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,25 @@ impl InnerAttributes() {
124124
mod InnerAttributes {
125125
#![this_is_an_inner_attribute(foo)]
126126
}
127+
128+
fn attributes_on_statements() {
129+
// Local
130+
#[attr(on(local))]
131+
let x = 3;
132+
133+
// Item
134+
#[attr(on(item))]
135+
use foo;
136+
137+
// Expr
138+
#[attr(on(expr))]
139+
{}
140+
141+
// Semi
142+
#[attr(on(semi))]
143+
foo();
144+
145+
// Mac
146+
#[attr(on(mac))]
147+
foo!();
148+
}

0 commit comments

Comments
 (0)