diff --git a/src/expr.rs b/src/expr.rs index d9fa4717357b..8f167650507b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,6 +31,7 @@ use lists::{ use macros::{rewrite_macro, MacroArg, MacroPosition}; use matches::rewrite_match; use overflow; +use pairs::{rewrite_pair, PairParts}; use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; @@ -435,109 +436,6 @@ fn rewrite_simple_binaries( None } -/// Sigils that decorate a binop pair. -#[derive(new, Clone, Copy)] -pub struct PairParts<'a> { - prefix: &'a str, - infix: &'a str, - suffix: &'a str, -} - -impl<'a> PairParts<'a> { - pub fn infix(infix: &'a str) -> PairParts<'a> { - PairParts { - prefix: "", - infix, - suffix: "", - } - } -} - -pub fn rewrite_pair( - lhs: &LHS, - rhs: &RHS, - pp: PairParts, - context: &RewriteContext, - shape: Shape, - separator_place: SeparatorPlace, -) -> Option -where - LHS: Rewrite, - RHS: Rewrite, -{ - let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), - SeparatorPlace::Front => shape.used_width(), - }; - let lhs_shape = Shape { - width: context.budget(lhs_overhead), - ..shape - }; - let lhs_result = lhs - .rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; - - // Try to put both lhs and rhs on the same line. - let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + pp.infix.len()) - .and_then(|s| s.sub_width(pp.suffix.len())) - .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); - if let Some(ref rhs_result) = rhs_orig_result { - // If the length of the lhs is equal to or shorter than the tab width or - // the rhs looks like block expression, we put the rhs on the same - // line with the lhs even if the rhs is multi-lined. - let allow_same_line = lhs_result.len() <= context.config.tab_spaces() - || rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); - if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) - + pp.infix.len() - + first_line_width(rhs_result) - + pp.suffix.len(); - if one_line_width <= shape.width { - return Some(format!( - "{}{}{}{}", - lhs_result, pp.infix, rhs_result, pp.suffix - )); - } - } - } - - // We have to use multiple lines. - // Re-evaluate the rhs because we have more space now: - let mut rhs_shape = match context.config.indent_style() { - IndentStyle::Visual => shape - .sub_width(pp.suffix.len() + pp.prefix.len())? - .visual_indent(pp.prefix.len()), - IndentStyle::Block => { - // Try to calculate the initial constraint on the right hand side. - let rhs_overhead = shape.rhs_overhead(context.config); - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead)? - } - }; - let infix = match separator_place { - SeparatorPlace::Back => pp.infix.trim_right(), - SeparatorPlace::Front => pp.infix.trim_left(), - }; - if separator_place == SeparatorPlace::Front { - rhs_shape = rhs_shape.offset_left(infix.len())?; - } - let rhs_result = rhs.rewrite(context, rhs_shape)?; - let indent_str = rhs_shape.indent.to_string_with_newline(context.config); - let infix_with_sep = match separator_place { - SeparatorPlace::Back => format!("{}{}", infix, indent_str), - SeparatorPlace::Front => format!("{}{}", indent_str, infix), - }; - Some(format!( - "{}{}{}{}", - lhs_result, infix_with_sep, rhs_result, pp.suffix - )) -} - pub fn rewrite_array( name: &str, exprs: &[&T], diff --git a/src/lib.rs b/src/lib.rs index 817ed426e522..2c9a792d92d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ mod matches; mod missed_spans; pub(crate) mod modules; mod overflow; +mod pairs; mod patterns; mod reorder; mod rewrite; diff --git a/src/pairs.rs b/src/pairs.rs new file mode 100644 index 000000000000..55c78b641a01 --- /dev/null +++ b/src/pairs.rs @@ -0,0 +1,119 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::lists::*; + +use config::IndentStyle; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{first_line_width, last_line_width}; + +/// Sigils that decorate a binop pair. +#[derive(new, Clone, Copy)] +pub struct PairParts<'a> { + prefix: &'a str, + infix: &'a str, + suffix: &'a str, +} + +impl<'a> PairParts<'a> { + pub fn infix(infix: &'a str) -> PairParts<'a> { + PairParts { + prefix: "", + infix, + suffix: "", + } + } +} + +pub fn rewrite_pair( + lhs: &LHS, + rhs: &RHS, + pp: PairParts, + context: &RewriteContext, + shape: Shape, + separator_place: SeparatorPlace, +) -> Option +where + LHS: Rewrite, + RHS: Rewrite, +{ + let lhs_overhead = match separator_place { + SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), + SeparatorPlace::Front => shape.used_width(), + }; + let lhs_shape = Shape { + width: context.budget(lhs_overhead), + ..shape + }; + let lhs_result = lhs + .rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; + + // Try to put both lhs and rhs on the same line. + let rhs_orig_result = shape + .offset_left(last_line_width(&lhs_result) + pp.infix.len()) + .and_then(|s| s.sub_width(pp.suffix.len())) + .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); + if let Some(ref rhs_result) = rhs_orig_result { + // If the length of the lhs is equal to or shorter than the tab width or + // the rhs looks like block expression, we put the rhs on the same + // line with the lhs even if the rhs is multi-lined. + let allow_same_line = lhs_result.len() <= context.config.tab_spaces() + || rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); + if !rhs_result.contains('\n') || allow_same_line { + let one_line_width = last_line_width(&lhs_result) + + pp.infix.len() + + first_line_width(rhs_result) + + pp.suffix.len(); + if one_line_width <= shape.width { + return Some(format!( + "{}{}{}{}", + lhs_result, pp.infix, rhs_result, pp.suffix + )); + } + } + } + + // We have to use multiple lines. + // Re-evaluate the rhs because we have more space now: + let mut rhs_shape = match context.config.indent_style() { + IndentStyle::Visual => shape + .sub_width(pp.suffix.len() + pp.prefix.len())? + .visual_indent(pp.prefix.len()), + IndentStyle::Block => { + // Try to calculate the initial constraint on the right hand side. + let rhs_overhead = shape.rhs_overhead(context.config); + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(rhs_overhead)? + } + }; + let infix = match separator_place { + SeparatorPlace::Back => pp.infix.trim_right(), + SeparatorPlace::Front => pp.infix.trim_left(), + }; + if separator_place == SeparatorPlace::Front { + rhs_shape = rhs_shape.offset_left(infix.len())?; + } + let rhs_result = rhs.rewrite(context, rhs_shape)?; + let indent_str = rhs_shape.indent.to_string_with_newline(context.config); + let infix_with_sep = match separator_place { + SeparatorPlace::Back => format!("{}{}", infix, indent_str), + SeparatorPlace::Front => format!("{}{}", indent_str, infix), + }; + Some(format!( + "{}{}{}{}", + lhs_result, infix_with_sep, rhs_result, pp.suffix + )) +} diff --git a/src/patterns.rs b/src/patterns.rs index 5e3cbfc31f3c..dbe0c8a6f662 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,15 +15,14 @@ use syntax::ptr; use codemap::SpanUtils; use comment::FindUncommented; -use expr::{ - can_be_overflowed_expr, rewrite_pair, rewrite_unary_prefix, wrap_struct_field, PairParts, -}; +use expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use lists::{ itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; use macros::{rewrite_macro, MacroPosition}; use overflow; +use pairs::{rewrite_pair, PairParts}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; diff --git a/src/types.rs b/src/types.rs index 42dfd3596c89..0c978ea28a67 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,12 +18,11 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{ - rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, ToExpr, -}; +use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; +use pairs::{rewrite_pair, PairParts}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned;