Skip to content

Commit c4789a0

Browse files
authored
Prevent including preceeding whitespaces if line contains non blanks (rust-lang#14480)
This extra condition prevents a problem when removing the '}' in: ```rust ( // There was an opening bracket after the parenthesis, which has been removed // This is a comment }) ``` Removing the whitespaces, including the linefeed, before the '}', would put the closing parenthesis at the end of the `// This is a comment` line, which would make it part of the comment as well. In this case, it is best to keep the span on the '}' alone. changelog: none Note to reviewer: `manual_inspect` and `collapsible_if` were two lints exhibiting this problem in cooked up test cases, which have been included as non-regression tests.
2 parents fe4dd5b + 9b1945d commit c4789a0

9 files changed

+98
-12
lines changed

clippy_utils/src/source.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,19 @@ pub trait SpanRangeExt: SpanRange {
142142
map_range(cx.sess().source_map(), self.into_range(), f)
143143
}
144144

145-
/// Extends the range to include all preceding whitespace characters.
145+
/// Extends the range to include all preceding whitespace characters, unless there
146+
/// are non-whitespace characters left on the same line after `self`.
147+
///
148+
/// This extra condition prevents a problem when removing the '}' in:
149+
/// ```ignore
150+
/// ( // There was an opening bracket after the parenthesis, which has been removed
151+
/// // This is a comment
152+
/// })
153+
/// ```
154+
/// Removing the whitespaces, including the linefeed, before the '}', would put the
155+
/// closing parenthesis at the end of the `// This is a comment` line, which would
156+
/// make it part of the comment as well. In this case, it is best to keep the span
157+
/// on the '}' alone.
146158
fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
147159
with_leading_whitespace(cx.sess().source_map(), self.into_range())
148160
}
@@ -263,10 +275,15 @@ fn map_range(
263275
}
264276

265277
fn with_leading_whitespace(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
266-
map_range(sm, sp.clone(), |src, range| {
267-
Some(src.get(..range.start)?.trim_end().len()..range.end)
278+
map_range(sm, sp, |src, range| {
279+
let non_blank_after = src.len() - src.get(range.end..)?.trim_start().len();
280+
if src.get(range.end..non_blank_after)?.contains(['\r', '\n']) {
281+
Some(src.get(..range.start)?.trim_end().len()..range.end)
282+
} else {
283+
Some(range)
284+
}
268285
})
269-
.unwrap_or(sp)
286+
.unwrap()
270287
}
271288

272289
fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {

tests/ui-toml/collapsible_if/collapsible_if.fixed

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn main() {
1313
//~^^^^^^ collapsible_if
1414

1515
// The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
16-
if x == "hello" // Inner comment
16+
if x == "hello" // Inner comment
1717
&& y == "world" {
1818
println!("Hello world!");
1919
}
@@ -26,7 +26,7 @@ fn main() {
2626
}
2727
//~^^^^^^ collapsible_if
2828

29-
if x == "hello" /* Inner comment */
29+
if x == "hello" /* Inner comment */
3030
&& y == "world" {
3131
println!("Hello world!");
3232
}

tests/ui-toml/collapsible_if/collapsible_if.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ LL | | }
3232
|
3333
help: collapse nested if block
3434
|
35-
LL ~ if x == "hello" // Inner comment
35+
LL ~ if x == "hello" // Inner comment
3636
LL ~ && y == "world" {
3737
LL | println!("Hello world!");
3838
LL ~ }
@@ -70,7 +70,7 @@ LL | | }
7070
|
7171
help: collapse nested if block
7272
|
73-
LL ~ if x == "hello" /* Inner comment */
73+
LL ~ if x == "hello" /* Inner comment */
7474
LL ~ && y == "world" {
7575
LL | println!("Hello world!");
7676
LL ~ }

tests/ui/collapsible_if.fixed

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,13 @@ fn main() {
152152
}
153153
}
154154
}
155+
156+
#[rustfmt::skip]
157+
fn layout_check() -> u32 {
158+
if true
159+
&& true {
160+
}
161+
// This is a comment, do not collapse code to it
162+
; 3
163+
//~^^^^^ collapsible_if
164+
}

tests/ui/collapsible_if.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,13 @@ fn main() {
162162
}
163163
}
164164
}
165+
166+
#[rustfmt::skip]
167+
fn layout_check() -> u32 {
168+
if true {
169+
if true {
170+
}
171+
// This is a comment, do not collapse code to it
172+
}; 3
173+
//~^^^^^ collapsible_if
174+
}

tests/ui/collapsible_if.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,23 @@ LL | println!("No comment, linted");
172172
LL ~ }
173173
|
174174

175-
error: aborting due to 10 previous errors
175+
error: this `if` statement can be collapsed
176+
--> tests/ui/collapsible_if.rs:168:5
177+
|
178+
LL | / if true {
179+
LL | | if true {
180+
... |
181+
LL | | }; 3
182+
| |_____^
183+
|
184+
help: collapse nested if block
185+
|
186+
LL ~ if true
187+
LL ~ && true {
188+
LL | }
189+
LL | // This is a comment, do not collapse code to it
190+
LL ~ ; 3
191+
|
192+
193+
error: aborting due to 11 previous errors
176194

tests/ui/manual_inspect.fixed

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ fn main() {
107107
let _ = || {
108108
let _x = x;
109109
};
110-
return;
110+
return ;
111111
}
112112
println!("test");
113113
});
@@ -185,3 +185,12 @@ fn main() {
185185
});
186186
}
187187
}
188+
189+
#[rustfmt::skip]
190+
fn layout_check() {
191+
if let Some(x) = Some(1).inspect(|&x| { println!("{x}"); //~ manual_inspect
192+
// Do not collapse code into this comment
193+
}) {
194+
println!("{x}");
195+
}
196+
}

tests/ui/manual_inspect.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,12 @@ fn main() {
197197
});
198198
}
199199
}
200+
201+
#[rustfmt::skip]
202+
fn layout_check() {
203+
if let Some(x) = Some(1).map(|x| { println!("{x}"); //~ manual_inspect
204+
// Do not collapse code into this comment
205+
x }) {
206+
println!("{x}");
207+
}
208+
}

tests/ui/manual_inspect.stderr

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ LL | if x.is_empty() {
9898
LL | let _ = || {
9999
LL ~ let _x = x;
100100
LL | };
101-
LL ~ return;
101+
LL ~ return ;
102102
LL | }
103103
LL ~ println!("test");
104104
|
@@ -187,5 +187,18 @@ LL |
187187
LL ~ println!("{}", x);
188188
|
189189

190-
error: aborting due to 13 previous errors
190+
error: using `map` over `inspect`
191+
--> tests/ui/manual_inspect.rs:203:30
192+
|
193+
LL | if let Some(x) = Some(1).map(|x| { println!("{x}");
194+
| ^^^
195+
|
196+
help: try
197+
|
198+
LL ~ if let Some(x) = Some(1).inspect(|&x| { println!("{x}");
199+
LL | // Do not collapse code into this comment
200+
LL ~ }) {
201+
|
202+
203+
error: aborting due to 14 previous errors
191204

0 commit comments

Comments
 (0)