[clang-format] Add IfMacros option

https://bugs.llvm.org/show_bug.cgi?id=49354

Differential Revision: https://reviews.llvm.org/D102730
This commit is contained in:
Vitali Lovich 2021-05-18 13:57:07 -07:00
parent 656001e7b2
commit be9a87fe9b
8 changed files with 656 additions and 12 deletions

View File

@ -2377,6 +2377,28 @@ the configuration (without a prefix: ``Auto``).
For example: BOOST_FOREACH.
**IfMacros** (``std::vector<std::string>``)
A vector of macros that should be interpreted as conditionals
instead of as function calls.
These are expected to be macros of the form:
.. code-block:: c++
IF(...)
<conditional-body>
else IF(...)
<conditional-body>
In the .clang-format configuration file, this can be configured like:
.. code-block:: yaml
IfMacros: ['IF']
For example: `KJ_IF_MAYBE
<https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#maybes>`_
**IncludeBlocks** (``IncludeBlocksStyle``)
Dependent on the value, multiple ``#include`` blocks can be sorted
as one and divided based on category.
@ -3480,10 +3502,12 @@ the configuration (without a prefix: ``Auto``).
}
}
* ``SBPO_ControlStatementsExceptForEachMacros`` (in configuration: ``ControlStatementsExceptForEachMacros``)
* ``SBPO_ControlStatementsExceptControlMacros`` (in configuration: ``ControlStatementsExceptControlMacros``)
Same as ``SBPO_ControlStatements`` except this option doesn't apply to
ForEach macros. This is useful in projects where ForEach macros are
treated as function calls instead of control statements.
ForEach and If macros. This is useful in projects where ForEach/If
macros are treated as function calls instead of control statements.
``SBPO_ControlStatementsExceptForEachMacros`` remains an alias for
backward compatability.
.. code-block:: c++

View File

@ -265,6 +265,10 @@ clang-format
change that so that the lambda body is indented one level relative to the scope
containing the lambda, regardless of where the lambda signature was placed.
- Option ``IfMacros`` has been added. This lets you define macros that get
formatted like conditionals much like ``ForEachMacros`` get styled like
foreach loops.
- ``git-clang-format`` no longer formats changes to symbolic links. (Fixes
https://llvm.org/PR46992.)

View File

@ -2117,6 +2117,26 @@ struct FormatStyle {
/// For example: BOOST_FOREACH.
std::vector<std::string> ForEachMacros;
/// A vector of macros that should be interpreted as conditionals
/// instead of as function calls.
///
/// These are expected to be macros of the form:
/// \code
/// IF(...)
/// <conditional-body>
/// else IF(...)
/// <conditional-body>
/// \endcode
///
/// In the .clang-format configuration file, this can be configured like:
/// \code{.yaml}
/// IfMacros: ['IF']
/// \endcode
///
/// For example: `KJ_IF_MAYBE
/// <https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#maybes>`_
std::vector<std::string> IfMacros;
/// \brief A vector of macros that should be interpreted as type declarations
/// instead of as function calls.
///
@ -3033,8 +3053,10 @@ struct FormatStyle {
/// \endcode
SBPO_ControlStatements,
/// Same as ``SBPO_ControlStatements`` except this option doesn't apply to
/// ForEach macros. This is useful in projects where ForEach macros are
/// treated as function calls instead of control statements.
/// ForEach and If macros. This is useful in projects where ForEach/If
/// macros are treated as function calls instead of control statements.
/// ``SBPO_ControlStatementsExceptForEachMacros`` remains an alias for
/// backward compatability.
/// \code
/// void f() {
/// Q_FOREACH(...) {
@ -3042,7 +3064,7 @@ struct FormatStyle {
/// }
/// }
/// \endcode
SBPO_ControlStatementsExceptForEachMacros,
SBPO_ControlStatementsExceptControlMacros,
/// Put a space before opening parentheses only if the parentheses are not
/// empty i.e. '()'
/// \code

View File

@ -424,8 +424,8 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
IO.enumCase(Value, "ControlStatements",
FormatStyle::SBPO_ControlStatements);
IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
IO.enumCase(Value, "ControlStatementsExceptControlMacros",
FormatStyle::SBPO_ControlStatementsExceptControlMacros);
IO.enumCase(Value, "NonEmptyParentheses",
FormatStyle::SBPO_NonEmptyParentheses);
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
@ -433,6 +433,8 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
// For backward compatibility.
IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
FormatStyle::SBPO_ControlStatementsExceptControlMacros);
}
};
@ -637,6 +639,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
IO.mapOptional("IfMacros", Style.IfMacros);
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
@ -1031,6 +1035,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
LLVMStyle.IncludeStyle.IncludeCategories = {
{"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
{"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
@ -3143,4 +3148,4 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
}
} // namespace format
} // namespace clang
} // namespace clang

View File

@ -52,6 +52,7 @@ namespace format {
TYPE(FunctionDeclarationName) \
TYPE(FunctionLBrace) \
TYPE(FunctionTypeLParen) \
TYPE(IfMacro) \
TYPE(ImplicitStringLiteral) \
TYPE(InheritanceColon) \
TYPE(InheritanceComma) \

View File

@ -39,6 +39,8 @@ FormatTokenLexer::FormatTokenLexer(
for (const std::string &ForEachMacro : Style.ForEachMacros)
Macros.insert({&IdentTable.get(ForEachMacro), TT_ForEachMacro});
for (const std::string &IfMacro : Style.IfMacros)
Macros.insert({&IdentTable.get(IfMacro), TT_IfMacro});
for (const std::string &AttributeMacro : Style.AttributeMacros)
Macros.insert({&IdentTable.get(AttributeMacro), TT_AttributeMacro});
for (const std::string &StatementMacro : Style.StatementMacros)
@ -1014,6 +1016,13 @@ FormatToken *FormatTokenLexer::getNextToken() {
tok::pp_define) &&
it != Macros.end()) {
FormatTok->setType(it->second);
if (it->second == TT_IfMacro) {
// The lexer token currently has type tok::kw_unknown. However, for this
// substitution to be treated correctly in the TokenAnnotator, faking
// the tok value seems to be needed. Not sure if there's a more elegant
// way.
FormatTok->Tok.setKind(tok::kw_if);
}
} else if (FormatTok->is(tok::identifier)) {
if (MacroBlockBeginRegex.match(Text)) {
FormatTok->setType(TT_MacroBlockBegin);

8
clang/lib/Format/TokenAnnotator.cpp Executable file → Normal file
View File

@ -1409,7 +1409,7 @@ 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_LambdaLBrace, TT_AttributeMacro,
TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro,
TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,
TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,
TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
@ -3120,9 +3120,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
return true;
if (Style.SpaceBeforeParens ==
FormatStyle::SBPO_ControlStatementsExceptForEachMacros &&
FormatStyle::SBPO_ControlStatementsExceptControlMacros &&
Left.is(TT_ForEachMacro))
return false;
if (Style.SpaceBeforeParens ==
FormatStyle::SBPO_ControlStatementsExceptControlMacros &&
Left.is(TT_IfMacro))
return false;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
(Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,

View File

@ -525,6 +525,7 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatement) {
"}");
FormatStyle AllowsMergedIf = getLLVMStyle();
AllowsMergedIf.IfMacros.push_back("MYIF");
AllowsMergedIf.AlignEscapedNewlines = FormatStyle::ENAS_Left;
AllowsMergedIf.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
@ -564,17 +565,62 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatement) {
" f();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" // comment\n"
" f();",
AllowsMergedIf);
verifyFormat("{\n"
" MYIF (a)\n"
" label:\n"
" f();\n"
"}",
AllowsMergedIf);
verifyFormat("#define A \\\n"
" MYIF (a) \\\n"
" label: \\\n"
" f()",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" ;",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" MYIF (b) return;",
AllowsMergedIf);
verifyFormat("MYIF (a) // Can't merge this\n"
" f();\n",
AllowsMergedIf);
verifyFormat("MYIF (a) /* still don't merge */\n"
" f();",
AllowsMergedIf);
verifyFormat("MYIF (a) { // Never merge this\n"
" f();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) { /* Never merge this */\n"
" f();\n"
"}",
AllowsMergedIf);
AllowsMergedIf.ColumnLimit = 14;
// Where line-lengths matter, a 2-letter synonym that maintains line length.
// Not IF to avoid any confusion that IF is somehow special.
AllowsMergedIf.IfMacros.push_back("FI");
verifyFormat("if (a) return;", AllowsMergedIf);
verifyFormat("if (aaaaaaaaa)\n"
" return;",
AllowsMergedIf);
verifyFormat("FI (a) return;", AllowsMergedIf);
verifyFormat("FI (aaaaaaaaa)\n"
" return;",
AllowsMergedIf);
AllowsMergedIf.ColumnLimit = 13;
verifyFormat("if (a)\n return;", AllowsMergedIf);
verifyFormat("FI (a)\n return;", AllowsMergedIf);
FormatStyle AllowsMergedIfElse = getLLVMStyle();
AllowsMergedIfElse.IfMacros.push_back("MYIF");
AllowsMergedIfElse.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_AllIfsAndElse;
verifyFormat("if (a)\n"
@ -626,10 +672,60 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatement) {
" else if constexpr (c) return;\n"
" else return;",
AllowsMergedIfElse);
verifyFormat("MYIF (a)\n"
" // comment\n"
" f();\n"
"else\n"
" // comment\n"
" f();",
AllowsMergedIfElse);
verifyFormat("{\n"
" MYIF (a)\n"
" label:\n"
" f();\n"
" else\n"
" label:\n"
" f();\n"
"}",
AllowsMergedIfElse);
verifyFormat("MYIF (a)\n"
" ;\n"
"else\n"
" ;",
AllowsMergedIfElse);
verifyFormat("MYIF (a) {\n"
"} else {\n"
"}",
AllowsMergedIfElse);
verifyFormat("MYIF (a) return;\n"
"else MYIF (b) return;\n"
"else return;",
AllowsMergedIfElse);
verifyFormat("MYIF (a) {\n"
"} else return;",
AllowsMergedIfElse);
verifyFormat("MYIF (a) {\n"
"} else MYIF (b) return;\n"
"else return;",
AllowsMergedIfElse);
verifyFormat("MYIF (a) return;\n"
"else MYIF (b) {\n"
"} else return;",
AllowsMergedIfElse);
verifyFormat("MYIF (a)\n"
" MYIF (b) return;\n"
" else return;",
AllowsMergedIfElse);
verifyFormat("MYIF constexpr (a)\n"
" MYIF constexpr (b) return;\n"
" else MYIF constexpr (c) return;\n"
" else return;",
AllowsMergedIfElse);
}
TEST_F(FormatTest, FormatIfWithoutCompoundStatementButElseWith) {
FormatStyle AllowsMergedIf = getLLVMStyle();
AllowsMergedIf.IfMacros.push_back("MYIF");
AllowsMergedIf.AlignEscapedNewlines = FormatStyle::ENAS_Left;
AllowsMergedIf.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
@ -717,6 +813,135 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatementButElseWith) {
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" f();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" f();\n"
"else\n"
" g();\n",
AllowsMergedIf);
verifyFormat("MYIF (a) g();", AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g()\n"
"};",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else MYIF (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else if (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else MYIF (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else if (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else MYIF (b) {\n"
" g();\n"
"} else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else if (b) {\n"
" g();\n"
"} else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else MYIF (b)\n"
" g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else if (b)\n"
" g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else MYIF (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a)\n"
" g();\n"
"else if (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else MYIF (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else if (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
AllowsMergedIf.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_OnlyFirstIf;
@ -802,6 +1027,128 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatementButElseWith) {
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) f();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) f();\n"
"else {\n"
" if (a) f();\n"
" else {\n"
" g();\n"
" }\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();", AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g()\n"
"};",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else MYIF (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else if (b)\n"
" g();\n"
"else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b) {\n"
" g();\n"
"} else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b) {\n"
" g();\n"
"} else\n"
" g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b)\n"
" g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b)\n"
" g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else MYIF (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else if (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
AllowsMergedIf.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_AllIfsAndElse;
@ -879,6 +1226,114 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatementButElseWith) {
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) f();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) f();\n"
"else {\n"
" if (a) f();\n"
" else {\n"
" g();\n"
" }\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();", AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g()\n"
"};",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b) g();\n"
"else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b) g();\n"
"else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else MYIF (b) g();\n"
"else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else if (b) g();\n"
"else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b) {\n"
" g();\n"
"} else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b) {\n"
" g();\n"
"} else g();",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b) g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b) g();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else MYIF (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) g();\n"
"else if (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else MYIF (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("MYIF (a) {\n"
" g();\n"
"} else if (b) {\n"
" g();\n"
"} else {\n"
" g();\n"
"}",
AllowsMergedIf);
}
TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) {
@ -930,6 +1385,10 @@ TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) {
TEST_F(FormatTest, FormatShortBracedStatements) {
FormatStyle AllowSimpleBracedStatements = getLLVMStyle();
AllowSimpleBracedStatements.IfMacros.push_back("MYIF");
// Where line-lengths matter, a 2-letter synonym that maintains line length.
// Not IF to avoid any confusion that IF is somehow special.
AllowSimpleBracedStatements.IfMacros.push_back("FI");
AllowSimpleBracedStatements.ColumnLimit = 40;
AllowSimpleBracedStatements.AllowShortBlocksOnASingleLine =
FormatStyle::SBS_Always;
@ -945,11 +1404,17 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements);
verifyFormat("if CONSTEXPR (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF constexpr (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF CONSTEXPR (true) {}", AllowSimpleBracedStatements);
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
verifyFormat("for (;;) {}", AllowSimpleBracedStatements);
verifyFormat("if (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if CONSTEXPR (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("MYIF (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("MYIF constexpr (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("MYIF CONSTEXPR (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("while (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("for (;;) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if (true) { fffffffffffffffffffffff(); }",
@ -977,6 +1442,31 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("FI (true) { fffffffffffffffffffffff(); }",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {\n"
" ffffffffffffffffffffffff();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {\n"
" ffffffffffffffffffffffffffffffffffffffffffffffffffffff();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) { //\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {\n"
" f();\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {\n"
" f();\n"
"} else {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("struct A2 {\n"
" int X;\n"
@ -1004,6 +1494,17 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {\n"
" f();\n"
"} else {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = false;
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
@ -1026,11 +1527,17 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements);
verifyFormat("if CONSTEXPR (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF constexpr (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF CONSTEXPR (true) {}", AllowSimpleBracedStatements);
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
verifyFormat("for (;;) {}", AllowSimpleBracedStatements);
verifyFormat("if (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if CONSTEXPR (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("MYIF (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("MYIF constexpr (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("MYIF CONSTEXPR (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("while (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("for (;;) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if (true) { fffffffffffffffffffffff(); }",
@ -1064,6 +1571,37 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("FI (true) { fffffffffffffffffffffff(); }",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{\n"
" ffffffffffffffffffffffff();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{\n"
" ffffffffffffffffffffffffffffffffffffffffffffffffffffff();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{ //\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{\n"
" f();\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{\n"
" f();\n"
"} else\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_Never;
@ -1081,6 +1619,20 @@ TEST_F(FormatTest, FormatShortBracedStatements) {
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true) {}", AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("MYIF (true)\n"
"{\n"
" f();\n"
"} else\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = false;
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
@ -1342,7 +1894,7 @@ TEST_F(FormatTest, ForEachLoops) {
FormatStyle Style = getLLVMStyle();
Style.SpaceBeforeParens =
FormatStyle::SBPO_ControlStatementsExceptForEachMacros;
FormatStyle::SBPO_ControlStatementsExceptControlMacros;
verifyFormat("void f() {\n"
" foreach(Item *item, itemlist) {}\n"
" Q_FOREACH(Item *item, itemlist) {}\n"
@ -17624,6 +18176,9 @@ TEST_F(FormatTest, ParsesConfiguration) {
FormatStyle::SBPO_Always);
CHECK_PARSE("SpaceBeforeParens: ControlStatements", SpaceBeforeParens,
FormatStyle::SBPO_ControlStatements);
CHECK_PARSE("SpaceBeforeParens: ControlStatementsExceptControlMacros",
SpaceBeforeParens,
FormatStyle::SBPO_ControlStatementsExceptControlMacros);
CHECK_PARSE("SpaceBeforeParens: NonEmptyParentheses", SpaceBeforeParens,
FormatStyle::SBPO_NonEmptyParentheses);
// For backward compatibility:
@ -17631,6 +18186,9 @@ TEST_F(FormatTest, ParsesConfiguration) {
FormatStyle::SBPO_Never);
CHECK_PARSE("SpaceAfterControlStatementKeyword: true", SpaceBeforeParens,
FormatStyle::SBPO_ControlStatements);
CHECK_PARSE("SpaceBeforeParens: ControlStatementsExceptForEachMacros",
SpaceBeforeParens,
FormatStyle::SBPO_ControlStatementsExceptControlMacros);
Style.ColumnLimit = 123;
FormatStyle BaseStyle = getLLVMStyle();
@ -17778,6 +18336,11 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", ForEachMacros,
BoostAndQForeach);
Style.IfMacros.clear();
std::vector<std::string> CustomIfs;
CustomIfs.push_back("MYIF");
CHECK_PARSE("IfMacros: [MYIF]", IfMacros, CustomIfs);
Style.AttributeMacros.clear();
CHECK_PARSE("BasedOnStyle: LLVM", AttributeMacros,
std::vector<std::string>{"__capability"});
@ -20463,11 +21026,16 @@ TEST_F(FormatTest, AmbersandInLamda) {
TEST_F(FormatTest, SpacesInConditionalStatement) {
FormatStyle Spaces = getLLVMStyle();
Spaces.IfMacros.clear();
Spaces.IfMacros.push_back("MYIF");
Spaces.SpacesInConditionalStatement = true;
verifyFormat("for ( int i = 0; i; i++ )\n continue;", Spaces);
verifyFormat("if ( !a )\n return;", Spaces);
verifyFormat("if ( a )\n return;", Spaces);
verifyFormat("if constexpr ( a )\n return;", Spaces);
verifyFormat("MYIF ( a )\n return;", Spaces);
verifyFormat("MYIF ( a )\n return;\nelse MYIF ( b )\n return;", Spaces);
verifyFormat("MYIF ( a )\n return;\nelse\n return;", Spaces);
verifyFormat("switch ( a )\ncase 1:\n return;", Spaces);
verifyFormat("while ( a )\n return;", Spaces);
verifyFormat("while ( (a && b) )\n return;", Spaces);
@ -20476,6 +21044,13 @@ TEST_F(FormatTest, SpacesInConditionalStatement) {
// Check that space on the left of "::" is inserted as expected at beginning
// of condition.
verifyFormat("while ( ::func() )\n return;", Spaces);
// Check impact of ControlStatementsExceptControlMacros is honored.
Spaces.SpaceBeforeParens =
FormatStyle::SBPO_ControlStatementsExceptControlMacros;
verifyFormat("MYIF( a )\n return;", Spaces);
verifyFormat("MYIF( a )\n return;\nelse MYIF( b )\n return;", Spaces);
verifyFormat("MYIF( a )\n return;\nelse\n return;", Spaces);
}
TEST_F(FormatTest, AlternativeOperators) {