Skip to content

Commit ee7b580

Browse files
committed
Format try shorthand
1 parent fc2549b commit ee7b580

File tree

4 files changed

+88
-12
lines changed

4 files changed

+88
-12
lines changed

src/chains.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
/// Formatting of chained expressions, i.e. expressions which are chained by
12-
/// dots: struct and enum field access and method calls.
12+
/// dots: struct and enum field access, method calls, and try shorthand (?).
1313
///
1414
/// Instead of walking these subexpressions one-by-one, as is our usual strategy
1515
/// for expression formatting, we collect maximal sequences of these expressions
@@ -81,7 +81,6 @@
8181
/// true, then we allow the last method call to spill over multiple lines without
8282
/// forcing the rest of the chain to be split.
8383
84-
8584
use Indent;
8685
use rewrite::{Rewrite, RewriteContext};
8786
use utils::{wrap_str, first_line_width};
@@ -109,8 +108,16 @@ pub fn rewrite_chain(expr: &ast::Expr,
109108
// put the first non-parent item on the same line as the parent.
110109
let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) ||
111110
parent_rewrite.len() <= context.config.tab_spaces {
112-
// Try and put at least the first two items on the same line.
113-
(chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), true)
111+
// <<<<<<< HEAD
112+
// // Try and put at least the first two items on the same line.
113+
// (chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), true)
114+
// =======
115+
let indent = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node {
116+
parent_block_indent.block_indent(context.config)
117+
} else {
118+
offset + Indent::new(0, parent_rewrite.len())
119+
};
120+
(indent, true)
114121
} else if is_block_expr(parent, &parent_rewrite) {
115122
// The parent is a block, so align the rest of the chain with the closing
116123
// brace.
@@ -184,12 +191,27 @@ pub fn rewrite_chain(expr: &ast::Expr,
184191
wrap_str(format!("{}{}{}",
185192
parent_rewrite,
186193
first_connector,
187-
rewrites.join(&connector)),
194+
join_rewrites(&rewrites, &subexpr_list, &connector)),
188195
context.config.max_width,
189196
width,
190197
offset)
191198
}
192199

200+
fn join_rewrites(rewrites: &[String], subexps: &[&ast::Expr], connector: &str) -> String {
201+
let mut rewrite_iter = rewrites.iter();
202+
let mut result = rewrite_iter.next().unwrap().clone();
203+
204+
for (rewrite, expr) in rewrite_iter.zip(subexps.iter()) {
205+
match expr.node {
206+
ast::ExprKind::Try(_) => (),
207+
_ => result.push_str(connector),
208+
};
209+
result.push_str(&rewrite[..]);
210+
}
211+
212+
result
213+
}
214+
193215
// States whether an expression's last line exclusively consists of closing
194216
// parens, braces, and brackets in its idiomatic formatting.
195217
fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool {
@@ -293,6 +315,16 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind,
293315
}
294316
}
295317

318+
fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> {
319+
match expr.node {
320+
ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]),
321+
ast::ExprKind::TupField(ref subexpr, _) |
322+
ast::ExprKind::Field(ref subexpr, _) |
323+
ast::ExprKind::Try(ref subexpr) => Some(subexpr),
324+
_ => None,
325+
}
326+
}
327+
296328
// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite
297329
// `.c`.
298330
fn rewrite_chain_subexpr(expr: &ast::Expr,
@@ -328,6 +360,13 @@ fn rewrite_chain_subexpr(expr: &ast::Expr,
328360
None
329361
}
330362
}
363+
ast::ExprKind::Try(_) => {
364+
if width >= 1 {
365+
Some("?".into())
366+
} else {
367+
None
368+
}
369+
}
331370
_ => unreachable!(),
332371
}
333372
}

src/expr.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ impl Rewrite for ast::Expr {
148148
ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => {
149149
rewrite_closure(capture, fn_decl, body, self.span, context, width, offset)
150150
}
151+
// ast::ExprKind::Try(..) |
151152
ast::ExprKind::Field(..) |
152153
ast::ExprKind::TupField(..) |
153154
ast::ExprKind::MethodCall(..) => rewrite_chain(self, context, width, offset),
@@ -199,21 +200,20 @@ impl Rewrite for ast::Expr {
199200
rewrite_unary_prefix(context, delim, &**rhs, width, offset)
200201
}
201202
(Some(ref lhs), None) => {
202-
Some(format!("{}{}",
203-
try_opt!(lhs.rewrite(context,
204-
try_opt!(width.checked_sub(delim.len())),
205-
offset)),
206-
delim))
203+
rewrite_unary_suffix(context, delim, &**lhs, width, offset)
207204
}
208205
(None, None) => wrap_str(delim.into(), context.config.max_width, width, offset),
209206
}
210207
}
208+
ast::ExprKind::Try(ref expr) => {
209+
rewrite_unary_suffix(context, "?", &**expr, width, offset)
210+
}
211211
// We do not format these expressions yet, but they should still
212212
// satisfy our width restrictions.
213213
ast::ExprKind::InPlace(..) |
214214
ast::ExprKind::InlineAsm(..) |
215-
// TODO(#867): Handle try shorthand
216-
ast::ExprKind::Try(_) => {
215+
// TODO(#848): Handle type ascription
216+
ast::ExprKind::Type(_, _) => {
217217
wrap_str(context.snippet(self.span),
218218
context.config.max_width,
219219
width,
@@ -1762,6 +1762,21 @@ pub fn rewrite_unary_prefix<R: Rewrite>(context: &RewriteContext,
17621762
.map(|r| format!("{}{}", prefix, r))
17631763
}
17641764

1765+
// FIXME: this is probably not correct for multi-line Rewrites. we should
1766+
// subtract suffix.len() from the last line budget, not the first!
1767+
pub fn rewrite_unary_suffix<R: Rewrite>(context: &RewriteContext,
1768+
suffix: &str,
1769+
rewrite: &R,
1770+
width: usize,
1771+
offset: Indent)
1772+
-> Option<String> {
1773+
rewrite.rewrite(context, try_opt!(width.checked_sub(suffix.len())), offset)
1774+
.map(|mut r| {
1775+
r.push_str(suffix);
1776+
r
1777+
})
1778+
}
1779+
17651780
fn rewrite_unary_op(context: &RewriteContext,
17661781
op: &ast::UnOp,
17671782
expr: &ast::Expr,

tests/source/chains.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,12 @@ fn issue587() {
112112

113113
std::mem::transmute(dl.symbol::<()>("init").unwrap())
114114
}
115+
116+
fn try_shorthand() {
117+
let x = expr?;
118+
let y = expr.kaas()?.test();
119+
let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?;
120+
let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test();
121+
let zzzz = expr?.another?.another?.another?.another?;
122+
let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??;
123+
}

tests/target/chains.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,16 @@ fn issue587() {
133133

134134
std::mem::transmute(dl.symbol::<()>("init").unwrap())
135135
}
136+
137+
fn try_shorthand() {
138+
let x = expr?;
139+
let y = expr.kaas()?.test();
140+
let loooooooooooooooooooooooooooooooooooooooooong = does_this?
141+
.look?
142+
.good?
143+
.should_we_break?
144+
.after_the_first_question_mark?;
145+
let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test();
146+
let zzzz = expr?.another?.another?.another?.another?;
147+
let aaa = x??????????????????????????????????????????????????????????????????????????;
148+
}

0 commit comments

Comments
 (0)