Skip to content

Commit 61042e6

Browse files
studootnrc
authored andcommitted
Fix issue 1124 - detect start of output rather than start of input file when writing output source file (#1133)
* Change required to prevent a trailing space at the end of a separate module being propagated * Detect the start of the output file rather than the start of the input file when deciding whether to output preceding snippets - this stops unnecessary whitespace and blank lines from being inserted when spans and statements are output in an order other than that from the input file. * Add code to prevent space from being added with the prefix snippet if a) the snippet is entirely horizontal whitespace, or b) the snippet contains whitespace followed by a newline. This prevents trailing spaces at the end of a line from being added. * Tests for this issue * Tidy up `match` statements * Add test with blank lines between `use` statements
1 parent d022f05 commit 61042e6

File tree

6 files changed

+57
-11
lines changed

6 files changed

+57
-11
lines changed

src/imports.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,19 +178,26 @@ impl<'a> FmtVisitor<'a> {
178178
// Order the imports by view-path & other import path properties
179179
ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap());
180180
// First, output the span before the first import
181+
let prev_span_str = self.snippet(codemap::mk_sp(self.last_pos, pos_before_first_use_item));
182+
// Look for purely trailing space at the start of the prefix snippet before a linefeed, or
183+
// a prefix that's entirely horizontal whitespace.
184+
let prefix_span_start = match prev_span_str.find('\n') {
185+
Some(offset) if prev_span_str[..offset].trim().is_empty() => {
186+
self.last_pos + BytePos(offset as u32)
187+
}
188+
None if prev_span_str.trim().is_empty() => pos_before_first_use_item,
189+
_ => self.last_pos,
190+
};
181191
// Look for indent (the line part preceding the use is all whitespace) and excise that
182192
// from the prefix
183-
let prev_span_str = self.snippet(codemap::mk_sp(self.last_pos, pos_before_first_use_item));
184193
let span_end = match prev_span_str.rfind('\n') {
185-
Some(offset) => {
186-
if prev_span_str[offset..].trim().is_empty() {
187-
self.last_pos + BytePos(offset as u32)
188-
} else {
189-
pos_before_first_use_item
190-
}
194+
Some(offset) if prev_span_str[offset..].trim().is_empty() => {
195+
self.last_pos + BytePos(offset as u32)
191196
}
192-
None => pos_before_first_use_item,
197+
_ => pos_before_first_use_item,
193198
};
199+
200+
self.last_pos = prefix_span_start;
194201
self.format_missing(span_end);
195202
for ordered in ordered_use_items {
196203
// Fake out the formatter by setting `self.last_pos` to the appropriate location before

src/missed_spans.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ use syntax::codemap::{self, BytePos, Span, Pos};
1414
use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment};
1515

1616
impl<'a> FmtVisitor<'a> {
17+
fn output_at_start(&self) -> bool {
18+
self.buffer.len == 0
19+
}
20+
1721
// TODO these format_missing methods are ugly. Refactor and add unit tests
1822
// for the central whitespace stripping loop.
1923
pub fn format_missing(&mut self, end: BytePos) {
@@ -25,7 +29,7 @@ impl<'a> FmtVisitor<'a> {
2529
let config = self.config;
2630
self.format_missing_inner(end, |this, last_snippet, snippet| {
2731
this.buffer.push_str(last_snippet.trim_right());
28-
if last_snippet == snippet {
32+
if last_snippet == snippet && !this.output_at_start() {
2933
// No new lines in the snippet.
3034
this.buffer.push_str("\n");
3135
}
@@ -41,7 +45,7 @@ impl<'a> FmtVisitor<'a> {
4145

4246
if start == end {
4347
// Do nothing if this is the beginning of the file.
44-
if start != self.codemap.lookup_char_pos(start).file.start_pos {
48+
if !self.output_at_start() {
4549
process_last_snippet(self, "", "");
4650
}
4751
return;

src/visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ impl<'a> FmtVisitor<'a> {
559559
self.last_pos = filemap.start_pos;
560560
self.block_indent = Indent::empty();
561561
self.walk_mod_items(m);
562-
self.format_missing(filemap.end_pos);
562+
self.format_missing_with_indent(filemap.end_pos);
563563
}
564564

565565
pub fn get_context(&self) -> RewriteContext {

tests/config/issue-1124.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
reorder_imports = true

tests/source/issue-1124.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use d; use c; use b; use a;
2+
// The previous line has a space after the `use a;`
3+
4+
mod a { use d; use c; use b; use a; }
5+
6+
use z;
7+
8+
use y;
9+
10+
11+
12+
use x;
13+
use a;

tests/target/issue-1124.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use a;
2+
use b;
3+
use c;
4+
use d;
5+
// The previous line has a space after the `use a;`
6+
7+
mod a {
8+
use a;
9+
use b;
10+
use c;
11+
use d;
12+
}
13+
14+
use a;
15+
16+
17+
18+
use x;
19+
20+
use y;
21+
use z;

0 commit comments

Comments
 (0)