Skip to content

Commit 754925e

Browse files
committed
Merge pull request #484 from marcusklaas/patternz
Format some patterns
2 parents c719d68 + ca023ba commit 754925e

File tree

14 files changed

+236
-88
lines changed

14 files changed

+236
-88
lines changed

src/expr.rs

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::cmp::Ordering;
1212
use std::borrow::Borrow;
1313
use std::mem::swap;
1414

15-
use Indent;
15+
use {Indent, Spanned};
1616
use rewrite::{Rewrite, RewriteContext};
1717
use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic,
1818
DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args};
@@ -76,7 +76,7 @@ impl Rewrite for ast::Expr {
7676
offset)
7777
}
7878
ast::Expr_::ExprTup(ref items) => {
79-
rewrite_tuple_lit(context, items, self.span, width, offset)
79+
rewrite_tuple(context, items, self.span, width, offset)
8080
}
8181
ast::Expr_::ExprWhile(ref cond, ref block, label) => {
8282
Loop::new_while(None, cond, block, label).rewrite(context, width, offset)
@@ -479,13 +479,6 @@ impl Rewrite for ast::Block {
479479
}
480480
}
481481

482-
// FIXME(#18): implement pattern formatting
483-
impl Rewrite for ast::Pat {
484-
fn rewrite(&self, context: &RewriteContext, _: usize, _: Indent) -> Option<String> {
485-
Some(context.snippet(self.span))
486-
}
487-
}
488-
489482
// Abstraction over for, while and loop expressions
490483
struct Loop<'a> {
491484
cond: Option<&'a ast::Expr>,
@@ -849,11 +842,7 @@ impl Rewrite for ast::Arm {
849842
// 5 = ` => {`
850843
let pat_budget = try_opt!(width.checked_sub(5));
851844
let pat_strs = try_opt!(pats.iter()
852-
.map(|p| {
853-
p.rewrite(context,
854-
pat_budget,
855-
offset.block_indent(context.config))
856-
})
845+
.map(|p| p.rewrite(context, pat_budget, offset))
857846
.collect::<Option<Vec<_>>>());
858847

859848
let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len());
@@ -1187,7 +1176,9 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
11871176
// Replace the stub with the full overflowing last argument if the rewrite
11881177
// succeeded and its first line fits with the other arguments.
11891178
match (overflow_last, tactic, placeholder) {
1190-
(true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => {
1179+
(true,
1180+
DefinitiveListTactic::Horizontal,
1181+
placeholder @ Some(..)) => {
11911182
item_vec[arg_count - 1].item = placeholder;
11921183
}
11931184
(true, _, _) => {
@@ -1206,8 +1197,6 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
12061197
config: context.config,
12071198
};
12081199

1209-
// format_fn_args(items, remaining_width, offset, context.config)
1210-
12111200
let list_str = match write_list(&item_vec, &fmt) {
12121201
Some(str) => str,
12131202
None => return Err(Ordering::Less),
@@ -1382,12 +1371,14 @@ fn rewrite_field(context: &RewriteContext,
13821371
expr.map(|s| format!("{}: {}", name, s))
13831372
}
13841373

1385-
fn rewrite_tuple_lit(context: &RewriteContext,
1386-
items: &[ptr::P<ast::Expr>],
1387-
span: Span,
1388-
width: usize,
1389-
offset: Indent)
1390-
-> Option<String> {
1374+
pub fn rewrite_tuple<'a, R>(context: &RewriteContext,
1375+
items: &'a [ptr::P<R>],
1376+
span: Span,
1377+
width: usize,
1378+
offset: Indent)
1379+
-> Option<String>
1380+
where R: Rewrite + Spanned + 'a
1381+
{
13911382
debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset);
13921383
let indent = offset + 1;
13931384
// In case of length 1, need a trailing comma
@@ -1400,8 +1391,8 @@ fn rewrite_tuple_lit(context: &RewriteContext,
14001391
let items = itemize_list(context.codemap,
14011392
items.iter(),
14021393
")",
1403-
|item| item.span.lo,
1404-
|item| item.span.hi,
1394+
|item| item.span().lo,
1395+
|item| item.span().hi,
14051396
|item| {
14061397
let inner_width = context.config.max_width - indent.width() - 1;
14071398
item.rewrite(context, inner_width, indent)

src/items.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,41 +29,16 @@ impl<'a> FmtVisitor<'a> {
2929
pub fn visit_let(&mut self, local: &ast::Local, span: Span) {
3030
self.format_missing_with_indent(span.lo);
3131

32-
// String that is placed within the assignment pattern and expression.
33-
let infix = {
34-
let mut infix = String::new();
35-
36-
if let Some(ref ty) = local.ty {
37-
// 2 = ": ".len()
38-
let offset = self.block_indent + 2;
39-
let width = self.config.max_width - offset.width();
40-
let rewrite = ty.rewrite(&self.get_context(), width, offset);
41-
42-
match rewrite {
43-
Some(result) => {
44-
infix.push_str(": ");
45-
infix.push_str(&result);
46-
}
47-
None => return,
48-
}
49-
}
50-
51-
if local.init.is_some() {
52-
infix.push_str(" =");
53-
}
54-
55-
infix
56-
};
57-
5832
// New scope so we drop the borrow of self (context) in time to mutably
5933
// borrow self to mutate its buffer.
6034
let result = {
6135
let context = self.get_context();
6236
let mut result = "let ".to_owned();
63-
let pattern_offset = self.block_indent + result.len() + infix.len();
37+
let pattern_offset = self.block_indent + result.len();
6438
// 1 = ;
65-
let pattern_width = self.config.max_width.checked_sub(pattern_offset.width() + 1);
66-
let pattern_width = match pattern_width {
39+
let pattern_width = match self.config
40+
.max_width
41+
.checked_sub(pattern_offset.width() + 1) {
6742
Some(width) => width,
6843
None => return,
6944
};
@@ -73,6 +48,36 @@ impl<'a> FmtVisitor<'a> {
7348
None => return,
7449
}
7550

51+
// String that is placed within the assignment pattern and expression.
52+
let infix = {
53+
let mut infix = String::new();
54+
55+
if let Some(ref ty) = local.ty {
56+
// 2 = ": ".len()
57+
// 1 = ;
58+
let offset = self.block_indent + result.len() + 2;
59+
let width = match self.config.max_width.checked_sub(offset.width() + 1) {
60+
Some(w) => w,
61+
None => return,
62+
};
63+
let rewrite = ty.rewrite(&self.get_context(), width, offset);
64+
65+
match rewrite {
66+
Some(result) => {
67+
infix.push_str(": ");
68+
infix.push_str(&result);
69+
}
70+
None => return,
71+
}
72+
}
73+
74+
if local.init.is_some() {
75+
infix.push_str(" =");
76+
}
77+
78+
infix
79+
};
80+
7681
result.push_str(&infix);
7782

7883
if let Some(ref ex) = local.init {
@@ -86,7 +91,7 @@ impl<'a> FmtVisitor<'a> {
8691
let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent);
8792

8893
match rhs {
89-
Some(result) => result,
94+
Some(s) => s,
9095
None => return,
9196
}
9297
} else {

src/lib.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use rustc::session::config::Input;
4141
use rustc_driver::{driver, CompilerCalls, Compilation};
4242

4343
use syntax::ast;
44-
use syntax::codemap::CodeMap;
44+
use syntax::codemap::{CodeMap, Span};
4545
use syntax::diagnostics;
4646

4747
use std::ops::{Add, Sub};
@@ -76,11 +76,34 @@ mod modules;
7676
pub mod rustfmt_diff;
7777
mod chains;
7878
mod macros;
79+
mod patterns;
7980

8081
const MIN_STRING: usize = 10;
8182
// When we get scoped annotations, we should have rustfmt::skip.
8283
const SKIP_ANNOTATION: &'static str = "rustfmt_skip";
8384

85+
pub trait Spanned {
86+
fn span(&self) -> Span;
87+
}
88+
89+
impl Spanned for ast::Expr {
90+
fn span(&self) -> Span {
91+
self.span
92+
}
93+
}
94+
95+
impl Spanned for ast::Pat {
96+
fn span(&self) -> Span {
97+
self.span
98+
}
99+
}
100+
101+
impl Spanned for ast::Ty {
102+
fn span(&self) -> Span {
103+
self.span
104+
}
105+
}
106+
84107
#[derive(Copy, Clone, Debug)]
85108
pub struct Indent {
86109
// Width of the block indent, in characters. Must be a multiple of

src/patterns.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use Indent;
12+
use rewrite::{Rewrite, RewriteContext};
13+
use utils::{wrap_str, format_mutability, span_after};
14+
use lists::{format_item_list, itemize_list};
15+
use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple};
16+
use types::rewrite_path;
17+
18+
use syntax::ast::{PatWildKind, BindingMode, Pat, Pat_};
19+
20+
// FIXME(#18): implement pattern formatting.
21+
impl Rewrite for Pat {
22+
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
23+
match self.node {
24+
Pat_::PatBox(ref pat) => {
25+
rewrite_unary_prefix(context, "box ", &**pat, width, offset)
26+
}
27+
Pat_::PatIdent(binding_mode, ident, None) => {
28+
let (prefix, mutability) = match binding_mode {
29+
BindingMode::BindByRef(mutability) => ("ref ", mutability),
30+
BindingMode::BindByValue(mutability) => ("", mutability),
31+
};
32+
let mut_infix = format_mutability(mutability);
33+
let result = format!("{}{}{}", prefix, mut_infix, ident.node);
34+
wrap_str(result, context.config.max_width, width, offset)
35+
}
36+
Pat_::PatWild(kind) => {
37+
let result = match kind {
38+
PatWildKind::PatWildSingle => "_",
39+
PatWildKind::PatWildMulti => "..",
40+
};
41+
if result.len() <= width {
42+
Some(result.to_owned())
43+
} else {
44+
None
45+
}
46+
}
47+
Pat_::PatQPath(ref q_self, ref path) => {
48+
rewrite_path(context, Some(q_self), path, width, offset)
49+
}
50+
Pat_::PatRange(ref lhs, ref rhs) => {
51+
rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset)
52+
}
53+
Pat_::PatRegion(ref pat, mutability) => {
54+
let prefix = format!("&{}", format_mutability(mutability));
55+
rewrite_unary_prefix(context, &prefix, &**pat, width, offset)
56+
}
57+
Pat_::PatTup(ref items) => {
58+
rewrite_tuple(context, items, self.span, width, offset)
59+
}
60+
Pat_::PatEnum(ref path, Some(ref pat_vec)) => {
61+
let path_str = try_opt!(::types::rewrite_path(context, None, path, width, offset));
62+
63+
if pat_vec.is_empty() {
64+
Some(path_str)
65+
} else {
66+
let width = try_opt!(width.checked_sub(path_str.len()));
67+
let offset = offset + path_str.len();
68+
let items = itemize_list(context.codemap,
69+
pat_vec.iter(),
70+
")",
71+
|item| item.span.lo,
72+
|item| item.span.hi,
73+
|item| item.rewrite(context, width, offset),
74+
span_after(self.span, "(", context.codemap),
75+
self.span.hi);
76+
Some(format!("{}({})",
77+
path_str,
78+
try_opt!(format_item_list(items, width, offset, context.config))))
79+
}
80+
}
81+
Pat_::PatLit(ref expr) => expr.rewrite(context, width, offset),
82+
// FIXME(#8): format remaining pattern variants.
83+
Pat_::PatIdent(_, _, Some(..)) |
84+
Pat_::PatEnum(_, None) |
85+
Pat_::PatStruct(..) |
86+
Pat_::PatVec(..) |
87+
Pat_::PatMac(..) => {
88+
wrap_str(context.snippet(self.span),
89+
context.config.max_width,
90+
width,
91+
offset)
92+
}
93+
}
94+
}
95+
}

src/types.rs

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ use syntax::print::pprust;
1313
use syntax::codemap::{self, Span, BytePos, CodeMap};
1414

1515
use Indent;
16-
use lists::{format_item_list, itemize_list, format_fn_args, list_helper, ListTactic};
16+
use lists::{format_item_list, itemize_list, format_fn_args};
1717
use rewrite::{Rewrite, RewriteContext};
1818
use utils::{extra_offset, span_after, format_mutability, wrap_str};
19-
use expr::{rewrite_unary_prefix, rewrite_pair};
19+
use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple};
2020

2121
impl Rewrite for ast::Path {
2222
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
@@ -491,28 +491,8 @@ impl Rewrite for ast::Ty {
491491
let budget = try_opt!(width.checked_sub(2));
492492
ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str))
493493
}
494-
ast::TyTup(ref tup_ret) => {
495-
if tup_ret.is_empty() {
496-
Some("()".to_owned())
497-
} else if let [ref item] = &**tup_ret {
498-
let budget = try_opt!(width.checked_sub(3));
499-
let inner = try_opt!(item.rewrite(context, budget, offset + 1));
500-
let ret = format!("({},)", inner);
501-
wrap_str(ret, context.config.max_width, budget, offset + 1)
502-
} else {
503-
let budget = try_opt!(width.checked_sub(2));
504-
let items = itemize_list(context.codemap,
505-
tup_ret.iter(),
506-
")",
507-
|item| item.span.lo,
508-
|item| item.span.hi,
509-
|item| item.rewrite(context, budget, offset + 1),
510-
span_after(self.span, "(", context.codemap),
511-
self.span.hi);
512-
513-
list_helper(items, budget, offset + 1, context.config, ListTactic::Mixed)
514-
.map(|s| format!("({})", s))
515-
}
494+
ast::TyTup(ref items) => {
495+
rewrite_tuple(context, items, self.span, width, offset)
516496
}
517497
ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset),
518498
ast::TyPath(ref q_self, ref path) => {

tests/source/match.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ fn main() {
8888

8989
fn matches() {
9090
match 1 {
91+
-1 => 10,
9192
1 => 1, // foo
9293
2 => 2,
9394
// bar

tests/source/pattern.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn main() {
2+
let z = match x {
3+
"pat1" => 1,
4+
( ref x, ref mut y /*comment*/) => 2,
5+
};
6+
7+
if let < T as Trait > :: CONST = ident {
8+
do_smth();
9+
}
10+
11+
let Some ( ref xyz /* comment! */) = opt;
12+
13+
if let None = opt2 { panic!("oh noes"); }
14+
}

0 commit comments

Comments
 (0)