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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189818
91177308-0d34-0410-b5e6-
96231b3b80d8
parseBracedList();
}
break;
+ case tok::l_square:
+ tryToParseLambda();
+ break;
default:
nextToken();
break;
} 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();
// 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;
nextToken();
addUnwrappedLine();
return;
+ case tok::l_square:
+ tryToParseLambda();
+ break;
default:
nextToken();
break;
void parseObjCUntilAtEnd();
void parseObjCInterfaceOrImplementation();
void parseObjCProtocol();
+ void tryToParseLambda();
+ bool tryToParseLambdaIntroducer();
void addUnwrappedLine();
bool eof() const;
void nextToken();
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;");
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 *);");
"}");
}
+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