Skip to content

Commit

Permalink
[clang-format] Add style option AllowShortLambdasOnASingleLine
Browse files Browse the repository at this point in the history
Summary:
This option `AllowShortLambdasOnASingleLine` similar to the other `AllowShort*` options, but applied to C++ lambdas.

Reviewers: djasper, klimek

Reviewed By: klimek

Subscribers: MyDeveloperDay, cfe-commits

Tags: #clang

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

llvm-svn: 357027
  • Loading branch information
rdwampler committed Mar 26, 2019
1 parent 02e9664 commit a83e2db
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 6 deletions.
39 changes: 39 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,45 @@ the configuration (without a prefix: ``Auto``).
return;
}

**AllowShortLambdasOnASingleLine** (``ShortLambdaStyle``)
Dependent on the value, ``auto lambda []() { return 0; }`` can be put on a
single line.

Possible values:

* ``SLS_None`` (in configuration: ``None``)
Never merge lambdas into a single line.

* ``SLS_Empty`` (in configuration: ``Empty``)
Only merge empty lambdas.

.. code-block:: c++

auto lambda = [](int a) {}
auto lambda2 = [](int a) {
return a;
};

* ``SLS_Inline`` (in configuration: ``Inline``)
Merge lambda into a single line if argument of a function.

.. code-block:: c++

auto lambda = [](int a) {
return a;
};
sort(a.begin(), a.end(), ()[] { return x < y; })

* ``SLS_All`` (in configuration: ``All``)
Merge all lambdas fitting on a single line.

.. code-block:: c++

auto lambda = [](int a) {}
auto lambda2 = [](int a) { return a; };



**AllowShortLoopsOnASingleLine** (``bool``)
If ``true``, ``while (true) continue;`` can be put on a single
line.
Expand Down
34 changes: 34 additions & 0 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,39 @@ struct FormatStyle {
/// If ``true``, ``if (a) return;`` can be put on a single line.
ShortIfStyle AllowShortIfStatementsOnASingleLine;

/// Different styles for merging short lambdas containing at most one
/// statement.
enum ShortLambdaStyle {
/// Never merge lambdas into a single line.
SLS_None,
/// Only merge empty lambdas.
/// \code
/// auto lambda = [](int a) {}
/// auto lambda2 = [](int a) {
/// return a;
/// };
/// \endcode
SLS_Empty,
/// Merge lambda into a single line if argument of a function.
/// \code
/// auto lambda = [](int a) {
/// return a;
/// };
/// sort(a.begin(), a.end(), ()[] { return x < y; })
/// \endcode
SLS_Inline,
/// Merge all lambdas fitting on a single line.
/// \code
/// auto lambda = [](int a) {}
/// auto lambda2 = [](int a) { return a; };
/// \endcode
SLS_All,
};

/// Dependent on the value, ``auto lambda []() { return 0; }`` can be put on a
/// single line.
ShortLambdaStyle AllowShortLambdasOnASingleLine;

/// If ``true``, ``while (true) continue;`` can be put on a single
/// line.
bool AllowShortLoopsOnASingleLine;
Expand Down Expand Up @@ -1805,6 +1838,7 @@ struct FormatStyle {
R.AllowShortFunctionsOnASingleLine &&
AllowShortIfStatementsOnASingleLine ==
R.AllowShortIfStatementsOnASingleLine &&
AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine &&
AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType &&
AlwaysBreakBeforeMultilineStrings ==
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
}
};

template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::SLS_None);
IO.enumCase(Value, "false", FormatStyle::SLS_None);
IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
IO.enumCase(Value, "All", FormatStyle::SLS_All);
IO.enumCase(Value, "true", FormatStyle::SLS_All);
}
};

template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
Expand Down Expand Up @@ -347,6 +358,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowShortCaseLabelsOnASingleLine);
IO.mapOptional("AllowShortFunctionsOnASingleLine",
Style.AllowShortFunctionsOnASingleLine);
IO.mapOptional("AllowShortLambdasOnASingleLine",
Style.AllowShortLambdasOnASingleLine);
IO.mapOptional("AllowShortIfStatementsOnASingleLine",
Style.AllowShortIfStatementsOnASingleLine);
IO.mapOptional("AllowShortLoopsOnASingleLine",
Expand Down Expand Up @@ -653,6 +666,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AllowShortBlocksOnASingleLine = false;
LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace format {
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
TYPE(LambdaArrow) \
TYPE(LambdaLBrace) \
TYPE(LambdaLSquare) \
TYPE(LeadingJavaAnnotation) \
TYPE(LineComment) \
Expand Down
25 changes: 19 additions & 6 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,11 +1191,11 @@ class AnnotatingParser {

// Reset token type in case we have already looked at it and then
// recovered from an error (e.g. failure to find the matching >).
if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral,
TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
TT_OverloadedOperator, TT_RegexLiteral,
TT_TemplateString, TT_ObjCStringLiteral))
if (!CurrentToken->isOneOf(
TT_LambdaLSquare, TT_LambdaLBrace, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral, TT_InlineASMBrace,
TT_JsFatArrow, TT_LambdaArrow, TT_OverloadedOperator,
TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral))
CurrentToken->Type = TT_Unknown;
CurrentToken->Role.reset();
CurrentToken->MatchingParen = nullptr;
Expand Down Expand Up @@ -2896,7 +2896,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.
static bool isAllmanBrace(const FormatToken &Tok) {
return Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block &&
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral);
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);
}

bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Expand Down Expand Up @@ -3024,6 +3024,19 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine)
return true;

if (Left.is(TT_LambdaLBrace)) {
if (Left.MatchingParen && Left.MatchingParen->Next &&
Left.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren) &&
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline)
return false;

if (Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_None ||
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline ||
(!Left.Children.empty() &&
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty))
return true;
}

// Put multiple C# attributes on a new line.
if (Style.isCSharp() &&
((Left.is(TT_AttributeSquare) && Left.is(tok::r_square)) ||
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
return true;
}
}
FormatTok->Type = TT_LambdaLBrace;
LSquare.Type = TT_LambdaLSquare;
parseChildBlock();
return true;
Expand Down
37 changes: 37 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12432,6 +12432,43 @@ TEST_F(FormatTest, FormatsLambdas) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> {\n"
" //\n"
" });");

FormatStyle DoNotMerge = getLLVMStyle();
DoNotMerge.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
verifyFormat("auto c = []() {\n"
" return b;\n"
"};",
"auto c = []() { return b; };", DoNotMerge);
verifyFormat("auto c = []() {\n"
"};",
" auto c = []() {};", DoNotMerge);

FormatStyle MergeEmptyOnly = getLLVMStyle();
MergeEmptyOnly.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
verifyFormat("auto c = []() {\n"
" return b;\n"
"};",
"auto c = []() {\n"
" return b;\n"
" };",
MergeEmptyOnly);
verifyFormat("auto c = []() {};",
"auto c = []() {\n"
"};",
MergeEmptyOnly);

FormatStyle MergeInline = getLLVMStyle();
MergeInline.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
verifyFormat("auto c = []() {\n"
" return b;\n"
"};",
"auto c = []() { return b; };", MergeInline);
verifyFormat("function([]() { return b; })", "function([]() { return b; })",
MergeInline);
verifyFormat("function([]() { return b; }, a)",
"function([]() { return b; }, a)", MergeInline);
verifyFormat("function(a, []() { return b; })",
"function(a, []() { return b; })", MergeInline);
}

TEST_F(FormatTest, EmptyLinesInLambdas) {
Expand Down

0 comments on commit a83e2db

Please sign in to comment.