Skip to content

Commit 6646248

Browse files
authored
Formatting pre and post cast comments enhancements (#4406)
* Fix issues in handling cast pre/post comments and adding test cases * Add target for cast pre/post comments test cases * Add test cases related to #2896 and #3528 * Changes per comments to the original PR
1 parent 4e72871 commit 6646248

File tree

5 files changed

+289
-25
lines changed

5 files changed

+289
-25
lines changed

Diff for: src/formatting/expr.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,34 @@ pub(crate) fn format_expr(
219219
ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => {
220220
rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape)
221221
}
222-
ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair(
223-
&**expr,
224-
&**ty,
225-
PairParts::infix(" as "),
226-
context,
227-
shape,
228-
SeparatorPlace::Front,
229-
),
222+
ast::ExprKind::Cast(ref subexpr, ref ty) => {
223+
/* Retrieving the comments before and after cast */
224+
let prefix_span = mk_sp(
225+
subexpr.span.hi(),
226+
context.snippet_provider.span_before(expr.span, "as"),
227+
);
228+
let suffix_span = mk_sp(
229+
context.snippet_provider.span_after(expr.span, "as"),
230+
ty.span.lo(),
231+
);
232+
let infix_prefix_comments = rewrite_missing_comment(prefix_span, shape, context)?;
233+
let infix_suffix_comments = rewrite_missing_comment(suffix_span, shape, context)?;
234+
235+
rewrite_pair(
236+
&**subexpr,
237+
&**ty,
238+
PairParts::new(
239+
"",
240+
&infix_prefix_comments,
241+
" as ",
242+
&infix_suffix_comments,
243+
"",
244+
),
245+
context,
246+
shape,
247+
SeparatorPlace::Front,
248+
)
249+
}
230250
ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair(
231251
&**expr,
232252
&**ty,
@@ -241,7 +261,7 @@ pub(crate) fn format_expr(
241261
ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair(
242262
&**expr,
243263
&*repeats.value,
244-
PairParts::new("[", "; ", "]"),
264+
PairParts::new("[", "", "; ", "", "]"),
245265
context,
246266
shape,
247267
SeparatorPlace::Back,

Diff for: src/formatting/pairs.rs

+62-15
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,36 @@ use crate::formatting::{
1212
#[derive(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
/// Constructs a new `PairParts`.
21-
pub(crate) fn new(prefix: &'a str, infix: &'a str, suffix: &'a str) -> Self {
22-
Self {
23+
pub(crate) fn new(
24+
prefix: &'a str,
25+
infix_prefix: &'a str,
26+
infix: &'a str,
27+
infix_suffix: &'a str,
28+
suffix: &'a str,
29+
) -> Self {
30+
PairParts {
2331
prefix,
32+
infix_prefix,
2433
infix,
34+
infix_suffix,
2535
suffix,
2636
}
2737
}
2838

2939
pub(crate) fn infix(infix: &'a str) -> PairParts<'a> {
3040
PairParts {
3141
prefix: "",
42+
infix_prefix: "",
3243
infix,
44+
infix_suffix: "",
3345
suffix: "",
3446
}
3547
}
@@ -172,22 +184,32 @@ where
172184
RHS: Rewrite,
173185
{
174186
let tab_spaces = context.config.tab_spaces();
187+
let infix_result = format!("{}{}", pp.infix, pp.infix_suffix);
188+
let infix_suffix_separator = if pp.infix_suffix.is_empty() { "" } else { " " };
189+
let infix_prefix_separator = if pp.infix_prefix.is_empty() { "" } else { " " };
175190
let lhs_overhead = match separator_place {
176-
SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_end().len(),
191+
SeparatorPlace::Back => {
192+
shape.used_width() + pp.prefix.len() + pp.infix.trim_end().len() + pp.infix_prefix.len()
193+
}
177194
SeparatorPlace::Front => shape.used_width(),
178195
};
179196
let lhs_shape = Shape {
180197
width: context.budget(lhs_overhead),
181198
..shape
182199
};
183-
let lhs_result = lhs
184-
.rewrite(context, lhs_shape)
185-
.map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?;
200+
let lhs_result = lhs.rewrite(context, lhs_shape).map(|lhs_str| {
201+
format!(
202+
"{}{}{}{}",
203+
pp.prefix, lhs_str, infix_prefix_separator, pp.infix_prefix
204+
)
205+
})?;
186206

187207
// Try to put both lhs and rhs on the same line.
188208
let rhs_orig_result = shape
189209
.offset_left(last_line_width(&lhs_result) + pp.infix.len())
190-
.and_then(|s| s.sub_width(pp.suffix.len()))
210+
.and_then(|s| {
211+
s.sub_width(pp.suffix.len() + pp.infix_suffix.len() + infix_suffix_separator.len())
212+
})
191213
.and_then(|rhs_shape| rhs.rewrite(context, rhs_shape));
192214
if let Some(ref rhs_result) = rhs_orig_result {
193215
// If the length of the lhs is equal to or shorter than the tab width or
@@ -201,13 +223,13 @@ where
201223
.unwrap_or(false);
202224
if !rhs_result.contains('\n') || allow_same_line {
203225
let one_line_width = last_line_width(&lhs_result)
204-
+ pp.infix.len()
226+
+ infix_result.len()
205227
+ first_line_width(rhs_result)
206228
+ pp.suffix.len();
207229
if one_line_width <= shape.width {
208230
return Some(format!(
209-
"{}{}{}{}",
210-
lhs_result, pp.infix, rhs_result, pp.suffix
231+
"{}{}{}{}{}",
232+
lhs_result, infix_result, infix_suffix_separator, rhs_result, pp.suffix
211233
));
212234
}
213235
}
@@ -228,20 +250,45 @@ where
228250
};
229251
let infix = match separator_place {
230252
SeparatorPlace::Back => pp.infix.trim_end(),
231-
SeparatorPlace::Front => pp.infix.trim_start(),
253+
SeparatorPlace::Front => {
254+
if pp.infix_suffix.is_empty() {
255+
pp.infix.trim_start()
256+
} else {
257+
pp.infix
258+
}
259+
}
260+
};
261+
let infix_suffix = if separator_place == SeparatorPlace::Front && !pp.infix_suffix.is_empty() {
262+
pp.infix_suffix.trim_start()
263+
} else {
264+
pp.infix_suffix
232265
};
233266
if separator_place == SeparatorPlace::Front {
234267
rhs_shape = rhs_shape.offset_left(infix.len())?;
235268
}
236269
let rhs_result = rhs.rewrite(context, rhs_shape)?;
237270
let indent_str = rhs_shape.indent.to_string_with_newline(context.config);
238-
let infix_with_sep = match separator_place {
239-
SeparatorPlace::Back => format!("{}{}", infix, indent_str),
240-
SeparatorPlace::Front => format!("{}{}", indent_str, infix),
271+
let mut infix_with_sep = match separator_place {
272+
SeparatorPlace::Back => format!("{}{}{}", infix, infix_suffix.trim_end(), indent_str),
273+
SeparatorPlace::Front => format!(
274+
"{}{}{}{}",
275+
indent_str,
276+
infix.trim_start(),
277+
infix_suffix,
278+
infix_suffix_separator
279+
),
280+
};
281+
let new_line_width = infix_with_sep.len() - 1 + rhs_result.len() + pp.suffix.len();
282+
let rhs_with_sep = if separator_place == SeparatorPlace::Front && new_line_width > shape.width {
283+
let s: String = String::from(infix_with_sep);
284+
infix_with_sep = s.trim_end().to_string();
285+
format!("{}{}", indent_str, rhs_result.trim_start())
286+
} else {
287+
rhs_result
241288
};
242289
Some(format!(
243290
"{}{}{}{}",
244-
lhs_result, infix_with_sep, rhs_result, pp.suffix
291+
lhs_result, infix_with_sep, rhs_with_sep, pp.suffix
245292
))
246293
}
247294

Diff for: src/formatting/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ impl Rewrite for ast::Ty {
726726
ast::TyKind::Array(ref ty, ref repeats) => rewrite_pair(
727727
&**ty,
728728
&*repeats.value,
729-
PairParts::new("[", "; ", "]"),
729+
PairParts::new("[", "", "; ", "", "]"),
730730
context,
731731
shape,
732732
SeparatorPlace::Back,

Diff for: tests/source/issue-4406-cast-comments.rs

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

0 commit comments

Comments
 (0)