r189818 - First step towards correctly formatting lambdas.

Manuel Klimek klimek at google.com
Tue Sep 3 08:10:01 PDT 2013


Author: klimek
Date: Tue Sep  3 10:10:01 2013
New Revision: 189818

URL: http://llvm.org/viewvc/llvm-project?rev=189818&view=rev
Log:
First step towards correctly formatting lambdas.

Implements parsing of lambdas in the UnwrappedLineParser.
This introduces the correct line breaks; the formatting of
lambda captures are still incorrect, and the braces are also
still formatted as if they were braced init lists instead of
blocks.

Modified:
    cfe/trunk/lib/Format/UnwrappedLineParser.cpp
    cfe/trunk/lib/Format/UnwrappedLineParser.h
    cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=189818&r1=189817&r2=189818&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Tue Sep  3 10:10:01 2013
@@ -640,6 +640,9 @@ void UnwrappedLineParser::parseStructura
         parseBracedList();
       }
       break;
+    case tok::l_square:
+      tryToParseLambda();
+      break;
     default:
       nextToken();
       break;
@@ -647,6 +650,77 @@ void UnwrappedLineParser::parseStructura
   } while (!eof());
 }
 
+void UnwrappedLineParser::tryToParseLambda() {
+  if (!tryToParseLambdaIntroducer()) {
+    return;
+  }
+  if (FormatTok->is(tok::l_paren)) {
+    parseParens();
+  }
+
+  while (FormatTok->isNot(tok::l_brace)) {
+    switch (FormatTok->Tok.getKind()) {
+      case tok::l_brace:
+        break;
+        return;
+      case tok::l_paren:
+        parseParens();
+        break;
+      case tok::semi:
+      case tok::equal:
+      case tok::eof:
+        return;
+      default:
+        nextToken();
+        break;
+    }
+  }
+  nextToken();
+  {
+    ScopedLineState LineState(*this);
+    ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
+                                            /*MustBeDeclaration=*/false);
+    Line->Level += 1;
+    parseLevel(/*HasOpeningBrace=*/true);
+    Line->Level -= 1;
+  }
+  nextToken();
+}
+
+bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
+  nextToken();
+  if (FormatTok->is(tok::equal)) {
+    nextToken();
+    if (FormatTok->is(tok::r_square)) return true;
+    if (FormatTok->isNot(tok::comma)) return false;
+    nextToken();
+  } else if (FormatTok->is(tok::amp)) {
+    nextToken();
+    if (FormatTok->is(tok::r_square)) return true;
+    if (!FormatTok->isOneOf(tok::comma, tok::identifier)) {
+      return false;
+    }
+    if (FormatTok->is(tok::comma)) nextToken();
+  } else if (FormatTok->is(tok::r_square)) {
+    nextToken();
+    return true;
+  }
+  do {
+    if (FormatTok->is(tok::amp)) nextToken();
+    if (!FormatTok->isOneOf(tok::identifier, tok::kw_this)) return false;
+    nextToken();
+    if (FormatTok->is(tok::comma)) {
+      nextToken();
+    } else if (FormatTok->is(tok::r_square)) {
+      nextToken();
+      return true;
+    } else {
+      return false;
+    }
+  } while (!eof());
+  return false;
+}
+
 bool UnwrappedLineParser::tryToParseBracedList() {
   if (FormatTok->BlockKind == BK_Unknown)
     calculateBraceTypes();
@@ -667,6 +741,9 @@ void UnwrappedLineParser::parseBracedLis
     // here, otherwise our bail-out scenarios below break. The better solution
     // might be to just implement a more or less complete expression parser.
     switch (FormatTok->Tok.getKind()) {
+      case tok::l_square:
+        tryToParseLambda();
+        break;
     case tok::l_brace:
       parseBracedList();
       break;
@@ -710,6 +787,9 @@ void UnwrappedLineParser::parseReturn()
       nextToken();
       addUnwrappedLine();
       return;
+    case tok::l_square:
+      tryToParseLambda();
+      break;
     default:
       nextToken();
       break;

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=189818&r1=189817&r2=189818&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Tue Sep  3 10:10:01 2013
@@ -93,6 +93,8 @@ private:
   void parseObjCUntilAtEnd();
   void parseObjCInterfaceOrImplementation();
   void parseObjCProtocol();
+  void tryToParseLambda();
+  bool tryToParseLambdaIntroducer();
   void addUnwrappedLine();
   bool eof() const;
   void nextToken();

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=189818&r1=189817&r2=189818&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Sep  3 10:10:01 2013
@@ -3681,7 +3681,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStar
   verifyGoogleFormat("return sizeof(int**);");
   verifyIndependentOfContext("Type **A = static_cast<Type **>(P);");
   verifyGoogleFormat("Type** A = static_cast<Type**>(P);");
-  verifyFormat("auto a = [](int **&, int ***) {};");
+  verifyFormat("auto a = [](int **&, int ***) {\n};");
 
   verifyIndependentOfContext("InvalidRegions[*R] = 0;");
 
@@ -3865,7 +3865,7 @@ TEST_F(FormatTest, FormatsCasts) {
   verifyFormat("f(foo).b;");
   verifyFormat("f(foo)(b);");
   verifyFormat("f(foo)[b];");
-  verifyFormat("[](foo) { return 4; }(bar)];");
+  verifyFormat("[](foo) {\n  return 4;\n}(bar);");
   verifyFormat("(*funptr)(foo)[4];");
   verifyFormat("funptrs[4](foo)[4];");
   verifyFormat("void f(int *);");
@@ -6257,5 +6257,45 @@ TEST_F(FormatTest, FormatsProtocolBuffer
                "}");
 }
 
+TEST_F(FormatTest, FormatsLambdas) {
+  // FIXME: The formatting is incorrect; this test currently checks that
+  // parsing of the unwrapped lines doesn't regress.
+  verifyFormat(
+      "int c = [b]() mutable {\n"
+      "  return [&b]{\n"
+      "    return b++;\n"
+      "  }();\n"
+      "}();\n");
+  verifyFormat(
+      "int c = [&]{\n"
+      "  [ = ]{\n"
+      "    return b++;\n"
+      "  }();\n"
+      "}();\n");
+  verifyFormat(
+      "int c = [ &, &a, a]{\n"
+      "  [ =, c, &d]{\n"
+      "    return b++;\n"
+      "  }();\n"
+      "}();\n");
+  verifyFormat(
+      "int c = [&a, &a, a]{\n"
+      "  [ =, a, b, &c]{\n"
+      "    return b++;\n"
+      "  }();\n"
+      "}();\n");
+  verifyFormat(
+      "auto c = {[&a, &a, a]{\n"
+      "  [ =, a, b, &c]{\n"
+      "    return b++;\n"
+      "  }();\n"
+      "} }\n");
+  verifyFormat(
+      "auto c = {[&a, &a, a]{\n"
+      "  [ =, a, b, &c]{\n"
+      "  }();\n"
+      "} }\n");
+}
+
 } // end namespace tooling
 } // end namespace clang





More information about the cfe-commits mailing list