forked from OSchip/llvm-project
[clang-format] Add experimental option to remove LLVM braces
See the style examples at: https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements Differential Revision: https://reviews.llvm.org/D116316
This commit is contained in:
parent
a4e255f9c6
commit
533fbae8d8
|
@ -3402,6 +3402,62 @@ the configuration (without a prefix: ``Auto``).
|
||||||
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
|
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
|
||||||
* information */
|
* information */
|
||||||
|
|
||||||
|
**RemoveBracesLLVM** (``Boolean``) :versionbadge:`clang-format 14`
|
||||||
|
Remove optional braces of control statements (``if``, ``else``, ``for``,
|
||||||
|
and ``while``) in C++ according to the LLVM coding style.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
This option will be renamed and expanded to support other styles.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Setting this option to `true` could lead to incorrect code formatting due
|
||||||
|
to clang-format's lack of complete semantic information. As such, extra
|
||||||
|
care should be taken to review code changes made by this option.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
false: true:
|
||||||
|
|
||||||
|
if (isa<FunctionDecl>(D)) { vs. if (isa<FunctionDecl>(D))
|
||||||
|
handleFunctionDecl(D); handleFunctionDecl(D);
|
||||||
|
} else if (isa<VarDecl>(D)) { else if (isa<VarDecl>(D))
|
||||||
|
handleVarDecl(D); handleVarDecl(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isa<VarDecl>(D)) { vs. if (isa<VarDecl>(D)) {
|
||||||
|
for (auto *A : D.attrs()) { for (auto *A : D.attrs())
|
||||||
|
if (shouldProcessAttr(A)) { if (shouldProcessAttr(A))
|
||||||
|
handleAttr(A); handleAttr(A);
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isa<FunctionDecl>(D)) { vs. if (isa<FunctionDecl>(D))
|
||||||
|
for (auto *A : D.attrs()) { for (auto *A : D.attrs())
|
||||||
|
handleAttr(A); handleAttr(A);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto *D = (T)(D)) { vs. if (auto *D = (T)(D)) {
|
||||||
|
if (shouldProcess(D)) { if (shouldProcess(D))
|
||||||
|
handleVarDecl(D); handleVarDecl(D);
|
||||||
|
} else { else
|
||||||
|
markAsIgnored(D); markAsIgnored(D);
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a) { vs. if (a)
|
||||||
|
b(); b();
|
||||||
|
} else { else if (c)
|
||||||
|
if (c) { d();
|
||||||
|
d(); else
|
||||||
|
} else { e();
|
||||||
|
e();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
**SeparateDefinitionBlocks** (``SeparateDefinitionStyle``) :versionbadge:`clang-format 14`
|
**SeparateDefinitionBlocks** (``SeparateDefinitionStyle``) :versionbadge:`clang-format 14`
|
||||||
Specifies the use of empty lines to separate definition blocks, including
|
Specifies the use of empty lines to separate definition blocks, including
|
||||||
classes, structs, enums, and functions.
|
classes, structs, enums, and functions.
|
||||||
|
|
|
@ -310,6 +310,9 @@ clang-format
|
||||||
`const` `volatile` `static` `inline` `constexpr` `restrict`
|
`const` `volatile` `static` `inline` `constexpr` `restrict`
|
||||||
to be controlled relative to the `type`.
|
to be controlled relative to the `type`.
|
||||||
|
|
||||||
|
- Option ``RemoveBracesLLVM`` has been added to remove optional braces of
|
||||||
|
control statements for the LLVM style.
|
||||||
|
|
||||||
- Option ``SeparateDefinitionBlocks`` has been added to insert or remove empty
|
- Option ``SeparateDefinitionBlocks`` has been added to insert or remove empty
|
||||||
lines between definition blocks including functions, classes, structs, enums,
|
lines between definition blocks including functions, classes, structs, enums,
|
||||||
and namespaces.
|
and namespaces.
|
||||||
|
|
|
@ -3049,6 +3049,60 @@ struct FormatStyle {
|
||||||
bool ReflowComments;
|
bool ReflowComments;
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
/// Remove optional braces of control statements (``if``, ``else``, ``for``,
|
||||||
|
/// and ``while``) in C++ according to the LLVM coding style.
|
||||||
|
/// \warning
|
||||||
|
/// This option will be renamed and expanded to support other styles.
|
||||||
|
/// \endwarning
|
||||||
|
/// \warning
|
||||||
|
/// Setting this option to `true` could lead to incorrect code formatting due
|
||||||
|
/// to clang-format's lack of complete semantic information. As such, extra
|
||||||
|
/// care should be taken to review code changes made by this option.
|
||||||
|
/// \endwarning
|
||||||
|
/// \code
|
||||||
|
/// false: true:
|
||||||
|
///
|
||||||
|
/// if (isa<FunctionDecl>(D)) { vs. if (isa<FunctionDecl>(D))
|
||||||
|
/// handleFunctionDecl(D); handleFunctionDecl(D);
|
||||||
|
/// } else if (isa<VarDecl>(D)) { else if (isa<VarDecl>(D))
|
||||||
|
/// handleVarDecl(D); handleVarDecl(D);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// if (isa<VarDecl>(D)) { vs. if (isa<VarDecl>(D)) {
|
||||||
|
/// for (auto *A : D.attrs()) { for (auto *A : D.attrs())
|
||||||
|
/// if (shouldProcessAttr(A)) { if (shouldProcessAttr(A))
|
||||||
|
/// handleAttr(A); handleAttr(A);
|
||||||
|
/// } }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// if (isa<FunctionDecl>(D)) { vs. if (isa<FunctionDecl>(D))
|
||||||
|
/// for (auto *A : D.attrs()) { for (auto *A : D.attrs())
|
||||||
|
/// handleAttr(A); handleAttr(A);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// if (auto *D = (T)(D)) { vs. if (auto *D = (T)(D)) {
|
||||||
|
/// if (shouldProcess(D)) { if (shouldProcess(D))
|
||||||
|
/// handleVarDecl(D); handleVarDecl(D);
|
||||||
|
/// } else { else
|
||||||
|
/// markAsIgnored(D); markAsIgnored(D);
|
||||||
|
/// } }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// if (a) { vs. if (a)
|
||||||
|
/// b(); b();
|
||||||
|
/// } else { else if (c)
|
||||||
|
/// if (c) { d();
|
||||||
|
/// d(); else
|
||||||
|
/// } else { e();
|
||||||
|
/// e();
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
/// \version 14
|
||||||
|
bool RemoveBracesLLVM;
|
||||||
|
|
||||||
/// \brief The style if definition blocks should be separated.
|
/// \brief The style if definition blocks should be separated.
|
||||||
enum SeparateDefinitionStyle {
|
enum SeparateDefinitionStyle {
|
||||||
/// Leave definition blocks as they are.
|
/// Leave definition blocks as they are.
|
||||||
|
@ -3858,6 +3912,7 @@ struct FormatStyle {
|
||||||
QualifierOrder == R.QualifierOrder &&
|
QualifierOrder == R.QualifierOrder &&
|
||||||
RawStringFormats == R.RawStringFormats &&
|
RawStringFormats == R.RawStringFormats &&
|
||||||
ReferenceAlignment == R.ReferenceAlignment &&
|
ReferenceAlignment == R.ReferenceAlignment &&
|
||||||
|
RemoveBracesLLVM == R.RemoveBracesLLVM &&
|
||||||
SeparateDefinitionBlocks == R.SeparateDefinitionBlocks &&
|
SeparateDefinitionBlocks == R.SeparateDefinitionBlocks &&
|
||||||
ShortNamespaceLines == R.ShortNamespaceLines &&
|
ShortNamespaceLines == R.ShortNamespaceLines &&
|
||||||
SortIncludes == R.SortIncludes &&
|
SortIncludes == R.SortIncludes &&
|
||||||
|
|
|
@ -781,6 +781,7 @@ template <> struct MappingTraits<FormatStyle> {
|
||||||
IO.mapOptional("RawStringFormats", Style.RawStringFormats);
|
IO.mapOptional("RawStringFormats", Style.RawStringFormats);
|
||||||
IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
|
IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
|
||||||
IO.mapOptional("ReflowComments", Style.ReflowComments);
|
IO.mapOptional("ReflowComments", Style.ReflowComments);
|
||||||
|
IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
|
||||||
IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
|
IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
|
||||||
IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
|
IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
|
||||||
IO.mapOptional("SortIncludes", Style.SortIncludes);
|
IO.mapOptional("SortIncludes", Style.SortIncludes);
|
||||||
|
@ -1214,6 +1215,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
||||||
LLVMStyle.UseCRLF = false;
|
LLVMStyle.UseCRLF = false;
|
||||||
LLVMStyle.UseTab = FormatStyle::UT_Never;
|
LLVMStyle.UseTab = FormatStyle::UT_Never;
|
||||||
LLVMStyle.ReflowComments = true;
|
LLVMStyle.ReflowComments = true;
|
||||||
|
LLVMStyle.RemoveBracesLLVM = false;
|
||||||
LLVMStyle.SpacesInParentheses = false;
|
LLVMStyle.SpacesInParentheses = false;
|
||||||
LLVMStyle.SpacesInSquareBrackets = false;
|
LLVMStyle.SpacesInSquareBrackets = false;
|
||||||
LLVMStyle.SpaceInEmptyBlock = false;
|
LLVMStyle.SpaceInEmptyBlock = false;
|
||||||
|
@ -1748,6 +1750,45 @@ FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class BracesRemover : public TokenAnalyzer {
|
||||||
|
public:
|
||||||
|
BracesRemover(const Environment &Env, const FormatStyle &Style)
|
||||||
|
: TokenAnalyzer(Env, Style) {}
|
||||||
|
|
||||||
|
std::pair<tooling::Replacements, unsigned>
|
||||||
|
analyze(TokenAnnotator &Annotator,
|
||||||
|
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
|
||||||
|
FormatTokenLexer &Tokens) override {
|
||||||
|
AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
|
||||||
|
tooling::Replacements Result;
|
||||||
|
removeBraces(AnnotatedLines, Result);
|
||||||
|
return {Result, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Remove optional braces.
|
||||||
|
void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
|
||||||
|
tooling::Replacements &Result) {
|
||||||
|
const auto &SourceMgr = Env.getSourceManager();
|
||||||
|
for (AnnotatedLine *Line : Lines) {
|
||||||
|
removeBraces(Line->Children, Result);
|
||||||
|
if (!Line->Affected)
|
||||||
|
continue;
|
||||||
|
for (FormatToken *Token = Line->First; Token; Token = Token->Next) {
|
||||||
|
if (!Token->Optional)
|
||||||
|
continue;
|
||||||
|
assert(Token->isOneOf(tok::l_brace, tok::r_brace));
|
||||||
|
const auto Start = Token == Line->Last
|
||||||
|
? Token->WhitespaceRange.getBegin()
|
||||||
|
: Token->Tok.getLocation();
|
||||||
|
const auto Range =
|
||||||
|
CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
|
||||||
|
cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class JavaScriptRequoter : public TokenAnalyzer {
|
class JavaScriptRequoter : public TokenAnalyzer {
|
||||||
public:
|
public:
|
||||||
JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
|
JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
|
||||||
|
@ -3049,6 +3090,11 @@ reformat(const FormatStyle &Style, StringRef Code,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Style.isCpp() && Style.RemoveBracesLLVM)
|
||||||
|
Passes.emplace_back([&](const Environment &Env) {
|
||||||
|
return BracesRemover(Env, Expanded).process();
|
||||||
|
});
|
||||||
|
|
||||||
if (Style.Language == FormatStyle::LK_Cpp) {
|
if (Style.Language == FormatStyle::LK_Cpp) {
|
||||||
if (Style.FixNamespaceComments)
|
if (Style.FixNamespaceComments)
|
||||||
Passes.emplace_back([&](const Environment &Env) {
|
Passes.emplace_back([&](const Environment &Env) {
|
||||||
|
|
|
@ -442,6 +442,9 @@ public:
|
||||||
/// This starts an array initializer.
|
/// This starts an array initializer.
|
||||||
bool IsArrayInitializer = false;
|
bool IsArrayInitializer = false;
|
||||||
|
|
||||||
|
/// Is optional and can be removed.
|
||||||
|
bool Optional = false;
|
||||||
|
|
||||||
/// If this token starts a block, this contains all the unwrapped lines
|
/// If this token starts a block, this contains all the unwrapped lines
|
||||||
/// in it.
|
/// in it.
|
||||||
SmallVector<AnnotatedLine *, 1> Children;
|
SmallVector<AnnotatedLine *, 1> Children;
|
||||||
|
|
|
@ -780,6 +780,7 @@ private:
|
||||||
unsigned CommaCount = 0;
|
unsigned CommaCount = 0;
|
||||||
while (CurrentToken) {
|
while (CurrentToken) {
|
||||||
if (CurrentToken->is(tok::r_brace)) {
|
if (CurrentToken->is(tok::r_brace)) {
|
||||||
|
assert(Left->Optional == CurrentToken->Optional);
|
||||||
Left->MatchingParen = CurrentToken;
|
Left->MatchingParen = CurrentToken;
|
||||||
CurrentToken->MatchingParen = Left;
|
CurrentToken->MatchingParen = Left;
|
||||||
if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
|
if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "UnwrappedLineParser.h"
|
#include "UnwrappedLineParser.h"
|
||||||
#include "FormatToken.h"
|
#include "FormatToken.h"
|
||||||
|
#include "TokenAnnotator.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
@ -315,6 +316,7 @@ void UnwrappedLineParser::reset() {
|
||||||
PreprocessorDirectives.clear();
|
PreprocessorDirectives.clear();
|
||||||
CurrentLines = &Lines;
|
CurrentLines = &Lines;
|
||||||
DeclarationScopeStack.clear();
|
DeclarationScopeStack.clear();
|
||||||
|
NestedTooDeep.clear();
|
||||||
PPStack.clear();
|
PPStack.clear();
|
||||||
Line->FirstStartColumn = FirstStartColumn;
|
Line->FirstStartColumn = FirstStartColumn;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +430,47 @@ void UnwrappedLineParser::parseCSharpAttribute() {
|
||||||
} while (!eof());
|
} while (!eof());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
|
bool UnwrappedLineParser::precededByCommentOrPPDirective() const {
|
||||||
|
if (!Lines.empty() && Lines.back().InPPDirective)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const FormatToken *Previous = Tokens->getPreviousToken();
|
||||||
|
return Previous && Previous->is(tok::comment) &&
|
||||||
|
(Previous->IsMultiline || Previous->NewlinesBefore > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnwrappedLineParser::mightFitOnOneLine() const {
|
||||||
|
const auto ColumnLimit = Style.ColumnLimit;
|
||||||
|
if (ColumnLimit == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (Lines.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const auto &PreviousLine = Lines.back();
|
||||||
|
const auto &Tokens = PreviousLine.Tokens;
|
||||||
|
assert(!Tokens.empty());
|
||||||
|
const auto *LastToken = Tokens.back().Tok;
|
||||||
|
assert(LastToken);
|
||||||
|
if (!LastToken->isOneOf(tok::semi, tok::comment))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
AnnotatedLine Line(PreviousLine);
|
||||||
|
assert(Line.Last == LastToken);
|
||||||
|
|
||||||
|
TokenAnnotator Annotator(Style, Keywords);
|
||||||
|
Annotator.annotate(Line);
|
||||||
|
Annotator.calculateFormattingInformation(Line);
|
||||||
|
|
||||||
|
return Line.Level * Style.IndentWidth + LastToken->TotalLength <= ColumnLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if a simple block, or false otherwise. (A simple block has a
|
||||||
|
// single statement that fits on a single line.)
|
||||||
|
bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace, IfStmtKind *IfKind) {
|
||||||
|
const bool IsPrecededByCommentOrPPDirective =
|
||||||
|
!Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
|
||||||
|
unsigned StatementCount = 0;
|
||||||
bool SwitchLabelEncountered = false;
|
bool SwitchLabelEncountered = false;
|
||||||
do {
|
do {
|
||||||
tok::TokenKind kind = FormatTok->Tok.getKind();
|
tok::TokenKind kind = FormatTok->Tok.getKind();
|
||||||
|
@ -449,11 +491,24 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
|
||||||
if (!FormatTok->is(TT_MacroBlockBegin) && tryToParseBracedList())
|
if (!FormatTok->is(TT_MacroBlockBegin) && tryToParseBracedList())
|
||||||
continue;
|
continue;
|
||||||
parseBlock();
|
parseBlock();
|
||||||
|
++StatementCount;
|
||||||
|
assert(StatementCount > 0 && "StatementCount overflow!");
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
break;
|
break;
|
||||||
case tok::r_brace:
|
case tok::r_brace:
|
||||||
if (HasOpeningBrace)
|
if (HasOpeningBrace) {
|
||||||
return;
|
if (!Style.RemoveBracesLLVM)
|
||||||
|
return false;
|
||||||
|
if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 ||
|
||||||
|
IsPrecededByCommentOrPPDirective ||
|
||||||
|
precededByCommentOrPPDirective()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const FormatToken *Next = Tokens->peekNextToken();
|
||||||
|
if (Next->is(tok::comment) && Next->NewlinesBefore == 0)
|
||||||
|
return false;
|
||||||
|
return mightFitOnOneLine();
|
||||||
|
}
|
||||||
nextToken();
|
nextToken();
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
break;
|
break;
|
||||||
|
@ -493,10 +548,13 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
|
||||||
}
|
}
|
||||||
LLVM_FALLTHROUGH;
|
LLVM_FALLTHROUGH;
|
||||||
default:
|
default:
|
||||||
parseStructuralElement(!HasOpeningBrace);
|
parseStructuralElement(IfKind, !HasOpeningBrace);
|
||||||
|
++StatementCount;
|
||||||
|
assert(StatementCount > 0 && "StatementCount overflow!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (!eof());
|
} while (!eof());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
||||||
|
@ -652,11 +710,13 @@ size_t UnwrappedLineParser::computePPHash() const {
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels,
|
UnwrappedLineParser::IfStmtKind
|
||||||
bool MunchSemi,
|
UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels,
|
||||||
bool UnindentWhitesmithsBraces) {
|
bool MunchSemi,
|
||||||
|
bool UnindentWhitesmithsBraces) {
|
||||||
assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
|
assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
|
||||||
"'{' or macro block token expected");
|
"'{' or macro block token expected");
|
||||||
|
FormatToken *Tok = FormatTok;
|
||||||
const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
|
const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
|
||||||
FormatTok->setBlockKind(BK_Block);
|
FormatTok->setBlockKind(BK_Block);
|
||||||
|
|
||||||
|
@ -691,16 +751,28 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels,
|
||||||
MustBeDeclaration);
|
MustBeDeclaration);
|
||||||
if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)
|
if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)
|
||||||
Line->Level += AddLevels;
|
Line->Level += AddLevels;
|
||||||
parseLevel(/*HasOpeningBrace=*/true);
|
|
||||||
|
IfStmtKind IfKind = IfStmtKind::NotIf;
|
||||||
|
const bool SimpleBlock = parseLevel(/*HasOpeningBrace=*/true, &IfKind);
|
||||||
|
|
||||||
if (eof())
|
if (eof())
|
||||||
return;
|
return IfKind;
|
||||||
|
|
||||||
if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
|
if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
|
||||||
: !FormatTok->is(tok::r_brace)) {
|
: !FormatTok->is(tok::r_brace)) {
|
||||||
Line->Level = InitialLevel;
|
Line->Level = InitialLevel;
|
||||||
FormatTok->setBlockKind(BK_Block);
|
FormatTok->setBlockKind(BK_Block);
|
||||||
return;
|
return IfKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SimpleBlock && Tok->is(tok::l_brace)) {
|
||||||
|
assert(FormatTok->is(tok::r_brace));
|
||||||
|
const FormatToken *Previous = Tokens->getPreviousToken();
|
||||||
|
assert(Previous);
|
||||||
|
if (Previous->isNot(tok::r_brace) || Previous->Optional) {
|
||||||
|
Tok->MatchingParen = FormatTok;
|
||||||
|
FormatTok->MatchingParen = Tok;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PPEndHash = computePPHash();
|
size_t PPEndHash = computePPHash();
|
||||||
|
@ -731,6 +803,8 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels,
|
||||||
CurrentLines->size() - 1;
|
CurrentLines->size() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return IfKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isGoogScope(const UnwrappedLine &Line) {
|
static bool isGoogScope(const UnwrappedLine &Line) {
|
||||||
|
@ -1185,7 +1259,8 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
|
||||||
return addUnwrappedLine();
|
return addUnwrappedLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
|
void UnwrappedLineParser::parseStructuralElement(IfStmtKind *IfKind,
|
||||||
|
bool IsTopLevel) {
|
||||||
if (Style.Language == FormatStyle::LK_TableGen &&
|
if (Style.Language == FormatStyle::LK_TableGen &&
|
||||||
FormatTok->is(tok::pp_include)) {
|
FormatTok->is(tok::pp_include)) {
|
||||||
nextToken();
|
nextToken();
|
||||||
|
@ -1228,7 +1303,7 @@ void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
|
||||||
if (Style.isJavaScript() && Line->MustBeDeclaration)
|
if (Style.isJavaScript() && Line->MustBeDeclaration)
|
||||||
// field/method declaration.
|
// field/method declaration.
|
||||||
break;
|
break;
|
||||||
parseIfThenElse();
|
parseIfThenElse(IfKind);
|
||||||
return;
|
return;
|
||||||
case tok::kw_for:
|
case tok::kw_for:
|
||||||
case tok::kw_while:
|
case tok::kw_while:
|
||||||
|
@ -2138,7 +2213,39 @@ void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
|
||||||
} while (!eof());
|
} while (!eof());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseIfThenElse() {
|
void UnwrappedLineParser::keepAncestorBraces() {
|
||||||
|
if (!Style.RemoveBracesLLVM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int MaxNestingLevels = 2;
|
||||||
|
const int Size = NestedTooDeep.size();
|
||||||
|
if (Size >= MaxNestingLevels)
|
||||||
|
NestedTooDeep[Size - MaxNestingLevels] = true;
|
||||||
|
NestedTooDeep.push_back(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void markOptionalBraces(FormatToken *LeftBrace) {
|
||||||
|
if (!LeftBrace)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(LeftBrace->is(tok::l_brace));
|
||||||
|
|
||||||
|
FormatToken *RightBrace = LeftBrace->MatchingParen;
|
||||||
|
if (!RightBrace) {
|
||||||
|
assert(!LeftBrace->Optional);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(RightBrace->is(tok::r_brace));
|
||||||
|
assert(RightBrace->MatchingParen == LeftBrace);
|
||||||
|
assert(LeftBrace->Optional == RightBrace->Optional);
|
||||||
|
|
||||||
|
LeftBrace->Optional = true;
|
||||||
|
RightBrace->Optional = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
|
||||||
|
bool KeepBraces) {
|
||||||
auto HandleAttributes = [this]() {
|
auto HandleAttributes = [this]() {
|
||||||
// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
|
// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
|
||||||
if (FormatTok->is(TT_AttributeMacro))
|
if (FormatTok->is(TT_AttributeMacro))
|
||||||
|
@ -2155,10 +2262,17 @@ void UnwrappedLineParser::parseIfThenElse() {
|
||||||
if (FormatTok->Tok.is(tok::l_paren))
|
if (FormatTok->Tok.is(tok::l_paren))
|
||||||
parseParens();
|
parseParens();
|
||||||
HandleAttributes();
|
HandleAttributes();
|
||||||
|
|
||||||
bool NeedsUnwrappedLine = false;
|
bool NeedsUnwrappedLine = false;
|
||||||
|
keepAncestorBraces();
|
||||||
|
|
||||||
|
FormatToken *IfLeftBrace = nullptr;
|
||||||
|
IfStmtKind IfBlockKind = IfStmtKind::NotIf;
|
||||||
|
|
||||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||||
|
IfLeftBrace = FormatTok;
|
||||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||||
parseBlock();
|
IfBlockKind = parseBlock();
|
||||||
if (Style.BraceWrapping.BeforeElse)
|
if (Style.BraceWrapping.BeforeElse)
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
else
|
else
|
||||||
|
@ -2169,22 +2283,48 @@ void UnwrappedLineParser::parseIfThenElse() {
|
||||||
parseStructuralElement();
|
parseStructuralElement();
|
||||||
--Line->Level;
|
--Line->Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeepIfBraces = false;
|
||||||
|
if (Style.RemoveBracesLLVM) {
|
||||||
|
assert(!NestedTooDeep.empty());
|
||||||
|
KeepIfBraces = (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
|
||||||
|
NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
|
||||||
|
IfBlockKind == IfStmtKind::IfElseIf;
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatToken *ElseLeftBrace = nullptr;
|
||||||
|
IfStmtKind Kind = IfStmtKind::IfOnly;
|
||||||
|
|
||||||
if (FormatTok->Tok.is(tok::kw_else)) {
|
if (FormatTok->Tok.is(tok::kw_else)) {
|
||||||
|
if (Style.RemoveBracesLLVM) {
|
||||||
|
NestedTooDeep.back() = false;
|
||||||
|
Kind = IfStmtKind::IfElse;
|
||||||
|
}
|
||||||
nextToken();
|
nextToken();
|
||||||
HandleAttributes();
|
HandleAttributes();
|
||||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||||
|
ElseLeftBrace = FormatTok;
|
||||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||||
parseBlock();
|
if (parseBlock() == IfStmtKind::IfOnly)
|
||||||
|
Kind = IfStmtKind::IfElseIf;
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
} else if (FormatTok->Tok.is(tok::kw_if)) {
|
} else if (FormatTok->Tok.is(tok::kw_if)) {
|
||||||
FormatToken *Previous = Tokens->getPreviousToken();
|
FormatToken *Previous = Tokens->getPreviousToken();
|
||||||
bool PrecededByComment = Previous && Previous->is(tok::comment);
|
const bool IsPrecededByComment = Previous && Previous->is(tok::comment);
|
||||||
if (PrecededByComment) {
|
if (IsPrecededByComment) {
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
++Line->Level;
|
++Line->Level;
|
||||||
}
|
}
|
||||||
parseIfThenElse();
|
bool TooDeep = true;
|
||||||
if (PrecededByComment)
|
if (Style.RemoveBracesLLVM) {
|
||||||
|
Kind = IfStmtKind::IfElseIf;
|
||||||
|
TooDeep = NestedTooDeep.pop_back_val();
|
||||||
|
}
|
||||||
|
ElseLeftBrace =
|
||||||
|
parseIfThenElse(/*IfKind=*/nullptr, KeepBraces || KeepIfBraces);
|
||||||
|
if (Style.RemoveBracesLLVM)
|
||||||
|
NestedTooDeep.push_back(TooDeep);
|
||||||
|
if (IsPrecededByComment)
|
||||||
--Line->Level;
|
--Line->Level;
|
||||||
} else {
|
} else {
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
|
@ -2194,9 +2334,40 @@ void UnwrappedLineParser::parseIfThenElse() {
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
--Line->Level;
|
--Line->Level;
|
||||||
}
|
}
|
||||||
} else if (NeedsUnwrappedLine) {
|
} else {
|
||||||
addUnwrappedLine();
|
if (Style.RemoveBracesLLVM)
|
||||||
|
KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
|
||||||
|
if (NeedsUnwrappedLine)
|
||||||
|
addUnwrappedLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Style.RemoveBracesLLVM)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
assert(!NestedTooDeep.empty());
|
||||||
|
const bool KeepElseBraces =
|
||||||
|
(ElseLeftBrace && !ElseLeftBrace->MatchingParen) || NestedTooDeep.back();
|
||||||
|
|
||||||
|
NestedTooDeep.pop_back();
|
||||||
|
|
||||||
|
if (!KeepBraces && !KeepIfBraces && !KeepElseBraces) {
|
||||||
|
markOptionalBraces(IfLeftBrace);
|
||||||
|
markOptionalBraces(ElseLeftBrace);
|
||||||
|
} else if (IfLeftBrace) {
|
||||||
|
FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
|
||||||
|
if (IfRightBrace) {
|
||||||
|
assert(IfRightBrace->MatchingParen == IfLeftBrace);
|
||||||
|
assert(!IfLeftBrace->Optional);
|
||||||
|
assert(!IfRightBrace->Optional);
|
||||||
|
IfLeftBrace->MatchingParen = nullptr;
|
||||||
|
IfRightBrace->MatchingParen = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IfKind)
|
||||||
|
*IfKind = Kind;
|
||||||
|
|
||||||
|
return IfLeftBrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseTryCatch() {
|
void UnwrappedLineParser::parseTryCatch() {
|
||||||
|
@ -2234,6 +2405,9 @@ void UnwrappedLineParser::parseTryCatch() {
|
||||||
if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren)) {
|
if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren)) {
|
||||||
parseParens();
|
parseParens();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keepAncestorBraces();
|
||||||
|
|
||||||
if (FormatTok->is(tok::l_brace)) {
|
if (FormatTok->is(tok::l_brace)) {
|
||||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||||
parseBlock();
|
parseBlock();
|
||||||
|
@ -2267,8 +2441,11 @@ void UnwrappedLineParser::parseTryCatch() {
|
||||||
parseParens();
|
parseParens();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof))
|
if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof)) {
|
||||||
|
if (Style.RemoveBracesLLVM)
|
||||||
|
NestedTooDeep.pop_back();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
nextToken();
|
nextToken();
|
||||||
}
|
}
|
||||||
NeedsUnwrappedLine = false;
|
NeedsUnwrappedLine = false;
|
||||||
|
@ -2279,6 +2456,10 @@ void UnwrappedLineParser::parseTryCatch() {
|
||||||
else
|
else
|
||||||
NeedsUnwrappedLine = true;
|
NeedsUnwrappedLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Style.RemoveBracesLLVM)
|
||||||
|
NestedTooDeep.pop_back();
|
||||||
|
|
||||||
if (NeedsUnwrappedLine)
|
if (NeedsUnwrappedLine)
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
}
|
}
|
||||||
|
@ -2385,9 +2566,18 @@ void UnwrappedLineParser::parseForOrWhileLoop() {
|
||||||
nextToken();
|
nextToken();
|
||||||
if (FormatTok->Tok.is(tok::l_paren))
|
if (FormatTok->Tok.is(tok::l_paren))
|
||||||
parseParens();
|
parseParens();
|
||||||
|
|
||||||
|
keepAncestorBraces();
|
||||||
|
|
||||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||||
|
FormatToken *LeftBrace = FormatTok;
|
||||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||||
parseBlock();
|
parseBlock();
|
||||||
|
if (Style.RemoveBracesLLVM) {
|
||||||
|
assert(!NestedTooDeep.empty());
|
||||||
|
if (!NestedTooDeep.back())
|
||||||
|
markOptionalBraces(LeftBrace);
|
||||||
|
}
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
} else {
|
} else {
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
|
@ -2395,11 +2585,17 @@ void UnwrappedLineParser::parseForOrWhileLoop() {
|
||||||
parseStructuralElement();
|
parseStructuralElement();
|
||||||
--Line->Level;
|
--Line->Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Style.RemoveBracesLLVM)
|
||||||
|
NestedTooDeep.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseDoWhile() {
|
void UnwrappedLineParser::parseDoWhile() {
|
||||||
assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected");
|
assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected");
|
||||||
nextToken();
|
nextToken();
|
||||||
|
|
||||||
|
keepAncestorBraces();
|
||||||
|
|
||||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||||
parseBlock();
|
parseBlock();
|
||||||
|
@ -2412,6 +2608,9 @@ void UnwrappedLineParser::parseDoWhile() {
|
||||||
--Line->Level;
|
--Line->Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Style.RemoveBracesLLVM)
|
||||||
|
NestedTooDeep.pop_back();
|
||||||
|
|
||||||
// FIXME: Add error handling.
|
// FIXME: Add error handling.
|
||||||
if (!FormatTok->Tok.is(tok::kw_while)) {
|
if (!FormatTok->Tok.is(tok::kw_while)) {
|
||||||
addUnwrappedLine();
|
addUnwrappedLine();
|
||||||
|
@ -2481,6 +2680,9 @@ void UnwrappedLineParser::parseSwitch() {
|
||||||
nextToken();
|
nextToken();
|
||||||
if (FormatTok->Tok.is(tok::l_paren))
|
if (FormatTok->Tok.is(tok::l_paren))
|
||||||
parseParens();
|
parseParens();
|
||||||
|
|
||||||
|
keepAncestorBraces();
|
||||||
|
|
||||||
if (FormatTok->Tok.is(tok::l_brace)) {
|
if (FormatTok->Tok.is(tok::l_brace)) {
|
||||||
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
CompoundStatementIndenter Indenter(this, Style, Line->Level);
|
||||||
parseBlock();
|
parseBlock();
|
||||||
|
@ -2491,6 +2693,9 @@ void UnwrappedLineParser::parseSwitch() {
|
||||||
parseStructuralElement();
|
parseStructuralElement();
|
||||||
--Line->Level;
|
--Line->Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Style.RemoveBracesLLVM)
|
||||||
|
NestedTooDeep.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnwrappedLineParser::parseAccessSpecifier() {
|
void UnwrappedLineParser::parseAccessSpecifier() {
|
||||||
|
|
|
@ -81,12 +81,21 @@ public:
|
||||||
void parse();
|
void parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class IfStmtKind {
|
||||||
|
NotIf, // Not an if statement.
|
||||||
|
IfOnly, // An if statement without the else clause.
|
||||||
|
IfElse, // An if statement followed by else but not else if.
|
||||||
|
IfElseIf // An if statement followed by else if.
|
||||||
|
};
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void parseFile();
|
void parseFile();
|
||||||
void parseLevel(bool HasOpeningBrace);
|
bool precededByCommentOrPPDirective() const;
|
||||||
void parseBlock(bool MustBeDeclaration = false, unsigned AddLevels = 1u,
|
bool mightFitOnOneLine() const;
|
||||||
bool MunchSemi = true,
|
bool parseLevel(bool HasOpeningBrace, IfStmtKind *IfKind = nullptr);
|
||||||
bool UnindentWhitesmithsBraces = false);
|
IfStmtKind parseBlock(bool MustBeDeclaration = false, unsigned AddLevels = 1u,
|
||||||
|
bool MunchSemi = true,
|
||||||
|
bool UnindentWhitesmithsBraces = false);
|
||||||
void parseChildBlock();
|
void parseChildBlock();
|
||||||
void parsePPDirective();
|
void parsePPDirective();
|
||||||
void parsePPDefine();
|
void parsePPDefine();
|
||||||
|
@ -96,13 +105,15 @@ private:
|
||||||
void parsePPEndIf();
|
void parsePPEndIf();
|
||||||
void parsePPUnknown();
|
void parsePPUnknown();
|
||||||
void readTokenWithJavaScriptASI();
|
void readTokenWithJavaScriptASI();
|
||||||
void parseStructuralElement(bool IsTopLevel = false);
|
void parseStructuralElement(IfStmtKind *IfKind = nullptr,
|
||||||
|
bool IsTopLevel = false);
|
||||||
bool tryToParseBracedList();
|
bool tryToParseBracedList();
|
||||||
bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false,
|
bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false,
|
||||||
tok::TokenKind ClosingBraceKind = tok::r_brace);
|
tok::TokenKind ClosingBraceKind = tok::r_brace);
|
||||||
void parseParens();
|
void parseParens();
|
||||||
void parseSquare(bool LambdaIntroducer = false);
|
void parseSquare(bool LambdaIntroducer = false);
|
||||||
void parseIfThenElse();
|
void keepAncestorBraces();
|
||||||
|
FormatToken *parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces = false);
|
||||||
void parseTryCatch();
|
void parseTryCatch();
|
||||||
void parseForOrWhileLoop();
|
void parseForOrWhileLoop();
|
||||||
void parseDoWhile();
|
void parseDoWhile();
|
||||||
|
@ -235,6 +246,10 @@ private:
|
||||||
// owned outside of and handed into the UnwrappedLineParser.
|
// owned outside of and handed into the UnwrappedLineParser.
|
||||||
ArrayRef<FormatToken *> AllTokens;
|
ArrayRef<FormatToken *> AllTokens;
|
||||||
|
|
||||||
|
// Keeps a stack of the states of nested control statements (true if the
|
||||||
|
// statement contains more than some predefined number of nested statements).
|
||||||
|
SmallVector<bool, 8> NestedTooDeep;
|
||||||
|
|
||||||
// Represents preprocessor branch type, so we can find matching
|
// Represents preprocessor branch type, so we can find matching
|
||||||
// #if/#else/#endif directives.
|
// #if/#else/#endif directives.
|
||||||
enum PPBranchKind {
|
enum PPBranchKind {
|
||||||
|
|
|
@ -18889,6 +18889,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
|
||||||
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
|
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
|
||||||
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
|
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
|
||||||
CHECK_PARSE_BOOL(ReflowComments);
|
CHECK_PARSE_BOOL(ReflowComments);
|
||||||
|
CHECK_PARSE_BOOL(RemoveBracesLLVM);
|
||||||
CHECK_PARSE_BOOL(SortUsingDeclarations);
|
CHECK_PARSE_BOOL(SortUsingDeclarations);
|
||||||
CHECK_PARSE_BOOL(SpacesInParentheses);
|
CHECK_PARSE_BOOL(SpacesInParentheses);
|
||||||
CHECK_PARSE_BOOL(SpacesInSquareBrackets);
|
CHECK_PARSE_BOOL(SpacesInSquareBrackets);
|
||||||
|
@ -23334,6 +23335,367 @@ TEST_F(FormatTest, ShortTemplatedArgumentLists) {
|
||||||
verifyFormat("struct Z : X<decltype([] { return 0; }){}> {};", Style);
|
verifyFormat("struct Z : X<decltype([] { return 0; }){}> {};", Style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(FormatTest, RemoveBraces) {
|
||||||
|
FormatStyle Style = getLLVMStyle();
|
||||||
|
Style.RemoveBracesLLVM = true;
|
||||||
|
|
||||||
|
// The following eight test cases are fully-braced versions of the examples at
|
||||||
|
// "llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-
|
||||||
|
// statement-bodies-of-if-else-loop-statements".
|
||||||
|
|
||||||
|
// 1. Omit the braces, since the body is simple and clearly associated with
|
||||||
|
// the if.
|
||||||
|
verifyFormat("if (isa<FunctionDecl>(D))\n"
|
||||||
|
" handleFunctionDecl(D);\n"
|
||||||
|
"else if (isa<VarDecl>(D))\n"
|
||||||
|
" handleVarDecl(D);",
|
||||||
|
"if (isa<FunctionDecl>(D)) {\n"
|
||||||
|
" handleFunctionDecl(D);\n"
|
||||||
|
"} else if (isa<VarDecl>(D)) {\n"
|
||||||
|
" handleVarDecl(D);\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 2. Here we document the condition itself and not the body.
|
||||||
|
verifyFormat("if (isa<VarDecl>(D)) {\n"
|
||||||
|
" // It is necessary that we explain the situation with this\n"
|
||||||
|
" // surprisingly long comment, so it would be unclear\n"
|
||||||
|
" // without the braces whether the following statement is in\n"
|
||||||
|
" // the scope of the `if`.\n"
|
||||||
|
" // Because the condition is documented, we can't really\n"
|
||||||
|
" // hoist this comment that applies to the body above the\n"
|
||||||
|
" // if.\n"
|
||||||
|
" handleOtherDecl(D);\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 3. Use braces on the outer `if` to avoid a potential dangling else
|
||||||
|
// situation.
|
||||||
|
verifyFormat("if (isa<VarDecl>(D)) {\n"
|
||||||
|
" for (auto *A : D.attrs())\n"
|
||||||
|
" if (shouldProcessAttr(A))\n"
|
||||||
|
" handleAttr(A);\n"
|
||||||
|
"}",
|
||||||
|
"if (isa<VarDecl>(D)) {\n"
|
||||||
|
" for (auto *A : D.attrs()) {\n"
|
||||||
|
" if (shouldProcessAttr(A)) {\n"
|
||||||
|
" handleAttr(A);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 4. Use braces for the `if` block to keep it uniform with the else block.
|
||||||
|
verifyFormat("if (isa<FunctionDecl>(D)) {\n"
|
||||||
|
" handleFunctionDecl(D);\n"
|
||||||
|
"} else {\n"
|
||||||
|
" // In this else case, it is necessary that we explain the\n"
|
||||||
|
" // situation with this surprisingly long comment, so it\n"
|
||||||
|
" // would be unclear without the braces whether the\n"
|
||||||
|
" // following statement is in the scope of the `if`.\n"
|
||||||
|
" handleOtherDecl(D);\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 5. This should also omit braces. The `for` loop contains only a single
|
||||||
|
// statement, so it shouldn't have braces. The `if` also only contains a
|
||||||
|
// single simple statement (the for loop), so it also should omit braces.
|
||||||
|
verifyFormat("if (isa<FunctionDecl>(D))\n"
|
||||||
|
" for (auto *A : D.attrs())\n"
|
||||||
|
" handleAttr(A);",
|
||||||
|
"if (isa<FunctionDecl>(D)) {\n"
|
||||||
|
" for (auto *A : D.attrs()) {\n"
|
||||||
|
" handleAttr(A);\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 6. Use braces for the outer `if` since the nested `for` is braced.
|
||||||
|
verifyFormat("if (isa<FunctionDecl>(D)) {\n"
|
||||||
|
" for (auto *A : D.attrs()) {\n"
|
||||||
|
" // In this for loop body, it is necessary that we explain\n"
|
||||||
|
" // the situation with this surprisingly long comment,\n"
|
||||||
|
" // forcing braces on the `for` block.\n"
|
||||||
|
" handleAttr(A);\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 7. Use braces on the outer block because there are more than two levels of
|
||||||
|
// nesting.
|
||||||
|
verifyFormat("if (isa<FunctionDecl>(D)) {\n"
|
||||||
|
" for (auto *A : D.attrs())\n"
|
||||||
|
" for (ssize_t i : llvm::seq<ssize_t>(count))\n"
|
||||||
|
" handleAttrOnDecl(D, A, i);\n"
|
||||||
|
"}",
|
||||||
|
"if (isa<FunctionDecl>(D)) {\n"
|
||||||
|
" for (auto *A : D.attrs()) {\n"
|
||||||
|
" for (ssize_t i : llvm::seq<ssize_t>(count)) {\n"
|
||||||
|
" handleAttrOnDecl(D, A, i);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
// 8. Use braces on the outer block because of a nested `if`, otherwise the
|
||||||
|
// compiler would warn: `add explicit braces to avoid dangling else`
|
||||||
|
verifyFormat("if (auto *D = dyn_cast<FunctionDecl>(D)) {\n"
|
||||||
|
" if (shouldProcess(D))\n"
|
||||||
|
" handleVarDecl(D);\n"
|
||||||
|
" else\n"
|
||||||
|
" markAsIgnored(D);\n"
|
||||||
|
"}",
|
||||||
|
"if (auto *D = dyn_cast<FunctionDecl>(D)) {\n"
|
||||||
|
" if (shouldProcess(D)) {\n"
|
||||||
|
" handleVarDecl(D);\n"
|
||||||
|
" } else {\n"
|
||||||
|
" markAsIgnored(D);\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a)\n"
|
||||||
|
" b; // comment\n"
|
||||||
|
"else if (c)\n"
|
||||||
|
" d; /* comment */\n"
|
||||||
|
"else\n"
|
||||||
|
" e;",
|
||||||
|
"if (a) {\n"
|
||||||
|
" b; // comment\n"
|
||||||
|
"} else if (c) {\n"
|
||||||
|
" d; /* comment */\n"
|
||||||
|
"} else {\n"
|
||||||
|
" e;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" b;\n"
|
||||||
|
" c;\n"
|
||||||
|
"} else if (d) {\n"
|
||||||
|
" e;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
"#undef NDEBUG\n"
|
||||||
|
" b;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" c;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" // comment\n"
|
||||||
|
"} else if (b) {\n"
|
||||||
|
" c;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" b;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" { c; }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" if (b) // comment\n"
|
||||||
|
" c;\n"
|
||||||
|
"} else if (d) {\n"
|
||||||
|
" e;\n"
|
||||||
|
"}",
|
||||||
|
"if (a) {\n"
|
||||||
|
" if (b) { // comment\n"
|
||||||
|
" c;\n"
|
||||||
|
" }\n"
|
||||||
|
"} else if (d) {\n"
|
||||||
|
" e;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" if (b) {\n"
|
||||||
|
" c;\n"
|
||||||
|
" // comment\n"
|
||||||
|
" } else if (d) {\n"
|
||||||
|
" e;\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" if (b)\n"
|
||||||
|
" c;\n"
|
||||||
|
"}",
|
||||||
|
"if (a) {\n"
|
||||||
|
" if (b) {\n"
|
||||||
|
" c;\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a)\n"
|
||||||
|
" if (b)\n"
|
||||||
|
" c;\n"
|
||||||
|
" else\n"
|
||||||
|
" d;\n"
|
||||||
|
"else\n"
|
||||||
|
" e;",
|
||||||
|
"if (a) {\n"
|
||||||
|
" if (b) {\n"
|
||||||
|
" c;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" d;\n"
|
||||||
|
" }\n"
|
||||||
|
"} else {\n"
|
||||||
|
" e;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" // comment\n"
|
||||||
|
" if (b)\n"
|
||||||
|
" c;\n"
|
||||||
|
" else if (d)\n"
|
||||||
|
" e;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" g;\n"
|
||||||
|
"}",
|
||||||
|
"if (a) {\n"
|
||||||
|
" // comment\n"
|
||||||
|
" if (b) {\n"
|
||||||
|
" c;\n"
|
||||||
|
" } else if (d) {\n"
|
||||||
|
" e;\n"
|
||||||
|
" }\n"
|
||||||
|
"} else {\n"
|
||||||
|
" g;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a)\n"
|
||||||
|
" b;\n"
|
||||||
|
"else if (c)\n"
|
||||||
|
" d;\n"
|
||||||
|
"else\n"
|
||||||
|
" e;",
|
||||||
|
"if (a) {\n"
|
||||||
|
" b;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" if (c) {\n"
|
||||||
|
" d;\n"
|
||||||
|
" } else {\n"
|
||||||
|
" e;\n"
|
||||||
|
" }\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" if (b)\n"
|
||||||
|
" c;\n"
|
||||||
|
" else if (d)\n"
|
||||||
|
" e;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" g;\n"
|
||||||
|
"}",
|
||||||
|
"if (a) {\n"
|
||||||
|
" if (b)\n"
|
||||||
|
" c;\n"
|
||||||
|
" else {\n"
|
||||||
|
" if (d)\n"
|
||||||
|
" e;\n"
|
||||||
|
" }\n"
|
||||||
|
"} else {\n"
|
||||||
|
" g;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a)\n"
|
||||||
|
" b;\n"
|
||||||
|
"else if (c)\n"
|
||||||
|
" while (d)\n"
|
||||||
|
" e;\n"
|
||||||
|
"// comment",
|
||||||
|
"if (a)\n"
|
||||||
|
"{\n"
|
||||||
|
" b;\n"
|
||||||
|
"} else if (c) {\n"
|
||||||
|
" while (d) {\n"
|
||||||
|
" e;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"// comment",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" b;\n"
|
||||||
|
"} else if (c) {\n"
|
||||||
|
" d;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" e;\n"
|
||||||
|
" g;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" b;\n"
|
||||||
|
"} else if (c) {\n"
|
||||||
|
" d;\n"
|
||||||
|
"} else {\n"
|
||||||
|
" e;\n"
|
||||||
|
"} // comment",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("int abs = [](int i) {\n"
|
||||||
|
" if (i >= 0)\n"
|
||||||
|
" return i;\n"
|
||||||
|
" return -i;\n"
|
||||||
|
"};",
|
||||||
|
"int abs = [](int i) {\n"
|
||||||
|
" if (i >= 0) {\n"
|
||||||
|
" return i;\n"
|
||||||
|
" }\n"
|
||||||
|
" return -i;\n"
|
||||||
|
"};",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
Style.ColumnLimit = 20;
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" b = c + // 1 -\n"
|
||||||
|
" d;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a) {\n"
|
||||||
|
" b = c >= 0 ? d\n"
|
||||||
|
" : e;\n"
|
||||||
|
"}",
|
||||||
|
"if (a) {\n"
|
||||||
|
" b = c >= 0 ? d : e;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
verifyFormat("if (a)\n"
|
||||||
|
" b = c > 0 ? d : e;",
|
||||||
|
"if (a) {\n"
|
||||||
|
" b = c > 0 ? d : e;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
|
||||||
|
Style.ColumnLimit = 0;
|
||||||
|
|
||||||
|
verifyFormat("if (a)\n"
|
||||||
|
" b234567890223456789032345678904234567890 = "
|
||||||
|
"c234567890223456789032345678904234567890;",
|
||||||
|
"if (a) {\n"
|
||||||
|
" b234567890223456789032345678904234567890 = "
|
||||||
|
"c234567890223456789032345678904234567890;\n"
|
||||||
|
"}",
|
||||||
|
Style);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace format
|
} // namespace format
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
Loading…
Reference in New Issue