]> granicus.if.org Git - clang/commitdiff
clang-format: [JS] handle parenthesized class expressions.
authorMartin Probst <martin@probst.io>
Tue, 7 Feb 2017 14:05:30 +0000 (14:05 +0000)
committerMartin Probst <martin@probst.io>
Tue, 7 Feb 2017 14:05:30 +0000 (14:05 +0000)
Summary:
In JavaScript, classes are expressions, so they can appear e.g. in
argument lists.

    var C = foo(class {
      bar() {
        return 1;
      }
    };

Reviewers: djasper

Subscribers: cfe-commits, klimek

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

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

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

index 66da1feee9dfa764472c29d0d890060afbdd2e7d..5ffada8ae7c583d58882d0dc8f6811f8cffae850 100644 (file)
@@ -1381,6 +1381,12 @@ void UnwrappedLineParser::parseParens() {
       if (FormatTok->Tok.is(tok::l_brace))
         parseBracedList();
       break;
+    case tok::kw_class:
+      if (Style.Language == FormatStyle::LK_JavaScript)
+        parseRecord(/*ParseAsExpr=*/true);
+      else
+        nextToken();
+      break;
     case tok::identifier:
       if (Style.Language == FormatStyle::LK_JavaScript &&
           (FormatTok->is(Keywords.kw_function) ||
@@ -1819,7 +1825,7 @@ void UnwrappedLineParser::parseJavaEnumBody() {
   addUnwrappedLine();
 }
 
-void UnwrappedLineParser::parseRecord() {
+void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
   const FormatToken &InitialToken = *FormatTok;
   nextToken();
 
@@ -1863,11 +1869,15 @@ void UnwrappedLineParser::parseRecord() {
     }
   }
   if (FormatTok->Tok.is(tok::l_brace)) {
-    if (ShouldBreakBeforeBrace(Style, InitialToken))
-      addUnwrappedLine();
+    if (ParseAsExpr) {
+      parseChildBlock();
+    } else {
+      if (ShouldBreakBeforeBrace(Style, InitialToken))
+        addUnwrappedLine();
 
-    parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
-               /*MunchSemi=*/false);
+      parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
+                 /*MunchSemi=*/false);
+    }
   }
   // There is no addUnwrappedLine() here so that we fall through to parsing a
   // structural element afterwards. Thus, in "class A {} n, m;",
index b03009511d3bfc7769dfb7c38dc8fadb32963283..c34e5b9ec779845691ef7b623f4b208d29f14461 100644 (file)
@@ -100,7 +100,10 @@ private:
   void parseAccessSpecifier();
   bool parseEnum();
   void parseJavaEnumBody();
-  void parseRecord();
+  // Parses a record (aka class) as a top level element. If ParseAsExpr is true,
+  // parses the record as a child block, i.e. if the class declaration is an
+  // expression.
+  void parseRecord(bool ParseAsExpr = false);
   void parseObjCProtocolList();
   void parseObjCUntilAtEnd();
   void parseObjCInterfaceOrImplementation();
@@ -162,7 +165,7 @@ private:
 
   const FormatStyle &Style;
   const AdditionalKeywords &Keywords;
-  
+
   llvm::Regex CommentPragmasRegex;
 
   FormatTokenSource *Tokens;
index 70bccb9f4936044b8755541fc99de2ceefa617d8..b64d13ad50993d8b6007e55a6274d44c31166ed3 100644 (file)
@@ -1109,6 +1109,10 @@ TEST_F(FormatTestJS, ClassDeclarations) {
   verifyFormat("class C {\n  static x(): string {\n    return 'asd';\n  }\n}");
   verifyFormat("class C extends P implements I {}");
   verifyFormat("class C extends p.P implements i.I {}");
+  verifyFormat(
+      "x(class {\n"
+      "  a(): A {}\n"
+      "});");
   verifyFormat("class Test {\n"
                "  aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
                "      aaaaaaaaaaaaaaaaaaaaaa {}\n"