Address some issues with multiline patterns in let statements

This commit is contained in:
Marcus Klaas 2015-10-24 12:19:58 +02:00
parent 58ff0d8730
commit d122ad5adc
6 changed files with 154 additions and 76 deletions

View File

@ -1398,7 +1398,10 @@ pub fn rewrite_tuple<'a, R>(context: &RewriteContext,
|item| item.span().lo,
|item| item.span().hi,
|item| {
let inner_width = context.config.max_width - indent.width() - 1;
let inner_width = try_opt!(context.config
.max_width
.checked_sub(indent.width() +
1));
item.rewrite(context, inner_width, indent)
},
span.lo + BytePos(1), // Remove parens
@ -1522,10 +1525,15 @@ pub fn rewrite_assign_rhs<S: Into<String>>(context: &RewriteContext,
offset: Indent)
-> Option<String> {
let mut result = lhs.into();
let last_line_width = last_line_width(&result) -
if result.contains('\n') {
offset.width()
} else {
0
};
// 1 = space between operator and rhs.
let max_width = try_opt!(width.checked_sub(result.len() + 1));
let rhs = ex.rewrite(&context, max_width, offset + result.len() + 1);
let max_width = try_opt!(width.checked_sub(last_line_width + 1));
let rhs = ex.rewrite(&context, max_width, offset + last_line_width + 1);
match rhs {
Some(new_str) => {

View File

@ -26,85 +26,59 @@ use syntax::codemap::{Span, BytePos, mk_sp};
use syntax::print::pprust;
use syntax::parse::token;
impl<'a> FmtVisitor<'a> {
pub fn visit_let(&mut self, local: &ast::Local, span: Span) {
self.format_missing_with_indent(span.lo);
// Statements of the form
// let pat: ty = init;
impl Rewrite for ast::Local {
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
let mut result = "let ".to_owned();
let pattern_offset = offset + result.len();
// 1 = ;
let pattern_width = try_opt!(width.checked_sub(pattern_offset.width() + 1));
// 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();
// 1 = ;
let pattern_width = match self.config
.max_width
.checked_sub(pattern_offset.width() + 1) {
Some(width) => width,
None => return,
};
let pat_str = try_opt!(self.pat.rewrite(&context, pattern_width, pattern_offset));
result.push_str(&pat_str);
match local.pat.rewrite(&context, pattern_width, pattern_offset) {
Some(ref pat_string) => result.push_str(pat_string),
None => return,
// String that is placed within the assignment pattern and expression.
let infix = {
let mut infix = String::new();
if let Some(ref ty) = self.ty {
// 2 = ": ".len()
// 1 = ;
let indent = offset + last_line_width(&result) + 2;
let budget = try_opt!(width.checked_sub(indent.width() + 1));
let rewrite = try_opt!(ty.rewrite(context, budget, indent));
infix.push_str(": ");
infix.push_str(&rewrite);
}
// 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 {
let max_width = self.config.max_width.checked_sub(context.block_indent.width() + 1);
let max_width = match max_width {
Some(width) => width,
None => return,
};
// 1 = trailing semicolon;
let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent);
match rhs {
Some(s) => s,
None => return,
}
} else {
result
if self.init.is_some() {
infix.push_str(" =");
}
infix
};
self.buffer.push_str(&result);
self.buffer.push_str(";");
self.last_pos = span.hi;
}
result.push_str(&infix);
if let Some(ref ex) = self.init {
let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1));
// 1 = trailing semicolon;
result = try_opt!(rewrite_assign_rhs(&context,
result,
ex,
budget,
context.block_indent));
}
result.push(';');
Some(result)
}
}
impl<'a> FmtVisitor<'a> {
pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
self.buffer.push_str("extern ");

View File

@ -168,6 +168,14 @@ impl Add<usize> for Indent {
}
}
impl Sub<usize> for Indent {
type Output = Indent;
fn sub(self, rhs: usize) -> Indent {
Indent::new(self.block_indent, self.alignment - rhs)
}
}
#[derive(Copy, Clone)]
pub enum WriteMode {
// Backups the original file and overwrites the orignal.

View File

@ -37,7 +37,13 @@ impl<'a> FmtVisitor<'a> {
match stmt.node {
ast::Stmt_::StmtDecl(ref decl, _) => {
match decl.node {
ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span),
ast::Decl_::DeclLocal(ref local) => {
let rewrite = {
let context = self.get_context();
local.rewrite(&context, self.config.max_width, self.block_indent)
};
self.push_rewrite(stmt.span, rewrite);
}
ast::Decl_::DeclItem(ref item) => self.visit_item(item),
}
}

39
tests/source/issue-510.rs Normal file
View File

@ -0,0 +1,39 @@
impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
fn solve_inline_size_constraints(&self,
block: &mut BlockFlow,
input: &ISizeConstraintInput)
-> ISizeConstraintSolution {
let (inline_start,inline_size,margin_inline_start,margin_inline_end) =
match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
// Now it is the same situation as inline-start Specified and inline-end
// and inline-size Auto.
//
// Set inline-end to zero to calculate inline-size.
let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
(Au(0), inline_size, margin_start, margin_end)
}
};
// FIXME(#501): tuple width heuristic may not be optimal for patterns.
let (inline_start, inline_size, margin_inline_start, margin_inline_end) =
match (inline_start, inline_end, computed_inline_size) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
// Now it is the same situation as inline-start Specified and inline-end
// and inline-size Auto.
//
// Set inline-end to zero to calculate inline-size.
let inline_size =
block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
(Au(0), inline_size, margin_start, margin_end)
}
};
}
}

43
tests/target/issue-510.rs Normal file
View File

@ -0,0 +1,43 @@
impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
fn solve_inline_size_constraints(&self,
block: &mut BlockFlow,
input: &ISizeConstraintInput)
-> ISizeConstraintSolution {
let (inline_start,
inline_size,
margin_inline_start,
margin_inline_end) = match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,
inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
// Now it is the same situation as inline-start Specified and inline-end
// and inline-size Auto.
//
// Set inline-end to zero to calculate inline-size.
let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
(Au(0), inline_size, margin_start, margin_end)
}
};
// FIXME(#501): tuple width heuristic may not be optimal for patterns.
let (inline_start,
inline_size,
margin_inline_start,
margin_inline_end) = match (inline_start, inline_end, computed_inline_size) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
// Now it is the same situation as inline-start Specified and inline-end
// and inline-size Auto.
//
// Set inline-end to zero to calculate inline-size.
let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
(Au(0), inline_size, margin_start, margin_end)
}
};
}
}