1
Fork 0

Preserve some whitespace between struct fields etc.

This commit is contained in:
Nick Cameron 2015-09-02 14:11:19 +12:00
parent 000ea50123
commit 97e92b35cc
4 changed files with 94 additions and 22 deletions

View file

@ -632,13 +632,11 @@ impl<'a> FmtVisitor<'a> {
let break_line = !is_tuple || generics_str.contains('\n') || let break_line = !is_tuple || generics_str.contains('\n') ||
single_line_cost as usize + used_budget > self.config.max_width; single_line_cost as usize + used_budget > self.config.max_width;
if break_line { let tactic = if break_line {
let indentation = make_indent(offset + self.config.tab_spaces); let indentation = make_indent(offset + self.config.tab_spaces);
result.push('\n'); result.push('\n');
result.push_str(&indentation); result.push_str(&indentation);
}
let tactic = if break_line {
ListTactic::Vertical ListTactic::Vertical
} else { } else {
ListTactic::Horizontal ListTactic::Horizontal

View file

@ -70,9 +70,11 @@ impl<'a> ListFormatting<'a> {
pub struct ListItem { pub struct ListItem {
pub pre_comment: Option<String>, pub pre_comment: Option<String>,
// Item should include attributes and doc comments // Item should include attributes and doc comments.
pub item: String, pub item: String,
pub post_comment: Option<String>, pub post_comment: Option<String>,
// Whether there is extra whitespace before this item.
pub new_lines: bool,
} }
impl ListItem { impl ListItem {
@ -86,7 +88,7 @@ impl ListItem {
} }
pub fn from_str<S: Into<String>>(s: S) -> ListItem { pub fn from_str<S: Into<String>>(s: S) -> ListItem {
ListItem { pre_comment: None, item: s.into(), post_comment: None } ListItem { pre_comment: None, item: s.into(), post_comment: None, new_lines: false }
} }
} }
@ -206,10 +208,8 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
// Post-comments // Post-comments
if tactic != ListTactic::Vertical && item.post_comment.is_some() { if tactic != ListTactic::Vertical && item.post_comment.is_some() {
let formatted_comment = rewrite_comment(item.post_comment.as_ref().unwrap(), let comment = item.post_comment.as_ref().unwrap();
true, let formatted_comment = rewrite_comment(comment, true, formatting.v_width, 0);
formatting.v_width,
0);
result.push(' '); result.push(' ');
result.push_str(&formatted_comment); result.push_str(&formatted_comment);
@ -234,6 +234,10 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
result.push(' '); result.push(' ');
result.push_str(&formatted_comment); result.push_str(&formatted_comment);
} }
if !last && tactic == ListTactic::Vertical && item.new_lines {
result.push('\n');
}
} }
result result
@ -264,13 +268,14 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
let white_space: &[_] = &[' ', '\t']; let white_space: &[_] = &[' ', '\t'];
self.inner.next().map(|item| { self.inner.next().map(|item| {
let mut new_lines = false;
// Pre-comment // Pre-comment
let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end, let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end,
(self.get_lo)(&item))) (self.get_lo)(&item)))
.unwrap(); .unwrap();
let pre_snippet = pre_snippet.trim(); let trimmed_pre_snippet = pre_snippet.trim();
let pre_comment = if !pre_snippet.is_empty() { let pre_comment = if !trimmed_pre_snippet.is_empty() {
Some(pre_snippet.to_owned()) Some(trimmed_pre_snippet.to_owned())
} else { } else {
None None
}; };
@ -307,7 +312,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
separator_index + 1) separator_index + 1)
} }
// Potential *single* line comment. // Potential *single* line comment.
(_, Some(j)) => { j + 1 } (_, Some(j)) => j + 1,
_ => post_snippet.len() _ => post_snippet.len()
} }
}, },
@ -317,18 +322,40 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
} }
}; };
// Cleanup post-comment: strip separators and whitespace. if !post_snippet.is_empty() && comment_end > 0 {
self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); // Account for extra whitespace between items. This is fiddly
let mut post_snippet = post_snippet[..comment_end].trim(); // because of the way we divide pre- and post- comments.
if post_snippet.starts_with(',') { // Everything from the separator to the next item.
post_snippet = post_snippet[1..].trim_matches(white_space); let test_snippet = &post_snippet[comment_end-1..];
} else if post_snippet.ends_with(",") { let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len());
post_snippet = post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space); // From the end of the first line of comments.
let test_snippet = &test_snippet[first_newline..];
let first = test_snippet.find(|c: char| !c.is_whitespace())
.unwrap_or(test_snippet.len());
// From the end of the first line of comments to the next non-whitespace char.
let test_snippet = &test_snippet[..first];
if test_snippet.chars().filter(|c| c == &'\n').count() > 1 {
// There were multiple line breaks which got trimmed to nothing.
new_lines = true;
}
} }
let post_comment = if !post_snippet.is_empty() { // Cleanup post-comment: strip separators and whitespace.
Some(post_snippet.to_owned()) self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32);
let post_snippet = post_snippet[..comment_end].trim();
let post_snippet_trimmed = if post_snippet.starts_with(',') {
post_snippet[1..].trim_matches(white_space)
} else if post_snippet.ends_with(",") {
post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
} else {
post_snippet
};
let post_comment = if !post_snippet_trimmed.is_empty() {
Some(post_snippet_trimmed.to_owned())
} else { } else {
None None
}; };
@ -337,6 +364,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
pre_comment: pre_comment, pre_comment: pre_comment,
item: (self.get_item_string)(&item), item: (self.get_item_string)(&item),
post_comment: post_comment, post_comment: post_comment,
new_lines: new_lines,
} }
}) })
} }

View file

@ -49,15 +49,43 @@ pub struct Foo<'a, Y: Baz>
} }
struct Baz { struct Baz {
a: A, // Comment A a: A, // Comment A
b: B, // Comment B b: B, // Comment B
c: C, // Comment C c: C, // Comment C
}
struct Baz {
a: A, // Comment A
b: B, // Comment B
c: C, // Comment C
}
struct Baz {
a: A,
b: B,
c: C,
d: D
} }
struct Baz struct Baz
{ {
// Comment A // Comment A
a: A, a: A,
// Comment B // Comment B
b: B, b: B,
// Comment C // Comment C

View file

@ -54,9 +54,27 @@ struct Baz {
c: C, // Comment C c: C, // Comment C
} }
struct Baz {
a: A, // Comment A
b: B, // Comment B
c: C, // Comment C
}
struct Baz {
a: A,
b: B,
c: C,
d: D,
}
struct Baz { struct Baz {
// Comment A // Comment A
a: A, a: A,
// Comment B // Comment B
b: B, b: B,
// Comment C // Comment C