Format some patterns
This commit is contained in:
parent
8a9bbd9d7c
commit
ca023ba9b7
41
src/expr.rs
41
src/expr.rs
@ -12,7 +12,7 @@ use std::cmp::Ordering;
|
||||
use std::borrow::Borrow;
|
||||
use std::mem::swap;
|
||||
|
||||
use Indent;
|
||||
use {Indent, Spanned};
|
||||
use rewrite::{Rewrite, RewriteContext};
|
||||
use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic,
|
||||
DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args};
|
||||
@ -76,7 +76,7 @@ impl Rewrite for ast::Expr {
|
||||
offset)
|
||||
}
|
||||
ast::Expr_::ExprTup(ref items) => {
|
||||
rewrite_tuple_lit(context, items, self.span, width, offset)
|
||||
rewrite_tuple(context, items, self.span, width, offset)
|
||||
}
|
||||
ast::Expr_::ExprWhile(ref cond, ref block, label) => {
|
||||
Loop::new_while(None, cond, block, label).rewrite(context, width, offset)
|
||||
@ -479,13 +479,6 @@ impl Rewrite for ast::Block {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#18): implement pattern formatting
|
||||
impl Rewrite for ast::Pat {
|
||||
fn rewrite(&self, context: &RewriteContext, _: usize, _: Indent) -> Option<String> {
|
||||
Some(context.snippet(self.span))
|
||||
}
|
||||
}
|
||||
|
||||
// Abstraction over for, while and loop expressions
|
||||
struct Loop<'a> {
|
||||
cond: Option<&'a ast::Expr>,
|
||||
@ -849,11 +842,7 @@ impl Rewrite for ast::Arm {
|
||||
// 5 = ` => {`
|
||||
let pat_budget = try_opt!(width.checked_sub(5));
|
||||
let pat_strs = try_opt!(pats.iter()
|
||||
.map(|p| {
|
||||
p.rewrite(context,
|
||||
pat_budget,
|
||||
offset.block_indent(context.config))
|
||||
})
|
||||
.map(|p| p.rewrite(context, pat_budget, offset))
|
||||
.collect::<Option<Vec<_>>>());
|
||||
|
||||
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,
|
||||
// Replace the stub with the full overflowing last argument if the rewrite
|
||||
// succeeded and its first line fits with the other arguments.
|
||||
match (overflow_last, tactic, placeholder) {
|
||||
(true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => {
|
||||
(true,
|
||||
DefinitiveListTactic::Horizontal,
|
||||
placeholder @ Some(..)) => {
|
||||
item_vec[arg_count - 1].item = placeholder;
|
||||
}
|
||||
(true, _, _) => {
|
||||
@ -1206,8 +1197,6 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
|
||||
config: context.config,
|
||||
};
|
||||
|
||||
// format_fn_args(items, remaining_width, offset, context.config)
|
||||
|
||||
let list_str = match write_list(&item_vec, &fmt) {
|
||||
Some(str) => str,
|
||||
None => return Err(Ordering::Less),
|
||||
@ -1382,12 +1371,14 @@ fn rewrite_field(context: &RewriteContext,
|
||||
expr.map(|s| format!("{}: {}", name, s))
|
||||
}
|
||||
|
||||
fn rewrite_tuple_lit(context: &RewriteContext,
|
||||
items: &[ptr::P<ast::Expr>],
|
||||
span: Span,
|
||||
width: usize,
|
||||
offset: Indent)
|
||||
-> Option<String> {
|
||||
pub fn rewrite_tuple<'a, R>(context: &RewriteContext,
|
||||
items: &'a [ptr::P<R>],
|
||||
span: Span,
|
||||
width: usize,
|
||||
offset: Indent)
|
||||
-> Option<String>
|
||||
where R: Rewrite + Spanned + 'a
|
||||
{
|
||||
debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset);
|
||||
let indent = offset + 1;
|
||||
// In case of length 1, need a trailing comma
|
||||
@ -1400,8 +1391,8 @@ fn rewrite_tuple_lit(context: &RewriteContext,
|
||||
let items = itemize_list(context.codemap,
|
||||
items.iter(),
|
||||
")",
|
||||
|item| item.span.lo,
|
||||
|item| item.span.hi,
|
||||
|item| item.span().lo,
|
||||
|item| item.span().hi,
|
||||
|item| {
|
||||
let inner_width = context.config.max_width - indent.width() - 1;
|
||||
item.rewrite(context, inner_width, indent)
|
||||
|
65
src/items.rs
65
src/items.rs
@ -29,41 +29,16 @@ impl<'a> FmtVisitor<'a> {
|
||||
pub fn visit_let(&mut self, local: &ast::Local, span: Span) {
|
||||
self.format_missing_with_indent(span.lo);
|
||||
|
||||
// String that is placed within the assignment pattern and expression.
|
||||
let infix = {
|
||||
let mut infix = String::new();
|
||||
|
||||
if let Some(ref ty) = local.ty {
|
||||
// 2 = ": ".len()
|
||||
let offset = self.block_indent + 2;
|
||||
let width = self.config.max_width - offset.width();
|
||||
let rewrite = ty.rewrite(&self.get_context(), width, offset);
|
||||
|
||||
match rewrite {
|
||||
Some(result) => {
|
||||
infix.push_str(": ");
|
||||
infix.push_str(&result);
|
||||
}
|
||||
None => return,
|
||||
}
|
||||
}
|
||||
|
||||
if local.init.is_some() {
|
||||
infix.push_str(" =");
|
||||
}
|
||||
|
||||
infix
|
||||
};
|
||||
|
||||
// New scope so we drop the borrow of self (context) in time to mutably
|
||||
// borrow self to mutate its buffer.
|
||||
let result = {
|
||||
let context = self.get_context();
|
||||
let mut result = "let ".to_owned();
|
||||
let pattern_offset = self.block_indent + result.len() + infix.len();
|
||||
let pattern_offset = self.block_indent + result.len();
|
||||
// 1 = ;
|
||||
let pattern_width = self.config.max_width.checked_sub(pattern_offset.width() + 1);
|
||||
let pattern_width = match pattern_width {
|
||||
let pattern_width = match self.config
|
||||
.max_width
|
||||
.checked_sub(pattern_offset.width() + 1) {
|
||||
Some(width) => width,
|
||||
None => return,
|
||||
};
|
||||
@ -73,6 +48,36 @@ impl<'a> FmtVisitor<'a> {
|
||||
None => return,
|
||||
}
|
||||
|
||||
// String that is placed within the assignment pattern and expression.
|
||||
let infix = {
|
||||
let mut infix = String::new();
|
||||
|
||||
if let Some(ref ty) = local.ty {
|
||||
// 2 = ": ".len()
|
||||
// 1 = ;
|
||||
let offset = self.block_indent + result.len() + 2;
|
||||
let width = match self.config.max_width.checked_sub(offset.width() + 1) {
|
||||
Some(w) => w,
|
||||
None => return,
|
||||
};
|
||||
let rewrite = ty.rewrite(&self.get_context(), width, offset);
|
||||
|
||||
match rewrite {
|
||||
Some(result) => {
|
||||
infix.push_str(": ");
|
||||
infix.push_str(&result);
|
||||
}
|
||||
None => return,
|
||||
}
|
||||
}
|
||||
|
||||
if local.init.is_some() {
|
||||
infix.push_str(" =");
|
||||
}
|
||||
|
||||
infix
|
||||
};
|
||||
|
||||
result.push_str(&infix);
|
||||
|
||||
if let Some(ref ex) = local.init {
|
||||
@ -86,7 +91,7 @@ impl<'a> FmtVisitor<'a> {
|
||||
let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent);
|
||||
|
||||
match rhs {
|
||||
Some(result) => result,
|
||||
Some(s) => s,
|
||||
None => return,
|
||||
}
|
||||
} else {
|
||||
|
25
src/lib.rs
25
src/lib.rs
@ -41,7 +41,7 @@ use rustc::session::config::Input;
|
||||
use rustc_driver::{driver, CompilerCalls, Compilation};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap::CodeMap;
|
||||
use syntax::codemap::{CodeMap, Span};
|
||||
use syntax::diagnostics;
|
||||
|
||||
use std::ops::{Add, Sub};
|
||||
@ -76,11 +76,34 @@ mod modules;
|
||||
pub mod rustfmt_diff;
|
||||
mod chains;
|
||||
mod macros;
|
||||
mod patterns;
|
||||
|
||||
const MIN_STRING: usize = 10;
|
||||
// When we get scoped annotations, we should have rustfmt::skip.
|
||||
const SKIP_ANNOTATION: &'static str = "rustfmt_skip";
|
||||
|
||||
pub trait Spanned {
|
||||
fn span(&self) -> Span;
|
||||
}
|
||||
|
||||
impl Spanned for ast::Expr {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl Spanned for ast::Pat {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl Spanned for ast::Ty {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Indent {
|
||||
// Width of the block indent, in characters. Must be a multiple of
|
||||
|
95
src/patterns.rs
Normal file
95
src/patterns.rs
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use Indent;
|
||||
use rewrite::{Rewrite, RewriteContext};
|
||||
use utils::{wrap_str, format_mutability, span_after};
|
||||
use lists::{format_item_list, itemize_list};
|
||||
use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple};
|
||||
use types::rewrite_path;
|
||||
|
||||
use syntax::ast::{PatWildKind, BindingMode, Pat, Pat_};
|
||||
|
||||
// FIXME(#18): implement pattern formatting.
|
||||
impl Rewrite for Pat {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
|
||||
match self.node {
|
||||
Pat_::PatBox(ref pat) => {
|
||||
rewrite_unary_prefix(context, "box ", &**pat, width, offset)
|
||||
}
|
||||
Pat_::PatIdent(binding_mode, ident, None) => {
|
||||
let (prefix, mutability) = match binding_mode {
|
||||
BindingMode::BindByRef(mutability) => ("ref ", mutability),
|
||||
BindingMode::BindByValue(mutability) => ("", mutability),
|
||||
};
|
||||
let mut_infix = format_mutability(mutability);
|
||||
let result = format!("{}{}{}", prefix, mut_infix, ident.node);
|
||||
wrap_str(result, context.config.max_width, width, offset)
|
||||
}
|
||||
Pat_::PatWild(kind) => {
|
||||
let result = match kind {
|
||||
PatWildKind::PatWildSingle => "_",
|
||||
PatWildKind::PatWildMulti => "..",
|
||||
};
|
||||
if result.len() <= width {
|
||||
Some(result.to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Pat_::PatQPath(ref q_self, ref path) => {
|
||||
rewrite_path(context, Some(q_self), path, width, offset)
|
||||
}
|
||||
Pat_::PatRange(ref lhs, ref rhs) => {
|
||||
rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset)
|
||||
}
|
||||
Pat_::PatRegion(ref pat, mutability) => {
|
||||
let prefix = format!("&{}", format_mutability(mutability));
|
||||
rewrite_unary_prefix(context, &prefix, &**pat, width, offset)
|
||||
}
|
||||
Pat_::PatTup(ref items) => {
|
||||
rewrite_tuple(context, items, self.span, width, offset)
|
||||
}
|
||||
Pat_::PatEnum(ref path, Some(ref pat_vec)) => {
|
||||
let path_str = try_opt!(::types::rewrite_path(context, None, path, width, offset));
|
||||
|
||||
if pat_vec.is_empty() {
|
||||
Some(path_str)
|
||||
} else {
|
||||
let width = try_opt!(width.checked_sub(path_str.len()));
|
||||
let offset = offset + path_str.len();
|
||||
let items = itemize_list(context.codemap,
|
||||
pat_vec.iter(),
|
||||
")",
|
||||
|item| item.span.lo,
|
||||
|item| item.span.hi,
|
||||
|item| item.rewrite(context, width, offset),
|
||||
span_after(self.span, "(", context.codemap),
|
||||
self.span.hi);
|
||||
Some(format!("{}({})",
|
||||
path_str,
|
||||
try_opt!(format_item_list(items, width, offset, context.config))))
|
||||
}
|
||||
}
|
||||
Pat_::PatLit(ref expr) => expr.rewrite(context, width, offset),
|
||||
// FIXME(#8): format remaining pattern variants.
|
||||
Pat_::PatIdent(_, _, Some(..)) |
|
||||
Pat_::PatEnum(_, None) |
|
||||
Pat_::PatStruct(..) |
|
||||
Pat_::PatVec(..) |
|
||||
Pat_::PatMac(..) => {
|
||||
wrap_str(context.snippet(self.span),
|
||||
context.config.max_width,
|
||||
width,
|
||||
offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
src/types.rs
28
src/types.rs
@ -13,10 +13,10 @@ use syntax::print::pprust;
|
||||
use syntax::codemap::{self, Span, BytePos, CodeMap};
|
||||
|
||||
use Indent;
|
||||
use lists::{format_item_list, itemize_list, format_fn_args, list_helper, ListTactic};
|
||||
use lists::{format_item_list, itemize_list, format_fn_args};
|
||||
use rewrite::{Rewrite, RewriteContext};
|
||||
use utils::{extra_offset, span_after, format_mutability, wrap_str};
|
||||
use expr::{rewrite_unary_prefix, rewrite_pair};
|
||||
use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple};
|
||||
|
||||
impl Rewrite for ast::Path {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
|
||||
@ -491,28 +491,8 @@ impl Rewrite for ast::Ty {
|
||||
let budget = try_opt!(width.checked_sub(2));
|
||||
ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str))
|
||||
}
|
||||
ast::TyTup(ref tup_ret) => {
|
||||
if tup_ret.is_empty() {
|
||||
Some("()".to_owned())
|
||||
} else if let [ref item] = &**tup_ret {
|
||||
let budget = try_opt!(width.checked_sub(3));
|
||||
let inner = try_opt!(item.rewrite(context, budget, offset + 1));
|
||||
let ret = format!("({},)", inner);
|
||||
wrap_str(ret, context.config.max_width, budget, offset + 1)
|
||||
} else {
|
||||
let budget = try_opt!(width.checked_sub(2));
|
||||
let items = itemize_list(context.codemap,
|
||||
tup_ret.iter(),
|
||||
")",
|
||||
|item| item.span.lo,
|
||||
|item| item.span.hi,
|
||||
|item| item.rewrite(context, budget, offset + 1),
|
||||
span_after(self.span, "(", context.codemap),
|
||||
self.span.hi);
|
||||
|
||||
list_helper(items, budget, offset + 1, context.config, ListTactic::Mixed)
|
||||
.map(|s| format!("({})", s))
|
||||
}
|
||||
ast::TyTup(ref items) => {
|
||||
rewrite_tuple(context, items, self.span, width, offset)
|
||||
}
|
||||
ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset),
|
||||
ast::TyPath(ref q_self, ref path) => {
|
||||
|
@ -88,6 +88,7 @@ fn main() {
|
||||
|
||||
fn matches() {
|
||||
match 1 {
|
||||
-1 => 10,
|
||||
1 => 1, // foo
|
||||
2 => 2,
|
||||
// bar
|
||||
|
14
tests/source/pattern.rs
Normal file
14
tests/source/pattern.rs
Normal file
@ -0,0 +1,14 @@
|
||||
fn main() {
|
||||
let z = match x {
|
||||
"pat1" => 1,
|
||||
( ref x, ref mut y /*comment*/) => 2,
|
||||
};
|
||||
|
||||
if let < T as Trait > :: CONST = ident {
|
||||
do_smth();
|
||||
}
|
||||
|
||||
let Some ( ref xyz /* comment! */) = opt;
|
||||
|
||||
if let None = opt2 { panic!("oh noes"); }
|
||||
}
|
@ -2,4 +2,5 @@ fn types() {
|
||||
let x: [ Vec < _ > ] = [];
|
||||
let y: * mut [ SomeType ; konst_funk() ] = expr();
|
||||
let z: (/*#digits*/ usize, /*exp*/ i16) = funk();
|
||||
let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk();
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ fn foo() -> bool {
|
||||
tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 +
|
||||
2222 {}
|
||||
|
||||
if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) =
|
||||
1 + 2 + 3 {
|
||||
if let (some_very_large,
|
||||
tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {
|
||||
}
|
||||
|
||||
let test = if true {
|
||||
|
@ -28,8 +28,8 @@ fn main() {
|
||||
let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAA\
|
||||
AAAAAAAAAAAAaAa";
|
||||
|
||||
if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) =
|
||||
1 + 2 + 3 {
|
||||
if let (some_very_large,
|
||||
tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {
|
||||
}
|
||||
|
||||
if cond() {
|
||||
|
@ -32,7 +32,16 @@ fn foo() {
|
||||
meh,
|
||||
|
||||
// Test that earlier patterns can take the guard space
|
||||
(aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) |
|
||||
(aaaa,
|
||||
bbbbb,
|
||||
ccccccc,
|
||||
aaaaa,
|
||||
bbbbbbbb,
|
||||
cccccc,
|
||||
aaaa,
|
||||
bbbbbbbb,
|
||||
cccccc,
|
||||
dddddd) |
|
||||
Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {}
|
||||
|
||||
_ => {}
|
||||
@ -83,6 +92,7 @@ fn main() {
|
||||
|
||||
fn matches() {
|
||||
match 1 {
|
||||
-1 => 10,
|
||||
1 => 1, // foo
|
||||
2 => 2,
|
||||
// bar
|
||||
|
@ -143,12 +143,20 @@ fn main() {
|
||||
}
|
||||
|
||||
fn deconstruct()
|
||||
-> (SocketAddr, Method, Headers, RequestUri, HttpVersion,
|
||||
-> (SocketAddr,
|
||||
Method,
|
||||
Headers,
|
||||
RequestUri,
|
||||
HttpVersion,
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
|
||||
{
|
||||
}
|
||||
|
||||
fn deconstruct(foo: Bar)
|
||||
-> (SocketAddr, Method, Headers, RequestUri, HttpVersion,
|
||||
-> (SocketAddr,
|
||||
Method,
|
||||
Headers,
|
||||
RequestUri,
|
||||
HttpVersion,
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) {
|
||||
}
|
||||
|
16
tests/target/pattern.rs
Normal file
16
tests/target/pattern.rs
Normal file
@ -0,0 +1,16 @@
|
||||
fn main() {
|
||||
let z = match x {
|
||||
"pat1" => 1,
|
||||
(ref x, ref mut y /* comment */) => 2,
|
||||
};
|
||||
|
||||
if let <T as Trait>::CONST = ident {
|
||||
do_smth();
|
||||
}
|
||||
|
||||
let Some(ref xyz /* comment! */) = opt;
|
||||
|
||||
if let None = opt2 {
|
||||
panic!("oh noes");
|
||||
}
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
fn types() {
|
||||
let x: [Vec<_>] = [];
|
||||
let y: *mut [SomeType; konst_funk()] = expr();
|
||||
let z: (/* #digits */ usize, /* exp */ i16) = funk();
|
||||
let z: (// #digits
|
||||
usize,
|
||||
// exp
|
||||
i16) = funk();
|
||||
let z: (usize /* #digits */, i16 /* exp */) = funk();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user