From daf4789b768444035efef2383da75011237f4ef7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 27 Oct 2017 16:35:40 +0900 Subject: [PATCH 1/2] Add a test for #2087 --- tests/source/macros.rs | 6 ++++++ tests/target/macros.rs | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 616a275876fd..73044aa7ab2c 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -21,6 +21,12 @@ fn main() { kaas!(/* comments */ a /* post macro */, b /* another */); trailingcomma!( a , b , c , ); + // Preserve trailing comma only when necessary. + ok!(file.seek( + SeekFrom::Start( + table.map(|table| fixture.offset(table)).unwrap_or(0), + ) + )); noexpr!( i am not an expression, OK? ); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 394cac3820f3..a15dd14c9fb7 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -33,6 +33,10 @@ fn main() { ); trailingcomma!(a, b, c,); + // Preserve trailing comma only when necessary. + ok!(file.seek(SeekFrom::Start( + table.map(|table| fixture.offset(table)).unwrap_or(0), + ))); noexpr!( i am not an expression, OK? ); From fa7d8de29fba0d691b3ba543e90f272afe499e36 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 27 Oct 2017 16:41:31 +0900 Subject: [PATCH 2/2] Only read the trailing comma of outermost fn call --- src/expr.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 4eaf52681add..33dc3a40e21a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2359,11 +2359,24 @@ pub fn wrap_args_with_parens( } } +/// Return true if a function call or a method call represented by the given span ends with a +/// trailing comma. This function is used when rewriting macro, as adding or removing a trailing +/// comma from macro can potentially break the code. fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { - let snippet = context.snippet(span); - snippet - .trim_right_matches(|c: char| c == ')' || c.is_whitespace()) - .ends_with(',') + let mut encountered_closing_paren = false; + for c in context.snippet(span).chars().rev() { + match c { + ',' => return true, + ')' => if encountered_closing_paren { + return false; + } else { + encountered_closing_paren = true; + }, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + false } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option {