Use multi line when type bounds does not fit in a single line

This commit is contained in:
topecongiro 2017-06-11 23:26:49 +09:00
parent 9b195ae228
commit f135641cc8
3 changed files with 82 additions and 127 deletions

View file

@ -2063,12 +2063,12 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
// FIXME if context.config.struct_lit_style() == Visual, but we run out
// of space, we should fall back to BlockIndent.
}
pub fn struct_lit_field_separator(config: &Config) -> &str {
colon_spaces(config.space_before_struct_lit_field_colon(),
config.space_after_struct_lit_field_colon())
}
fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option<String> {
let name = &field.ident.node.to_string();
if field.is_shorthand {

View file

@ -21,7 +21,8 @@ use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs};
use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed};
use visitor::FmtVisitor;
use rewrite::{Rewrite, RewriteContext};
use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity};
use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style};
use types::join_bounds;
use syntax::{ast, abi, ptr, symbol};
use syntax::codemap::{Span, BytePos};
@ -666,7 +667,7 @@ fn format_impl_ref_and_type(context: &RewriteContext,
context.config),
0);
let generics_str =
try_opt!(rewrite_generics(context, generics, shape, shape.width, mk_sp(lo, hi)));
try_opt!(rewrite_generics_inner(context, generics, shape, shape.width, mk_sp(lo, hi)));
let polarity_str = if polarity == ast::ImplPolarity::Negative {
"!"
@ -684,7 +685,7 @@ fn format_impl_ref_and_type(context: &RewriteContext,
&mut result);
if !success {
let generics_str =
try_opt!(rewrite_generics(context, generics, shape, 0, mk_sp(lo, hi)));
try_opt!(rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi)));
if !format_trait_ref_then_update_result(context,
&trait_ref,
offset,
@ -839,15 +840,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
let body_lo = context.codemap.span_after(item.span, "{");
let generics_indent = offset + last_line_width(&result);
let shape = generics_shape_from_config(context.config,
Shape::indented(generics_indent, context.config),
0);
let generics_str = try_opt!(rewrite_generics(context,
generics,
shape,
shape.width,
mk_sp(item.span.lo, body_lo)));
let shape = Shape::indented(offset + last_line_width(&result), context.config);
let generics_str =
try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo)));
result.push_str(&generics_str);
let trait_bound_str =
@ -1091,16 +1086,9 @@ fn format_tuple_struct(context: &RewriteContext,
let where_clause_str = match generics {
Some(generics) => {
let generics_indent = offset + last_line_width(&header_str);
let shape = generics_shape_from_config(context.config,
Shape::indented(generics_indent,
context.config),
0);
let generics_str = try_opt!(rewrite_generics(context,
generics,
shape,
shape.width,
mk_sp(span.lo, body_lo)));
let shape = Shape::indented(offset + last_line_width(&header_str), context.config);
let g_span = mk_sp(span.lo, body_lo);
let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
result.push_str(&generics_str);
let where_budget = try_opt!(context
@ -1227,16 +1215,10 @@ pub fn rewrite_type_alias(context: &RewriteContext,
result.push_str("type ");
result.push_str(&ident.to_string());
let generics_indent = indent + result.len();
let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo);
let shape = generics_shape_from_config(context.config,
try_opt!(Shape::indented(generics_indent,
context.config)
.sub_width(" =".len())),
0);
let generics_str =
try_opt!(rewrite_generics(context, generics, shape, shape.width, generics_span));
// 2 = `= `
let shape = try_opt!(Shape::indented(indent + result.len(), context.config).sub_width(2));
let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo);
let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
result.push_str(&generics_str);
let where_budget = try_opt!(context
@ -1470,23 +1452,14 @@ pub fn rewrite_associated_type(ident: ast::Ident,
let prefix = format!("type {}", ident);
let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt {
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let shape = Shape::legacy(context.config.max_width(), indent);
let bounds: &[_] = ty_param_bounds;
let bound_str =
try_opt!(bounds
.iter()
.map(|ty_bound| {
ty_bound.rewrite(context,
Shape::legacy(context.config.max_width(),
indent))
})
.collect::<Option<Vec<_>>>())
.join(joiner);
let bound_str = try_opt!(bounds
.iter()
.map(|ty_bound| ty_bound.rewrite(context, shape))
.collect::<Option<Vec<_>>>());
if bounds.len() > 0 {
format!(": {}", bound_str)
format!(": {}", join_bounds(context, shape, &bound_str))
} else {
String::new()
}
@ -1711,13 +1684,9 @@ fn rewrite_fn_base(context: &RewriteContext,
result.push_str(&ident.to_string());
// Generics.
let generics_indent = indent + last_line_width(&result);
let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo);
let shape = generics_shape_from_config(context.config,
Shape::indented(generics_indent, context.config),
0);
let generics_str =
try_opt!(rewrite_generics(context, generics, shape, shape.width, generics_span));
let shape = Shape::indented(indent + last_line_width(&result), context.config);
let g_span = mk_sp(span.lo, span_for_return(&fd.output).lo);
let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
result.push_str(&generics_str);
let snuggle_angle_bracket = generics_str
@ -2182,9 +2151,19 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool {
fn rewrite_generics(context: &RewriteContext,
generics: &ast::Generics,
shape: Shape,
one_line_width: usize,
span: Span)
-> Option<String> {
let shape = generics_shape_from_config(context.config, shape, 0);
rewrite_generics_inner(context, generics, shape, shape.width, span)
.or_else(|| rewrite_generics_inner(context, generics, shape, 0, span))
}
fn rewrite_generics_inner(context: &RewriteContext,
generics: &ast::Generics,
shape: Shape,
one_line_width: usize,
span: Span)
-> Option<String> {
// FIXME: convert bounds to where clauses where they get too big or if
// there is a where clause at all.
let lifetimes: &[_] = &generics.lifetimes;
@ -2286,20 +2265,11 @@ fn rewrite_trait_bounds(context: &RewriteContext,
if bounds.is_empty() {
return Some(String::new());
}
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let bound_str = try_opt!(bounds
.iter()
.map(|ty_bound| ty_bound.rewrite(&context, shape))
.collect::<Option<Vec<_>>>())
.join(joiner);
let mut result = String::new();
result.push_str(": ");
result.push_str(&bound_str);
Some(result)
.collect::<Option<Vec<_>>>());
Some(format!(": {}", join_bounds(context, shape, &bound_str)))
}
fn rewrite_where_clause_rfc_style(context: &RewriteContext,
@ -2463,9 +2433,8 @@ fn format_generics(context: &RewriteContext,
offset: Indent,
span: Span)
-> Option<String> {
let shape =
generics_shape_from_config(context.config, Shape::indented(offset, context.config), 0);
let mut result = try_opt!(rewrite_generics(context, generics, shape, shape.width, span));
let shape = Shape::indented(offset, context.config);
let mut result = try_opt!(rewrite_generics(context, generics, shape, span));
if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
let budget = try_opt!(context

View file

@ -22,7 +22,7 @@ use codemap::SpanUtils;
use items::{format_generics_item_list, generics_shape_from_config};
use lists::{itemize_list, format_fn_args};
use rewrite::{Rewrite, RewriteContext};
use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp};
use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width};
use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type};
use config::TypeDensity;
@ -362,22 +362,15 @@ impl Rewrite for ast::WherePredicate {
.collect::<Option<Vec<_>>>())
.join(", ");
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
// 6 = "for<> ".len()
let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6;
let budget = try_opt!(shape.width.checked_sub(used_width));
let bounds_str: String = try_opt!(
bounds
.iter()
.map(|ty_bound| {
ty_bound.rewrite(context,
Shape::legacy(budget, shape.indent + used_width))
})
.collect::<Option<Vec<_>>>()
).join(joiner);
let ty_shape = try_opt!(shape.block_left(used_width));
let bounds: Vec<_> =
try_opt!(bounds
.iter()
.map(|ty_bound| ty_bound.rewrite(context, ty_shape))
.collect());
let bounds_str = join_bounds(context, ty_shape, &bounds);
if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
format!("for< {} > {}{}{}",
@ -389,21 +382,14 @@ impl Rewrite for ast::WherePredicate {
format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str)
}
} else {
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let used_width = type_str.len() + colon.len();
let budget = try_opt!(shape.width.checked_sub(used_width));
let bounds_str: String = try_opt!(
bounds
.iter()
.map(|ty_bound| {
ty_bound.rewrite(context,
Shape::legacy(budget, shape.indent + used_width))
})
.collect::<Option<Vec<_>>>()
).join(joiner);
let ty_shape = try_opt!(shape.block_left(used_width));
let bounds: Vec<_> =
try_opt!(bounds
.iter()
.map(|ty_bound| ty_bound.rewrite(context, ty_shape))
.collect());
let bounds_str = join_bounds(context, ty_shape, &bounds);
format!("{}{}{}", type_str, colon, bounds_str)
}
@ -458,11 +444,11 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime,
.map(|b| b.rewrite(context, shape))
.collect());
let colon = type_bound_colon(context);
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let result = format!("{}{}{}", result, colon, appendix.join(joiner));
let overhead = last_line_width(&result) + colon.len();
let result = format!("{}{}{}",
result,
colon,
join_bounds(context, try_opt!(shape.sub_width(overhead)), &appendix));
wrap_str(result, context.config.max_width(), shape)
}
}
@ -494,12 +480,8 @@ impl Rewrite for ast::Lifetime {
impl Rewrite for ast::TyParamBounds {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect());
wrap_str(strs.join(joiner), context.config.max_width(), shape)
join_bounds(context, shape, &strs).rewrite(context, shape)
}
}
@ -514,24 +496,12 @@ impl Rewrite for ast::TyParam {
result.push_str(&attr_str);
result.push_str(&self.ident.to_string());
if !self.bounds.is_empty() {
if context.config.space_before_bound() {
result.push_str(" ");
}
result.push_str(":");
if context.config.space_after_bound_colon() {
result.push_str(" ");
}
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let bounds: String = try_opt!(self.bounds
.iter()
.map(|ty_bound| ty_bound.rewrite(context, shape))
.collect::<Option<Vec<_>>>())
.join(joiner);
result.push_str(&bounds);
result.push_str(type_bound_colon(context));
let strs: Vec<_> = try_opt!(self.bounds
.iter()
.map(|ty_bound| ty_bound.rewrite(context, shape))
.collect());
result.push_str(&join_bounds(context, shape, &strs));
}
if let Some(ref def) = self.default {
@ -732,3 +702,19 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
Some(result)
}
pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &Vec<String>) -> String {
// Try to join types in a single line
let joiner = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "+",
TypeDensity::Wide => " + ",
};
let result = type_strs.join(joiner);
if result.contains('\n') || result.len() > shape.width {
let joiner_indent = shape.indent.block_indent(context.config);
let joiner = format!("\n{}+ ", joiner_indent.to_string(context.config));
type_strs.join(&joiner)
} else {
result
}
}