]> granicus.if.org Git - clang/commitdiff
clang-format: [JS] correcly format object literal methods.
authorMartin Probst <martin@probst.io>
Tue, 7 Feb 2017 16:33:13 +0000 (16:33 +0000)
committerMartin Probst <martin@probst.io>
Tue, 7 Feb 2017 16:33:13 +0000 (16:33 +0000)
Summary:
In JavaScript, object literals can contain methods:

   var x = {
     a() { return 1; },
   };

Previously, clang-format always parsed nested {} inside a braced list as
further braced lists. Special case this logic for JavaScript to try
parsing as a braced list, but fall back to parsing as a child block.

Reviewers: djasper

Subscribers: klimek, cfe-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294315 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/TokenAnnotator.cpp
lib/Format/UnwrappedLineParser.cpp
unittests/Format/FormatTestJS.cpp

index bfb74f0b962bbde145aaa3a4f6a8aeeb20941b97..940b5cc57e52a1de7a44ab4b4f121cfc7b895840 100644 (file)
@@ -2648,6 +2648,7 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
                  << " T=" << getTokenTypeName(Tok->Type)
                  << " S=" << Tok->SpacesRequiredBefore
                  << " B=" << Tok->BlockParameterCount
+                 << " BK=" << Tok->BlockKind
                  << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
                  << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
                  << " FakeLParens=";
index 5ffada8ae7c583d58882d0dc8f6811f8cffae850..5b6d0b73e403b42508316e1172710e9f329905c4 100644 (file)
@@ -335,8 +335,11 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
     case tok::l_brace:
       if (Style.Language == FormatStyle::LK_JavaScript && PrevTok &&
           PrevTok->is(tok::colon))
-        // In TypeScript's TypeMemberLists, there can be semicolons between the
-        // individual members.
+        // 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
         Tok->BlockKind = BK_Unknown;
@@ -1298,6 +1301,12 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
           continue;
         }
       }
+      if (FormatTok->is(tok::l_brace)) {
+        // Could be a method inside of a braced list `{a() { return 1; }}`.
+        if (tryToParseBracedList())
+          continue;
+        parseChildBlock();
+      }
     }
     switch (FormatTok->Tok.getKind()) {
     case tok::caret:
@@ -1309,12 +1318,6 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
     case tok::l_square:
       tryToParseLambda();
       break;
-    case tok::l_brace:
-      // Assume there are no blocks inside a braced init list apart
-      // from the ones we explicitly parse out (like lambdas).
-      FormatTok->BlockKind = BK_BracedInit;
-      parseBracedList();
-      break;
     case tok::l_paren:
       parseParens();
       // JavaScript can just have free standing methods and getters/setters in
@@ -1325,6 +1328,12 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
         break;
       }
       break;
+    case tok::l_brace:
+      // Assume there are no blocks inside a braced init list apart
+      // from the ones we explicitly parse out (like lambdas).
+      FormatTok->BlockKind = BK_BracedInit;
+      parseBracedList();
+      break;
     case tok::r_brace:
       nextToken();
       return !HasError;
index 61acce3a9774b0235b761350bf9d3732e9ad1544..4038e5125907573a9bf4b078af96a237c89f41ba 100644 (file)
@@ -240,6 +240,18 @@ TEST_F(FormatTestJS, ContainerLiterals) {
                "};");
   verifyFormat("var x = {y: (a) => a};");
 
+  // Methods in object literals.
+  verifyFormat("var x = {\n"
+               "  y(a: string): number {\n"
+               "    return a;\n"
+               "  }\n"
+               "};");
+  verifyFormat("var x = {\n"
+               "  y(a: string) {\n"
+               "    return a;\n"
+               "  }\n"
+               "};");
+
   // Computed keys.
   verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
   verifyFormat("var x = {\n"