about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorKevin Stenerson <2653498+kestred@users.noreply.github.com>2018-11-07 01:49:53 -0700
committerSeiichi Uchida <seuchida@gmail.com>2018-11-07 17:49:53 +0900
commitcd8bb50aea35f73fa4be62857dfed88f772cd07e (patch)
tree6d290160cc36277d5f7ea26697812addfbdc1f52 /src
parent16d5f507b63da32783bc920a33e39580d35e492a (diff)
Trim the indentation on macros which heuristically appear to use block-style indentation (#3178)
Diffstat (limited to 'src')
-rw-r--r--src/comment.rs2
-rw-r--r--src/macros.rs41
-rw-r--r--src/test/mod.rs2
-rw-r--r--src/utils.rs4
4 files changed, 37 insertions, 12 deletions
diff --git a/src/comment.rs b/src/comment.rs
index db5102a3755..4ba95bda053 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -332,7 +332,7 @@ fn identify_comment(
     let (first_group, rest) = orig.split_at(first_group_ending);
     let rewritten_first_group =
         if !config.normalize_comments() && has_bare_lines && style.is_block_comment() {
-            trim_left_preserve_layout(first_group, &shape.indent, config)?
+            trim_left_preserve_layout(first_group, shape.indent, config)?
         } else if !config.normalize_comments()
             && !config.wrap_comments()
             && !config.format_doc_comments()
diff --git a/src/macros.rs b/src/macros.rs
index 20592beaf17..e956ad4dbc8 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -144,11 +144,32 @@ fn rewrite_macro_name(
 }
 
 // Use this on failing to format the macro call.
-fn return_original_snippet_with_failure_marked(
+fn return_macro_parse_failure_fallback(
     context: &RewriteContext,
+    indent: Indent,
     span: Span,
 ) -> Option<String> {
+    // Mark this as a failure however we format it
     context.macro_rewrite_failure.replace(true);
+
+    // Heuristically determine whether the last line of the macro uses "Block" style
+    // rather than using "Visual" style, or another indentation style.
+    let is_like_block_indent_style = context
+        .snippet(span)
+        .lines()
+        .last()
+        .map(|closing_line| {
+            closing_line.trim().chars().all(|ch| match ch {
+                '}' | ')' | ']' => true,
+                _ => false,
+            })
+        })
+        .unwrap_or(false);
+    if is_like_block_indent_style {
+        return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
+    }
+
+    // Return the snippet unmodified if the macro is not block-like
     Some(context.snippet(span).to_owned())
 }
 
@@ -239,7 +260,9 @@ pub fn rewrite_macro_inner(
         loop {
             match parse_macro_arg(&mut parser) {
                 Some(arg) => arg_vec.push(arg),
-                None => return return_original_snippet_with_failure_marked(context, mac.span),
+                None => {
+                    return return_macro_parse_failure_fallback(context, shape.indent, mac.span);
+                }
             }
 
             match parser.token {
@@ -260,17 +283,19 @@ pub fn rewrite_macro_inner(
                                     }
                                 }
                                 None => {
-                                    return return_original_snippet_with_failure_marked(
-                                        context, mac.span,
-                                    )
+                                    return return_macro_parse_failure_fallback(
+                                        context,
+                                        shape.indent,
+                                        mac.span,
+                                    );
                                 }
                             }
                         }
                     }
-                    return return_original_snippet_with_failure_marked(context, mac.span);
+                    return return_macro_parse_failure_fallback(context, shape.indent, mac.span);
                 }
                 _ if arg_vec.last().map_or(false, MacroArg::is_item) => continue,
-                _ => return return_original_snippet_with_failure_marked(context, mac.span),
+                _ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span),
             }
 
             parser.bump();
@@ -376,7 +401,7 @@ pub fn rewrite_macro_inner(
         }
         DelimToken::Brace => {
             // Skip macro invocations with braces, for now.
-            trim_left_preserve_layout(context.snippet(mac.span), &shape.indent, &context.config)
+            trim_left_preserve_layout(context.snippet(mac.span), shape.indent, &context.config)
         }
         _ => unreachable!(),
     }
diff --git a/src/test/mod.rs b/src/test/mod.rs
index aa3e729bb43..5999d6f71bf 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -749,7 +749,7 @@ impl ConfigCodeBlock {
             .code_block
             .as_ref()
             .unwrap()
-            .split('\n')
+            .lines()
             .nth(0)
             .unwrap_or("")
             == "#![rustfmt::skip]";
diff --git a/src/utils.rs b/src/utils.rs
index 86c01af39fb..c5f9a5eda5e 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -511,7 +511,7 @@ pub fn remove_trailing_white_spaces(text: &str) -> String {
 ///     ),
 /// }
 /// ```
-pub fn trim_left_preserve_layout(orig: &str, indent: &Indent, config: &Config) -> Option<String> {
+pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Option<String> {
     let mut lines = LineClasses::new(orig);
     let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?;
     let mut trimmed_lines = Vec::with_capacity(16);
@@ -598,7 +598,7 @@ mod test {
         let config = Config::default();
         let indent = Indent::new(4, 0);
         assert_eq!(
-            trim_left_preserve_layout(&s, &indent, &config),
+            trim_left_preserve_layout(&s, indent, &config),
             Some("aaa\n    bbb\n    ccc".to_string())
         );
     }