about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWhizSid <whizsid@aol.com>2020-10-18 22:32:46 +0530
committerCaleb Cartwright <calebcartwright@users.noreply.github.com>2020-11-29 13:26:58 -0600
commit7d9ee7558e5992bb0929302109c97a2e3c267c86 (patch)
tree27f0149b20c8cd4c5489641291b2c11cf7ed77e2
parent823c4f820a46159661d681b6f982c6457c5eb0f6 (diff)
downloadrust-7d9ee7558e5992bb0929302109c97a2e3c267c86.tar.gz
rust-7d9ee7558e5992bb0929302109c97a2e3c267c86.zip
Comment between typebounds (#4474)
* Test cases and get spans

* Fixed type bounds

* Fixed issue of test cases

* Fixed first test case issue

* Removed unwanted whitespaces

* Removed tmp files
-rw-r--r--src/types.rs162
-rw-r--r--tests/source/issue-4243.rs21
-rw-r--r--tests/target/issue-4243.rs28
3 files changed, 167 insertions, 44 deletions
diff --git a/src/types.rs b/src/types.rs
index e8bd74d5a12..7eeee2ac979 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -874,57 +874,131 @@ fn join_bounds(
     items: &[ast::GenericBound],
     need_indent: bool,
 ) -> Option<String> {
-    debug_assert!(!items.is_empty());
-
-    // Try to join types in a single line
-    let joiner = match context.config.type_punctuation_density() {
-        TypeDensity::Compressed => "+",
-        TypeDensity::Wide => " + ",
-    };
-    let type_strs = items
-        .iter()
-        .map(|item| item.rewrite(context, shape))
-        .collect::<Option<Vec<_>>>()?;
-    let result = type_strs.join(joiner);
-    if items.len() <= 1 || (!result.contains('\n') && result.len() <= shape.width) {
-        return Some(result);
-    }
+    join_bounds_inner(context, shape, items, need_indent, false)
+}
 
-    // We need to use multiple lines.
-    let (type_strs, offset) = if need_indent {
-        // Rewrite with additional indentation.
-        let nested_shape = shape
-            .block_indent(context.config.tab_spaces())
-            .with_max_width(context.config);
-        let type_strs = items
-            .iter()
-            .map(|item| item.rewrite(context, nested_shape))
-            .collect::<Option<Vec<_>>>()?;
-        (type_strs, nested_shape.indent)
-    } else {
-        (type_strs, shape.indent)
-    };
+fn join_bounds_inner(
+    context: &RewriteContext<'_>,
+    shape: Shape,
+    items: &[ast::GenericBound],
+    need_indent: bool,
+    force_newline: bool,
+) -> Option<String> {
+    debug_assert!(!items.is_empty());
 
+    let generic_bounds_in_order = is_generic_bounds_in_order(items);
     let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b {
         ast::GenericBound::Outlives(..) => true,
         ast::GenericBound::Trait(..) => last_line_extendable(s),
     };
-    let mut result = String::with_capacity(128);
-    result.push_str(&type_strs[0]);
-    let mut can_be_put_on_the_same_line = is_bound_extendable(&result, &items[0]);
-    let generic_bounds_in_order = is_generic_bounds_in_order(items);
-    for (bound, bound_str) in items[1..].iter().zip(type_strs[1..].iter()) {
-        if generic_bounds_in_order && can_be_put_on_the_same_line {
-            result.push_str(joiner);
-        } else {
-            result.push_str(&offset.to_string_with_newline(context.config));
-            result.push_str("+ ");
-        }
-        result.push_str(bound_str);
-        can_be_put_on_the_same_line = is_bound_extendable(bound_str, bound);
-    }
 
-    Some(result)
+    let result = items.iter().enumerate().try_fold(
+        (String::new(), None, false),
+        |(strs, prev_trailing_span, prev_extendable), (i, item)| {
+            let trailing_span = if i < items.len() - 1 {
+                let hi = context
+                    .snippet_provider
+                    .span_before(mk_sp(items[i + 1].span().lo(), item.span().hi()), "+");
+
+                Some(mk_sp(item.span().hi(), hi))
+            } else {
+                None
+            };
+            let (leading_span, has_leading_comment) = if i > 0 {
+                let lo = context
+                    .snippet_provider
+                    .span_after(mk_sp(items[i - 1].span().hi(), item.span().lo()), "+");
+
+                let span = mk_sp(lo, item.span().lo());
+
+                let has_comments = contains_comment(context.snippet(span));
+
+                (Some(mk_sp(lo, item.span().lo())), has_comments)
+            } else {
+                (None, false)
+            };
+            let prev_has_trailing_comment = match prev_trailing_span {
+                Some(ts) => contains_comment(context.snippet(ts)),
+                _ => false,
+            };
+
+            let shape = if i > 0 && need_indent && force_newline {
+                shape
+                    .block_indent(context.config.tab_spaces())
+                    .with_max_width(context.config)
+            } else {
+                shape
+            };
+            let whitespace = if force_newline && (!prev_extendable || !generic_bounds_in_order) {
+                shape
+                    .indent
+                    .to_string_with_newline(context.config)
+                    .to_string()
+            } else {
+                String::from(" ")
+            };
+
+            let joiner = match context.config.type_punctuation_density() {
+                TypeDensity::Compressed => String::from("+"),
+                TypeDensity::Wide => whitespace + "+ ",
+            };
+            let joiner = if has_leading_comment {
+                joiner.trim_end()
+            } else {
+                &joiner
+            };
+            let joiner = if prev_has_trailing_comment {
+                joiner.trim_start()
+            } else {
+                joiner
+            };
+
+            let (trailing_str, extendable) = if i == 0 {
+                let bound_str = item.rewrite(context, shape)?;
+                let bound_str_clone = bound_str.clone();
+                (bound_str, is_bound_extendable(&bound_str_clone, item))
+            } else {
+                let bound_str = &item.rewrite(context, shape)?;
+                match leading_span {
+                    Some(ls) if has_leading_comment => (
+                        combine_strs_with_missing_comments(
+                            context, joiner, bound_str, ls, shape, true,
+                        )?,
+                        is_bound_extendable(bound_str, item),
+                    ),
+                    _ => (
+                        String::from(joiner) + bound_str,
+                        is_bound_extendable(bound_str, item),
+                    ),
+                }
+            };
+            match prev_trailing_span {
+                Some(ts) if prev_has_trailing_comment => combine_strs_with_missing_comments(
+                    context,
+                    &strs,
+                    &trailing_str,
+                    ts,
+                    shape,
+                    true,
+                )
+                .map(|v| (v, trailing_span, extendable)),
+                _ => Some((
+                    String::from(strs) + &trailing_str,
+                    trailing_span,
+                    extendable,
+                )),
+            }
+        },
+    )?;
+
+    if !force_newline
+        && items.len() > 1
+        && (result.0.contains('\n') || result.0.len() > shape.width)
+    {
+        join_bounds_inner(context, shape, items, need_indent, true)
+    } else {
+        Some(result.0)
+    }
 }
 
 pub(crate) fn can_be_overflowed_type(
diff --git a/tests/source/issue-4243.rs b/tests/source/issue-4243.rs
new file mode 100644
index 00000000000..d8a27f7a4a4
--- /dev/null
+++ b/tests/source/issue-4243.rs
@@ -0,0 +1,21 @@
+fn main() {
+    type A: AA /*AA*/ + /*AB*/ AB 
++ AC = AA 
+/*AA*/ + 
+ /*AB*/ AB+AC;
+
+    type B: BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/+/*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB
+   + BC = BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/ + /*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB+ BC;
+
+    type C: CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
+// CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+  +
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+   CB + CC = CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    +
+    // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        CB+ CC;
+}
diff --git a/tests/target/issue-4243.rs b/tests/target/issue-4243.rs
new file mode 100644
index 00000000000..67fa1d2a312
--- /dev/null
+++ b/tests/target/issue-4243.rs
@@ -0,0 +1,28 @@
+fn main() {
+    type A: AA /*AA*/ + /*AB*/ AB + AC = AA
+        /*AA*/
+        +
+        /*AB*/
+        AB
+        + AC;
+
+    type B: BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/
+        + /*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB
+        + BC = BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/
+        + /*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB
+        + BC;
+
+    type C: CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        +
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        CB
+        + CC = CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        +
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+        CB
+        + CC;
+}