summaryrefslogtreecommitdiff
path: root/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Format')
-rw-r--r--lib/Format/BreakableToken.cpp11
-rw-r--r--lib/Format/ContinuationIndenter.cpp23
-rw-r--r--lib/Format/Encoding.h3
-rw-r--r--lib/Format/Format.cpp246
-rw-r--r--lib/Format/FormatToken.h13
-rw-r--r--lib/Format/FormatTokenLexer.cpp20
-rw-r--r--lib/Format/FormatTokenLexer.h1
-rw-r--r--lib/Format/NamespaceEndCommentsFixer.cpp16
-rw-r--r--lib/Format/TokenAnnotator.cpp132
-rw-r--r--lib/Format/TokenAnnotator.h3
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp63
-rw-r--r--lib/Format/UnwrappedLineParser.cpp41
-rw-r--r--lib/Format/UnwrappedLineParser.h2
-rw-r--r--lib/Format/WhitespaceManager.cpp41
14 files changed, 468 insertions, 147 deletions
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index 72886ed00736..09ea5473c0c1 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -342,8 +342,8 @@ BreakableBlockComment::BreakableBlockComment(
StringRef TokenText(Tok.TokenText);
assert(TokenText.startswith("/*") && TokenText.endswith("*/"));
- TokenText.substr(2, TokenText.size() - 4).split(Lines,
- UseCRLF ? "\r\n" : "\n");
+ TokenText.substr(2, TokenText.size() - 4)
+ .split(Lines, UseCRLF ? "\r\n" : "\n");
int IndentDelta = StartColumn - OriginalStartColumn;
Content.resize(Lines.size());
@@ -456,10 +456,9 @@ BreakableBlockComment::BreakableBlockComment(
});
}
-BreakableToken::Split
-BreakableBlockComment::getSplit(unsigned LineIndex, unsigned TailOffset,
- unsigned ColumnLimit, unsigned ContentStartColumn,
- llvm::Regex &CommentPragmasRegex) const {
+BreakableToken::Split BreakableBlockComment::getSplit(
+ unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
+ unsigned ContentStartColumn, llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index b04ede6fa939..2ff6e5ec2344 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -473,7 +473,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
}
// If the return type spans multiple lines, wrap before the function name.
- if ((Current.is(TT_FunctionDeclarationName) ||
+ if (((Current.is(TT_FunctionDeclarationName) &&
+ // Don't break before a C# function when no break after return type
+ (!Style.isCSharp() ||
+ Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None)) ||
(Current.is(tok::kw_operator) && !Previous.is(tok::coloncolon))) &&
!Previous.is(tok::kw_template) && State.Stack.back().BreakBeforeParameter)
return true;
@@ -606,7 +609,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
// disallowing any further line breaks if there is no line break after the
// opening parenthesis. Don't break if it doesn't conserve columns.
if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak &&
- Previous.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
+ (Previous.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) ||
+ (Previous.is(tok::l_brace) && Previous.BlockKind != BK_Block &&
+ Style.Cpp11BracedListStyle)) &&
State.Column > getNewLineColumn(State) &&
(!Previous.Previous || !Previous.Previous->isOneOf(
tok::kw_for, tok::kw_while, tok::kw_switch)) &&
@@ -676,8 +681,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
State.Column += Spaces;
if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) &&
Previous.Previous &&
- (Previous.Previous->isOneOf(tok::kw_if, tok::kw_for) ||
- Previous.Previous->endsSequence(tok::kw_constexpr, tok::kw_if))) {
+ (Previous.Previous->is(tok::kw_for) || Previous.Previous->isIf())) {
// Treat the condition inside an if as if it was a second function
// parameter, i.e. let nested calls have a continuation indent.
State.Stack.back().LastSpace = State.Column;
@@ -930,6 +934,11 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return std::max(State.Stack.back().LastSpace,
State.Stack.back().Indent + Style.ContinuationIndentWidth);
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
+ State.Line->First->is(tok::kw_enum))
+ return (Style.IndentWidth * State.Line->First->IndentLevel) +
+ Style.IndentWidth;
+
if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block)
return Current.NestingLevel == 0 ? State.FirstIndent
: State.Stack.back().Indent;
@@ -1796,7 +1805,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
unsigned UnbreakableTailLength = (State.NextToken && canBreak(State))
? 0
: Current.UnbreakableTailLength;
- return llvm::make_unique<BreakableStringLiteral>(
+ return std::make_unique<BreakableStringLiteral>(
Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
State.Line->InPPDirective, Encoding, Style);
}
@@ -1808,7 +1817,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
switchesFormatting(Current)) {
return nullptr;
}
- return llvm::make_unique<BreakableBlockComment>(
+ return std::make_unique<BreakableBlockComment>(
Current, StartColumn, Current.OriginalColumn, !Current.Previous,
State.Line->InPPDirective, Encoding, Style, Whitespaces.useCRLF());
} else if (Current.is(TT_LineComment) &&
@@ -1818,7 +1827,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
switchesFormatting(Current))
return nullptr;
- return llvm::make_unique<BreakableLineCommentSection>(
+ return std::make_unique<BreakableLineCommentSection>(
Current, StartColumn, Current.OriginalColumn, !Current.Previous,
/*InPPDirective=*/false, Encoding, Style);
}
diff --git a/lib/Format/Encoding.h b/lib/Format/Encoding.h
index fe3d5f019858..a0d664121b2b 100644
--- a/lib/Format/Encoding.h
+++ b/lib/Format/Encoding.h
@@ -67,7 +67,8 @@ inline unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn,
if (TabPos == StringRef::npos)
return TotalWidth + columnWidth(Tail, Encoding);
TotalWidth += columnWidth(Tail.substr(0, TabPos), Encoding);
- TotalWidth += TabWidth - (TotalWidth + StartColumn) % TabWidth;
+ if (TabWidth)
+ TotalWidth += TabWidth - (TotalWidth + StartColumn) % TabWidth;
Tail = Tail.substr(TabPos + 1);
}
}
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index c48182976b04..cd44c0be85f0 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -67,10 +67,19 @@ template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
- IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
- IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
- IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
- IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
+ IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
+ IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
+ IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
+
+ IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
+ IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
+
+ IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
+ IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
+ IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
+
+ IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
+ IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
}
};
@@ -95,6 +104,16 @@ template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
+ static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
+ IO.enumCase(Value, "false", FormatStyle::SBS_Never);
+ IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
+ IO.enumCase(Value, "true", FormatStyle::SBS_Always);
+ IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::SFS_None);
@@ -155,6 +174,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
+ IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
@@ -162,6 +182,20 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
};
template <>
+struct ScalarEnumerationTraits<
+ FormatStyle::BraceWrappingAfterControlStatementStyle> {
+ static void
+ enumeration(IO &IO,
+ FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
+ IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
+ IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
+ IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
+ IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
+ IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
static void
enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
@@ -443,6 +477,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
+ IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
@@ -494,6 +529,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
Style.SpaceBeforeRangeBasedForLoopColon);
+ IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
@@ -607,9 +643,12 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
return Style;
FormatStyle Expanded = Style;
- Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false,
- false, false, true, true, true};
+ Expanded.BraceWrapping = {false, false, FormatStyle::BWACS_Never,
+ false, false, false,
+ false, false, false,
+ false, false, false,
+ false, true, true,
+ true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -634,7 +673,21 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
case FormatStyle::BS_Allman:
Expanded.BraceWrapping.AfterCaseLabel = true;
Expanded.BraceWrapping.AfterClass = true;
- Expanded.BraceWrapping.AfterControlStatement = true;
+ Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
+ Expanded.BraceWrapping.AfterEnum = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterNamespace = true;
+ Expanded.BraceWrapping.AfterObjCDeclaration = true;
+ Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.AfterUnion = true;
+ Expanded.BraceWrapping.AfterExternBlock = true;
+ Expanded.BraceWrapping.BeforeCatch = true;
+ Expanded.BraceWrapping.BeforeElse = true;
+ break;
+ case FormatStyle::BS_Whitesmiths:
+ Expanded.BraceWrapping.AfterCaseLabel = true;
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
Expanded.BraceWrapping.AfterEnum = true;
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterNamespace = true;
@@ -645,8 +698,12 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.BeforeElse = true;
break;
case FormatStyle::BS_GNU:
- Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
- true, true, true, true, true, true, true, true};
+ Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always,
+ true, true, true,
+ true, true, true,
+ true, true, true,
+ true, true, true,
+ true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -672,7 +729,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AllowAllConstructorInitializersOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
- LLVMStyle.AllowShortBlocksOnASingleLine = false;
+ LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
@@ -686,9 +743,12 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
- LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false,
- false, false, true, true, true};
+ LLVMStyle.BraceWrapping = {false, false, FormatStyle::BWACS_Never,
+ false, false, false,
+ false, false, false,
+ false, false, false,
+ false, true, true,
+ true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
@@ -707,12 +767,13 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IncludeStyle.IncludeCategories = {
- {"^\"(llvm|llvm-c|clang|clang-c)/", 2},
- {"^(<|\"(gtest|gmock|isl|json)/)", 3},
- {".*", 1}};
+ {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0},
+ {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0},
+ {".*", 1, 0}};
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
LLVMStyle.IndentCaseLabels = false;
+ LLVMStyle.IndentGotoLabels = true;
LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
@@ -728,11 +789,12 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
LLVMStyle.SpacesBeforeTrailingComments = 1;
- LLVMStyle.Standard = FormatStyle::LS_Cpp11;
+ LLVMStyle.Standard = FormatStyle::LS_Latest;
LLVMStyle.UseTab = FormatStyle::UT_Never;
LLVMStyle.ReflowComments = true;
LLVMStyle.SpacesInParentheses = false;
LLVMStyle.SpacesInSquareBrackets = false;
+ LLVMStyle.SpaceInEmptyBlock = false;
LLVMStyle.SpaceInEmptyParentheses = false;
LLVMStyle.SpacesInContainerLiterals = true;
LLVMStyle.SpacesInCStyleCastParentheses = false;
@@ -789,8 +851,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
GoogleStyle.DerivePointerAlignment = true;
- GoogleStyle.IncludeStyle.IncludeCategories = {
- {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
+ GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0},
+ {"^<.*\\.h>", 1, 0},
+ {"^<.*", 2, 0},
+ {".*", 3, 0}};
GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
GoogleStyle.IndentCaseLabels = true;
@@ -897,6 +961,27 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
FormatStyle ChromiumStyle = getGoogleStyle(Language);
+
+ // Disable include reordering across blocks in Chromium code.
+ // - clang-format tries to detect that foo.h is the "main" header for
+ // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
+ // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
+ // _private.cc, _impl.cc etc) in different permutations
+ // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
+ // better default for Chromium code.
+ // - The default for .cc and .mm files is different (r357695) for Google style
+ // for the same reason. The plan is to unify this again once the main
+ // header detection works for Google's ObjC code, but this hasn't happened
+ // yet. Since Chromium has some ObjC code, switching Chromium is blocked
+ // on that.
+ // - Finally, "If include reordering is harmful, put things in different
+ // blocks to prevent it" has been a recommendation for a long time that
+ // people are used to. We'll need a dev education push to change this to
+ // "If include reordering is harmful, put things in a different block and
+ // _prepend that with a comment_ to prevent it" before changing behavior.
+ ChromiumStyle.IncludeStyle.IncludeBlocks =
+ tooling::IncludeStyle::IBS_Preserve;
+
if (Language == FormatStyle::LK_Java) {
ChromiumStyle.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
@@ -966,6 +1051,7 @@ FormatStyle getWebKitStyle() {
Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Style.AlignOperands = false;
Style.AlignTrailingComments = false;
+ Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
@@ -978,6 +1064,7 @@ FormatStyle getWebKitStyle() {
Style.ObjCSpaceAfterProperty = true;
Style.PointerAlignment = FormatStyle::PAS_Left;
Style.SpaceBeforeCpp11BracedList = true;
+ Style.SpaceInEmptyBlock = true;
return Style;
}
@@ -997,14 +1084,14 @@ FormatStyle getGNUStyle() {
}
FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
- FormatStyle Style = getLLVMStyle();
+ FormatStyle Style = getLLVMStyle(Language);
Style.ColumnLimit = 120;
Style.TabWidth = 4;
Style.IndentWidth = 4;
Style.UseTab = FormatStyle::UT_Never;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterClass = true;
- Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
Style.BraceWrapping.AfterEnum = true;
Style.BraceWrapping.AfterFunction = true;
Style.BraceWrapping.AfterNamespace = true;
@@ -1015,10 +1102,11 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
Style.BraceWrapping.BeforeElse = true;
Style.PenaltyReturnTypeOnItsOwnLine = 1000;
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
- Style.AllowShortBlocksOnASingleLine = false;
Style.AllowShortCaseLabelsOnASingleLine = false;
Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
Style.AllowShortLoopsOnASingleLine = false;
+ Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
return Style;
}
@@ -1346,7 +1434,7 @@ private:
: FormatStyle::PAS_Right;
if (Style.Standard == FormatStyle::LS_Auto)
Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
- ? FormatStyle::LS_Cpp11
+ ? FormatStyle::LS_Latest
: FormatStyle::LS_Cpp03;
BinPackInconclusiveFunctions =
HasBinPackedFunction || !HasOnePerLineFunction;
@@ -1380,22 +1468,29 @@ public:
checkEmptyNamespace(AnnotatedLines);
- for (auto &Line : AnnotatedLines) {
- if (Line->Affected) {
- cleanupRight(Line->First, tok::comma, tok::comma);
- cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
- cleanupRight(Line->First, tok::l_paren, tok::comma);
- cleanupLeft(Line->First, tok::comma, tok::r_paren);
- cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
- cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
- cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
- }
- }
+ for (auto *Line : AnnotatedLines)
+ cleanupLine(Line);
return {generateFixes(), 0};
}
private:
+ void cleanupLine(AnnotatedLine *Line) {
+ for (auto *Child : Line->Children) {
+ cleanupLine(Child);
+ }
+
+ if (Line->Affected) {
+ cleanupRight(Line->First, tok::comma, tok::comma);
+ cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
+ cleanupRight(Line->First, tok::l_paren, tok::comma);
+ cleanupLeft(Line->First, tok::comma, tok::r_paren);
+ cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
+ cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
+ cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
+ }
+ }
+
bool containsOnlyComments(const AnnotatedLine &Line) {
for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) {
if (Tok->isNot(tok::comment))
@@ -1685,10 +1780,11 @@ private:
std::end(FoundationIdentifiers),
FormatTok->TokenText)) ||
FormatTok->is(TT_ObjCStringLiteral) ||
- FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
- TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
- TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
- TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
+ FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
+ Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
+ TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
+ TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
+ TT_ObjCProperty)) {
LLVM_DEBUG(llvm::dbgs()
<< "Detected ObjC at location "
<< FormatTok->Tok.getLocation().printToString(
@@ -1712,6 +1808,7 @@ struct IncludeDirective {
StringRef Text;
unsigned Offset;
int Category;
+ int Priority;
};
struct JavaImportDirective {
@@ -1763,6 +1860,28 @@ FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
return std::make_pair(CursorIndex, OffsetToEOL);
}
+// Replace all "\r\n" with "\n".
+std::string replaceCRLF(const std::string &Code) {
+ std::string NewCode;
+ size_t Pos = 0, LastPos = 0;
+
+ do {
+ Pos = Code.find("\r\n", LastPos);
+ if (Pos == LastPos) {
+ LastPos++;
+ continue;
+ }
+ if (Pos == std::string::npos) {
+ NewCode += Code.substr(LastPos);
+ break;
+ }
+ NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
+ LastPos = Pos + 2;
+ } while (Pos != std::string::npos);
+
+ return NewCode;
+}
+
// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
// source order.
@@ -1773,8 +1892,9 @@ FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
static void sortCppIncludes(const FormatStyle &Style,
const SmallVectorImpl<IncludeDirective> &Includes,
ArrayRef<tooling::Range> Ranges, StringRef FileName,
- StringRef Code,
- tooling::Replacements &Replaces, unsigned *Cursor) {
+ StringRef Code, tooling::Replacements &Replaces,
+ unsigned *Cursor) {
+ tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
unsigned IncludesBeginOffset = Includes.front().Offset;
unsigned IncludesEndOffset =
Includes.back().Offset + Includes.back().Text.size();
@@ -1782,11 +1902,12 @@ static void sortCppIncludes(const FormatStyle &Style,
if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
return;
SmallVector<unsigned, 16> Indices;
- for (unsigned i = 0, e = Includes.size(); i != e; ++i)
+ for (unsigned i = 0, e = Includes.size(); i != e; ++i) {
Indices.push_back(i);
+ }
llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
- return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
+ return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
});
// The index of the include on which the cursor will be put after
// sorting/deduplicating.
@@ -1834,7 +1955,8 @@ static void sortCppIncludes(const FormatStyle &Style,
// If the #includes are out of order, we generate a single replacement fixing
// the entire range of blocks. Otherwise, no replacement is generated.
- if (result == Code.substr(IncludesBeginOffset, IncludesBlockSize))
+ if (replaceCRLF(result) ==
+ replaceCRLF(Code.substr(IncludesBeginOffset, IncludesBlockSize)))
return;
auto Err = Replaces.add(tooling::Replacement(
@@ -1901,9 +2023,12 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
int Category = Categories.getIncludePriority(
IncludeName,
/*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
+ int Priority = Categories.getSortIncludePriority(
+ IncludeName, !MainIncludeFound && FirstIncludeBlock);
if (Category == 0)
MainIncludeFound = true;
- IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
+ IncludesInBlock.push_back(
+ {IncludeName, Line, Prev, Category, Priority});
} else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
Replaces, Cursor);
@@ -1999,7 +2124,8 @@ static void sortJavaImports(const FormatStyle &Style,
// If the imports are out of order, we generate a single replacement fixing
// the entire block. Otherwise, no replacement is generated.
- if (result == Code.substr(Imports.front().Offset, ImportsBlockSize))
+ if (replaceCRLF(result) ==
+ replaceCRLF(Code.substr(Imports.front().Offset, ImportsBlockSize)))
return;
auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
@@ -2288,8 +2414,8 @@ reformat(const FormatStyle &Style, StringRef Code,
});
auto Env =
- llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
- NextStartColumn, LastStartColumn);
+ std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
+ NextStartColumn, LastStartColumn);
llvm::Optional<std::string> CurrentCode = None;
tooling::Replacements Fixes;
unsigned Penalty = 0;
@@ -2302,7 +2428,7 @@ reformat(const FormatStyle &Style, StringRef Code,
Penalty += PassFixes.second;
if (I + 1 < E) {
CurrentCode = std::move(*NewCode);
- Env = llvm::make_unique<Environment>(
+ Env = std::make_unique<Environment>(
*CurrentCode, FileName,
tooling::calculateRangesAfterReplacements(Fixes, Ranges),
FirstStartColumn, NextStartColumn, LastStartColumn);
@@ -2364,11 +2490,18 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOptions LangOpts;
+
+ FormatStyle::LanguageStandard LexingStd = Style.Standard;
+ if (LexingStd == FormatStyle::LS_Auto)
+ LexingStd = FormatStyle::LS_Latest;
+ if (LexingStd == FormatStyle::LS_Latest)
+ LexingStd = FormatStyle::LS_Cpp20;
LangOpts.CPlusPlus = 1;
- LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
- LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
- LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
- LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
+ LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
+ LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
+ LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
+ LangOpts.CPlusPlus2a = LexingStd >= FormatStyle::LS_Cpp20;
+
LangOpts.LineComment = 1;
bool AlternativeOperators = Style.isCpp();
LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
@@ -2393,8 +2526,9 @@ const char *StyleOptionHelpDescription =
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
if (FileName.endswith(".java"))
return FormatStyle::LK_Java;
- if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts"))
- return FormatStyle::LK_JavaScript; // JavaScript or TypeScript.
+ if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") ||
+ FileName.endswith_lower(".ts"))
+ return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
if (FileName.endswith(".m") || FileName.endswith(".mm"))
return FormatStyle::LK_ObjC;
if (FileName.endswith_lower(".proto") ||
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index df7493742025..b11f36559a8b 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -327,6 +327,11 @@ struct FormatToken {
}
template <typename T> bool isNot(T Kind) const { return !is(Kind); }
+ bool isIf(bool AllowConstexprMacro = true) const {
+ return is(tok::kw_if) || endsSequence(tok::kw_constexpr, tok::kw_if) ||
+ (endsSequence(tok::identifier, tok::kw_if) && AllowConstexprMacro);
+ }
+
bool closesScopeAfterBlock() const {
if (BlockKind == BK_Block)
return true;
@@ -344,6 +349,10 @@ struct FormatToken {
/// \c true if this token ends a sequence with the given tokens in order,
/// following the ``Previous`` pointers, ignoring comments.
+ /// For example, given tokens [T1, T2, T3], the function returns true if
+ /// 3 tokens ending at this (ignoring comments) are [T3, T2, T1]. In other
+ /// words, the tokens passed to this function need to the reverse of the
+ /// order the tokens appear in code.
template <typename A, typename... Ts>
bool endsSequence(A K1, Ts... Tokens) const {
return endsSequenceInternal(K1, Tokens...);
@@ -677,8 +686,10 @@ struct AdditionalKeywords {
kw_override = &IdentTable.get("override");
kw_in = &IdentTable.get("in");
kw_of = &IdentTable.get("of");
+ kw_CF_CLOSED_ENUM = &IdentTable.get("CF_CLOSED_ENUM");
kw_CF_ENUM = &IdentTable.get("CF_ENUM");
kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS");
+ kw_NS_CLOSED_ENUM = &IdentTable.get("NS_CLOSED_ENUM");
kw_NS_ENUM = &IdentTable.get("NS_ENUM");
kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS");
@@ -787,8 +798,10 @@ struct AdditionalKeywords {
IdentifierInfo *kw_override;
IdentifierInfo *kw_in;
IdentifierInfo *kw_of;
+ IdentifierInfo *kw_CF_CLOSED_ENUM;
IdentifierInfo *kw_CF_ENUM;
IdentifierInfo *kw_CF_OPTIONS;
+ IdentifierInfo *kw_NS_CLOSED_ENUM;
IdentifierInfo *kw_NS_ENUM;
IdentifierInfo *kw_NS_OPTIONS;
IdentifierInfo *kw___except;
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 009b8849753c..5d8a77577c0b 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -80,6 +80,8 @@ void FormatTokenLexer::tryMergePreviousTokens() {
return;
if (tryMergeCSharpNullConditionals())
return;
+ if (tryTransformCSharpForEach())
+ return;
static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater};
if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
return;
@@ -254,6 +256,21 @@ bool FormatTokenLexer::tryMergeCSharpNullConditionals() {
return true;
}
+// In C# transform identifier foreach into kw_foreach
+bool FormatTokenLexer::tryTransformCSharpForEach() {
+ if (Tokens.size() < 1)
+ return false;
+ auto &Identifier = *(Tokens.end() - 1);
+ if (!Identifier->is(tok::identifier))
+ return false;
+ if (Identifier->TokenText != "foreach")
+ return false;
+
+ Identifier->Type = TT_ForEachMacro;
+ Identifier->Tok.setKind(tok::kw_for);
+ return true;
+}
+
bool FormatTokenLexer::tryMergeLessLess() {
// Merge X,less,less,Y into X,lessless,Y unless X or Y is less.
if (Tokens.size() < 3)
@@ -657,7 +674,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
++Column;
break;
case '\t':
- Column += Style.TabWidth - Column % Style.TabWidth;
+ Column +=
+ Style.TabWidth - (Style.TabWidth ? Column % Style.TabWidth : 0);
break;
case '\\':
if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n'))
diff --git a/lib/Format/FormatTokenLexer.h b/lib/Format/FormatTokenLexer.h
index 1e096fc50205..611211be055a 100644
--- a/lib/Format/FormatTokenLexer.h
+++ b/lib/Format/FormatTokenLexer.h
@@ -53,6 +53,7 @@ private:
bool tryMergeCSharpKeywordVariables();
bool tryMergeCSharpNullConditionals();
bool tryMergeCSharpDoubleQuestion();
+ bool tryTransformCSharpForEach();
bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);
diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp
index d04fc8f115fb..98901cff2681 100644
--- a/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -36,7 +36,7 @@ std::string computeName(const FormatToken *NamespaceTok) {
const FormatToken *Tok = NamespaceTok->getNextNonComment();
if (NamespaceTok->is(TT_NamespaceMacro)) {
// Collects all the non-comment tokens between opening parenthesis
- // and closing parenthesis or comma
+ // and closing parenthesis or comma.
assert(Tok && Tok->is(tok::l_paren) && "expected an opening parenthesis");
Tok = Tok->getNextNonComment();
while (Tok && !Tok->isOneOf(tok::r_paren, tok::comma)) {
@@ -44,9 +44,21 @@ std::string computeName(const FormatToken *NamespaceTok) {
Tok = Tok->getNextNonComment();
}
} else {
- // Collects all the non-comment tokens between 'namespace' and '{'.
+ // For `namespace [[foo]] A::B::inline C {` or
+ // `namespace MACRO1 MACRO2 A::B::inline C {`, returns "A::B::inline C".
+ // Peek for the first '::' (or '{') and then return all tokens from one
+ // token before that up until the '{'.
+ const FormatToken *FirstNSTok = Tok;
+ while (Tok && !Tok->is(tok::l_brace) && !Tok->is(tok::coloncolon)) {
+ FirstNSTok = Tok;
+ Tok = Tok->getNextNonComment();
+ }
+
+ Tok = FirstNSTok;
while (Tok && !Tok->is(tok::l_brace)) {
name += Tok->TokenText;
+ if (Tok->is(tok::kw_inline))
+ name += " ";
Tok = Tok->getNextNonComment();
}
}
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 490c4f46135e..1ed35597d075 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -15,6 +15,7 @@
#include "TokenAnnotator.h"
#include "FormatToken.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
@@ -40,6 +41,21 @@ static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
return Tok.Tok.getIdentifierInfo() != nullptr;
}
+/// With `Left` being '(', check if we're at either `[...](` or
+/// `[...]<...>(`, where the [ opens a lambda capture list.
+static bool isLambdaParameterList(const FormatToken *Left) {
+ // Skip <...> if present.
+ if (Left->Previous && Left->Previous->is(tok::greater) &&
+ Left->Previous->MatchingParen &&
+ Left->Previous->MatchingParen->is(TT_TemplateOpener))
+ Left = Left->Previous->MatchingParen;
+
+ // Check for `[...]`.
+ return Left->Previous && Left->Previous->is(tok::r_square) &&
+ Left->Previous->MatchingParen &&
+ Left->Previous->MatchingParen->is(TT_LambdaLSquare);
+}
+
/// A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
@@ -175,9 +191,9 @@ private:
Contexts.back().IsExpression = false;
} else if (Left->Previous &&
(Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
- tok::kw_if, tok::kw_while, tok::l_paren,
+ tok::kw_while, tok::l_paren,
tok::comma) ||
- Left->Previous->endsSequence(tok::kw_constexpr, tok::kw_if) ||
+ Left->Previous->isIf() ||
Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
@@ -191,9 +207,7 @@ private:
Left->Previous->is(TT_JsTypeColon)) {
// let x: (SomeType);
Contexts.back().IsExpression = false;
- } else if (Left->Previous && Left->Previous->is(tok::r_square) &&
- Left->Previous->MatchingParen &&
- Left->Previous->MatchingParen->is(TT_LambdaLSquare)) {
+ } else if (isLambdaParameterList(Left)) {
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
} else if (Line.InPPDirective &&
@@ -382,6 +396,12 @@ private:
Keywords.kw_internal)) {
return true;
}
+
+ // incase its a [XXX] retval func(....
+ if (AttrTok->Next &&
+ AttrTok->Next->startsSequence(tok::identifier, tok::l_paren))
+ return true;
+
return false;
}
@@ -476,6 +496,8 @@ private:
} else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->Type = TT_DesignatedInitializerLSquare;
+ } else if (IsCSharp11AttributeSpecifier) {
+ Left->Type = TT_AttributeSquare;
} else if (CurrentToken->is(tok::r_square) && Parent &&
Parent->is(TT_TemplateCloser)) {
Left->Type = TT_ArraySubscriptLSquare;
@@ -523,8 +545,6 @@ private:
// Should only be relevant to JavaScript:
tok::kw_default)) {
Left->Type = TT_ArrayInitializerLSquare;
- } else if (IsCSharp11AttributeSpecifier) {
- Left->Type = TT_AttributeSquare;
} else {
BindingIncrease = 10;
Left->Type = TT_ArraySubscriptLSquare;
@@ -826,7 +846,7 @@ private:
case tok::kw_if:
case tok::kw_while:
if (Tok->is(tok::kw_if) && CurrentToken &&
- CurrentToken->is(tok::kw_constexpr))
+ CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier))
next();
if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
@@ -918,6 +938,8 @@ private:
case tok::greater:
if (Style.Language != FormatStyle::LK_TextProto)
Tok->Type = TT_BinaryOperator;
+ if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))
+ Tok->SpacesRequiredBefore = 1;
break;
case tok::kw_operator:
if (Style.Language == FormatStyle::LK_TextProto ||
@@ -1078,6 +1100,7 @@ private:
case tok::pp_if:
case tok::pp_elif:
Contexts.back().IsExpression = true;
+ next();
parseLine();
break;
default:
@@ -1097,6 +1120,8 @@ private:
public:
LineType parseLine() {
+ if (!CurrentToken)
+ return LT_Invalid;
NonTemplateLess.clear();
if (CurrentToken->is(tok::hash))
return parsePreprocessorDirective();
@@ -1368,7 +1393,9 @@ private:
Style.Language == FormatStyle::LK_Java) {
Current.Type = TT_LambdaArrow;
} else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration &&
- Current.NestingLevel == 0) {
+ Current.NestingLevel == 0 &&
+ !Current.Previous->is(tok::kw_operator)) {
+ // not auto operator->() -> xxx;
Current.Type = TT_TrailingReturnArrow;
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
Current.Type = determineStarAmpUsage(Current,
@@ -1467,7 +1494,8 @@ private:
// colon after this, this is the only place which annotates the identifier
// as a selector.)
Current.Type = TT_SelectorName;
- } else if (Current.isOneOf(tok::identifier, tok::kw_const) &&
+ } else if (Current.isOneOf(tok::identifier, tok::kw_const,
+ tok::kw_noexcept) &&
Current.Previous &&
!Current.Previous->isOneOf(tok::equal, tok::at) &&
Line.MightBeFunctionDecl && Contexts.size() == 1) {
@@ -1576,6 +1604,14 @@ private:
if (Tok.Next->is(tok::question))
return false;
+ // Functions which end with decorations like volatile, noexcept are unlikely
+ // to be casts.
+ if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
+ tok::kw_throw, tok::arrow, Keywords.kw_override,
+ Keywords.kw_final) ||
+ isCpp11AttributeSpecifier(*Tok.Next))
+ return false;
+
// As Java has no function types, a "(" after the ")" likely means that this
// is a cast.
if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
@@ -1647,7 +1683,8 @@ private:
const FormatToken *NextToken = Tok.getNextNonComment();
if (!NextToken ||
- NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_const) ||
+ NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_const,
+ tok::kw_noexcept) ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
return TT_PointerOrReference;
@@ -1720,7 +1757,7 @@ private:
// Use heuristics to recognize unary operators.
if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square,
tok::question, tok::colon, tok::kw_return,
- tok::kw_case, tok::at, tok::l_brace))
+ tok::kw_case, tok::at, tok::l_brace, tok::kw_throw))
return TT_UnaryOperator;
// There can't be two consecutive binary operators.
@@ -2160,7 +2197,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
if (Current->is(TT_LineComment)) {
if (Current->Previous->BlockKind == BK_BracedInit &&
Current->Previous->opensScope())
- Current->SpacesRequiredBefore = Style.Cpp11BracedListStyle ? 0 : 1;
+ Current->SpacesRequiredBefore =
+ (Style.Cpp11BracedListStyle && !Style.SpacesInParentheses) ? 0 : 1;
else
Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
@@ -2409,8 +2447,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
return 100;
if (Left.is(tok::l_paren) && Left.Previous &&
- (Left.Previous->isOneOf(tok::kw_if, tok::kw_for) ||
- Left.Previous->endsSequence(tok::kw_constexpr, tok::kw_if)))
+ (Left.Previous->is(tok::kw_for) || Left.Previous->isIf()))
return 1000;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
@@ -2429,6 +2466,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(TT_JavaAnnotation))
return 50;
+ if (Left.is(TT_UnaryOperator))
+ return 60;
if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&
Left.Previous->isLabelString() &&
(Left.NextOperator || Left.OperatorIndex != 0))
@@ -2483,7 +2522,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Left.is(tok::hash);
if (Left.isOneOf(tok::hashhash, tok::hash))
return Right.is(tok::hash);
- if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
+ if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
+ (Left.is(tok::l_brace) && Left.BlockKind != BK_Block &&
+ Right.is(tok::r_brace) && Right.BlockKind != BK_Block))
return Style.SpaceInEmptyParentheses;
if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
return (Right.is(TT_CastRParen) ||
@@ -2560,7 +2601,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Style.PointerAlignment != FormatStyle::PAS_Right &&
!Line.IsMultiVariableDeclStmt) &&
Left.Previous &&
- !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
+ !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon,
+ tok::l_square));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
const auto SpaceRequiredForArrayInitializerLSquare =
@@ -2575,8 +2617,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::l_square))
return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
- (Left.isOneOf(TT_ArraySubscriptLSquare,
- TT_StructuredBindingLSquare) &&
+ (Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare,
+ TT_LambdaLSquare) &&
Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
if (Right.is(tok::r_square))
return Right.MatchingParen &&
@@ -2585,7 +2627,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Style)) ||
(Style.SpacesInSquareBrackets &&
Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
- TT_StructuredBindingLSquare)) ||
+ TT_StructuredBindingLSquare,
+ TT_LambdaLSquare)) ||
Right.MatchingParen->is(TT_AttributeParen));
if (Right.is(tok::l_square) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
@@ -2598,7 +2641,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if ((Left.is(tok::l_brace) && Left.BlockKind != BK_Block) ||
(Right.is(tok::r_brace) && Right.MatchingParen &&
Right.MatchingParen->BlockKind != BK_Block))
- return !Style.Cpp11BracedListStyle;
+ return Style.Cpp11BracedListStyle ? Style.SpacesInParentheses : true;
if (Left.is(TT_BlockComment))
// No whitespace in x(/*foo=*/1), except for JavaScript.
return Style.Language == FormatStyle::LK_JavaScript ||
@@ -2609,10 +2652,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return true;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
- (Left.isOneOf(tok::kw_if, tok::pp_elif, tok::kw_for, tok::kw_while,
+ (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,
tok::kw_switch, tok::kw_case, TT_ForEachMacro,
TT_ObjCForIn) ||
- Left.endsSequence(tok::kw_constexpr, tok::kw_if) ||
+ Left.isIf(Line.Type != LT_PreprocessorDirective) ||
(Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
tok::kw_new, tok::kw_delete) &&
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
@@ -2655,6 +2698,14 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at))
// Objective-C dictionary literal -> no space before closing brace.
return false;
+ if (Right.Type == TT_TrailingAnnotation &&
+ Right.isOneOf(tok::amp, tok::ampamp) &&
+ Left.isOneOf(tok::kw_const, tok::kw_volatile) &&
+ (!Right.Next || Right.Next->is(tok::semi)))
+ // Match const and volatile ref-qualifiers without any additional
+ // qualifiers such as
+ // void Fn() const &;
+ return Style.PointerAlignment != FormatStyle::PAS_Left;
return true;
}
@@ -2694,7 +2745,15 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// and "%d %d"
if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
return Right.WhitespaceRange.getEnd() != Right.WhitespaceRange.getBegin();
- } else if (Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) {
+ } else if (Style.isCSharp()) {
+ // space between type and variable e.g. Dictionary<string,string> foo;
+ if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))
+ return true;
+ // space between keywords and paren e.g. "using ("
+ if (Right.is(tok::l_paren))
+ if (Left.is(tok::kw_using))
+ return spaceRequiredBeforeParens(Left);
+ } else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
// for await ( ...
@@ -2739,6 +2798,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
tok::kw_void))
return true;
}
+ // `foo as const;` casts into a const type.
+ if (Left.endsSequence(tok::kw_const, Keywords.kw_as)) {
+ return false;
+ }
if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
tok::kw_const) ||
// "of" is only a keyword if it appears after another identifier
@@ -2842,9 +2905,19 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
return true;
}
- if (Left.is(TT_UnaryOperator))
+ if (Left.is(TT_UnaryOperator)) {
+ // The alternative operators for ~ and ! are "compl" and "not".
+ // If they are used instead, we do not want to combine them with
+ // the token to the right, unless that is a left paren.
+ if (!Right.is(tok::l_paren)) {
+ if (Left.is(tok::exclaim) && Left.TokenText == "not")
+ return true;
+ if (Left.is(tok::tilde) && Left.TokenText == "compl")
+ return true;
+ }
return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
Right.is(TT_BinaryOperator);
+ }
// If the next token is a binary operator or a selector name, we have
// incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
@@ -2857,13 +2930,13 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
(Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
return !Style.Cpp11BracedListStyle;
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
- (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
+ (Style.Standard < FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
}
if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
(Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
return false;
- if (!Style.SpaceBeforeAssignmentOperators &&
+ if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&
Right.getPrecedence() == prec::Assignment)
return false;
if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) &&
@@ -2876,7 +2949,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment))
return (Left.is(TT_TemplateOpener) &&
- Style.Standard == FormatStyle::LS_Cpp03) ||
+ Style.Standard < FormatStyle::LS_Cpp11) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
tok::kw___super, TT_TemplateCloser,
TT_TemplateOpener)) ||
@@ -3039,7 +3112,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Style.BraceWrapping.AfterEnum) ||
(Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
(Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
- if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine)
+ if (Left.is(TT_ObjCBlockLBrace) &&
+ Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
return true;
if (Left.is(TT_LambdaLBrace)) {
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index 702ac6c0d76e..537710029b00 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -114,8 +114,7 @@ public:
/// \c true if this line starts a namespace definition.
bool startsWithNamespace() const {
- return startsWith(tok::kw_namespace) ||
- startsWith(TT_NamespaceMacro) ||
+ return startsWith(tok::kw_namespace) || startsWith(TT_NamespaceMacro) ||
startsWith(tok::kw_inline, tok::kw_namespace) ||
startsWith(tok::kw_export, tok::kw_namespace);
}
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 3f3c80bc1ccf..8b8d357d9cbe 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -300,14 +300,30 @@ private:
// Try to merge a control statement block with left brace unwrapped
if (TheLine->Last->is(tok::l_brace) && TheLine->First != TheLine->Last &&
TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
- return Style.AllowShortBlocksOnASingleLine
+ return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
? tryMergeSimpleBlock(I, E, Limit)
: 0;
}
// Try to merge a control statement block with left brace wrapped
if (I[1]->First->is(tok::l_brace) &&
- TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
- return Style.BraceWrapping.AfterControlStatement
+ (TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
+ tok::kw_switch, tok::kw_try, tok::kw_do) ||
+ (TheLine->First->is(tok::r_brace) && TheLine->First->Next &&
+ TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) &&
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_MultiLine) {
+ // If possible, merge the next line's wrapped left brace with the current
+ // line. Otherwise, leave it on the next line, as this is a multi-line
+ // control statement.
+ return (Style.ColumnLimit == 0 ||
+ TheLine->Last->TotalLength <= Style.ColumnLimit)
+ ? 1
+ : 0;
+ } else if (I[1]->First->is(tok::l_brace) &&
+ TheLine->First->isOneOf(tok::kw_if, tok::kw_while,
+ tok::kw_for)) {
+ return (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
? tryMergeSimpleBlock(I, E, Limit)
: 0;
}
@@ -317,7 +333,7 @@ private:
I != AnnotatedLines.begin() &&
I[-1]->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) {
unsigned MergedLines = 0;
- if (Style.AllowShortBlocksOnASingleLine) {
+ if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never) {
MergedLines = tryMergeSimpleBlock(I - 1, E, Limit);
// If we managed to merge the block, discard the first merged line
// since we are merging starting from I.
@@ -410,8 +426,10 @@ private:
SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
if (Limit == 0)
return 0;
- if (Style.BraceWrapping.AfterControlStatement &&
- (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always &&
+ I[1]->First->is(tok::l_brace) &&
+ Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
return 0;
if (I[1]->InPPDirective != (*I)->InPPDirective ||
(I[1]->InPPDirective && I[1]->First->HasUnescapedNewline))
@@ -511,7 +529,7 @@ private:
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
tok::kw___try, tok::kw_catch, tok::kw___finally,
tok::kw_for, tok::r_brace, Keywords.kw___except)) {
- if (!Style.AllowShortBlocksOnASingleLine)
+ if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
return 0;
// Don't merge when we can't except the case when
// the control statement block is empty
@@ -522,8 +540,9 @@ private:
return 0;
if (!Style.AllowShortIfStatementsOnASingleLine &&
Line.startsWith(tok::kw_if) &&
- Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
- !I[2]->First->is(tok::r_brace))
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always &&
+ I + 2 != E && !I[2]->First->is(tok::r_brace))
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
@@ -532,8 +551,9 @@ private:
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) &&
- Style.BraceWrapping.AfterControlStatement && I + 2 != E &&
- !I[2]->First->is(tok::r_brace))
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always &&
+ I + 2 != E && !I[2]->First->is(tok::r_brace))
return 0;
// FIXME: Consider an option to allow short exception handling clauses on
// a single line.
@@ -551,7 +571,7 @@ private:
(Tok->getNextNonComment() == nullptr ||
Tok->getNextNonComment()->is(tok::semi))) {
// We merge empty blocks even if the line exceeds the column limit.
- Tok->SpacesRequiredBefore = 0;
+ Tok->SpacesRequiredBefore = Style.SpaceInEmptyBlock ? 1 : 0;
Tok->CanBreakBefore = true;
return 1;
} else if (Limit != 0 && !Line.startsWithNamespace() &&
@@ -596,6 +616,17 @@ private:
if (Tok->Next && Tok->Next->is(tok::kw_else))
return 0;
+ // Don't merge a trailing multi-line control statement block like:
+ // } else if (foo &&
+ // bar)
+ // { <-- current Line
+ // baz();
+ // }
+ if (Line.First == Line.Last &&
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_MultiLine)
+ return 0;
+
return 2;
}
} else if (I[1]->First->is(tok::l_brace)) {
@@ -607,7 +638,7 @@ private:
return 0;
Limit -= 2;
unsigned MergedLines = 0;
- if (Style.AllowShortBlocksOnASingleLine ||
+ if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
(I[1]->First == I[1]->Last && I + 2 != E &&
I[2]->First->is(tok::r_brace))) {
MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
@@ -1192,6 +1223,12 @@ void UnwrappedLineFormatter::formatFirstToken(
if (Newlines)
Indent = NewlineIndent;
+ // If in Whitemsmiths mode, indent start and end of blocks
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
+ if (RootToken.isOneOf(tok::l_brace, tok::r_brace, tok::kw_case))
+ Indent += Style.IndentWidth;
+ }
+
// Preprocessor directives get indented before the hash only if specified
if (Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
(Line.Type == LT_PreprocessorDirective ||
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index a35e98ae5503..bbe05602f6da 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -145,7 +145,7 @@ public:
else if (!Parser.Line->Tokens.empty())
Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
PreBlockLine = std::move(Parser.Line);
- Parser.Line = llvm::make_unique<UnwrappedLine>();
+ Parser.Line = std::make_unique<UnwrappedLine>();
Parser.Line->Level = PreBlockLine->Level;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
}
@@ -174,8 +174,7 @@ public:
const FormatStyle &Style, unsigned &LineLevel)
: CompoundStatementIndenter(Parser, LineLevel,
Style.BraceWrapping.AfterControlStatement,
- Style.BraceWrapping.IndentBraces) {
- }
+ Style.BraceWrapping.IndentBraces) {}
CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel,
bool WrapBrace, bool IndentBrace)
: LineLevel(LineLevel), OldLineLevel(LineLevel) {
@@ -1168,7 +1167,8 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::objc_autoreleasepool:
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BraceWrapping.AfterControlStatement)
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
}
@@ -1180,7 +1180,8 @@ void UnwrappedLineParser::parseStructuralElement() {
// Skip synchronization object
parseParens();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BraceWrapping.AfterControlStatement)
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
}
@@ -1215,7 +1216,9 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_typedef:
nextToken();
if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
- Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS))
+ Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
+ Keywords.kw_CF_CLOSED_ENUM,
+ Keywords.kw_NS_CLOSED_ENUM))
parseEnum();
break;
case tok::kw_struct:
@@ -1350,7 +1353,7 @@ void UnwrappedLineParser::parseStructuralElement() {
(TokenCount == 2 && Line->Tokens.front().Tok->is(tok::comment))) {
if (FormatTok->Tok.is(tok::colon) && !Line->MustBeDeclaration) {
Line->Tokens.begin()->Tok->MustBreakBefore = true;
- parseLabel();
+ parseLabel(!Style.IndentGotoLabels);
return;
}
// Recognize function-like macro usages without trailing semicolon as
@@ -1439,8 +1442,11 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::identifier:
case tok::numeric_constant:
case tok::coloncolon:
+ case tok::kw_class:
case tok::kw_mutable:
case tok::kw_noexcept:
+ case tok::kw_template:
+ case tok::kw_typename:
nextToken();
break;
// Specialization of a template with an integer parameter can contain
@@ -1454,6 +1460,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
// followed by an `a->b` expression, such as:
// ([obj func:arg] + a->b)
// Otherwise the code below would parse as a lambda.
+ //
+ // FIXME: This heuristic is incorrect for C++20 generic lambdas with
+ // explicit template lists: []<bool b = true && false>(U &&u){}
case tok::plus:
case tok::minus:
case tok::exclaim:
@@ -1755,7 +1764,7 @@ void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
void UnwrappedLineParser::parseIfThenElse() {
assert(FormatTok->Tok.is(tok::kw_if) && "'if' expected");
nextToken();
- if (FormatTok->Tok.is(tok::kw_constexpr))
+ if (FormatTok->Tok.isOneOf(tok::kw_constexpr, tok::identifier))
nextToken();
if (FormatTok->Tok.is(tok::l_paren))
parseParens();
@@ -1872,8 +1881,13 @@ void UnwrappedLineParser::parseNamespace() {
if (InitialToken.is(TT_NamespaceMacro)) {
parseParens();
} else {
- while (FormatTok->isOneOf(tok::identifier, tok::coloncolon))
- nextToken();
+ while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
+ tok::l_square)) {
+ if (FormatTok->is(tok::l_square))
+ parseSquare();
+ else
+ nextToken();
+ }
}
if (FormatTok->Tok.is(tok::l_brace)) {
if (ShouldBreakBeforeBrace(Style, InitialToken))
@@ -1964,18 +1978,21 @@ void UnwrappedLineParser::parseDoWhile() {
parseStructuralElement();
}
-void UnwrappedLineParser::parseLabel() {
+void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
nextToken();
unsigned OldLineLevel = Line->Level;
if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
--Line->Level;
+ if (LeftAlignLabel)
+ Line->Level = 0;
if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Line->Level,
Style.BraceWrapping.AfterCaseLabel,
Style.BraceWrapping.IndentBraces);
parseBlock(/*MustBeDeclaration=*/false);
if (FormatTok->Tok.is(tok::kw_break)) {
- if (Style.BraceWrapping.AfterControlStatement)
+ if (Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_Always)
addUnwrappedLine();
parseStructuralElement();
}
diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index e1b35317c7c0..5d9bafc429a7 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/lib/Format/UnwrappedLineParser.h
@@ -106,7 +106,7 @@ private:
void parseTryCatch();
void parseForOrWhileLoop();
void parseDoWhile();
- void parseLabel();
+ void parseLabel(bool LeftAlignLabel = false);
void parseCaseLabel();
void parseSwitch();
void parseNamespace();
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index 23fbf94c7588..5a44500d355f 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -17,8 +17,8 @@
namespace clang {
namespace format {
-bool WhitespaceManager::Change::IsBeforeInFile::
-operator()(const Change &C1, const Change &C2) const {
+bool WhitespaceManager::Change::IsBeforeInFile::operator()(
+ const Change &C1, const Change &C2) const {
return SourceMgr.isBeforeInTranslationUnit(
C1.OriginalWhitespaceRange.getBegin(),
C2.OriginalWhitespaceRange.getBegin());
@@ -815,19 +815,24 @@ void WhitespaceManager::appendIndentText(std::string &Text,
Text.append(Spaces, ' ');
break;
case FormatStyle::UT_Always: {
- unsigned FirstTabWidth =
- Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
- // Insert only spaces when we want to end up before the next tab.
- if (Spaces < FirstTabWidth || Spaces == 1) {
+ if (Style.TabWidth) {
+ unsigned FirstTabWidth =
+ Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
+
+ // Insert only spaces when we want to end up before the next tab.
+ if (Spaces < FirstTabWidth || Spaces == 1) {
+ Text.append(Spaces, ' ');
+ break;
+ }
+ // Align to the next tab.
+ Spaces -= FirstTabWidth;
+ Text.append("\t");
+
+ Text.append(Spaces / Style.TabWidth, '\t');
+ Text.append(Spaces % Style.TabWidth, ' ');
+ } else if (Spaces == 1) {
Text.append(Spaces, ' ');
- break;
}
- // Align to the next tab.
- Spaces -= FirstTabWidth;
- Text.append("\t");
-
- Text.append(Spaces / Style.TabWidth, '\t');
- Text.append(Spaces % Style.TabWidth, ' ');
break;
}
case FormatStyle::UT_ForIndentation:
@@ -837,14 +842,16 @@ void WhitespaceManager::appendIndentText(std::string &Text,
// the first one.
if (Indentation > Spaces)
Indentation = Spaces;
- unsigned Tabs = Indentation / Style.TabWidth;
- Text.append(Tabs, '\t');
- Spaces -= Tabs * Style.TabWidth;
+ if (Style.TabWidth) {
+ unsigned Tabs = Indentation / Style.TabWidth;
+ Text.append(Tabs, '\t');
+ Spaces -= Tabs * Style.TabWidth;
+ }
}
Text.append(Spaces, ' ');
break;
case FormatStyle::UT_ForContinuationAndIndentation:
- if (WhitespaceStartColumn == 0) {
+ if (WhitespaceStartColumn == 0 && Style.TabWidth) {
unsigned Tabs = Spaces / Style.TabWidth;
Text.append(Tabs, '\t');
Spaces -= Tabs * Style.TabWidth;