Skip to content

Commit 2d4b4b8

Browse files
committed
Format expressions with binary and unary operators
1 parent f16cf12 commit 2d4b4b8

File tree

4 files changed

+104
-26
lines changed

4 files changed

+104
-26
lines changed

src/expr.rs

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use rewrite::{Rewrite, RewriteContext};
1212
use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic};
1313
use string::{StringFormat, rewrite_string};
14-
use utils::span_after;
14+
use utils::{span_after, make_indent};
1515

1616
use syntax::{ast, ptr};
1717
use syntax::codemap::{Pos, Span, BytePos};
@@ -24,35 +24,37 @@ impl Rewrite for ast::Expr {
2424
ast::Expr_::ExprLit(ref l) => {
2525
match l.node {
2626
ast::Lit_::LitStr(ref is, _) => {
27-
let result = rewrite_string_lit(context, &is, l.span, width, offset);
28-
debug!("string lit: `{:?}`", result);
29-
return result;
27+
rewrite_string_lit(context, &is, l.span, width, offset)
3028
}
31-
_ => {}
29+
_ => context.codemap.span_to_snippet(self.span).ok()
3230
}
3331
}
3432
ast::Expr_::ExprCall(ref callee, ref args) => {
35-
return rewrite_call(context, callee, args, self.span, width, offset);
33+
rewrite_call(context, callee, args, self.span, width, offset)
3634
}
3735
ast::Expr_::ExprParen(ref subexpr) => {
38-
return rewrite_paren(context, subexpr, width, offset);
36+
rewrite_paren(context, subexpr, width, offset)
37+
}
38+
ast::Expr_::ExprBinary(ref op, ref lhs, ref rhs) => {
39+
rewrite_binary_op(context, op, lhs, rhs, width, offset)
40+
}
41+
ast::Expr_::ExprUnary(ref op, ref subexpr) => {
42+
rewrite_unary_op(context, op, subexpr, width, offset)
3943
}
4044
ast::Expr_::ExprStruct(ref path, ref fields, ref base) => {
41-
return rewrite_struct_lit(context,
42-
path,
43-
fields,
44-
base.as_ref().map(|e| &**e),
45-
self.span,
46-
width,
47-
offset);
45+
rewrite_struct_lit(context,
46+
path,
47+
fields,
48+
base.as_ref().map(|e| &**e),
49+
self.span,
50+
width,
51+
offset)
4852
}
4953
ast::Expr_::ExprTup(ref items) => {
50-
return rewrite_tuple_lit(context, items, self.span, width, offset);
54+
rewrite_tuple_lit(context, items, self.span, width, offset)
5155
}
52-
_ => {}
56+
_ => context.codemap.span_to_snippet(self.span).ok()
5357
}
54-
55-
context.codemap.span_to_snippet(self.span).ok()
5658
}
5759
}
5860

@@ -235,7 +237,7 @@ fn rewrite_tuple_lit(context: &RewriteContext,
235237
span: Span,
236238
width: usize,
237239
offset: usize)
238-
-> Option<String> {
240+
-> Option<String> {
239241
let indent = offset + 1;
240242

241243
let items = itemize_list(context.codemap,
@@ -272,3 +274,58 @@ fn rewrite_tuple_lit(context: &RewriteContext,
272274

273275
Some(format!("({})", write_list(&items, &fmt)))
274276
}
277+
278+
fn rewrite_binary_op(context: &RewriteContext,
279+
op: &ast::BinOp,
280+
lhs: &ast::Expr,
281+
rhs: &ast::Expr,
282+
width: usize,
283+
offset: usize)
284+
-> Option<String> {
285+
// FIXME: format comments between operands and operator
286+
287+
let operator_str = context.codemap.span_to_snippet(op.span).unwrap();
288+
289+
// 1 = space between lhs expr and operator
290+
let mut result = try_opt!(lhs.rewrite(context, width - 1 - operator_str.len(), offset));
291+
292+
result.push(' ');
293+
result.push_str(&operator_str);
294+
295+
let remaining_width = match result.rfind('\n') {
296+
Some(idx) => (context.config.max_width + idx).checked_sub(result.len()).unwrap_or(0),
297+
None => width.checked_sub(result.len()).unwrap_or(0)
298+
};
299+
300+
// Get "full width" rhs and see if it fits on the current line. This
301+
// usually works fairly well since it tends to place operands of
302+
// operations with high precendence close together.
303+
let rhs_result = try_opt!(rhs.rewrite(context, width, offset));
304+
305+
if rhs_result.len() > remaining_width {
306+
result.push('\n');
307+
result.push_str(&make_indent(offset));
308+
} else {
309+
result.push(' ');
310+
};
311+
312+
result.push_str(&rhs_result);
313+
Some(result)
314+
}
315+
316+
fn rewrite_unary_op(context: &RewriteContext,
317+
op: &ast::UnOp,
318+
expr: &ast::Expr,
319+
width: usize,
320+
offset: usize)
321+
-> Option<String> {
322+
// For some reason, an UnOp is not spanned like BinOp!
323+
let operator_str = match *op {
324+
ast::UnOp::UnUniq => "&",
325+
ast::UnOp::UnDeref => "*",
326+
ast::UnOp::UnNot => "!",
327+
ast::UnOp::UnNeg => "-"
328+
};
329+
330+
Some(format!("{}{}", operator_str, try_opt!(expr.rewrite(context, width - 1, offset))))
331+
}

tests/source/expr.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Test expressions
2+
3+
fn foo() -> bool {
4+
let very_long_variable_name = ( a + first + simple + test );
5+
let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c);
6+
7+
let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb -
8+
function_call(x, *very_long_pointer, y))
9+
+ 1000;
10+
11+
some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000
12+
- 50000 * sqrt(-1),
13+
trivial_value)
14+
}

tests/target/expr.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Test expressions
2+
3+
fn foo() -> bool {
4+
let very_long_variable_name = (a + first + simple + test);
5+
let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB +
6+
b + c);
7+
8+
let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb /
9+
(bbbbbb - function_call(x, *very_long_pointer, y)) + 1000;
10+
11+
some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 +
12+
40000 / 1002200000000 - 50000 * sqrt(-1),
13+
trivial_value)
14+
}

tests/target/paren.rs

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)