mprobst created this revision.
Herald added a subscriber: klimek.

clang-format already removes lines trailing at the end of blocks:

  function x() {
    foo();  // next line will be removed.
  
  }

However because JS arrow functions are parsed as expressions, the existing logic
to remove empty lines in UnwrappedLineFormatter doesn't handle them. This code
special cases arrow functions in ContinuationIndenter to remove any trailing
spaces:

  x = () => {
    foo();  // next line will (now) be removed.
  
  };


https://reviews.llvm.org/D40178

Files:
  lib/Format/ContinuationIndenter.cpp
  unittests/Format/FormatTestJS.cpp


Index: unittests/Format/FormatTestJS.cpp
===================================================================
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1606,6 +1606,16 @@
       Style);
 }
 
+TEST_F(FormatTestJS, RemoveEmptyLinesTrailingArrowFunctions) {
+  verifyFormat("x = () => {\n"
+               "  foo();\n"
+               "};\n",
+               "x = () => {\n"
+               "  foo();\n"
+               "\n"
+               "};\n");
+}
+
 TEST_F(FormatTestJS, Modules) {
   verifyFormat("import SomeThing from 'some/module.js';");
   verifyFormat("import {X, Y} from 'some/module.js';");
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -701,8 +701,18 @@
     State.Stack.back().BreakBeforeParameter = false;
 
   if (!DryRun) {
+    unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1;
+    if (Style.Language == FormatStyle::LK_JavaScript &&
+        Current.is(tok::r_brace) && Current.MatchingParen &&
+        Current.MatchingParen->Previous &&
+        Current.MatchingParen->Previous->is(TT_JsFatArrow)) {
+      // JavaScript arrow functions are experssions, thus their r_brace is not
+      // on its own line, and thus not covered by UnwrappedLineFormatter's 
logic
+      // about removing empty lines on closing blocks. Special case it here.
+      MaxEmptyLinesToKeep = 0;
+    }
     unsigned Newlines = std::max(
-        1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
+        1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
     bool ContinuePPDirective =
         State.Line->InPPDirective && State.Line->Type != LT_ImportStatement;
     Whitespaces.replaceWhitespace(Current, Newlines, State.Column, 
State.Column,


Index: unittests/Format/FormatTestJS.cpp
===================================================================
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1606,6 +1606,16 @@
       Style);
 }
 
+TEST_F(FormatTestJS, RemoveEmptyLinesTrailingArrowFunctions) {
+  verifyFormat("x = () => {\n"
+               "  foo();\n"
+               "};\n",
+               "x = () => {\n"
+               "  foo();\n"
+               "\n"
+               "};\n");
+}
+
 TEST_F(FormatTestJS, Modules) {
   verifyFormat("import SomeThing from 'some/module.js';");
   verifyFormat("import {X, Y} from 'some/module.js';");
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -701,8 +701,18 @@
     State.Stack.back().BreakBeforeParameter = false;
 
   if (!DryRun) {
+    unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1;
+    if (Style.Language == FormatStyle::LK_JavaScript &&
+        Current.is(tok::r_brace) && Current.MatchingParen &&
+        Current.MatchingParen->Previous &&
+        Current.MatchingParen->Previous->is(TT_JsFatArrow)) {
+      // JavaScript arrow functions are experssions, thus their r_brace is not
+      // on its own line, and thus not covered by UnwrappedLineFormatter's logic
+      // about removing empty lines on closing blocks. Special case it here.
+      MaxEmptyLinesToKeep = 0;
+    }
     unsigned Newlines = std::max(
-        1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
+        1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
     bool ContinuePPDirective =
         State.Line->InPPDirective && State.Line->Type != LT_ImportStatement;
     Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to