r304290 - clang-format: [JS] improve calculateBraceType heuristic

Martin Probst via cfe-commits cfe-commits at lists.llvm.org
Wed May 31 02:29:42 PDT 2017


Author: mprobst
Date: Wed May 31 04:29:40 2017
New Revision: 304290

URL: http://llvm.org/viewvc/llvm-project?rev=304290&view=rev
Log:
clang-format: [JS] improve calculateBraceType heuristic

Summary:

calculateBraceTypes decides for braced init for empty brace pairs ({}).
In context of a function declaration, this incorrectly classifies empty
function or method bodies as braced inits, leading to missing wraps:

    class C {
      foo() {}[bar]() {}
    }

Where code should have wrapped after "}", before "[". This change adds
another piece of contextual information in that braces following closing
parentheses must always be the opening braces of function blocks. This
fixes brace detection for methods immediately followed by brackets
(computed property declarations), but also curlies.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D33714

Modified:
    cfe/trunk/lib/Format/UnwrappedLineParser.cpp
    cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=304290&r1=304289&r2=304290&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Wed May 31 04:29:40 2017
@@ -360,16 +360,21 @@ void UnwrappedLineParser::calculateBrace
 
     switch (Tok->Tok.getKind()) {
     case tok::l_brace:
-      if (Style.Language == FormatStyle::LK_JavaScript && PrevTok &&
-          PrevTok->is(tok::colon))
-        // A colon indicates this code is in a type, or a braced list following
-        // a label in an object literal ({a: {b: 1}}).
-        // The code below could be confused by semicolons between the individual
-        // members in a type member list, which would normally trigger BK_Block.
-        // In both cases, this must be parsed as an inline braced init.
-        Tok->BlockKind = BK_BracedInit;
-      else
+      if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
+        if (PrevTok->is(tok::colon))
+          // A colon indicates this code is in a type, or a braced list
+          // following a label in an object literal ({a: {b: 1}}). The code
+          // below could be confused by semicolons between the individual
+          // members in a type member list, which would normally trigger
+          // BK_Block. In both cases, this must be parsed as an inline braced
+          // init.
+          Tok->BlockKind = BK_BracedInit;
+        else if (PrevTok->is(tok::r_paren))
+          // `) { }` can only occur in function or method declarations in JS.
+          Tok->BlockKind = BK_Block;
+      } else {
         Tok->BlockKind = BK_Unknown;
+      }
       LBraceStack.push_back(Tok);
       break;
     case tok::r_brace:
@@ -391,6 +396,8 @@ void UnwrappedLineParser::calculateBrace
           // BlockKind later if we parse a braced list (where all blocks
           // inside are by default braced lists), or when we explicitly detect
           // blocks (for example while parsing lambdas).
+          // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
+          // braced list in JS.
           ProbablyBracedList =
               (Style.Language == FormatStyle::LK_JavaScript &&
                NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=304290&r1=304289&r2=304290&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed May 31 04:29:40 2017
@@ -474,9 +474,8 @@ TEST_F(FormatTestJS, FormatsFreestanding
                "(function f() {\n"
                "  var x = 1;\n"
                "}());\n");
-  // Known issue: this should wrap after {}, but calculateBraceTypes
-  // misclassifies the first braces as a BK_BracedInit.
-  verifyFormat("function aFunction(){} {\n"
+  verifyFormat("function aFunction() {}\n"
+               "{\n"
                "  let x = 1;\n"
                "  console.log(x);\n"
                "}\n");
@@ -1233,6 +1232,10 @@ TEST_F(FormatTestJS, ClassDeclarations)
   verifyFormat("class C {\n  x: string = 12;\n}");
   verifyFormat("class C {\n  x(): string => 12;\n}");
   verifyFormat("class C {\n  ['x' + 2]: string = 12;\n}");
+  verifyFormat("class C {\n"
+               "  foo() {}\n"
+               "  [bar]() {}\n"
+               "}\n");
   verifyFormat("class C {\n  private x: string = 12;\n}");
   verifyFormat("class C {\n  private static x: string = 12;\n}");
   verifyFormat("class C {\n  static x(): string {\n    return 'asd';\n  }\n}");




More information about the cfe-commits mailing list