summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/ClangFormatStyleOptions.rst39
-rw-r--r--include/clang/Format/Format.h34
-rw-r--r--lib/Format/Format.cpp14
-rw-r--r--lib/Format/FormatToken.h1
-rw-r--r--lib/Format/TokenAnnotator.cpp25
-rw-r--r--lib/Format/UnwrappedLineParser.cpp1
-rw-r--r--unittests/Format/FormatTest.cpp37
7 files changed, 145 insertions, 6 deletions
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index 0ddc313d27..0614af3634 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -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.
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index fd84c924ff..f9d3f03a6c 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -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;
@@ -1805,6 +1838,7 @@ struct FormatStyle {
R.AllowShortFunctionsOnASingleLine &&
AllowShortIfStatementsOnASingleLine ==
R.AllowShortIfStatementsOnASingleLine &&
+ AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine &&
AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType &&
AlwaysBreakBeforeMultilineStrings ==
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 2d1adb58e4..39651ab74d 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -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);
@@ -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",
@@ -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;
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 461e0704a3..f54ffe9d54 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -65,6 +65,7 @@ namespace format {
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
TYPE(LambdaArrow) \
+ TYPE(LambdaLBrace) \
TYPE(LambdaLSquare) \
TYPE(LeadingJavaAnnotation) \
TYPE(LineComment) \
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 04fc3a64f5..c7b148c790 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -1191,11 +1191,11 @@ private:
// 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;
@@ -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,
@@ -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)) ||
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 5c7ab1240c..010b086587 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -1475,6 +1475,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
return true;
}
}
+ FormatTok->Type = TT_LambdaLBrace;
LSquare.Type = TT_LambdaLSquare;
parseChildBlock();
return true;
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index f9b2fe2e9f..6453d24386 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -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) {