Skip to content
Permalink
Browse files

clang-format: Add support for formatting (some) lambdas with explicit…

… template parameters.

This patch makes cases work where the lambda's template list doesn't
contain any of + - ! ~ / % << | || && ^ == != >= <= ? : true false
(see added FIXME).

Ports r359967 to clang-format.

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

llvm-svn: 371854
  • Loading branch information...
nico committed Sep 13, 2019
1 parent ab9acda commit 41f4d68a50beeaeb821baa29b5591a7146b98b05
@@ -40,6 +40,21 @@ static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
return Tok.Tok.getIdentifierInfo() != nullptr;
}

/// With `Left` being '(', check if we're at either `[...](` or
/// `[...]<...>(`, where the [ opens a lambda capture list.
static bool isLambdaParameterList(const FormatToken *Left) {
// Skip <...> if present.
if (Left->Previous && Left->Previous->is(tok::greater) &&
Left->Previous->MatchingParen &&
Left->Previous->MatchingParen->is(TT_TemplateOpener))
Left = Left->Previous->MatchingParen;

// Check for `[...]`.
return Left->Previous && Left->Previous->is(tok::r_square) &&
Left->Previous->MatchingParen &&
Left->Previous->MatchingParen->is(TT_LambdaLSquare);
}

/// A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
@@ -191,9 +206,7 @@ class AnnotatingParser {
Left->Previous->is(TT_JsTypeColon)) {
// let x: (SomeType);
Contexts.back().IsExpression = false;
} else if (Left->Previous && Left->Previous->is(tok::r_square) &&
Left->Previous->MatchingParen &&
Left->Previous->MatchingParen->is(TT_LambdaLSquare)) {
} else if (isLambdaParameterList(Left)) {
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
} else if (Line.InPPDirective &&
@@ -1440,8 +1440,11 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::identifier:
case tok::numeric_constant:
case tok::coloncolon:
case tok::kw_class:
case tok::kw_mutable:
case tok::kw_noexcept:
case tok::kw_template:
case tok::kw_typename:
nextToken();
break;
// Specialization of a template with an integer parameter can contain
@@ -1455,6 +1458,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
// followed by an `a->b` expression, such as:
// ([obj func:arg] + a->b)
// Otherwise the code below would parse as a lambda.
//
// FIXME: This heuristic is incorrect for C++20 generic lambdas with
// explicit template lists: []<bool b = true && false>(U &&u){}
case tok::plus:
case tok::minus:
case tok::exclaim:
@@ -12923,6 +12923,10 @@ TEST_F(FormatTest, FormatsLambdas) {
" return 1; //\n"
"};");

// Lambdas with explicit template argument lists.
verifyFormat(
"auto L = []<template <typename> class T, class U>(T<U> &&a) {};\n");

// Multiple lambdas in the same parentheses change indentation rules. These
// lambdas are forced to start on new lines.
verifyFormat("SomeFunction(\n"
@@ -12940,8 +12944,8 @@ TEST_F(FormatTest, FormatsLambdas) {
" },\n"
" 1);\n");

// A multi-line lambda passed as arg1 forces arg0 to be pushed out, just like the arg0
// case above.
// A multi-line lambda passed as arg1 forces arg0 to be pushed out, just like
// the arg0 case above.
auto Style = getGoogleStyle();
Style.BinPackArguments = false;
verifyFormat("SomeFunction(\n"

0 comments on commit 41f4d68

Please sign in to comment.
You can’t perform that action at this time.