Skip to content

Commit 86679a9

Browse files
committed
Backport rust-lang#4406 - Formatting pre and post cast comments enhancements
1 parent ea017d7 commit 86679a9

File tree

7 files changed

+484
-23
lines changed

7 files changed

+484
-23
lines changed

src/expr.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,34 @@ pub(crate) fn format_expr(
239239
ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => {
240240
rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape)
241241
}
242-
ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair(
243-
&**expr,
244-
&**ty,
245-
PairParts::infix(" as "),
246-
context,
247-
shape,
248-
SeparatorPlace::Front,
249-
),
242+
ast::ExprKind::Cast(ref subexpr, ref ty) => {
243+
/* Retrieving the comments before and after cast */
244+
let prefix_span = mk_sp(
245+
subexpr.span.hi(),
246+
context.snippet_provider.span_before(expr.span, "as"),
247+
);
248+
let suffix_span = mk_sp(
249+
context.snippet_provider.span_after(expr.span, "as"),
250+
ty.span.lo(),
251+
);
252+
let infix_prefix_comments = rewrite_missing_comment(prefix_span, shape, context)?;
253+
let infix_suffix_comments = rewrite_missing_comment(suffix_span, shape, context)?;
254+
255+
rewrite_pair(
256+
&**subexpr,
257+
&**ty,
258+
PairParts::new(
259+
"",
260+
&infix_prefix_comments,
261+
" as ",
262+
&infix_suffix_comments,
263+
"",
264+
),
265+
context,
266+
shape,
267+
SeparatorPlace::Front,
268+
)
269+
}
250270
ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair(
251271
&**expr,
252272
&**ty,
@@ -261,7 +281,7 @@ pub(crate) fn format_expr(
261281
ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair(
262282
&**expr,
263283
&*repeats.value,
264-
PairParts::new("[", "; ", "]"),
284+
PairParts::new("[", "", "; ", "", "]"),
265285
context,
266286
shape,
267287
SeparatorPlace::Back,

src/pairs.rs

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@ use crate::utils::{
1212
#[derive(new, Clone, Copy)]
1313
pub(crate) struct PairParts<'a> {
1414
prefix: &'a str,
15+
infix_prefix: &'a str, /* mainly for pre-infix comments */
1516
infix: &'a str,
17+
infix_suffix: &'a str, /* mainly for post-infix comments */
1618
suffix: &'a str,
1719
}
1820

1921
impl<'a> PairParts<'a> {
2022
pub(crate) fn infix(infix: &'a str) -> PairParts<'a> {
2123
PairParts {
2224
prefix: "",
25+
infix_prefix: "",
2326
infix,
27+
infix_suffix: "",
2428
suffix: "",
2529
}
2630
}
@@ -163,22 +167,32 @@ where
163167
RHS: Rewrite,
164168
{
165169
let tab_spaces = context.config.tab_spaces();
170+
let infix_result = format!("{}{}", pp.infix, pp.infix_suffix);
171+
let infix_suffix_separator = if pp.infix_suffix.is_empty() { "" } else { " " };
172+
let infix_prefix_separator = if pp.infix_prefix.is_empty() { "" } else { " " };
166173
let lhs_overhead = match separator_place {
167-
SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_end().len(),
174+
SeparatorPlace::Back => {
175+
shape.used_width() + pp.prefix.len() + pp.infix.trim_end().len() + pp.infix_prefix.len()
176+
}
168177
SeparatorPlace::Front => shape.used_width(),
169178
};
170179
let lhs_shape = Shape {
171180
width: context.budget(lhs_overhead),
172181
..shape
173182
};
174-
let lhs_result = lhs
175-
.rewrite(context, lhs_shape)
176-
.map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?;
183+
let lhs_result = lhs.rewrite(context, lhs_shape).map(|lhs_str| {
184+
format!(
185+
"{}{}{}{}",
186+
pp.prefix, lhs_str, infix_prefix_separator, pp.infix_prefix
187+
)
188+
})?;
177189

178190
// Try to put both lhs and rhs on the same line.
179191
let rhs_orig_result = shape
180192
.offset_left(last_line_width(&lhs_result) + pp.infix.len())
181-
.and_then(|s| s.sub_width(pp.suffix.len()))
193+
.and_then(|s| {
194+
s.sub_width(pp.suffix.len() + pp.infix_suffix.len() + infix_suffix_separator.len())
195+
})
182196
.and_then(|rhs_shape| rhs.rewrite(context, rhs_shape));
183197
if let Some(ref rhs_result) = rhs_orig_result {
184198
// If the length of the lhs is equal to or shorter than the tab width or
@@ -192,13 +206,13 @@ where
192206
.unwrap_or(false);
193207
if !rhs_result.contains('\n') || allow_same_line {
194208
let one_line_width = last_line_width(&lhs_result)
195-
+ pp.infix.len()
209+
+ infix_result.len()
196210
+ first_line_width(rhs_result)
197211
+ pp.suffix.len();
198212
if one_line_width <= shape.width {
199213
return Some(format!(
200-
"{}{}{}{}",
201-
lhs_result, pp.infix, rhs_result, pp.suffix
214+
"{}{}{}{}{}",
215+
lhs_result, infix_result, infix_suffix_separator, rhs_result, pp.suffix
202216
));
203217
}
204218
}
@@ -219,20 +233,45 @@ where
219233
};
220234
let infix = match separator_place {
221235
SeparatorPlace::Back => pp.infix.trim_end(),
222-
SeparatorPlace::Front => pp.infix.trim_start(),
236+
SeparatorPlace::Front => {
237+
if pp.infix_suffix.is_empty() {
238+
pp.infix.trim_start()
239+
} else {
240+
pp.infix
241+
}
242+
}
243+
};
244+
let infix_suffix = if separator_place == SeparatorPlace::Front && !pp.infix_suffix.is_empty() {
245+
pp.infix_suffix.trim_start()
246+
} else {
247+
pp.infix_suffix
223248
};
224249
if separator_place == SeparatorPlace::Front {
225250
rhs_shape = rhs_shape.offset_left(infix.len())?;
226251
}
227252
let rhs_result = rhs.rewrite(context, rhs_shape)?;
228253
let indent_str = rhs_shape.indent.to_string_with_newline(context.config);
229-
let infix_with_sep = match separator_place {
230-
SeparatorPlace::Back => format!("{}{}", infix, indent_str),
231-
SeparatorPlace::Front => format!("{}{}", indent_str, infix),
254+
let mut infix_with_sep = match separator_place {
255+
SeparatorPlace::Back => format!("{}{}{}", infix, infix_suffix.trim_end(), indent_str),
256+
SeparatorPlace::Front => format!(
257+
"{}{}{}{}",
258+
indent_str,
259+
infix.trim_start(),
260+
infix_suffix,
261+
infix_suffix_separator
262+
),
263+
};
264+
let new_line_width = infix_with_sep.len() - 1 + rhs_result.len() + pp.suffix.len();
265+
let rhs_with_sep = if separator_place == SeparatorPlace::Front && new_line_width > shape.width {
266+
let s: String = String::from(infix_with_sep);
267+
infix_with_sep = s.trim_end().to_string();
268+
format!("{}{}", indent_str, rhs_result.trim_start())
269+
} else {
270+
rhs_result
232271
};
233272
Some(format!(
234273
"{}{}{}{}",
235-
lhs_result, infix_with_sep, rhs_result, pp.suffix
274+
lhs_result, infix_with_sep, rhs_with_sep, pp.suffix
236275
))
237276
}
238277

src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ impl Rewrite for ast::Ty {
805805
ast::TyKind::Array(ref ty, ref repeats) => rewrite_pair(
806806
&**ty,
807807
&*repeats.value,
808-
PairParts::new("[", "; ", "]"),
808+
PairParts::new("[", "", "; ", "", "]"),
809809
context,
810810
shape,
811811
SeparatorPlace::Back,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// rustfmt-version: One
2+
3+
/*****
4+
* Tests for proper formatting of pre and post cast ("as") comments
5+
******/
6+
7+
// Test 1
8+
fn main() {
9+
let x = 0f64 /* x as */ as i32;
10+
}
11+
12+
// Test 2
13+
fn main() {
14+
let x = 1 /* foo as */ as i32;
15+
}
16+
17+
// Test 3
18+
fn main() {
19+
let x = 1 as /* bar as */ i32;
20+
}
21+
22+
// Test 4
23+
fn main() {
24+
let x = 1 /* as foo */ as /* as bar */ i32;
25+
}
26+
27+
// Test 5
28+
fn main() {
29+
let x = 1 /* as foo */as/* as bar */ i32;
30+
}
31+
32+
// Test 6
33+
fn main() {
34+
let x = 1 /* as foo */
35+
as/* as bar */
36+
i32;
37+
}
38+
39+
// Test 7
40+
fn main() {
41+
let x = 1 /* as foo yyyyyyyyyyy */as/* as bar xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ i32;
42+
}
43+
44+
// Test 8
45+
fn main() {
46+
let x = 1 /* as foo yyyyyyyyyyy */as/* as bar xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ i32;
47+
}
48+
49+
// Test 9
50+
fn main() {
51+
let x = 1 /* as foo yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy */
52+
as/* as bar xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
53+
i32;
54+
}
55+
56+
57+
/*****
58+
* Tests for not leaving trailing spaces related to cast comments (related to #2896?)
59+
******/
60+
// Test 10 - extra blank after the binary rhs at the 2nd line (comment followws at 3rd line)
61+
fn main() {
62+
if 0 == 1
63+
/* x */ as i32 {} }
64+
65+
// Test 11 - extra blank after the binary rhs at the end of 2nd line
66+
fn main() {
67+
if 0 == ' '
68+
as i32 {} }
69+
70+
// Test 12 - extra blank after the comment at the end of 2nd line
71+
fn main() {
72+
if 0 == ' ' /* x */
73+
as i32 {} }
74+
75+
76+
/*****
77+
* Tests for not moving "as" to new line unnecessarily - from #3528
78+
******/
79+
fn get_old_backends(old_toml_config: &toml::Value) -> Option<Vec<Box<dyn Backend>>> {
80+
old_toml_config.as_table().and_then(|table| {
81+
table
82+
.get("backends")
83+
.and_then(|backends| backends.as_table())
84+
.map(|backends| {
85+
backends
86+
.into_iter()
87+
.filter_map(|(key, value)| match AvailableBackend::from(key.as_str()) {
88+
AvailableBackend::Git => Some(Box::new(Git {
89+
config: value.clone().try_into::<GitConfig>().unwrap(),
90+
})
91+
as Box<dyn Backend>),
92+
AvailableBackend::Github => Some(Box::new(Github {
93+
config: value.clone().try_into::<GithubConfig>().unwrap(),
94+
})
95+
as Box<dyn Backend>),
96+
})
97+
.collect()
98+
})
99+
})
100+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// rustfmt-version: Two
2+
3+
/*****
4+
* Tests for proper formatting of pre and post cast ("as") comments
5+
******/
6+
7+
// Test 1
8+
fn main() {
9+
let x = 0f64 /* x as */ as i32;
10+
}
11+
12+
// Test 2
13+
fn main() {
14+
let x = 1 /* foo as */ as i32;
15+
}
16+
17+
// Test 3
18+
fn main() {
19+
let x = 1 as /* bar as */ i32;
20+
}
21+
22+
// Test 4
23+
fn main() {
24+
let x = 1 /* as foo */ as /* as bar */ i32;
25+
}
26+
27+
// Test 5
28+
fn main() {
29+
let x = 1 /* as foo */as/* as bar */ i32;
30+
}
31+
32+
// Test 6
33+
fn main() {
34+
let x = 1 /* as foo */
35+
as/* as bar */
36+
i32;
37+
}
38+
39+
// Test 7
40+
fn main() {
41+
let x = 1 /* as foo yyyyyyyyyyy */as/* as bar xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ i32;
42+
}
43+
44+
// Test 8
45+
fn main() {
46+
let x = 1 /* as foo yyyyyyyyyyy */as/* as bar xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ i32;
47+
}
48+
49+
// Test 9
50+
fn main() {
51+
let x = 1 /* as foo yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy */
52+
as/* as bar xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
53+
i32;
54+
}
55+
56+
57+
/*****
58+
* Tests for not leaving trailing spaces related to cast comments (related to #2896?)
59+
******/
60+
// Test 10 - extra blank after the binary rhs at the 2nd line (comment followws at 3rd line)
61+
fn main() {
62+
if 0 == 1
63+
/* x */ as i32 {} }
64+
65+
// Test 11 - extra blank after the binary rhs at the end of 2nd line
66+
fn main() {
67+
if 0 == ' '
68+
as i32 {} }
69+
70+
// Test 12 - extra blank after the comment at the end of 2nd line
71+
fn main() {
72+
if 0 == ' ' /* x */
73+
as i32 {} }
74+
75+
76+
/*****
77+
* Tests for not moving "as" to new line unnecessarily - from #3528
78+
******/
79+
fn get_old_backends(old_toml_config: &toml::Value) -> Option<Vec<Box<dyn Backend>>> {
80+
old_toml_config.as_table().and_then(|table| {
81+
table
82+
.get("backends")
83+
.and_then(|backends| backends.as_table())
84+
.map(|backends| {
85+
backends
86+
.into_iter()
87+
.filter_map(|(key, value)| match AvailableBackend::from(key.as_str()) {
88+
AvailableBackend::Git => Some(Box::new(Git {
89+
config: value.clone().try_into::<GitConfig>().unwrap(),
90+
})
91+
as Box<dyn Backend>),
92+
AvailableBackend::Github => Some(Box::new(Github {
93+
config: value.clone().try_into::<GithubConfig>().unwrap(),
94+
})
95+
as Box<dyn Backend>),
96+
})
97+
.collect()
98+
})
99+
})
100+
}

0 commit comments

Comments
 (0)