mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-28 20:16:58 +03:00
WIP
This commit is contained in:
+37
-35
@@ -93,6 +93,7 @@
|
||||
use syntax::codemap::{mk_sp, Span};
|
||||
|
||||
pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
debug!("rewrite_chain {:?}", shape);
|
||||
let total_span = expr.span;
|
||||
let (parent, subexpr_list) = make_subexpr_list(expr, context);
|
||||
|
||||
@@ -103,42 +104,45 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
|
||||
}
|
||||
|
||||
// Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`.
|
||||
let parent_block_indent = chain_base_indent(context, shape.indent);
|
||||
let parent_context = &RewriteContext { block_indent: parent_block_indent, ..*context };
|
||||
let parent_rewrite = try_opt!(parent.rewrite(parent_context, shape));
|
||||
let mut parent_shape = shape;
|
||||
if is_block_expr(&parent, "\n") {
|
||||
parent_shape = chain_base_indent(context, shape);
|
||||
}
|
||||
let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape));
|
||||
|
||||
// Decide how to layout the rest of the chain. `extend` is true if we can
|
||||
// put the first non-parent item on the same line as the parent.
|
||||
let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(&parent) ||
|
||||
parent_rewrite.len() <= context.config.tab_spaces {
|
||||
|
||||
let indent = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node {
|
||||
parent_block_indent.block_indent(context.config)
|
||||
let (nested_shape, extend) = if !parent_rewrite.contains('\n') && is_continuable(&parent) {
|
||||
let nested_shape = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node {
|
||||
parent_shape.block_indent(context.config.tab_spaces)
|
||||
} else {
|
||||
chain_indent(context, shape.indent + Indent::new(0, parent_rewrite.len()))
|
||||
chain_indent(context, shape.add_offset(parent_rewrite.len()))
|
||||
};
|
||||
(indent, true)
|
||||
(nested_shape, true)
|
||||
} else if is_block_expr(&parent, &parent_rewrite) {
|
||||
// The parent is a block, so align the rest of the chain with the closing
|
||||
// brace.
|
||||
(parent_block_indent, false)
|
||||
(parent_shape, false)
|
||||
} else if parent_rewrite.contains('\n') {
|
||||
(chain_indent(context, parent_block_indent.block_indent(context.config)), false)
|
||||
(chain_indent(context, parent_shape.block_indent(context.config.tab_spaces)), false)
|
||||
} else {
|
||||
(chain_indent_newline(context, shape.indent + Indent::new(0, parent_rewrite.len())), false)
|
||||
(chain_indent_newline(context, shape.add_offset(parent_rewrite.len())), false)
|
||||
};
|
||||
|
||||
let max_width = try_opt!((shape.width + shape.indent.width()).checked_sub(indent.width()));
|
||||
let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset).checked_sub(nested_shape.indent.width() + nested_shape.offset));
|
||||
// The alignement in the shape is only used if we start the item on a new
|
||||
// line, so we don't need to preserve the offset.
|
||||
let child_shape = Shape { width: max_width, ..nested_shape };
|
||||
debug!("child_shape {:?}", child_shape);
|
||||
let mut rewrites = try_opt!(subexpr_list.iter()
|
||||
.rev()
|
||||
.map(|e| rewrite_chain_subexpr(e, total_span, context, Shape::legacy(max_width, indent)))
|
||||
.map(|e| rewrite_chain_subexpr(e, total_span, context, child_shape))
|
||||
.collect::<Option<Vec<_>>>());
|
||||
|
||||
// Total of all items excluding the last.
|
||||
let almost_total = rewrites[..rewrites.len() - 1]
|
||||
.iter()
|
||||
.fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len();
|
||||
let total_width = almost_total + first_line_width(rewrites.last().unwrap());
|
||||
|
||||
let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 {
|
||||
// Look at the source code. Unless all chain elements start on the same
|
||||
@@ -152,7 +156,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
|
||||
false
|
||||
};
|
||||
|
||||
let mut fits_single_line = !veto_single_line && total_width <= shape.width;
|
||||
let mut fits_single_line = !veto_single_line && almost_total <= shape.width;
|
||||
if fits_single_line {
|
||||
let len = rewrites.len();
|
||||
let (init, last) = rewrites.split_at_mut(len - 1);
|
||||
@@ -178,7 +182,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
|
||||
String::new()
|
||||
} else {
|
||||
// Use new lines.
|
||||
format!("\n{}", indent.to_string(context.config))
|
||||
format!("\n{}", nested_shape.indent.to_string(context.config))
|
||||
};
|
||||
|
||||
let first_connector = if extend || subexpr_list.is_empty() {
|
||||
@@ -211,7 +215,7 @@ pub fn rewrite_try(expr: &ast::Expr,
|
||||
context: &RewriteContext,
|
||||
shape: Shape)
|
||||
-> Option<String> {
|
||||
let sub_expr = try_opt!(expr.rewrite(context, shape.sub_width(try_count)));
|
||||
let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count))));
|
||||
Some(format!("{}{}",
|
||||
sub_expr,
|
||||
iter::repeat("?").take(try_count).collect::<String>()))
|
||||
@@ -268,29 +272,29 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr,
|
||||
(parent, subexpr_list)
|
||||
}
|
||||
|
||||
fn chain_base_indent(context: &RewriteContext, offset: Indent) -> Indent {
|
||||
fn chain_base_indent(context: &RewriteContext, shape: Shape) -> Shape {
|
||||
match context.config.chain_base_indent {
|
||||
BlockIndentStyle::Visual => offset,
|
||||
BlockIndentStyle::Inherit => context.block_indent,
|
||||
BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config),
|
||||
BlockIndentStyle::Visual => shape,
|
||||
BlockIndentStyle::Inherit => shape.block_indent(0),
|
||||
BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces),
|
||||
}
|
||||
}
|
||||
|
||||
fn chain_indent(context: &RewriteContext, offset: Indent) -> Indent {
|
||||
fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape {
|
||||
match context.config.chain_indent {
|
||||
BlockIndentStyle::Visual => offset,
|
||||
BlockIndentStyle::Inherit => context.block_indent,
|
||||
BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config),
|
||||
BlockIndentStyle::Visual => shape,
|
||||
BlockIndentStyle::Inherit => shape.block_indent(0),
|
||||
BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces),
|
||||
}
|
||||
}
|
||||
|
||||
// Ignores visual indenting because this function should be called where it is
|
||||
// not possible to use visual indentation because we are starting on a newline.
|
||||
fn chain_indent_newline(context: &RewriteContext, _offset: Indent) -> Indent {
|
||||
fn chain_indent_newline(context: &RewriteContext, shape: Shape) -> Shape {
|
||||
match context.config.chain_indent {
|
||||
BlockIndentStyle::Inherit => context.block_indent,
|
||||
BlockIndentStyle::Inherit => shape.block_indent(0),
|
||||
BlockIndentStyle::Visual | BlockIndentStyle::Tabbed => {
|
||||
context.block_indent.block_indent(context.config)
|
||||
shape.block_indent(context.config.tab_spaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,7 +307,7 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind,
|
||||
shape: Shape)
|
||||
-> bool {
|
||||
if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind {
|
||||
let budget = match shape.width.checked_sub(almost_total) {
|
||||
let shape = match shape.shrink_left(almost_total) {
|
||||
Some(b) => b,
|
||||
None => return false,
|
||||
};
|
||||
@@ -312,8 +316,7 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind,
|
||||
expressions,
|
||||
total_span,
|
||||
context,
|
||||
Shape::legacy(budget,
|
||||
shape.indent + almost_total));
|
||||
shape);
|
||||
|
||||
if let Some(ref mut s) = last_rewrite {
|
||||
::std::mem::swap(s, last);
|
||||
@@ -362,8 +365,7 @@ fn rewrite_chain_subexpr(expr: &ast::Expr,
|
||||
-> Option<String> {
|
||||
match expr.node {
|
||||
ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => {
|
||||
let inner = &RewriteContext { block_indent: shape.indent, ..*context };
|
||||
rewrite_method_call(method_name.node, types, expressions, span, inner, shape)
|
||||
rewrite_method_call(method_name.node, types, expressions, span, context, shape)
|
||||
}
|
||||
ast::ExprKind::Field(_, ref field) => {
|
||||
let s = format!(".{}", field.node);
|
||||
|
||||
+190
-221
@@ -253,21 +253,20 @@ pub fn rewrite_pair<LHS, RHS>(lhs: &LHS,
|
||||
where LHS: Rewrite,
|
||||
RHS: Rewrite
|
||||
{
|
||||
let lhs_budget = try_opt!(shape.width.checked_sub(prefix.len() + infix.len()));
|
||||
let rhs_budget = try_opt!(shape.width.checked_sub(suffix.len()));
|
||||
|
||||
// Get "full width" rhs and see if it fits on the current line. This
|
||||
// usually works fairly well since it tends to place operands of
|
||||
// operations with high precendence close together.
|
||||
// Note that this is non-conservative, but its just to see if it's even
|
||||
// worth trying to put everything on one line.
|
||||
let rhs_result = rhs.rewrite(context, Shape::legacy(rhs_budget, shape.indent));
|
||||
let rhs_shape = try_opt!(shape.sub_width(suffix.len()));
|
||||
let rhs_result = rhs.rewrite(context, rhs_shape);
|
||||
|
||||
if let Some(rhs_result) = rhs_result {
|
||||
// This is needed in case of line break not caused by a
|
||||
// shortage of space, but by end-of-line comments, for example.
|
||||
if !rhs_result.contains('\n') {
|
||||
let lhs_result = lhs.rewrite(context, Shape::legacy(lhs_budget, shape.indent));
|
||||
let lhs_shape = try_opt!(shape.sub_width(prefix.len() + infix.len()));
|
||||
let lhs_result = lhs.rewrite(context, lhs_shape);
|
||||
if let Some(lhs_result) = lhs_result {
|
||||
let mut result = format!("{}{}{}", prefix, lhs_result, infix);
|
||||
|
||||
@@ -281,14 +280,15 @@ pub fn rewrite_pair<LHS, RHS>(lhs: &LHS,
|
||||
}
|
||||
|
||||
// Try rewriting the rhs into the remaining space.
|
||||
let rhs_budget = try_opt!(remaining_width.checked_sub(suffix.len()));
|
||||
if let Some(rhs_result) = rhs.rewrite(context,
|
||||
Shape::legacy(rhs_budget,
|
||||
shape.indent + result.len())) {
|
||||
if rhs_result.len() <= remaining_width {
|
||||
result.push_str(&rhs_result);
|
||||
result.push_str(suffix);
|
||||
return Some(result);
|
||||
let rhs_shape = shape.shrink_left(last_line_width(&result) + suffix.len());
|
||||
if let Some(rhs_shape) = rhs_shape {
|
||||
if let Some(rhs_result) = rhs.rewrite(context, rhs_shape) {
|
||||
// FIXME this should always hold.
|
||||
if rhs_result.len() <= remaining_width {
|
||||
result.push_str(&rhs_result);
|
||||
result.push_str(suffix);
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,17 +301,16 @@ pub fn rewrite_pair<LHS, RHS>(lhs: &LHS,
|
||||
let infix = infix.trim_right();
|
||||
let lhs_budget = try_opt!(context.config
|
||||
.max_width
|
||||
.checked_sub(shape.indent.width() + prefix.len() + infix.len()));
|
||||
let rhs_budget = try_opt!(rhs_budget.checked_sub(prefix.len()));
|
||||
let rhs_offset = shape.indent + prefix.len();
|
||||
.checked_sub(shape.used_width() + prefix.len() + infix.len()));
|
||||
let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len());
|
||||
|
||||
let rhs_result = try_opt!(rhs.rewrite(context, Shape::legacy(rhs_budget, rhs_offset)));
|
||||
let lhs_result = try_opt!(lhs.rewrite(context, Shape::legacy(lhs_budget, shape.indent)));
|
||||
let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape));
|
||||
let lhs_result = try_opt!(lhs.rewrite(context, Shape { width: lhs_budget, ..shape }));
|
||||
Some(format!("{}{}{}\n{}{}{}",
|
||||
prefix,
|
||||
lhs_result,
|
||||
infix,
|
||||
rhs_offset.to_string(context.config),
|
||||
rhs_shape.indent.to_string(context.config),
|
||||
rhs_result,
|
||||
suffix))
|
||||
}
|
||||
@@ -328,16 +327,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
|
||||
} else {
|
||||
1 // "["
|
||||
};
|
||||
let offset = shape.indent + bracket_size;
|
||||
let inner_context = &RewriteContext { block_indent: offset, ..*context };
|
||||
let max_item_width = try_opt!(shape.width.checked_sub(bracket_size * 2));
|
||||
let nested_shape = try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2));
|
||||
let items =
|
||||
itemize_list(context.codemap,
|
||||
expr_iter,
|
||||
"]",
|
||||
|item| item.span.lo,
|
||||
|item| item.span.hi,
|
||||
|item| item.rewrite(inner_context, Shape::legacy(max_item_width, offset)),
|
||||
|item| item.rewrite(context, nested_shape),
|
||||
span.lo,
|
||||
span.hi)
|
||||
.collect::<Vec<_>>();
|
||||
@@ -347,7 +344,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
|
||||
.fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y))));
|
||||
|
||||
let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) {
|
||||
definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width)
|
||||
definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width)
|
||||
} else {
|
||||
DefinitiveListTactic::Mixed
|
||||
};
|
||||
@@ -356,7 +353,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
|
||||
tactic: tactic,
|
||||
separator: ",",
|
||||
trailing_separator: SeparatorTactic::Never,
|
||||
shape: Shape::legacy(max_item_width, offset),
|
||||
shape: nested_shape,
|
||||
ends_with_newline: false,
|
||||
config: context.config,
|
||||
};
|
||||
@@ -390,17 +387,14 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let offset = shape.indent + mover.len();
|
||||
|
||||
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
||||
// a single expression.
|
||||
let budget = try_opt!(shape.width.checked_sub(4 + mover.len()));
|
||||
// 1 = |
|
||||
let argument_offset = offset + 1;
|
||||
let ret_str = try_opt!(fn_decl.output.rewrite(context, Shape::legacy(budget, argument_offset)));
|
||||
let nested_shape = try_opt!(try_opt!(shape.shrink_left(mover.len())).sub_width(4));
|
||||
|
||||
// 1 = space between arguments and return type.
|
||||
let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0);
|
||||
// 1 = |
|
||||
let argument_offset = nested_shape.indent + 1;
|
||||
let arg_shape = try_opt!(nested_shape.shrink_left(1)).visual_indent(0);
|
||||
let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape));
|
||||
|
||||
let arg_items =
|
||||
itemize_list(context.codemap,
|
||||
@@ -408,21 +402,23 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
"|",
|
||||
|arg| span_lo_for_arg(arg),
|
||||
|arg| span_hi_for_arg(arg),
|
||||
|arg| arg.rewrite(context, Shape::legacy(budget, argument_offset)),
|
||||
|arg| arg.rewrite(context, arg_shape),
|
||||
context.codemap.span_after(span, "|"),
|
||||
body.span.lo);
|
||||
let item_vec = arg_items.collect::<Vec<_>>();
|
||||
// 1 = space between arguments and return type.
|
||||
let horizontal_budget = nested_shape.width.checked_sub(ret_str.len() + 1).unwrap_or(0);
|
||||
let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget);
|
||||
let budget = match tactic {
|
||||
DefinitiveListTactic::Horizontal => horizontal_budget,
|
||||
_ => budget,
|
||||
let arg_shape = match tactic {
|
||||
DefinitiveListTactic::Horizontal => try_opt!(arg_shape.sub_width(ret_str.len() + 1)),
|
||||
_ => arg_shape,
|
||||
};
|
||||
|
||||
let fmt = ListFormatting {
|
||||
tactic: tactic,
|
||||
separator: ",",
|
||||
trailing_separator: SeparatorTactic::Never,
|
||||
shape: Shape::legacy(budget, argument_offset),
|
||||
shape: arg_shape,
|
||||
ends_with_newline: false,
|
||||
config: context.config,
|
||||
};
|
||||
@@ -440,12 +436,11 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
}
|
||||
|
||||
// 1 = space between `|...|` and body.
|
||||
let extra_offset = extra_offset(&prefix, offset) + 1;
|
||||
let budget = try_opt!(shape.width.checked_sub(extra_offset));
|
||||
let total_offset = offset + extra_offset;
|
||||
let extra_offset = extra_offset(&prefix, shape) + 1;
|
||||
let body_shape = try_opt!(shape.sub_width(extra_offset)).add_offset(extra_offset);
|
||||
|
||||
if let ast::ExprKind::Block(ref block) = body.node {
|
||||
// The body of the closure is a block.
|
||||
// The body of the closure is an empty block.
|
||||
if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) {
|
||||
return Some(format!("{} {{}}", prefix));
|
||||
}
|
||||
@@ -461,7 +456,7 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
if let Some(rw) = rewrite_closure_expr(expr,
|
||||
&prefix,
|
||||
context,
|
||||
Shape::legacy(budget, total_offset)) {
|
||||
body_shape) {
|
||||
return Some(rw);
|
||||
}
|
||||
}
|
||||
@@ -472,8 +467,7 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
let stmt = &block.stmts[0];
|
||||
// 4 = braces and spaces.
|
||||
let mut rewrite = stmt.rewrite(context,
|
||||
Shape::legacy(try_opt!(budget.checked_sub(4)),
|
||||
total_offset));
|
||||
try_opt!(body_shape.sub_width(4)));
|
||||
|
||||
// Checks if rewrite succeeded and fits on a single line.
|
||||
rewrite = and_one_line(rewrite);
|
||||
@@ -484,13 +478,14 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
}
|
||||
|
||||
// Either we require a block, or tried without and failed.
|
||||
return rewrite_closure_block(&block, prefix, context, budget);
|
||||
let body_shape = shape.block();
|
||||
return rewrite_closure_block(&block, prefix, context, body_shape);
|
||||
}
|
||||
|
||||
if let Some(rw) = rewrite_closure_expr(body,
|
||||
&prefix,
|
||||
context,
|
||||
Shape::legacy(budget, total_offset)) {
|
||||
body_shape) {
|
||||
return Some(rw);
|
||||
}
|
||||
|
||||
@@ -506,7 +501,7 @@ fn rewrite_closure(capture: ast::CaptureBy,
|
||||
rules: ast::BlockCheckMode::Default,
|
||||
span: body.span,
|
||||
};
|
||||
return rewrite_closure_block(&block, prefix, context, budget);
|
||||
return rewrite_closure_block(&block, prefix, context, body_shape.block());
|
||||
|
||||
fn rewrite_closure_expr(expr: &ast::Expr,
|
||||
prefix: &str,
|
||||
@@ -523,11 +518,11 @@ fn rewrite_closure_expr(expr: &ast::Expr,
|
||||
fn rewrite_closure_block(block: &ast::Block,
|
||||
prefix: String,
|
||||
context: &RewriteContext,
|
||||
budget: usize)
|
||||
shape: Shape)
|
||||
-> Option<String> {
|
||||
// Start with visual indent, then fall back to block indent if the
|
||||
// closure is large.
|
||||
let rewrite = try_opt!(block.rewrite(&context, Shape::legacy(budget, Indent::empty())));
|
||||
let rewrite = try_opt!(block.rewrite(&context, shape));
|
||||
|
||||
let block_threshold = context.config.closure_block_indent_threshold;
|
||||
if block_threshold < 0 || rewrite.matches('\n').count() <= block_threshold as usize {
|
||||
@@ -536,9 +531,8 @@ fn rewrite_closure_block(block: &ast::Block,
|
||||
|
||||
// The body of the closure is big enough to be block indented, that
|
||||
// means we must re-format.
|
||||
let mut context = context.clone();
|
||||
context.block_indent.alignment = 0;
|
||||
let rewrite = try_opt!(block.rewrite(&context, Shape::legacy(budget, Indent::empty())));
|
||||
let block_shape = shape.block();
|
||||
let rewrite = try_opt!(block.rewrite(&context, block_shape));
|
||||
Some(format!("{} {}", prefix, rewrite))
|
||||
}
|
||||
}
|
||||
@@ -581,7 +575,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
}
|
||||
|
||||
let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
|
||||
visitor.block_indent = context.block_indent;
|
||||
visitor.block_indent = shape.indent;
|
||||
|
||||
let prefix = match self.rules {
|
||||
ast::BlockCheckMode::Unsafe(..) => {
|
||||
@@ -648,9 +642,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
_ => unreachable!(),
|
||||
},
|
||||
context,
|
||||
Shape::legacy(context.config.max_width - shape.indent.width() -
|
||||
suffix.len(),
|
||||
shape.indent))
|
||||
try_opt!(shape.sub_width(suffix.len())))
|
||||
.map(|s| s + suffix)
|
||||
}
|
||||
ast::StmtKind::Mac(..) |
|
||||
@@ -815,32 +807,32 @@ fn rewrite_single_line(&self,
|
||||
impl<'a> Rewrite for ControlFlow<'a> {
|
||||
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
debug!("ControlFlow::rewrite {:?} {:?}", self, shape);
|
||||
let (budget, indent) = if self.nested_if {
|
||||
let constr_shape = if self.nested_if {
|
||||
// We are part of an if-elseif-else chain. Our constraints are tightened.
|
||||
// 7 = "} else " .len()
|
||||
(try_opt!(shape.width.checked_sub(7)), shape.indent + 7)
|
||||
try_opt!(shape.shrink_left(7))
|
||||
} else {
|
||||
(shape.width, shape.indent)
|
||||
shape
|
||||
};
|
||||
|
||||
let label_string = rewrite_label(self.label);
|
||||
// 1 = space after keyword.
|
||||
let inner_offset = indent + self.keyword.len() + label_string.len() + 1;
|
||||
let mut inner_width =
|
||||
try_opt!(budget.checked_sub(self.keyword.len() + label_string.len() + 1));
|
||||
if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine {
|
||||
// 2 = " {".len()
|
||||
inner_width = try_opt!(inner_width.checked_sub(2));
|
||||
}
|
||||
let add_offset = self.keyword.len() + label_string.len() + 1;
|
||||
|
||||
let pat_expr_string = match self.cond {
|
||||
Some(cond) => {
|
||||
let mut cond_shape = try_opt!(constr_shape.shrink_left(add_offset));
|
||||
if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine {
|
||||
// 2 = " {".len()
|
||||
cond_shape = try_opt!(cond_shape.sub_width(2));
|
||||
}
|
||||
|
||||
try_opt!(rewrite_pat_expr(context,
|
||||
self.pat,
|
||||
cond,
|
||||
self.matcher,
|
||||
self.connector,
|
||||
Shape::legacy(inner_width, inner_offset)))
|
||||
cond_shape))
|
||||
}
|
||||
None => String::new(),
|
||||
};
|
||||
@@ -855,21 +847,24 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
let used_width = if pat_expr_string.contains('\n') {
|
||||
last_line_width(&pat_expr_string)
|
||||
} else {
|
||||
// 2 = spaces after keyword and condition.
|
||||
label_string.len() + self.keyword.len() + pat_expr_string.len() + 2
|
||||
};
|
||||
let block_width = try_opt!(shape.width.checked_sub(used_width));
|
||||
// This is used only for the empty block case: `{}`. So, we use 1 if we know
|
||||
// we should avoid the single line case.
|
||||
// 2 = spaces after keyword and condition.
|
||||
let block_width = try_opt!(shape.width
|
||||
.checked_sub(label_string.len() + self.keyword.len() +
|
||||
extra_offset(&pat_expr_string, inner_offset) +
|
||||
2));
|
||||
let block_width = if self.else_block.is_some() || self.nested_if {
|
||||
min(1, block_width)
|
||||
} else {
|
||||
block_width
|
||||
};
|
||||
|
||||
let block_str = try_opt!(self.block
|
||||
.rewrite(context, Shape::legacy(block_width, shape.indent)));
|
||||
// TODO this .block() - not what we want if we are actually visually indented
|
||||
let block_shape = Shape { width: block_width, ..shape };
|
||||
let block_str = try_opt!(self.block.rewrite(context, block_shape));
|
||||
|
||||
let cond_span = if let Some(cond) = self.cond {
|
||||
cond.span
|
||||
@@ -891,7 +886,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
let after_cond_comment =
|
||||
extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape);
|
||||
|
||||
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
|
||||
let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config);
|
||||
let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() {
|
||||
""
|
||||
} else if context.config.control_brace_style ==
|
||||
@@ -913,14 +908,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
|
||||
if let Some(else_block) = self.else_block {
|
||||
// Since this is an else block, we should not indent for the assignment preceding
|
||||
// the original if, so set shape.indent.alignment to 0.
|
||||
let shape = Shape {
|
||||
width: shape.width,
|
||||
indent: Indent {
|
||||
block_indent: shape.indent.block_indent,
|
||||
alignment: 0,
|
||||
},
|
||||
};
|
||||
// the original if, so set shape.offset to 0.
|
||||
let shape = Shape { offset: 0, ..shape };
|
||||
let mut last_in_chain = false;
|
||||
let rewrite = match else_block.node {
|
||||
// If the else expression is another if-else expression, prevent it
|
||||
@@ -935,7 +924,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
false,
|
||||
true,
|
||||
mk_sp(else_block.span.lo, self.span.hi))
|
||||
.rewrite(context, shape)
|
||||
.rewrite(context, shape.visual_indent(0))
|
||||
}
|
||||
ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => {
|
||||
ControlFlow::new_if(cond,
|
||||
@@ -945,13 +934,14 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
false,
|
||||
true,
|
||||
mk_sp(else_block.span.lo, self.span.hi))
|
||||
.rewrite(context, shape)
|
||||
.rewrite(context, shape.visual_indent(0))
|
||||
}
|
||||
_ => {
|
||||
last_in_chain = true;
|
||||
// When rewriting a block, the width is only used for single line
|
||||
// blocks, passing 1 lets us avoid that.
|
||||
else_block.rewrite(context, Shape::legacy(min(1, shape.width), shape.indent))
|
||||
let else_shape = Shape { width: min(1, shape.width), ..shape };
|
||||
else_block.rewrite(context, else_shape)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1097,16 +1087,15 @@ fn rewrite_match(context: &RewriteContext,
|
||||
// `match `cond` {`
|
||||
let cond_budget = try_opt!(shape.width.checked_sub(8));
|
||||
let cond_str = try_opt!(cond.rewrite(context, Shape::legacy(cond_budget, shape.indent + 6)));
|
||||
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
|
||||
let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config);
|
||||
let block_sep = match context.config.control_brace_style {
|
||||
ControlBraceStyle::AlwaysSameLine => " ",
|
||||
_ => alt_block_sep.as_str(),
|
||||
};
|
||||
let mut result = format!("match {}{}{{", cond_str, block_sep);
|
||||
|
||||
let nested_context = context.nested_context();
|
||||
let arm_indent = nested_context.block_indent;
|
||||
let arm_indent_str = arm_indent.to_string(context.config);
|
||||
let arm_shape = shape.block_indent(context.config.tab_spaces);
|
||||
let arm_indent_str = arm_shape.indent.to_string(context.config);
|
||||
|
||||
let open_brace_pos = context.codemap
|
||||
.span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{");
|
||||
@@ -1120,15 +1109,14 @@ fn rewrite_match(context: &RewriteContext,
|
||||
};
|
||||
let comment = try_opt!(rewrite_match_arm_comment(context,
|
||||
&missed_str,
|
||||
Shape::legacy(shape.width, arm_indent),
|
||||
arm_shape,
|
||||
&arm_indent_str));
|
||||
result.push_str(&comment);
|
||||
result.push('\n');
|
||||
result.push_str(&arm_indent_str);
|
||||
|
||||
let arm_str = arm.rewrite(&nested_context,
|
||||
Shape::legacy(context.config.max_width - arm_indent.width(),
|
||||
arm_indent));
|
||||
let arm_str = arm.rewrite(&context,
|
||||
Shape { width: context.config.max_width - arm_shape.indent.width(), .. arm_shape });
|
||||
if let Some(ref arm_str) = arm_str {
|
||||
result.push_str(arm_str);
|
||||
} else {
|
||||
@@ -1143,11 +1131,11 @@ fn rewrite_match(context: &RewriteContext,
|
||||
let last_comment = context.snippet(last_span);
|
||||
let comment = try_opt!(rewrite_match_arm_comment(context,
|
||||
&last_comment,
|
||||
Shape::legacy(shape.width, arm_indent),
|
||||
arm_shape,
|
||||
&arm_indent_str));
|
||||
result.push_str(&comment);
|
||||
result.push('\n');
|
||||
result.push_str(&context.block_indent.to_string(context.config));
|
||||
result.push_str(&shape.indent.to_string(context.config));
|
||||
result.push('}');
|
||||
Some(result)
|
||||
}
|
||||
@@ -1197,7 +1185,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
// We only use this visitor for the attributes, should we use it for
|
||||
// more?
|
||||
let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
|
||||
attr_visitor.block_indent = context.block_indent;
|
||||
attr_visitor.block_indent = shape.indent.block_only();
|
||||
attr_visitor.last_pos = attrs[0].span.lo;
|
||||
if attr_visitor.visit_attrs(attrs) {
|
||||
// Attributes included a skip instruction.
|
||||
@@ -1211,9 +1199,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
|
||||
// Patterns
|
||||
// 5 = ` => {`
|
||||
let pat_budget = try_opt!(shape.width.checked_sub(5));
|
||||
let pat_shape = try_opt!(shape.sub_width(5));
|
||||
|
||||
let pat_strs = try_opt!(pats.iter()
|
||||
.map(|p| p.rewrite(context, Shape::legacy(pat_budget, shape.indent)))
|
||||
.map(|p| p.rewrite(context, pat_shape))
|
||||
.collect::<Option<Vec<_>>>());
|
||||
|
||||
let all_simple = pat_strs.iter().all(|p| pat_is_simple(p));
|
||||
@@ -1226,29 +1215,26 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
},
|
||||
separator: " |",
|
||||
trailing_separator: SeparatorTactic::Never,
|
||||
shape: Shape::legacy(pat_budget, shape.indent),
|
||||
shape: pat_shape,
|
||||
ends_with_newline: false,
|
||||
config: context.config,
|
||||
};
|
||||
let pats_str = try_opt!(write_list(items, &fmt));
|
||||
|
||||
let budget = if pats_str.contains('\n') {
|
||||
context.config.max_width - shape.indent.width()
|
||||
let guard_shape = if pats_str.contains('\n') {
|
||||
Shape { width: context.config.max_width - shape.indent.width(), ..shape }
|
||||
} else {
|
||||
shape.width
|
||||
shape
|
||||
};
|
||||
|
||||
let guard_str = try_opt!(rewrite_guard(context,
|
||||
guard,
|
||||
Shape::legacy(budget, shape.indent),
|
||||
guard_shape,
|
||||
trimmed_last_line_width(&pats_str)));
|
||||
|
||||
let pats_str = format!("{}{}", pats_str, guard_str);
|
||||
// Where the next text can start.
|
||||
let mut line_start = last_line_width(&pats_str);
|
||||
if !pats_str.contains('\n') {
|
||||
line_start += shape.indent.width();
|
||||
}
|
||||
let mut line_start = trimmed_last_line_width(&pats_str);
|
||||
|
||||
let body = match body.node {
|
||||
ast::ExprKind::Block(ref block) if !is_unsafe_block(block) &&
|
||||
@@ -1264,16 +1250,17 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
};
|
||||
|
||||
let comma = arm_comma(&context.config, self, body);
|
||||
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
|
||||
let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config);
|
||||
|
||||
// Let's try and get the arm body on the same line as the condition.
|
||||
// 4 = ` => `.len()
|
||||
if context.config.max_width > line_start + comma.len() + 4 {
|
||||
let budget = context.config.max_width - line_start - comma.len() - 4;
|
||||
let offset = Indent::new(shape.indent.block_indent,
|
||||
line_start + 4 - shape.indent.block_indent);
|
||||
let rewrite = nop_block_collapse(body.rewrite(context, Shape::legacy(budget, offset)),
|
||||
budget);
|
||||
if shape.width > line_start + comma.len() + 4 {
|
||||
let arm_shape = shape.shrink_left(line_start + 4).unwrap().sub_width(comma.len()).unwrap().block();
|
||||
// TODO
|
||||
// let offset = Indent::new(shape.indent.block_indent,
|
||||
// line_start + 4 - shape.indent.block_indent);
|
||||
let rewrite = nop_block_collapse(body.rewrite(context, arm_shape),
|
||||
arm_shape.width);
|
||||
let is_block = if let ast::ExprKind::Block(..) = body.node {
|
||||
true
|
||||
} else {
|
||||
@@ -1301,13 +1288,12 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
|
||||
// FIXME: we're doing a second rewrite of the expr; This may not be
|
||||
// necessary.
|
||||
let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces));
|
||||
let indent = context.block_indent.block_indent(context.config);
|
||||
let inner_context = &RewriteContext { block_indent: indent, ..*context };
|
||||
let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context,
|
||||
Shape::legacy(body_budget,
|
||||
indent)),
|
||||
body_budget));
|
||||
// TODO
|
||||
// let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces));
|
||||
// let indent = shape.indent.block_only().block_indent(context.config);
|
||||
let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces)).block_indent(context.config.tab_spaces);
|
||||
let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape),
|
||||
body_shape.width));
|
||||
let indent_str = shape.indent.block_indent(context.config).to_string(context.config);
|
||||
let (body_prefix, body_suffix) = if context.config.wrap_match_arms {
|
||||
if context.config.match_block_trailing_comma {
|
||||
@@ -1394,6 +1380,7 @@ fn rewrite_pat_expr(context: &RewriteContext,
|
||||
connector: &str,
|
||||
shape: Shape)
|
||||
-> Option<String> {
|
||||
debug!("rewrite_pat_expr {:?}", shape);
|
||||
let mut result = match pat {
|
||||
Some(pat) => {
|
||||
let matcher = if matcher.is_empty() {
|
||||
@@ -1401,26 +1388,22 @@ fn rewrite_pat_expr(context: &RewriteContext,
|
||||
} else {
|
||||
format!("{} ", matcher)
|
||||
};
|
||||
let pat_budget = try_opt!(shape.width.checked_sub(connector.len() + matcher.len()));
|
||||
let pat_offset = shape.indent + matcher.len();
|
||||
let pat_string = try_opt!(pat.rewrite(context, Shape::legacy(pat_budget, pat_offset)));
|
||||
let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())).sub_width(connector.len()));
|
||||
let pat_string = try_opt!(pat.rewrite(context, pat_shape));
|
||||
format!("{}{}{}", matcher, pat_string, connector)
|
||||
}
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
// Consider only the last line of the pat string.
|
||||
let extra_offset = extra_offset(&result, shape.indent);
|
||||
let extra_offset = extra_offset(&result, shape);
|
||||
|
||||
// The expression may (partionally) fit on the current line.
|
||||
// The expression may (partially) fit on the current line.
|
||||
if shape.width > extra_offset + 1 {
|
||||
let spacer = if pat.is_some() { " " } else { "" };
|
||||
|
||||
let expr_rewrite = expr.rewrite(context,
|
||||
Shape::legacy(try_opt!(shape.width
|
||||
.checked_sub(extra_offset +
|
||||
spacer.len())),
|
||||
shape.indent + extra_offset + spacer.len()));
|
||||
let expr_shape = try_opt!(shape.sub_width(extra_offset + spacer.len())).add_offset(extra_offset + spacer.len());
|
||||
let expr_rewrite = expr.rewrite(context, expr_shape);
|
||||
|
||||
if let Some(expr_string) = expr_rewrite {
|
||||
let pat_simple = pat.and_then(|p| {
|
||||
@@ -1437,17 +1420,17 @@ fn rewrite_pat_expr(context: &RewriteContext,
|
||||
}
|
||||
}
|
||||
|
||||
let nested = context.nested_context();
|
||||
let nested_indent = shape.indent.block_only().block_indent(context.config);
|
||||
|
||||
// The expression won't fit on the current line, jump to next.
|
||||
result.push('\n');
|
||||
result.push_str(&nested.block_indent.to_string(context.config));
|
||||
result.push_str(&nested_indent.to_string(context.config));
|
||||
|
||||
let expr_rewrite = expr.rewrite(&nested,
|
||||
let expr_rewrite = expr.rewrite(&context,
|
||||
Shape::legacy(try_opt!(context.config
|
||||
.max_width
|
||||
.checked_sub(nested.block_indent.width())),
|
||||
nested.block_indent));
|
||||
.checked_sub(nested_indent.width())),
|
||||
nested_indent));
|
||||
result.push_str(&try_opt!(expr_rewrite));
|
||||
|
||||
Some(result)
|
||||
@@ -1533,7 +1516,7 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
|
||||
let callee = callee.borrow();
|
||||
// FIXME using byte lens instead of char lens (and probably all over the
|
||||
// place too)
|
||||
let callee_str = match callee.rewrite(context, Shape::legacy(max_callee_width, shape.indent)) {
|
||||
let callee_str = match callee.rewrite(context, Shape { width: max_callee_width, ..shape }) {
|
||||
Some(string) => {
|
||||
if !string.contains('\n') && string.len() > max_callee_width {
|
||||
panic!("{:?} {}", string, max_callee_width);
|
||||
@@ -1547,20 +1530,15 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
|
||||
let span_lo = context.codemap.span_after(span, "(");
|
||||
let span = mk_sp(span_lo, span.hi);
|
||||
|
||||
let extra_offset = extra_offset(&callee_str, shape.indent);
|
||||
let used_width = extra_offset(&callee_str, shape);
|
||||
// 2 is for parens.
|
||||
let remaining_width = match shape.width.checked_sub(extra_offset + 2) {
|
||||
Some(str) => str,
|
||||
let remaining_width = match shape.width.checked_sub(used_width + 2) {
|
||||
Some(s) => s,
|
||||
None => return Err(Ordering::Greater),
|
||||
};
|
||||
let offset = shape.indent + extra_offset + 1;
|
||||
// 1 = (
|
||||
let nested_shape = shape.visual_indent(used_width + 1);
|
||||
let arg_count = args.len();
|
||||
let block_indent = if arg_count == 1 {
|
||||
context.block_indent
|
||||
} else {
|
||||
offset
|
||||
};
|
||||
let inner_context = &RewriteContext { block_indent: block_indent, ..*context };
|
||||
|
||||
let items =
|
||||
itemize_list(context.codemap,
|
||||
@@ -1568,7 +1546,7 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
|
||||
")",
|
||||
|item| item.span.lo,
|
||||
|item| item.span.hi,
|
||||
|item| item.rewrite(inner_context, Shape::legacy(remaining_width, offset)),
|
||||
|item| item.rewrite(context, Shape { width: remaining_width, ..nested_shape }),
|
||||
span.lo,
|
||||
span.hi);
|
||||
let mut item_vec: Vec<_> = items.collect();
|
||||
@@ -1588,9 +1566,12 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
|
||||
// Replace the last item with its first line to see if it fits with
|
||||
// first arguments.
|
||||
if overflow_last {
|
||||
let inner_context = &RewriteContext { block_indent: context.block_indent, ..*context };
|
||||
let rewrite =
|
||||
args.last().unwrap().rewrite(inner_context, Shape::legacy(remaining_width, offset));
|
||||
let nested_shape = Shape {
|
||||
width: remaining_width,
|
||||
indent: nested_shape.indent.block_only(),
|
||||
..nested_shape
|
||||
};
|
||||
let rewrite = args.last().unwrap().rewrite(context, nested_shape);
|
||||
|
||||
if let Some(rewrite) = rewrite {
|
||||
let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned());
|
||||
@@ -1622,7 +1603,7 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
|
||||
tactic: tactic,
|
||||
separator: ",",
|
||||
trailing_separator: SeparatorTactic::Never,
|
||||
shape: Shape::legacy(shape.width, offset),
|
||||
shape: nested_shape,
|
||||
ends_with_newline: false,
|
||||
config: context.config,
|
||||
};
|
||||
@@ -1643,9 +1624,8 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) ->
|
||||
debug!("rewrite_paren, shape: {:?}", shape);
|
||||
// 1 is for opening paren, 2 is for opening+closing, we want to keep the closing
|
||||
// paren on the same line as the subexpr.
|
||||
let subexpr_str = subexpr.rewrite(context,
|
||||
Shape::legacy(try_opt!(shape.width.checked_sub(2)),
|
||||
shape.indent + 1));
|
||||
let sub_shape = try_opt!(shape.sub_width(2)).visual_indent(1);
|
||||
let subexpr_str = subexpr.rewrite(context, sub_shape);
|
||||
debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str);
|
||||
|
||||
subexpr_str.map(|s| if context.config.spaces_within_parens && s.len() > 0 {
|
||||
@@ -1699,24 +1679,20 @@ enum StructLitField<'a> {
|
||||
}
|
||||
|
||||
// 2 = " {".len()
|
||||
let path_budget = try_opt!(shape.width.checked_sub(2));
|
||||
let path_shape = try_opt!(shape.sub_width(2));
|
||||
let path_str = try_opt!(rewrite_path(context,
|
||||
PathContext::Expr,
|
||||
None,
|
||||
path,
|
||||
Shape::legacy(path_budget, shape.indent)));
|
||||
path_shape));
|
||||
|
||||
// Foo { a: Foo } - indent is +3, width is -5.
|
||||
let h_budget = shape.width.checked_sub(path_str.len() + 5).unwrap_or(0);
|
||||
// The 1 taken from the v_budget is for the comma.
|
||||
let (indent, v_budget) = match context.config.struct_lit_style {
|
||||
StructLitStyle::Visual => (shape.indent + path_str.len() + 3, h_budget),
|
||||
let h_shape = shape.sub_width(path_str.len() + 5);
|
||||
let v_shape = match context.config.struct_lit_style {
|
||||
StructLitStyle::Visual => try_opt!(try_opt!(shape.shrink_left(path_str.len() + 3)).sub_width(2)),
|
||||
StructLitStyle::Block => {
|
||||
// If we are all on one line, then we'll ignore the indent, and we
|
||||
// have a smaller budget.
|
||||
let indent = context.block_indent.block_indent(context.config);
|
||||
let v_budget = context.config.max_width.checked_sub(indent.width()).unwrap_or(0);
|
||||
(indent, v_budget)
|
||||
let shape = shape.block_indent(context.config.tab_spaces);
|
||||
Shape { width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), ..shape }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1724,8 +1700,6 @@ enum StructLitField<'a> {
|
||||
.map(StructLitField::Regular)
|
||||
.chain(base.into_iter().map(StructLitField::Base));
|
||||
|
||||
let inner_context = &RewriteContext { block_indent: indent, ..*context };
|
||||
|
||||
let items = itemize_list(context.codemap,
|
||||
field_iter,
|
||||
"}",
|
||||
@@ -1747,14 +1721,15 @@ enum StructLitField<'a> {
|
||||
|item| {
|
||||
match *item {
|
||||
StructLitField::Regular(field) => {
|
||||
rewrite_field(inner_context,
|
||||
// The 1 taken from the v_budget is for the comma.
|
||||
rewrite_field(context,
|
||||
field,
|
||||
Shape::legacy(v_budget.checked_sub(1).unwrap_or(0), indent))
|
||||
try_opt!(v_shape.sub_width(1)))
|
||||
}
|
||||
StructLitField::Base(expr) => {
|
||||
// 2 = ..
|
||||
expr.rewrite(inner_context,
|
||||
Shape::legacy(try_opt!(v_budget.checked_sub(2)), indent + 2))
|
||||
expr.rewrite(context,
|
||||
try_opt!(v_shape.shrink_left(2)))
|
||||
.map(|s| format!("..{}", s))
|
||||
}
|
||||
}
|
||||
@@ -1763,7 +1738,7 @@ enum StructLitField<'a> {
|
||||
span.hi);
|
||||
let item_vec = items.collect::<Vec<_>>();
|
||||
|
||||
let tactic = {
|
||||
let tactic = if let Some(h_shape) = h_shape {
|
||||
let mut prelim_tactic = match (context.config.struct_lit_style, fields.len()) {
|
||||
(StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical,
|
||||
_ => context.config.struct_lit_multiline_style.to_list_tactic(),
|
||||
@@ -1773,12 +1748,14 @@ enum StructLitField<'a> {
|
||||
prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width);
|
||||
}
|
||||
|
||||
definitive_tactic(&item_vec, prelim_tactic, h_budget)
|
||||
definitive_tactic(&item_vec, prelim_tactic, h_shape.width)
|
||||
} else {
|
||||
DefinitiveListTactic::Vertical
|
||||
};
|
||||
|
||||
let budget = match tactic {
|
||||
DefinitiveListTactic::Horizontal => h_budget,
|
||||
_ => v_budget,
|
||||
let nested_shape = match tactic {
|
||||
DefinitiveListTactic::Horizontal => h_shape.unwrap(),
|
||||
_ => v_shape,
|
||||
};
|
||||
|
||||
let ends_with_newline = context.config.struct_lit_style != StructLitStyle::Visual &&
|
||||
@@ -1792,36 +1769,33 @@ enum StructLitField<'a> {
|
||||
} else {
|
||||
context.config.struct_lit_trailing_comma
|
||||
},
|
||||
shape: Shape::legacy(budget, indent),
|
||||
shape: nested_shape,
|
||||
ends_with_newline: ends_with_newline,
|
||||
config: context.config,
|
||||
};
|
||||
let fields_str = try_opt!(write_list(&item_vec, &fmt));
|
||||
|
||||
// Empty struct.
|
||||
if fields_str.is_empty() {
|
||||
return Some(format!("{} {{}}", path_str));
|
||||
}
|
||||
|
||||
let format_on_newline = || {
|
||||
let inner_indent = context.block_indent
|
||||
.block_indent(context.config)
|
||||
.to_string(context.config);
|
||||
let outer_indent = context.block_indent.to_string(context.config);
|
||||
Some(format!("{} {{\n{}{}\n{}}}",
|
||||
path_str,
|
||||
inner_indent,
|
||||
fields_str,
|
||||
outer_indent))
|
||||
};
|
||||
|
||||
match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) {
|
||||
(StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => {
|
||||
format_on_newline()
|
||||
}
|
||||
(StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(),
|
||||
_ => Some(format!("{} {{ {} }}", path_str, fields_str)),
|
||||
// One liner or visual indent.
|
||||
if context.config.struct_lit_style == StructLitStyle::Visual ||
|
||||
(context.config.struct_lit_multiline_style != MultilineStyle::ForceMulti &&
|
||||
!fields_str.contains('\n') &&
|
||||
fields_str.len() <= h_shape.map(|s| s.width).unwrap_or(0)) {
|
||||
return Some(format!("{} {{ {} }}", path_str, fields_str));
|
||||
}
|
||||
|
||||
// Multiple lines.
|
||||
let inner_indent = v_shape.indent.to_string(context.config);
|
||||
let outer_indent = shape.indent.to_string(context.config);
|
||||
Some(format!("{} {{\n{}{}\n{}}}",
|
||||
path_str,
|
||||
inner_indent,
|
||||
fields_str,
|
||||
outer_indent))
|
||||
// FIXME if context.config.struct_lit_style == Visual, but we run out
|
||||
// of space, we should fall back to BlockIndent.
|
||||
}
|
||||
@@ -1842,9 +1816,9 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) ->
|
||||
} else {
|
||||
let separator = type_annotation_separator(context.config);
|
||||
let overhead = name.len() + separator.len();
|
||||
let expr = field.expr.rewrite(context,
|
||||
Shape::legacy(try_opt!(shape.width.checked_sub(overhead)),
|
||||
shape.indent + overhead));
|
||||
let mut expr_shape = try_opt!(shape.sub_width(overhead));
|
||||
expr_shape.offset += overhead;
|
||||
let expr = field.expr.rewrite(context, expr_shape);
|
||||
|
||||
match expr {
|
||||
Some(e) => Some(format!("{}{}{}", name, separator, e)),
|
||||
@@ -1871,16 +1845,14 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext,
|
||||
<I as Iterator>::Item: Deref,
|
||||
<I::Item as Deref>::Target: Rewrite + Spanned + 'a
|
||||
{
|
||||
let indent = shape.indent + 1;
|
||||
let aligned = RewriteContext { block_indent: indent, ..context.clone() };
|
||||
|
||||
debug!("rewrite_tuple {:?}", shape);
|
||||
// In case of length 1, need a trailing comma
|
||||
if items.len() == 1 {
|
||||
// 3 = "(" + ",)"
|
||||
let budget = try_opt!(shape.width.checked_sub(3));
|
||||
let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1);
|
||||
return items.next()
|
||||
.unwrap()
|
||||
.rewrite(&aligned, Shape::legacy(budget, indent))
|
||||
.rewrite(context, nested_shape)
|
||||
.map(|s| if context.config.spaces_within_parens {
|
||||
format!("( {}, )", s)
|
||||
} else {
|
||||
@@ -1889,16 +1861,16 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext,
|
||||
}
|
||||
|
||||
let list_lo = context.codemap.span_after(span, "(");
|
||||
let budget = try_opt!(shape.width.checked_sub(2));
|
||||
let nested_shape = try_opt!(shape.sub_width(2)).visual_indent(1);
|
||||
let items = itemize_list(context.codemap,
|
||||
items,
|
||||
")",
|
||||
|item| item.span().lo,
|
||||
|item| item.span().hi,
|
||||
|item| item.rewrite(&aligned, Shape::legacy(budget, indent)),
|
||||
|item| item.rewrite(context, nested_shape),
|
||||
list_lo,
|
||||
span.hi - BytePos(1));
|
||||
let list_str = try_opt!(format_item_list(items, Shape::legacy(budget, indent), context.config));
|
||||
let list_str = try_opt!(format_item_list(items, nested_shape, context.config));
|
||||
|
||||
if context.config.spaces_within_parens && list_str.len() > 0 {
|
||||
Some(format!("( {} )", list_str))
|
||||
@@ -1912,10 +1884,8 @@ pub fn rewrite_unary_prefix<R: Rewrite>(context: &RewriteContext,
|
||||
rewrite: &R,
|
||||
shape: Shape)
|
||||
-> Option<String> {
|
||||
rewrite.rewrite(context,
|
||||
Shape::legacy(try_opt!(shape.width.checked_sub(prefix.len())),
|
||||
shape.indent + prefix.len()))
|
||||
.map(|r| format!("{}{}", prefix, r))
|
||||
let shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0);
|
||||
rewrite.rewrite(context, shape).map(|r| format!("{}{}", prefix, r))
|
||||
}
|
||||
|
||||
// FIXME: this is probably not correct for multi-line Rewrites. we should
|
||||
@@ -1925,9 +1895,7 @@ pub fn rewrite_unary_suffix<R: Rewrite>(context: &RewriteContext,
|
||||
rewrite: &R,
|
||||
shape: Shape)
|
||||
-> Option<String> {
|
||||
rewrite.rewrite(context,
|
||||
Shape::legacy(try_opt!(shape.width.checked_sub(suffix.len())),
|
||||
shape.indent))
|
||||
rewrite.rewrite(context, try_opt!(shape.sub_width(suffix.len())))
|
||||
.map(|mut r| {
|
||||
r.push_str(suffix);
|
||||
r
|
||||
@@ -1960,9 +1928,9 @@ fn rewrite_assignment(context: &RewriteContext,
|
||||
};
|
||||
|
||||
// 1 = space between lhs and operator.
|
||||
let max_width = try_opt!(shape.width.checked_sub(operator_str.len() + 1));
|
||||
let lhs_shape = try_opt!(shape.sub_width(operator_str.len() + 1));
|
||||
let lhs_str = format!("{} {}",
|
||||
try_opt!(lhs.rewrite(context, Shape::legacy(max_width, shape.indent))),
|
||||
try_opt!(lhs.rewrite(context, lhs_shape)),
|
||||
operator_str);
|
||||
|
||||
rewrite_assign_rhs(context, lhs_str, rhs, shape)
|
||||
@@ -1985,7 +1953,9 @@ pub fn rewrite_assign_rhs<S: Into<String>>(context: &RewriteContext,
|
||||
// 1 = space between operator and rhs.
|
||||
let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1));
|
||||
let rhs = ex.rewrite(context,
|
||||
Shape::legacy(max_width, shape.indent + last_line_width + 1));
|
||||
Shape::offset(max_width,
|
||||
shape.indent.block_only(),
|
||||
shape.indent.alignment + last_line_width + 1));
|
||||
|
||||
fn count_line_breaks(src: &str) -> usize {
|
||||
src.chars().filter(|&x| x == '\n').count()
|
||||
@@ -2003,8 +1973,7 @@ fn count_line_breaks(src: &str) -> usize {
|
||||
let new_offset = shape.indent.block_indent(context.config);
|
||||
let max_width = try_opt!((shape.width + shape.indent.width())
|
||||
.checked_sub(new_offset.width()));
|
||||
let inner_context = context.nested_context();
|
||||
let new_rhs = ex.rewrite(&inner_context, Shape::legacy(max_width, new_offset));
|
||||
let new_rhs = ex.rewrite(context, Shape::legacy(max_width, new_offset));
|
||||
|
||||
// FIXME: DRY!
|
||||
match (rhs, new_rhs) {
|
||||
|
||||
+28
-27
@@ -70,12 +70,12 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||
|
||||
if let Some(ref ex) = self.init {
|
||||
// 1 = trailing semicolon;
|
||||
let budget = try_opt!(shape.width.checked_sub(context.block_indent.width() + 1));
|
||||
let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1));
|
||||
|
||||
result = try_opt!(rewrite_assign_rhs(&context,
|
||||
result,
|
||||
ex,
|
||||
Shape::legacy(budget, context.block_indent)));
|
||||
Shape::legacy(budget, shape.indent.block_only())));
|
||||
}
|
||||
|
||||
result.push(';');
|
||||
@@ -520,7 +520,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -
|
||||
context.config,
|
||||
context.config.item_brace_style,
|
||||
Shape::legacy(where_budget,
|
||||
context.block_indent),
|
||||
offset.block_only()),
|
||||
context.config.where_density,
|
||||
"{",
|
||||
true,
|
||||
@@ -539,7 +539,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -
|
||||
|
||||
if !where_clause_str.is_empty() && !where_clause_str.contains('\n') {
|
||||
result.push('\n');
|
||||
let width = context.block_indent.width() + context.config.tab_spaces - 1;
|
||||
let width = offset.block_indent + context.config.tab_spaces - 1;
|
||||
let where_indent = Indent::new(0, width);
|
||||
result.push_str(&where_indent.to_string(context.config));
|
||||
}
|
||||
@@ -568,7 +568,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -
|
||||
|
||||
if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
|
||||
let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
|
||||
visitor.block_indent = context.block_indent.block_indent(context.config);
|
||||
visitor.block_indent = offset.block_only().block_indent(context.config);
|
||||
visitor.last_pos = item.span.lo + BytePos(open_pos as u32);
|
||||
|
||||
for item in items {
|
||||
@@ -578,7 +578,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -
|
||||
visitor.format_missing(item.span.hi - BytePos(1));
|
||||
|
||||
let inner_indent_str = visitor.block_indent.to_string(context.config);
|
||||
let outer_indent_str = context.block_indent.to_string(context.config);
|
||||
let outer_indent_str = offset.block_only().to_string(context.config);
|
||||
|
||||
result.push('\n');
|
||||
result.push_str(&inner_indent_str);
|
||||
@@ -654,7 +654,7 @@ fn format_impl_ref_and_type(context: &RewriteContext,
|
||||
result.push('\n');
|
||||
|
||||
// Add indentation of one additional tab.
|
||||
let width = context.block_indent.width() + context.config.tab_spaces;
|
||||
let width = offset.block_indent + context.config.tab_spaces;
|
||||
let for_indent = Indent::new(0, width);
|
||||
result.push_str(&for_indent.to_string(context.config));
|
||||
|
||||
@@ -762,7 +762,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
|
||||
if offset.width() + last_line_width(&result) + trait_bound_str.len() >
|
||||
context.config.ideal_width {
|
||||
result.push('\n');
|
||||
let trait_indent = context.block_indent.block_indent(context.config);
|
||||
let trait_indent = offset.block_only().block_indent(context.config);
|
||||
result.push_str(&trait_indent.to_string(context.config));
|
||||
}
|
||||
result.push_str(&trait_bound_str);
|
||||
@@ -789,7 +789,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
|
||||
context.config,
|
||||
context.config.item_brace_style,
|
||||
Shape::legacy(where_budget,
|
||||
context.block_indent),
|
||||
offset.block_only()),
|
||||
where_density,
|
||||
"{",
|
||||
has_body,
|
||||
@@ -800,7 +800,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
|
||||
last_line_width(&result) + where_clause_str.len() + offset.width() >
|
||||
context.config.ideal_width {
|
||||
result.push('\n');
|
||||
let width = context.block_indent.width() + context.config.tab_spaces - 1;
|
||||
let width = offset.block_indent + context.config.tab_spaces - 1;
|
||||
let where_indent = Indent::new(0, width);
|
||||
result.push_str(&where_indent.to_string(context.config));
|
||||
}
|
||||
@@ -829,7 +829,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
|
||||
|
||||
if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
|
||||
let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
|
||||
visitor.block_indent = context.block_indent.block_indent(context.config);
|
||||
visitor.block_indent = offset.block_only().block_indent(context.config);
|
||||
visitor.last_pos = item.span.lo + BytePos(open_pos as u32);
|
||||
|
||||
for item in trait_items {
|
||||
@@ -839,7 +839,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
|
||||
visitor.format_missing(item.span.hi - BytePos(1));
|
||||
|
||||
let inner_indent_str = visitor.block_indent.to_string(context.config);
|
||||
let outer_indent_str = context.block_indent.to_string(context.config);
|
||||
let outer_indent_str = offset.block_only().to_string(context.config);
|
||||
|
||||
result.push('\n');
|
||||
result.push_str(&inner_indent_str);
|
||||
@@ -892,7 +892,7 @@ fn format_struct_struct(context: &RewriteContext,
|
||||
}
|
||||
None => {
|
||||
if context.config.item_brace_style == BraceStyle::AlwaysNextLine && !fields.is_empty() {
|
||||
format!("\n{}{{", context.block_indent.to_string(context.config))
|
||||
format!("\n{}{{", offset.block_only().to_string(context.config))
|
||||
} else {
|
||||
" {".to_owned()
|
||||
}
|
||||
@@ -1004,7 +1004,7 @@ fn format_tuple_struct(context: &RewriteContext,
|
||||
&generics.where_clause,
|
||||
context.config,
|
||||
context.config.item_brace_style,
|
||||
Shape::legacy(where_budget, context.block_indent),
|
||||
Shape::legacy(where_budget, offset.block_only()),
|
||||
Density::Compressed,
|
||||
";",
|
||||
false,
|
||||
@@ -1014,7 +1014,7 @@ fn format_tuple_struct(context: &RewriteContext,
|
||||
};
|
||||
result.push('(');
|
||||
|
||||
let item_indent = context.block_indent + result.len();
|
||||
let item_indent = offset.block_only() + result.len();
|
||||
// 2 = ");"
|
||||
let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2));
|
||||
|
||||
@@ -1052,12 +1052,12 @@ fn format_tuple_struct(context: &RewriteContext,
|
||||
|
||||
if !where_clause_str.is_empty() && !where_clause_str.contains('\n') &&
|
||||
(result.contains('\n') ||
|
||||
context.block_indent.width() + result.len() + where_clause_str.len() + 1 >
|
||||
offset.block_indent + result.len() + where_clause_str.len() + 1 >
|
||||
context.config.max_width) {
|
||||
// We need to put the where clause on a new line, but we didn'to_string
|
||||
// know that earlier, so the where clause will not be indented properly.
|
||||
result.push('\n');
|
||||
result.push_str(&(context.block_indent + (context.config.tab_spaces - 1))
|
||||
result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1))
|
||||
.to_string(context.config));
|
||||
}
|
||||
result.push_str(&where_clause_str);
|
||||
@@ -1192,6 +1192,7 @@ pub fn rewrite_static(prefix: &str,
|
||||
ty: &ast::Ty,
|
||||
mutability: ast::Mutability,
|
||||
expr_opt: Option<&ptr::P<ast::Expr>>,
|
||||
offset: Indent,
|
||||
context: &RewriteContext)
|
||||
-> Option<String> {
|
||||
let type_annotation_spacing = type_annotation_spacing(context.config);
|
||||
@@ -1205,19 +1206,19 @@ pub fn rewrite_static(prefix: &str,
|
||||
// 2 = " =".len()
|
||||
let ty_str = try_opt!(ty.rewrite(context,
|
||||
Shape::legacy(context.config.max_width -
|
||||
context.block_indent.width() -
|
||||
offset.block_indent -
|
||||
prefix.len() -
|
||||
2,
|
||||
context.block_indent)));
|
||||
offset.block_only())));
|
||||
|
||||
if let Some(expr) = expr_opt {
|
||||
let lhs = format!("{}{} =", prefix, ty_str);
|
||||
// 1 = ;
|
||||
let remaining_width = context.config.max_width - context.block_indent.width() - 1;
|
||||
let remaining_width = context.config.max_width - offset.block_indent - 1;
|
||||
rewrite_assign_rhs(context,
|
||||
lhs,
|
||||
expr,
|
||||
Shape::legacy(remaining_width, context.block_indent))
|
||||
Shape::legacy(remaining_width, offset.block_only()))
|
||||
.map(|s| s + ";")
|
||||
} else {
|
||||
let lhs = format!("{}{};", prefix, ty_str);
|
||||
@@ -1253,10 +1254,10 @@ pub fn rewrite_associated_type(ident: ast::Ident,
|
||||
if let Some(ty) = ty_opt {
|
||||
let ty_str = try_opt!(ty.rewrite(context,
|
||||
Shape::legacy(context.config.max_width -
|
||||
context.block_indent.width() -
|
||||
indent.block_indent -
|
||||
prefix.len() -
|
||||
2,
|
||||
context.block_indent)));
|
||||
indent.block_only())));
|
||||
Some(format!("{} = {};", prefix, ty_str))
|
||||
} else {
|
||||
Some(format!("{}{};", prefix, type_bounds_str))
|
||||
@@ -1473,7 +1474,7 @@ fn rewrite_fn_base(context: &RewriteContext,
|
||||
multi_line_budget = context.config.max_width - arg_indent.width();
|
||||
}
|
||||
|
||||
debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
|
||||
debug!("rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
|
||||
one_line_budget,
|
||||
multi_line_budget,
|
||||
arg_indent);
|
||||
@@ -2020,7 +2021,7 @@ fn format_generics(context: &RewriteContext,
|
||||
context.config,
|
||||
brace_style,
|
||||
Shape::legacy(budget,
|
||||
context.block_indent),
|
||||
offset.block_only()),
|
||||
Density::Tall,
|
||||
terminator,
|
||||
true,
|
||||
@@ -2029,7 +2030,7 @@ fn format_generics(context: &RewriteContext,
|
||||
if !force_same_line_brace &&
|
||||
(brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) {
|
||||
result.push('\n');
|
||||
result.push_str(&context.block_indent.to_string(context.config));
|
||||
result.push_str(&offset.block_only().to_string(context.config));
|
||||
} else {
|
||||
result.push(' ');
|
||||
}
|
||||
@@ -2037,7 +2038,7 @@ fn format_generics(context: &RewriteContext,
|
||||
} else {
|
||||
if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine {
|
||||
result.push('\n');
|
||||
result.push_str(&context.block_indent.to_string(context.config));
|
||||
result.push_str(&offset.block_only().to_string(context.config));
|
||||
} else {
|
||||
result.push(' ');
|
||||
}
|
||||
|
||||
+93
-3
@@ -133,6 +133,13 @@ pub fn empty() -> Indent {
|
||||
Indent::new(0, 0)
|
||||
}
|
||||
|
||||
pub fn block_only(&self) -> Indent {
|
||||
Indent {
|
||||
block_indent: self.block_indent,
|
||||
alignment: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_indent(mut self, config: &Config) -> Indent {
|
||||
self.block_indent += config.tab_spaces;
|
||||
self
|
||||
@@ -204,7 +211,11 @@ fn sub(self, rhs: usize) -> Indent {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Shape {
|
||||
pub width: usize,
|
||||
// The current indentation of code.
|
||||
pub indent: Indent,
|
||||
// Indentation + any already emitted text on the first line of the current
|
||||
// statement.
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
@@ -212,6 +223,7 @@ pub fn indented(indent: Indent, config: &Config) -> Shape {
|
||||
Shape {
|
||||
width: config.max_width,
|
||||
indent: indent,
|
||||
offset: indent.width(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,14 +246,92 @@ pub fn legacy(width: usize, indent: Indent) -> Shape {
|
||||
Shape {
|
||||
width: width,
|
||||
indent: indent,
|
||||
offset: indent.alignment,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sub_width(self, width: usize) -> Shape {
|
||||
pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape {
|
||||
Shape {
|
||||
width: self.width - width,
|
||||
indent: self.indent,
|
||||
width: width,
|
||||
indent: indent,
|
||||
offset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visual_indent(&self, extra_width: usize) -> Shape {
|
||||
let alignment = self.offset + extra_width;
|
||||
Shape {
|
||||
width: self.width,
|
||||
indent: Indent {
|
||||
block_indent: self.indent.block_indent,
|
||||
alignment: alignment,
|
||||
},
|
||||
offset: alignment,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_indent(&self, extra_width: usize) -> Shape {
|
||||
if self.indent.alignment == 0 {
|
||||
Shape {
|
||||
width: self.width,
|
||||
indent: Indent {
|
||||
block_indent: self.indent.block_indent + extra_width,
|
||||
alignment: 0,
|
||||
},
|
||||
offset: 0,
|
||||
}
|
||||
} else {
|
||||
Shape {
|
||||
width: self.width,
|
||||
indent: Indent {
|
||||
block_indent: self.indent.block_indent,
|
||||
alignment: self.indent.alignment + extra_width,
|
||||
},
|
||||
offset: self.indent.alignment + extra_width,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_offset(&self, extra_width: usize) -> Shape {
|
||||
Shape {
|
||||
width: self.width,
|
||||
indent: Indent {
|
||||
block_indent: self.indent.block_indent,
|
||||
alignment: self.indent.alignment,
|
||||
},
|
||||
offset: self.offset + extra_width,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block(&self) -> Shape {
|
||||
Shape {
|
||||
width: self.width,
|
||||
indent: Indent {
|
||||
block_indent: self.indent.block_indent,
|
||||
alignment: 0,
|
||||
},
|
||||
offset: self.offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sub_width(&self, width: usize) -> Option<Shape> {
|
||||
Some(Shape {
|
||||
width: try_opt!(self.width.checked_sub(width)),
|
||||
indent: self.indent,
|
||||
offset: self.offset,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn shrink_left(&self, width: usize) -> Option<Shape> {
|
||||
Some(Shape {
|
||||
width: try_opt!(self.width.checked_sub(width)),
|
||||
indent: self.indent + width,
|
||||
offset: self.offset + width,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn used_width(&self) -> usize {
|
||||
self.indent.block_indent + self.offset
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -155,15 +155,14 @@ pub fn rewrite_macro(mac: &ast::Mac,
|
||||
MacroStyle::Brackets => {
|
||||
// Format macro invocation as array literal.
|
||||
let extra_offset = macro_name.len();
|
||||
let shape = try_opt!(shape.shrink_left(extra_offset));
|
||||
let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
|
||||
mk_sp(context.codemap
|
||||
.span_after(mac.span,
|
||||
original_style.opener()),
|
||||
mac.span.hi - BytePos(1)),
|
||||
context,
|
||||
Shape::legacy(try_opt!(shape.width
|
||||
.checked_sub(extra_offset)),
|
||||
shape.indent + extra_offset)));
|
||||
shape));
|
||||
|
||||
Some(format!("{}{}", macro_name, rewrite))
|
||||
}
|
||||
|
||||
+5
-5
@@ -220,16 +220,16 @@ fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>],
|
||||
|
||||
let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0);
|
||||
// 2 = "()".len(), 3 = "(,)".len()
|
||||
let width = try_opt!(shape.width.checked_sub(path_len + if add_comma { 3 } else { 2 }));
|
||||
let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 }));
|
||||
// 1 = "(".len()
|
||||
let offset = shape.indent + path_len + 1;
|
||||
let nested_shape = nested_shape.visual_indent(path_len + 1);
|
||||
let mut items: Vec<_> =
|
||||
itemize_list(context.codemap,
|
||||
pat_vec.iter(),
|
||||
if add_comma { ",)" } else { ")" },
|
||||
|item| item.span().lo,
|
||||
|item| item.span().hi,
|
||||
|item| item.rewrite(context, Shape::legacy(width, offset)),
|
||||
|item| item.rewrite(context, nested_shape),
|
||||
context.codemap.span_after(span, "("),
|
||||
span.hi - BytePos(1))
|
||||
.collect();
|
||||
@@ -242,10 +242,10 @@ fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>],
|
||||
items[new_item_count - 1].item = Some("..".to_owned());
|
||||
|
||||
let da_iter = items.into_iter().take(new_item_count);
|
||||
try_opt!(format_item_list(da_iter, Shape::legacy(width, offset), context.config))
|
||||
try_opt!(format_item_list(da_iter, nested_shape, context.config))
|
||||
} else {
|
||||
try_opt!(format_item_list(items.into_iter(),
|
||||
Shape::legacy(width, offset),
|
||||
nested_shape,
|
||||
context.config))
|
||||
};
|
||||
|
||||
|
||||
+1
-12
@@ -13,7 +13,7 @@
|
||||
use syntax::codemap::{CodeMap, Span};
|
||||
use syntax::parse::ParseSess;
|
||||
|
||||
use {Indent, Shape};
|
||||
use Shape;
|
||||
use config::Config;
|
||||
|
||||
pub trait Rewrite {
|
||||
@@ -26,20 +26,9 @@ pub struct RewriteContext<'a> {
|
||||
pub parse_session: &'a ParseSess,
|
||||
pub codemap: &'a CodeMap,
|
||||
pub config: &'a Config,
|
||||
// Indentation due to nesting of blocks.
|
||||
pub block_indent: Indent,
|
||||
}
|
||||
|
||||
impl<'a> RewriteContext<'a> {
|
||||
pub fn nested_context(&self) -> RewriteContext<'a> {
|
||||
RewriteContext {
|
||||
parse_session: self.parse_session,
|
||||
codemap: self.codemap,
|
||||
config: self.config,
|
||||
block_indent: self.block_indent.block_indent(self.config),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snippet(&self, span: Span) -> String {
|
||||
self.codemap.span_to_snippet(span).unwrap()
|
||||
}
|
||||
|
||||
+3
-2
@@ -36,7 +36,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
|
||||
let stripped_str = re.replace_all(orig, "$1");
|
||||
|
||||
let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::<Vec<&str>>();
|
||||
let indent = fmt.shape.indent.to_string(fmt.config);
|
||||
let shape = fmt.shape.visual_indent(0);
|
||||
let indent = shape.indent.to_string(fmt.config);
|
||||
let punctuation = ":,;.";
|
||||
|
||||
// `cur_start` is the position in `orig` of the start of the current line.
|
||||
@@ -49,7 +50,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
|
||||
let ender_length = fmt.line_end.len();
|
||||
// If we cannot put at least a single character per line, the rewrite won't
|
||||
// succeed.
|
||||
let max_chars = try_opt!(fmt.shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1;
|
||||
let max_chars = try_opt!(shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1;
|
||||
|
||||
// Snip a line at a time from `orig` until it is used up. Push the snippet
|
||||
// onto result.
|
||||
|
||||
+16
-24
@@ -66,9 +66,9 @@ pub fn rewrite_path(context: &RewriteContext,
|
||||
result.push_str("::");
|
||||
}
|
||||
|
||||
let extra_offset = extra_offset(&result, shape.indent);
|
||||
let extra_offset = extra_offset(&result, shape);
|
||||
// 3 = ">::".len()
|
||||
let budget = try_opt!(shape.width.checked_sub(extra_offset + 3));
|
||||
let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3));
|
||||
|
||||
result = try_opt!(rewrite_path_segments(PathContext::Type,
|
||||
result,
|
||||
@@ -76,8 +76,7 @@ pub fn rewrite_path(context: &RewriteContext,
|
||||
span_lo,
|
||||
path.span.hi,
|
||||
context,
|
||||
Shape::legacy(budget,
|
||||
shape.indent + extra_offset)));
|
||||
shape));
|
||||
}
|
||||
|
||||
if context.config.spaces_within_angle_brackets {
|
||||
@@ -88,15 +87,15 @@ pub fn rewrite_path(context: &RewriteContext,
|
||||
span_lo = qself.ty.span.hi + BytePos(1);
|
||||
}
|
||||
|
||||
let extra_offset = extra_offset(&result, shape.indent);
|
||||
let budget = try_opt!(shape.width.checked_sub(extra_offset));
|
||||
let extra_offset = extra_offset(&result, shape);
|
||||
let shape = try_opt!(shape.shrink_left(extra_offset));
|
||||
rewrite_path_segments(path_context,
|
||||
result,
|
||||
path.segments.iter().skip(skip_count),
|
||||
span_lo,
|
||||
path.span.hi,
|
||||
context,
|
||||
Shape::legacy(budget, shape.indent + extra_offset))
|
||||
shape)
|
||||
}
|
||||
|
||||
fn rewrite_path_segments<'a, I>(path_context: PathContext,
|
||||
@@ -110,6 +109,7 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext,
|
||||
where I: Iterator<Item = &'a ast::PathSegment>
|
||||
{
|
||||
let mut first = true;
|
||||
let shape = shape.visual_indent(0);
|
||||
|
||||
for segment in iter {
|
||||
// Indicates a global path, shouldn't be rendered.
|
||||
@@ -122,15 +122,14 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext,
|
||||
buffer.push_str("::");
|
||||
}
|
||||
|
||||
let extra_offset = extra_offset(&buffer, shape.indent);
|
||||
let remaining_width = try_opt!(shape.width.checked_sub(extra_offset));
|
||||
let new_offset = shape.indent + extra_offset;
|
||||
let extra_offset = extra_offset(&buffer, shape);
|
||||
let new_shape = try_opt!(shape.shrink_left(extra_offset));
|
||||
let segment_string = try_opt!(rewrite_segment(path_context,
|
||||
segment,
|
||||
&mut span_lo,
|
||||
span_hi,
|
||||
context,
|
||||
Shape::legacy(remaining_width, new_offset)));
|
||||
new_shape));
|
||||
|
||||
buffer.push_str(&segment_string);
|
||||
}
|
||||
@@ -190,8 +189,7 @@ fn rewrite_segment(path_context: PathContext,
|
||||
shape: Shape)
|
||||
-> Option<String> {
|
||||
let ident_len = segment.identifier.to_string().len();
|
||||
let width = try_opt!(shape.width.checked_sub(ident_len));
|
||||
let offset = shape.indent + ident_len;
|
||||
let shape = try_opt!(shape.shrink_left(ident_len));
|
||||
|
||||
let params = if let Some(ref params) = segment.parameters {
|
||||
match **params {
|
||||
@@ -216,24 +214,18 @@ fn rewrite_segment(path_context: PathContext,
|
||||
// 1 for <
|
||||
let extra_offset = 1 + separator.len();
|
||||
// 1 for >
|
||||
let list_width = try_opt!(width.checked_sub(extra_offset + 1));
|
||||
// TODO bad visual indent
|
||||
let list_shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(1)).visual_indent(0);
|
||||
|
||||
let items = itemize_list(context.codemap,
|
||||
param_list.into_iter(),
|
||||
">",
|
||||
|param| param.get_span().lo,
|
||||
|param| param.get_span().hi,
|
||||
|seg| {
|
||||
seg.rewrite(context,
|
||||
Shape::legacy(list_width,
|
||||
offset + extra_offset))
|
||||
},
|
||||
|seg| seg.rewrite(context, list_shape),
|
||||
list_lo,
|
||||
span_hi);
|
||||
let list_str = try_opt!(format_item_list(items,
|
||||
Shape::legacy(list_width,
|
||||
offset + extra_offset),
|
||||
context.config));
|
||||
let list_str = try_opt!(format_item_list(items, list_shape, context.config));
|
||||
|
||||
// Update position of last bracket.
|
||||
*span_lo = next_span_lo;
|
||||
@@ -254,7 +246,7 @@ fn rewrite_segment(path_context: PathContext,
|
||||
false,
|
||||
data.span,
|
||||
context,
|
||||
Shape::legacy(width, offset)))
|
||||
shape))
|
||||
}
|
||||
_ => String::new(),
|
||||
}
|
||||
|
||||
+3
-3
@@ -18,16 +18,16 @@
|
||||
use syntax::codemap::BytePos;
|
||||
use syntax::abi;
|
||||
|
||||
use {Indent, Shape};
|
||||
use Shape;
|
||||
use rewrite::{Rewrite, RewriteContext};
|
||||
|
||||
use SKIP_ANNOTATION;
|
||||
|
||||
// Computes the length of a string's last line, minus offset.
|
||||
pub fn extra_offset(text: &str, offset: Indent) -> usize {
|
||||
pub fn extra_offset(text: &str, shape: Shape) -> usize {
|
||||
match text.rfind('\n') {
|
||||
// 1 for newline character
|
||||
Some(idx) => text.len().checked_sub(idx + 1 + offset.width()).unwrap_or(0),
|
||||
Some(idx) => text.len().checked_sub(idx + 1 + shape.used_width()).unwrap_or(0),
|
||||
None => text.len(),
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -294,6 +294,7 @@ pub fn visit_item(&mut self, item: &ast::Item) {
|
||||
ty,
|
||||
mutability,
|
||||
Some(expr),
|
||||
self.block_indent,
|
||||
&self.get_context());
|
||||
self.push_rewrite(item.span, rewrite);
|
||||
}
|
||||
@@ -304,6 +305,7 @@ pub fn visit_item(&mut self, item: &ast::Item) {
|
||||
ty,
|
||||
ast::Mutability::Immutable,
|
||||
Some(expr),
|
||||
self.block_indent,
|
||||
&self.get_context());
|
||||
self.push_rewrite(item.span, rewrite);
|
||||
}
|
||||
@@ -353,6 +355,7 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
|
||||
ty,
|
||||
ast::Mutability::Immutable,
|
||||
expr_opt.as_ref(),
|
||||
self.block_indent,
|
||||
&self.get_context());
|
||||
self.push_rewrite(ti.span, rewrite);
|
||||
}
|
||||
@@ -403,6 +406,7 @@ pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
|
||||
ty,
|
||||
ast::Mutability::Immutable,
|
||||
Some(expr),
|
||||
self.block_indent,
|
||||
&self.get_context());
|
||||
self.push_rewrite(ii.span, rewrite);
|
||||
}
|
||||
@@ -560,7 +564,6 @@ pub fn get_context(&self) -> RewriteContext {
|
||||
parse_session: self.parse_session,
|
||||
codemap: self.codemap,
|
||||
config: self.config,
|
||||
block_indent: self.block_indent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user