]> git.lizzy.rs Git - rust.git/blobdiff - src/pairs.rs
Placate tidy in submodule.
[rust.git] / src / pairs.rs
index c4451a8e466093cff12969ac2fd9cf7f4f901c89..d1c75126ea4a7fce24a8eede42ecd677df916d3e 100644 (file)
@@ -1,20 +1,12 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+use rustc_ast::ast;
 
-use syntax::ast;
-
-use config::lists::*;
-use config::IndentStyle;
-use rewrite::{Rewrite, RewriteContext};
-use shape::Shape;
-use utils::{first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str};
+use crate::config::lists::*;
+use crate::config::IndentStyle;
+use crate::rewrite::{Rewrite, RewriteContext};
+use crate::shape::Shape;
+use crate::utils::{
+    first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str,
+};
 
 /// Sigils that decorate a binop pair.
 #[derive(new, Clone, Copy)]
@@ -40,51 +32,44 @@ pub(crate) fn infix(infix: &'a str) -> PairParts<'a> {
 pub(crate) fn rewrite_all_pairs(
     expr: &ast::Expr,
     shape: Shape,
-    context: &RewriteContext,
+    context: &RewriteContext<'_>,
 ) -> Option<String> {
-    // First we try formatting on one line.
-    if let Some(list) = expr.flatten(false) {
-        if let Some(r) = rewrite_pairs_one_line(&list, shape, context) {
-            return Some(r);
-        }
-    }
-
-    // We can't format on line, so try many. When we flatten here we make sure
-    // to only flatten pairs with the same operator, that way we don't
-    // necessarily need one line per sub-expression, but we don't do anything
-    // too funny wrt precedence.
-    expr.flatten(true)
-        .and_then(|list| rewrite_pairs_multiline(list, shape, context))
+    expr.flatten(context, shape).and_then(|list| {
+        // First we try formatting on one line.
+        rewrite_pairs_one_line(&list, shape, context)
+            .or_else(|| rewrite_pairs_multiline(&list, shape, context))
+    })
 }
 
 // This may return a multi-line result since we allow the last expression to go
 // multiline in a 'single line' formatting.
 fn rewrite_pairs_one_line<T: Rewrite>(
-    list: &PairList<T>,
+    list: &PairList<'_, '_, T>,
     shape: Shape,
-    context: &RewriteContext,
+    context: &RewriteContext<'_>,
 ) -> Option<String> {
     assert!(list.list.len() >= 2, "Not a pair?");
 
     let mut result = String::new();
     let base_shape = shape.block();
 
-    for (e, s) in list.list.iter().zip(list.separators.iter()) {
-        let cur_shape = base_shape.offset_left(last_line_width(&result))?;
-        let rewrite = e.rewrite(context, cur_shape)?;
+    for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
+        if let Some(rewrite) = rewrite {
+            if !is_single_line(rewrite) || result.len() > shape.width {
+                return None;
+            }
 
-        if !is_single_line(&rewrite) || result.len() > shape.width {
+            result.push_str(rewrite);
+            result.push(' ');
+            result.push_str(s);
+            result.push(' ');
+        } else {
             return None;
         }
-
-        result.push_str(&rewrite);
-        result.push(' ');
-        result.push_str(s);
-        result.push(' ');
     }
 
     let prefix_len = result.len();
-    let last = list.list.last().unwrap();
+    let last = list.list.last()?.0;
     let cur_shape = base_shape.offset_left(last_line_width(&result))?;
     let last_rewrite = last.rewrite(context, cur_shape)?;
     result.push_str(&last_rewrite);
@@ -105,25 +90,24 @@ fn rewrite_pairs_one_line<T: Rewrite>(
 }
 
 fn rewrite_pairs_multiline<T: Rewrite>(
-    list: PairList<T>,
+    list: &PairList<'_, '_, T>,
     shape: Shape,
-    context: &RewriteContext,
+    context: &RewriteContext<'_>,
 ) -> Option<String> {
-    let rhs_offset = shape.rhs_overhead(&context.config);
+    let rhs_offset = shape.rhs_overhead(context.config);
     let nested_shape = (match context.config.indent_style() {
         IndentStyle::Visual => shape.visual_indent(0),
         IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
     })
-    .with_max_width(&context.config)
+    .with_max_width(context.config)
     .sub_width(rhs_offset)?;
 
     let indent_str = nested_shape.indent.to_string_with_newline(context.config);
     let mut result = String::new();
 
-    let rewrite = list.list[0].rewrite(context, shape)?;
-    result.push_str(&rewrite);
+    result.push_str(list.list[0].1.as_ref()?);
 
-    for (e, s) in list.list[1..].iter().zip(list.separators.iter()) {
+    for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
         // The following test checks if we should keep two subexprs on the same
         // line. We do this if not doing so would create an orphan and there is
         // enough space to do so.
@@ -147,24 +131,20 @@ fn rewrite_pairs_multiline<T: Rewrite>(
             }
         }
 
-        let nested_overhead = s.len() + 1;
-        let line_shape = match context.config.binop_separator() {
+        match context.config.binop_separator() {
             SeparatorPlace::Back => {
                 result.push(' ');
                 result.push_str(s);
                 result.push_str(&indent_str);
-                nested_shape.sub_width(nested_overhead)?
             }
             SeparatorPlace::Front => {
                 result.push_str(&indent_str);
                 result.push_str(s);
                 result.push(' ');
-                nested_shape.offset_left(nested_overhead)?
             }
-        };
+        }
 
-        let rewrite = e.rewrite(context, line_shape)?;
-        result.push_str(&rewrite);
+        result.push_str(default_rw.as_ref()?);
     }
     Some(result)
 }
@@ -173,8 +153,8 @@ fn rewrite_pairs_multiline<T: Rewrite>(
 pub(crate) fn rewrite_pair<LHS, RHS>(
     lhs: &LHS,
     rhs: &RHS,
-    pp: PairParts,
-    context: &RewriteContext,
+    pp: PairParts<'_>,
+    context: &RewriteContext<'_>,
     shape: Shape,
     separator_place: SeparatorPlace,
 ) -> Option<String>
@@ -184,7 +164,7 @@ pub(crate) fn rewrite_pair<LHS, RHS>(
 {
     let tab_spaces = context.config.tab_spaces();
     let lhs_overhead = match separator_place {
-        SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(),
+        SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_end().len(),
         SeparatorPlace::Front => shape.used_width(),
     };
     let lhs_shape = Shape {
@@ -204,11 +184,12 @@ pub(crate) fn rewrite_pair<LHS, RHS>(
         // 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() <= tab_spaces || rhs_result
-            .lines()
-            .next()
-            .map(|first_line| first_line.ends_with('{'))
-            .unwrap_or(false);
+        let allow_same_line = lhs_result.len() <= 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()
@@ -237,8 +218,8 @@ pub(crate) fn rewrite_pair<LHS, RHS>(
         }
     };
     let infix = match separator_place {
-        SeparatorPlace::Back => pp.infix.trim_right(),
-        SeparatorPlace::Front => pp.infix.trim_left(),
+        SeparatorPlace::Back => pp.infix.trim_end(),
+        SeparatorPlace::Front => pp.infix.trim_start(),
     };
     if separator_place == SeparatorPlace::Front {
         rhs_shape = rhs_shape.offset_left(infix.len())?;
@@ -257,27 +238,46 @@ pub(crate) fn rewrite_pair<LHS, RHS>(
 
 // A pair which forms a tree and can be flattened (e.g., binops).
 trait FlattenPair: Rewrite + Sized {
-    // If `_same_op` is `true`, then we only combine binops with the same
-    // operator into the list. E.g,, if the source is `a * b + c`, if `_same_op`
-    // is true, we make `[(a * b), c]` if `_same_op` is false, we make
-    // `[a, b, c]`
-    fn flatten(&self, _same_op: bool) -> Option<PairList<Self>> {
+    fn flatten(&self, _: &RewriteContext<'_>, _: Shape) -> Option<PairList<'_, '_, Self>> {
         None
     }
 }
 
-struct PairList<'a, 'b, T: Rewrite + 'b> {
-    list: Vec<&'b T>,
+struct PairList<'a, 'b, T: Rewrite> {
+    list: Vec<(&'b T, Option<String>)>,
     separators: Vec<&'a str>,
 }
 
 impl FlattenPair for ast::Expr {
-    fn flatten(&self, same_op: bool) -> Option<PairList<ast::Expr>> {
-        let top_op = match self.node {
+    fn flatten(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> Option<PairList<'_, '_, ast::Expr>> {
+        let top_op = match self.kind {
             ast::ExprKind::Binary(op, _, _) => op.node,
             _ => return None,
         };
 
+        let default_rewrite = |node: &ast::Expr, sep: usize, is_first: bool| {
+            if is_first {
+                return node.rewrite(context, shape);
+            }
+            let nested_overhead = sep + 1;
+            let rhs_offset = shape.rhs_overhead(context.config);
+            let nested_shape = (match context.config.indent_style() {
+                IndentStyle::Visual => shape.visual_indent(0),
+                IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
+            })
+            .with_max_width(context.config)
+            .sub_width(rhs_offset)?;
+            let default_shape = match context.config.binop_separator() {
+                SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,
+                SeparatorPlace::Front => nested_shape.offset_left(nested_overhead)?,
+            };
+            node.rewrite(context, default_shape)
+        };
+
         // Turn a tree of binop expressions into a list using a depth-first,
         // in-order traversal.
         let mut stack = vec![];
@@ -285,15 +285,17 @@ fn flatten(&self, same_op: bool) -> Option<PairList<ast::Expr>> {
         let mut separators = vec![];
         let mut node = self;
         loop {
-            match node.node {
-                ast::ExprKind::Binary(op, ref lhs, _) if !same_op || op.node == top_op => {
+            match node.kind {
+                ast::ExprKind::Binary(op, ref lhs, _) if op.node == top_op => {
                     stack.push(node);
                     node = lhs;
                 }
                 _ => {
-                    list.push(node);
+                    let op_len = separators.last().map_or(0, |s: &&str| s.len());
+                    let rw = default_rewrite(node, op_len, list.is_empty());
+                    list.push((node, rw));
                     if let Some(pop) = stack.pop() {
-                        match pop.node {
+                        match pop.kind {
                             ast::ExprKind::Binary(op, _, ref rhs) => {
                                 separators.push(op.node.to_string());
                                 node = rhs;
@@ -308,10 +310,7 @@ fn flatten(&self, same_op: bool) -> Option<PairList<ast::Expr>> {
         }
 
         assert_eq!(list.len() - 1, separators.len());
-        Some(PairList {
-            list,
-            separators,
-        })
+        Some(PairList { list, separators })
     }
 }