Skip to content

Commit 649be92

Browse files
committed
Merge pull request #245 from nrc/bugs
Fix a bunch of misc. bugs I found
2 parents 000ea50 + 183dac9 commit 649be92

File tree

10 files changed

+171
-40
lines changed

10 files changed

+171
-40
lines changed

src/expr.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ fn rewrite_closure(capture: ast::CaptureClause,
203203

204204
let fmt = ListFormatting::for_fn(argument_budget, argument_offset);
205205
let prefix = format!("{}|{}|", mover, write_list(&arg_items.collect::<Vec<_>>(), &fmt));
206-
let block_indent = closure_block_indent(context, offset);
206+
let closure_indent = closure_indent(context, offset);
207207

208208
// Try to format closure body as a single line expression without braces.
209209
if body.stmts.is_empty() {
@@ -232,11 +232,11 @@ fn rewrite_closure(capture: ast::CaptureClause,
232232

233233
// We couldn't format the closure body as a single line expression; fall
234234
// back to block formatting.
235-
let inner_context = &RewriteContext { block_indent: block_indent, ..*context };
235+
let inner_context = context.overflow_context(closure_indent - context.block_indent);
236236
let body_rewrite = if let ast::Expr_::ExprBlock(ref inner) = body.expr.as_ref().unwrap().node {
237-
inner.rewrite(inner_context, 0, 0)
237+
inner.rewrite(&inner_context, 0, 0)
238238
} else {
239-
body.rewrite(inner_context, 0, 0)
239+
body.rewrite(&inner_context, 0, 0)
240240
};
241241

242242
Some(format!("{} {}", prefix, try_opt!(body_rewrite)))
@@ -250,7 +250,7 @@ impl Rewrite for ast::Block {
250250
}
251251

252252
let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config);
253-
visitor.block_indent = context.block_indent;
253+
visitor.block_indent = context.block_indent + context.overflow_indent;
254254

255255
let prefix = match self.rules {
256256
ast::BlockCheckMode::PushUnsafeBlock(..) |
@@ -541,9 +541,9 @@ fn rewrite_match(context: &RewriteContext,
541541
let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6));
542542
let mut result = format!("match {} {{", cond_str);
543543

544-
let block_indent = context.block_indent;
545544
let nested_context = context.nested_context();
546-
let arm_indent_str = make_indent(nested_context.block_indent);
545+
let arm_indent = nested_context.block_indent + context.overflow_indent;
546+
let arm_indent_str = make_indent(arm_indent);
547547

548548
let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])),
549549
"{",
@@ -578,9 +578,8 @@ fn rewrite_match(context: &RewriteContext,
578578
result.push_str(&arm_indent_str);
579579

580580
let arm_str = arm.rewrite(&nested_context,
581-
context.config.max_width -
582-
nested_context.block_indent,
583-
nested_context.block_indent);
581+
context.config.max_width - arm_indent,
582+
arm_indent);
584583
if let Some(ref arm_str) = arm_str {
585584
result.push_str(arm_str);
586585
} else {
@@ -594,7 +593,7 @@ fn rewrite_match(context: &RewriteContext,
594593
// match expression, but meh.
595594

596595
result.push('\n');
597-
result.push_str(&make_indent(block_indent));
596+
result.push_str(&make_indent(context.block_indent + context.overflow_indent));
598597
result.push('}');
599598
Some(result)
600599
}
@@ -694,15 +693,14 @@ impl Rewrite for ast::Arm {
694693
} else {
695694
","
696695
};
697-
let nested_indent = context.block_indent + context.config.tab_spaces;
698696

699697
// Let's try and get the arm body on the same line as the condition.
700698
// 4 = ` => `.len()
701699
if context.config.max_width > line_start + comma.len() + 4 {
702700
let budget = context.config.max_width - line_start - comma.len() - 4;
703701
if let Some(ref body_str) = body.rewrite(context,
704702
budget,
705-
nested_indent) {
703+
line_start + 4) {
706704
if first_line_width(body_str) <= budget {
707705
return Some(format!("{}{} => {}{}",
708706
attr_str.trim_left(),
@@ -720,7 +718,9 @@ impl Rewrite for ast::Arm {
720718
}
721719

722720
let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces));
723-
let body_str = try_opt!(body.rewrite(context, body_budget, nested_indent));
721+
let body_str = try_opt!(body.rewrite(context,
722+
body_budget,
723+
context.block_indent));
724724
Some(format!("{}{} =>\n{}{},",
725725
attr_str.trim_left(),
726726
pats_str,
@@ -868,8 +868,8 @@ fn rewrite_call(context: &RewriteContext,
868868
// 2 is for parens.
869869
let remaining_width = try_opt!(width.checked_sub(extra_offset + 2));
870870
let offset = offset + extra_offset + 1;
871-
let block_indent = expr_block_indent(context, offset);
872-
let inner_context = &RewriteContext { block_indent: block_indent, ..*context };
871+
let inner_indent = expr_indent(context, offset);
872+
let inner_context = context.overflow_context(inner_indent - context.block_indent);
873873

874874
let items = itemize_list(context.codemap,
875875
args.iter(),
@@ -878,7 +878,7 @@ fn rewrite_call(context: &RewriteContext,
878878
|item| item.span.hi,
879879
// Take old span when rewrite fails.
880880
|item| {
881-
item.rewrite(inner_context, remaining_width, offset)
881+
item.rewrite(&inner_context, remaining_width, offset)
882882
.unwrap_or(context.snippet(item.span))
883883
},
884884
callee.span.hi + BytePos(1),
@@ -901,8 +901,8 @@ macro_rules! block_indent_helper {
901901
);
902902
}
903903

904-
block_indent_helper!(expr_block_indent, expr_indent_style);
905-
block_indent_helper!(closure_block_indent, closure_indent_style);
904+
block_indent_helper!(expr_indent, expr_indent_style);
905+
block_indent_helper!(closure_indent, closure_indent_style);
906906

907907
fn rewrite_paren(context: &RewriteContext,
908908
subexpr: &ast::Expr,
@@ -1192,7 +1192,9 @@ pub fn rewrite_assign_rhs<S: Into<String>>(context: &RewriteContext,
11921192
result.push_str(&format!("\n{}", make_indent(new_offset)));
11931193

11941194
let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1));
1195-
let rhs = try_opt!(ex.rewrite(&context, max_width, new_offset));
1195+
let rhs = try_opt!(ex.rewrite(&context.overflow_context(context.config.tab_spaces),
1196+
max_width,
1197+
new_offset));
11961198

11971199
result.push_str(&rhs);
11981200
}

src/items.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -632,13 +632,11 @@ impl<'a> FmtVisitor<'a> {
632632
let break_line = !is_tuple || generics_str.contains('\n') ||
633633
single_line_cost as usize + used_budget > self.config.max_width;
634634

635-
if break_line {
635+
let tactic = if break_line {
636636
let indentation = make_indent(offset + self.config.tab_spaces);
637637
result.push('\n');
638638
result.push_str(&indentation);
639-
}
640639

641-
let tactic = if break_line {
642640
ListTactic::Vertical
643641
} else {
644642
ListTactic::Horizontal

src/lists.rs

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,11 @@ impl<'a> ListFormatting<'a> {
7070

7171
pub struct ListItem {
7272
pub pre_comment: Option<String>,
73-
// Item should include attributes and doc comments
73+
// Item should include attributes and doc comments.
7474
pub item: String,
7575
pub post_comment: Option<String>,
76+
// Whether there is extra whitespace before this item.
77+
pub new_lines: bool,
7678
}
7779

7880
impl ListItem {
@@ -86,7 +88,7 @@ impl ListItem {
8688
}
8789

8890
pub fn from_str<S: Into<String>>(s: S) -> ListItem {
89-
ListItem { pre_comment: None, item: s.into(), post_comment: None }
91+
ListItem { pre_comment: None, item: s.into(), post_comment: None, new_lines: false }
9092
}
9193
}
9294

@@ -206,10 +208,8 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
206208

207209
// Post-comments
208210
if tactic != ListTactic::Vertical && item.post_comment.is_some() {
209-
let formatted_comment = rewrite_comment(item.post_comment.as_ref().unwrap(),
210-
true,
211-
formatting.v_width,
212-
0);
211+
let comment = item.post_comment.as_ref().unwrap();
212+
let formatted_comment = rewrite_comment(comment, true, formatting.v_width, 0);
213213

214214
result.push(' ');
215215
result.push_str(&formatted_comment);
@@ -234,6 +234,10 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
234234
result.push(' ');
235235
result.push_str(&formatted_comment);
236236
}
237+
238+
if !last && tactic == ListTactic::Vertical && item.new_lines {
239+
result.push('\n');
240+
}
237241
}
238242

239243
result
@@ -264,13 +268,14 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
264268
let white_space: &[_] = &[' ', '\t'];
265269

266270
self.inner.next().map(|item| {
271+
let mut new_lines = false;
267272
// Pre-comment
268273
let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end,
269274
(self.get_lo)(&item)))
270275
.unwrap();
271-
let pre_snippet = pre_snippet.trim();
272-
let pre_comment = if !pre_snippet.is_empty() {
273-
Some(pre_snippet.to_owned())
276+
let trimmed_pre_snippet = pre_snippet.trim();
277+
let pre_comment = if !trimmed_pre_snippet.is_empty() {
278+
Some(trimmed_pre_snippet.to_owned())
274279
} else {
275280
None
276281
};
@@ -307,7 +312,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
307312
separator_index + 1)
308313
}
309314
// Potential *single* line comment.
310-
(_, Some(j)) => { j + 1 }
315+
(_, Some(j)) => j + 1,
311316
_ => post_snippet.len()
312317
}
313318
},
@@ -317,18 +322,40 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
317322
}
318323
};
319324

325+
if !post_snippet.is_empty() && comment_end > 0 {
326+
// Account for extra whitespace between items. This is fiddly
327+
// because of the way we divide pre- and post- comments.
328+
329+
// Everything from the separator to the next item.
330+
let test_snippet = &post_snippet[comment_end-1..];
331+
let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len());
332+
// From the end of the first line of comments.
333+
let test_snippet = &test_snippet[first_newline..];
334+
let first = test_snippet.find(|c: char| !c.is_whitespace())
335+
.unwrap_or(test_snippet.len());
336+
// From the end of the first line of comments to the next non-whitespace char.
337+
let test_snippet = &test_snippet[..first];
338+
339+
if test_snippet.chars().filter(|c| c == &'\n').count() > 1 {
340+
// There were multiple line breaks which got trimmed to nothing.
341+
new_lines = true;
342+
}
343+
}
344+
320345
// Cleanup post-comment: strip separators and whitespace.
321346
self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32);
322-
let mut post_snippet = post_snippet[..comment_end].trim();
347+
let post_snippet = post_snippet[..comment_end].trim();
323348

324-
if post_snippet.starts_with(',') {
325-
post_snippet = post_snippet[1..].trim_matches(white_space);
349+
let post_snippet_trimmed = if post_snippet.starts_with(',') {
350+
post_snippet[1..].trim_matches(white_space)
326351
} else if post_snippet.ends_with(",") {
327-
post_snippet = post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space);
328-
}
352+
post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
353+
} else {
354+
post_snippet
355+
};
329356

330-
let post_comment = if !post_snippet.is_empty() {
331-
Some(post_snippet.to_owned())
357+
let post_comment = if !post_snippet_trimmed.is_empty() {
358+
Some(post_snippet_trimmed.to_owned())
332359
} else {
333360
None
334361
};
@@ -337,6 +364,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
337364
pre_comment: pre_comment,
338365
item: (self.get_item_string)(&item),
339366
post_comment: post_comment,
367+
new_lines: new_lines,
340368
}
341369
})
342370
}

src/rewrite.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,14 @@ pub trait Rewrite {
2828
pub struct RewriteContext<'a> {
2929
pub codemap: &'a CodeMap,
3030
pub config: &'a Config,
31+
32+
// Indentation due to nesting of blocks.
3133
pub block_indent: usize,
34+
// *Extra* indentation due to overflowing to the next line, e.g.,
35+
// let foo =
36+
// bar();
37+
// The extra 4 spaces when formatting `bar()` is overflow_indent.
38+
pub overflow_indent: usize,
3239
}
3340

3441
impl<'a> RewriteContext<'a> {
@@ -37,6 +44,16 @@ impl<'a> RewriteContext<'a> {
3744
codemap: self.codemap,
3845
config: self.config,
3946
block_indent: self.block_indent + self.config.tab_spaces,
47+
overflow_indent: self.overflow_indent,
48+
}
49+
}
50+
51+
pub fn overflow_context(&self, overflow: usize) -> RewriteContext<'a> {
52+
RewriteContext {
53+
codemap: self.codemap,
54+
config: self.config,
55+
block_indent: self.block_indent,
56+
overflow_indent: overflow,
4057
}
4158
}
4259

src/visitor.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ impl<'a> FmtVisitor<'a> {
338338
codemap: self.codemap,
339339
config: self.config,
340340
block_indent: self.block_indent,
341+
overflow_indent: 0,
341342
};
342343
// 1 = ";"
343344
match vp.rewrite(&context, self.config.max_width - offset - 1, offset) {
@@ -369,6 +370,7 @@ impl<'a> FmtVisitor<'a> {
369370
codemap: self.codemap,
370371
config: self.config,
371372
block_indent: self.block_indent,
373+
overflow_indent: 0,
372374
}
373375
}
374376
}

tests/source/struct_lits.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ fn main() {
3232
second: Item
3333
};
3434

35+
Some(Data::MethodCallData(MethodCallData {
36+
span: sub_span.unwrap(),
37+
scope: self.enclosing_scope(id),
38+
ref_id: def_id,
39+
decl_id: Some(decl_id),
40+
}));
41+
3542
Diagram { /* o This graph demonstrates how
3643
* / \ significant whitespace is
3744
* o o preserved.

tests/source/structs.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,43 @@ pub struct Foo<'a, Y: Baz>
4949
}
5050

5151
struct Baz {
52+
5253
a: A, // Comment A
5354
b: B, // Comment B
5455
c: C, // Comment C
56+
57+
}
58+
59+
struct Baz {
60+
a: A, // Comment A
61+
62+
b: B, // Comment B
63+
64+
65+
66+
67+
c: C, // Comment C
68+
}
69+
70+
struct Baz {
71+
72+
a: A,
73+
74+
b: B,
75+
c: C,
76+
77+
78+
79+
80+
d: D
81+
5582
}
5683

5784
struct Baz
5885
{
5986
// Comment A
6087
a: A,
88+
6189
// Comment B
6290
b: B,
6391
// Comment C

0 commit comments

Comments
 (0)