Skip to content

Commit 0f5dcc6

Browse files
committed
Handle special-case macros
1 parent ffbe52e commit 0f5dcc6

File tree

2 files changed

+108
-15
lines changed

2 files changed

+108
-15
lines changed

src/expr.rs

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,9 +1862,6 @@ where
18621862
};
18631863
let used_width = extra_offset(callee_str, shape);
18641864
let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?;
1865-
// 1 = "("
1866-
let combine_arg_with_callee =
1867-
callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1;
18681865

18691866
// 1 = "(" or ")"
18701867
let one_line_shape = shape
@@ -1889,7 +1886,7 @@ where
18891886
one_line_width,
18901887
args_max_width,
18911888
force_trailing_comma,
1892-
combine_arg_with_callee,
1889+
callee_str,
18931890
)?;
18941891

18951892
if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable {
@@ -1930,7 +1927,7 @@ fn rewrite_call_args<'a, T>(
19301927
one_line_width: usize,
19311928
args_max_width: usize,
19321929
force_trailing_comma: bool,
1933-
combine_arg_with_callee: bool,
1930+
callee_str: &str,
19341931
) -> Option<(bool, String)>
19351932
where
19361933
T: Rewrite + Spanned + ToExpr + 'a,
@@ -1960,7 +1957,7 @@ where
19601957
nested_shape,
19611958
one_line_width,
19621959
args_max_width,
1963-
combine_arg_with_callee,
1960+
callee_str,
19641961
);
19651962

19661963
let fmt = ListFormatting {
@@ -1980,7 +1977,8 @@ where
19801977
config: context.config,
19811978
};
19821979

1983-
write_list(&item_vec, &fmt).map(|args_str| (tactic != DefinitiveListTactic::Vertical, args_str))
1980+
write_list(&item_vec, &fmt)
1981+
.map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str))
19841982
}
19851983

19861984
fn try_overflow_last_arg<'a, T>(
@@ -1991,11 +1989,14 @@ fn try_overflow_last_arg<'a, T>(
19911989
nested_shape: Shape,
19921990
one_line_width: usize,
19931991
args_max_width: usize,
1994-
combine_arg_with_callee: bool,
1992+
callee_str: &str,
19951993
) -> DefinitiveListTactic
19961994
where
19971995
T: Rewrite + Spanned + ToExpr + 'a,
19981996
{
1997+
// 1 = "("
1998+
let combine_arg_with_callee =
1999+
callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1;
19992000
let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args);
20002001

20012002
// Replace the last item with its first line to see if it fits with
@@ -2032,6 +2033,16 @@ where
20322033
_ if args.len() >= 1 => {
20332034
item_vec[args.len() - 1].item = args.last()
20342035
.and_then(|last_arg| last_arg.rewrite(context, nested_shape));
2036+
2037+
let default_tactic = || {
2038+
definitive_tactic(
2039+
&*item_vec,
2040+
ListTactic::LimitedHorizontalVertical(args_max_width),
2041+
Separator::Comma,
2042+
one_line_width,
2043+
)
2044+
};
2045+
20352046
// Use horizontal layout for a function with a single argument as long as
20362047
// everything fits in a single line.
20372048
if args.len() == 1
@@ -2042,12 +2053,44 @@ where
20422053
{
20432054
tactic = DefinitiveListTactic::Horizontal;
20442055
} else {
2045-
tactic = definitive_tactic(
2046-
&*item_vec,
2047-
ListTactic::LimitedHorizontalVertical(args_max_width),
2048-
Separator::Comma,
2049-
one_line_width,
2050-
);
2056+
tactic = default_tactic();
2057+
let is_simple_enough =
2058+
tactic == DefinitiveListTactic::Vertical && is_every_args_simple(args);
2059+
if is_simple_enough
2060+
&& FORMAT_LIKE_WHITELIST
2061+
.iter()
2062+
.find(|s| **s == callee_str)
2063+
.is_some()
2064+
{
2065+
let args_tactic = definitive_tactic(
2066+
&item_vec[1..],
2067+
ListTactic::HorizontalVertical,
2068+
Separator::Comma,
2069+
nested_shape.width,
2070+
);
2071+
tactic = if args_tactic == DefinitiveListTactic::Horizontal {
2072+
DefinitiveListTactic::FormatCall
2073+
} else {
2074+
default_tactic()
2075+
};
2076+
} else if is_simple_enough && item_vec.len() >= 2
2077+
&& WRITE_LIKE_WHITELIST
2078+
.iter()
2079+
.find(|s| **s == callee_str)
2080+
.is_some()
2081+
{
2082+
let args_tactic = definitive_tactic(
2083+
&item_vec[2..],
2084+
ListTactic::HorizontalVertical,
2085+
Separator::Comma,
2086+
nested_shape.width,
2087+
);
2088+
tactic = if args_tactic == DefinitiveListTactic::Horizontal {
2089+
DefinitiveListTactic::WriteCall
2090+
} else {
2091+
default_tactic()
2092+
};
2093+
}
20512094
}
20522095
}
20532096
_ => (),
@@ -2056,6 +2099,30 @@ where
20562099
tactic
20572100
}
20582101

2102+
fn is_simple_arg(expr: &ast::Expr) -> bool {
2103+
match expr.node {
2104+
ast::ExprKind::Lit(..) => true,
2105+
ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1,
2106+
ast::ExprKind::AddrOf(_, ref expr)
2107+
| ast::ExprKind::Box(ref expr)
2108+
| ast::ExprKind::Cast(ref expr, _)
2109+
| ast::ExprKind::Field(ref expr, _)
2110+
| ast::ExprKind::Try(ref expr)
2111+
| ast::ExprKind::TupField(ref expr, _)
2112+
| ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr),
2113+
ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => {
2114+
is_simple_arg(lhs) && is_simple_arg(rhs)
2115+
}
2116+
_ => false,
2117+
}
2118+
}
2119+
2120+
fn is_every_args_simple<T: ToExpr>(lists: &[&T]) -> bool {
2121+
lists
2122+
.iter()
2123+
.all(|arg| arg.to_expr().map_or(false, is_simple_arg))
2124+
}
2125+
20592126
/// Returns a shape for the last argument which is going to be overflowed.
20602127
fn last_arg_shape<T>(
20612128
lists: &[&T],

src/lists.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ pub enum DefinitiveListTactic {
160160
Vertical,
161161
Horizontal,
162162
Mixed,
163+
// Special case tactic for `format!()` variants.
164+
FormatCall,
165+
// Special case tactic for `write!()` varianta.
166+
WriteCall,
163167
}
164168

165169
impl DefinitiveListTactic {
@@ -267,7 +271,7 @@ where
267271
I: IntoIterator<Item = T> + Clone,
268272
T: AsRef<ListItem>,
269273
{
270-
let tactic = formatting.tactic;
274+
let mut tactic = formatting.tactic;
271275
let sep_len = formatting.separator.len();
272276

273277
// Now that we know how we will layout, we can decide for sure if there
@@ -309,6 +313,28 @@ where
309313
DefinitiveListTactic::Horizontal if !first => {
310314
result.push(' ');
311315
}
316+
DefinitiveListTactic::FormatCall if !first => {
317+
result.push('\n');
318+
result.push_str(indent_str);
319+
tactic = DefinitiveListTactic::Horizontal;
320+
}
321+
DefinitiveListTactic::WriteCall => {
322+
let second = i == 1;
323+
let third = i == 2;
324+
325+
if first {
326+
// Nothing
327+
} else if second {
328+
result.push('\n');
329+
result.push_str(indent_str);
330+
} else if third {
331+
result.push('\n');
332+
result.push_str(indent_str);
333+
tactic = DefinitiveListTactic::Horizontal;
334+
} else {
335+
unreachable!();
336+
}
337+
}
312338
DefinitiveListTactic::Vertical if !first => {
313339
result.push('\n');
314340
result.push_str(indent_str);

0 commit comments

Comments
 (0)