aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format')
-rw-r--r--clang/lib/Format/AffectedRangeManager.cpp10
-rw-r--r--clang/lib/Format/AffectedRangeManager.h4
-rw-r--r--clang/lib/Format/Format.cpp27
-rw-r--r--clang/lib/Format/FormatToken.h3
-rw-r--r--clang/lib/Format/FormatTokenLexer.cpp9
-rw-r--r--clang/lib/Format/FormatTokenLexer.h3
-rw-r--r--clang/lib/Format/MatchFilePath.cpp38
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp63
-rw-r--r--clang/lib/Format/TokenAnnotator.h8
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.cpp168
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp27
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h2
12 files changed, 274 insertions, 88 deletions
diff --git a/clang/lib/Format/AffectedRangeManager.cpp b/clang/lib/Format/AffectedRangeManager.cpp
index bf124d7..67108f3 100644
--- a/clang/lib/Format/AffectedRangeManager.cpp
+++ b/clang/lib/Format/AffectedRangeManager.cpp
@@ -21,8 +21,8 @@ namespace format {
bool AffectedRangeManager::computeAffectedLines(
SmallVectorImpl<AnnotatedLine *> &Lines) {
- SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin();
- SmallVectorImpl<AnnotatedLine *>::iterator E = Lines.end();
+ ArrayRef<AnnotatedLine *>::iterator I = Lines.begin();
+ ArrayRef<AnnotatedLine *>::iterator E = Lines.end();
bool SomeLineAffected = false;
const AnnotatedLine *PreviousLine = nullptr;
while (I != E) {
@@ -34,7 +34,7 @@ bool AffectedRangeManager::computeAffectedLines(
// if any token within the directive is affected.
if (Line->InPPDirective) {
FormatToken *Last = Line->Last;
- SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
+ const auto *PPEnd = I + 1;
while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
Last = (*PPEnd)->Last;
++PPEnd;
@@ -89,8 +89,8 @@ bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) {
}
void AffectedRangeManager::markAllAsAffected(
- SmallVectorImpl<AnnotatedLine *>::iterator I,
- SmallVectorImpl<AnnotatedLine *>::iterator E) {
+ ArrayRef<AnnotatedLine *>::iterator I,
+ ArrayRef<AnnotatedLine *>::iterator E) {
while (I != E) {
(*I)->Affected = true;
markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
diff --git a/clang/lib/Format/AffectedRangeManager.h b/clang/lib/Format/AffectedRangeManager.h
index add16bd..eef056f 100644
--- a/clang/lib/Format/AffectedRangeManager.h
+++ b/clang/lib/Format/AffectedRangeManager.h
@@ -47,8 +47,8 @@ private:
bool affectsLeadingEmptyLines(const FormatToken &Tok);
// Marks all lines between I and E as well as all their children as affected.
- void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I,
- SmallVectorImpl<AnnotatedLine *>::iterator E);
+ void markAllAsAffected(ArrayRef<AnnotatedLine *>::iterator I,
+ ArrayRef<AnnotatedLine *>::iterator E);
// Determines whether 'Line' is affected by the SourceRanges given as input.
// Returns \c true if line or one if its children is affected.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 95129a8..fc60c5e 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -839,6 +839,18 @@ template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
}
};
+template <>
+struct ScalarEnumerationTraits<
+ FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> {
+ static void
+ enumeration(IO &IO,
+ FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never);
+ IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always);
+ IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave);
+ }
+};
+
template <> struct MappingTraits<FormatStyle> {
static void mapping(IO &IO, FormatStyle &Style) {
// When reading, read the language first, we need it for getPredefinedStyle.
@@ -975,6 +987,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowShortLambdasOnASingleLine);
IO.mapOptional("AllowShortLoopsOnASingleLine",
Style.AllowShortLoopsOnASingleLine);
+ IO.mapOptional("AllowShortNamespacesOnASingleLine",
+ Style.AllowShortNamespacesOnASingleLine);
IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
Style.AlwaysBreakAfterDefinitionReturnType);
IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
@@ -1164,10 +1178,13 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("TypeNames", Style.TypeNames);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
IO.mapOptional("UseTab", Style.UseTab);
+ IO.mapOptional("VariableTemplates", Style.VariableTemplates);
IO.mapOptional("VerilogBreakBetweenInstancePorts",
Style.VerilogBreakBetweenInstancePorts);
IO.mapOptional("WhitespaceSensitiveMacros",
Style.WhitespaceSensitiveMacros);
+ IO.mapOptional("WrapNamespaceBodyWithEmptyLines",
+ Style.WrapNamespaceBodyWithEmptyLines);
// If AlwaysBreakAfterDefinitionReturnType was specified but
// BreakAfterReturnType was not, initialize the latter from the former for
@@ -1480,6 +1497,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
+ LLVMStyle.AllowShortNamespacesOnASingleLine = false;
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
LLVMStyle.AttributeMacros.push_back("__capability");
@@ -1635,6 +1653,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
+ LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave;
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
@@ -3066,8 +3085,8 @@ static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
// its current line.
// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
static std::pair<unsigned, unsigned>
-FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
- const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
+FindCursorIndex(const ArrayRef<IncludeDirective> &Includes,
+ const ArrayRef<unsigned> &Indices, unsigned Cursor) {
unsigned CursorIndex = UINT_MAX;
unsigned OffsetToEOL = 0;
for (int i = 0, e = Includes.size(); i != e; ++i) {
@@ -3116,7 +3135,7 @@ std::string replaceCRLF(const std::string &Code) {
// provided and put on a deleted #include, it will be moved to the remaining
// #include in the duplicate #includes.
static void sortCppIncludes(const FormatStyle &Style,
- const SmallVectorImpl<IncludeDirective> &Includes,
+ const ArrayRef<IncludeDirective> &Includes,
ArrayRef<tooling::Range> Ranges, StringRef FileName,
StringRef Code, tooling::Replacements &Replaces,
unsigned *Cursor) {
@@ -3359,7 +3378,7 @@ static unsigned findJavaImportGroup(const FormatStyle &Style,
// import group, a newline is inserted, and within each import group, a
// lexicographic sort based on ASCII value is performed.
static void sortJavaImports(const FormatStyle &Style,
- const SmallVectorImpl<JavaImportDirective> &Imports,
+ const ArrayRef<JavaImportDirective> &Imports,
ArrayRef<tooling::Range> Ranges, StringRef FileName,
StringRef Code, tooling::Replacements &Replaces) {
unsigned ImportsBeginOffset = Imports.front().Offset;
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index f6bb860..d97b652 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -25,6 +25,7 @@ namespace clang {
namespace format {
#define LIST_TOKEN_TYPES \
+ TYPE(AfterPPDirective) \
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
TYPE(AttributeColon) \
@@ -44,6 +45,7 @@ namespace format {
TYPE(CastRParen) \
TYPE(ClassLBrace) \
TYPE(ClassRBrace) \
+ TYPE(CompoundRequirementLBrace) \
/* ternary ?: expression */ \
TYPE(ConditionalExpr) \
/* the condition in an if statement */ \
@@ -186,6 +188,7 @@ namespace format {
TYPE(UnionLBrace) \
TYPE(UnionRBrace) \
TYPE(UntouchableMacroFunc) \
+ TYPE(VariableTemplate) \
/* Like in 'assign x = 0, y = 1;' . */ \
TYPE(VerilogAssignComma) \
/* like in begin : block */ \
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 7a264bd..a1d7eea 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -76,6 +76,8 @@ FormatTokenLexer::FormatTokenLexer(
TemplateNames.insert(&IdentTable.get(TemplateName));
for (const auto &TypeName : Style.TypeNames)
TypeNames.insert(&IdentTable.get(TypeName));
+ for (const auto &VariableTemplate : Style.VariableTemplates)
+ VariableTemplates.insert(&IdentTable.get(VariableTemplate));
}
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@@ -562,8 +564,7 @@ bool FormatTokenLexer::tryMergeTokens(ArrayRef<tok::TokenKind> Kinds,
if (Tokens.size() < Kinds.size())
return false;
- SmallVectorImpl<FormatToken *>::const_iterator First =
- Tokens.end() - Kinds.size();
+ const auto *First = Tokens.end() - Kinds.size();
for (unsigned i = 0; i < Kinds.size(); ++i)
if (First[i]->isNot(Kinds[i]))
return false;
@@ -575,7 +576,7 @@ bool FormatTokenLexer::tryMergeTokens(size_t Count, TokenType NewType) {
if (Tokens.size() < Count)
return false;
- SmallVectorImpl<FormatToken *>::const_iterator First = Tokens.end() - Count;
+ const auto *First = Tokens.end() - Count;
unsigned AddLength = 0;
for (size_t i = 1; i < Count; ++i) {
// If there is whitespace separating the token and the previous one,
@@ -1382,6 +1383,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
FormatTok->setFinalizedType(TT_TemplateName);
else if (TypeNames.contains(Identifier))
FormatTok->setFinalizedType(TT_TypeName);
+ else if (VariableTemplates.contains(Identifier))
+ FormatTok->setFinalizedType(TT_VariableTemplate);
}
}
diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h
index 71389d2..61474a3 100644
--- a/clang/lib/Format/FormatTokenLexer.h
+++ b/clang/lib/Format/FormatTokenLexer.h
@@ -129,7 +129,8 @@ private:
llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;
- llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames;
+ llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames,
+ VariableTemplates;
bool FormattingDisabled;
diff --git a/clang/lib/Format/MatchFilePath.cpp b/clang/lib/Format/MatchFilePath.cpp
index 062b334d..1f1e4bf 100644
--- a/clang/lib/Format/MatchFilePath.cpp
+++ b/clang/lib/Format/MatchFilePath.cpp
@@ -25,9 +25,11 @@ bool matchFilePath(StringRef Pattern, StringRef FilePath) {
assert(!Pattern.empty());
assert(!FilePath.empty());
+ const auto FilePathBack = FilePath.back();
+
// No match if `Pattern` ends with a non-meta character not equal to the last
// character of `FilePath`.
- if (const auto C = Pattern.back(); !strchr("?*]", C) && C != FilePath.back())
+ if (const auto C = Pattern.back(); !strchr("?*]", C) && C != FilePathBack)
return false;
constexpr auto Separator = '/';
@@ -49,25 +51,37 @@ bool matchFilePath(StringRef Pattern, StringRef FilePath) {
return false;
break;
case '*': {
- while (++I < EOP && Pattern[I] == '*') { // Skip consecutive stars.
+ bool Globstar = I == 0 || Pattern[I - 1] == Separator;
+ int StarCount = 1;
+ for (; ++I < EOP && Pattern[I] == '*'; ++StarCount) {
+ // Skip consecutive stars.
}
+ if (StarCount != 2)
+ Globstar = false;
const auto K = FilePath.find(Separator, J); // Index of next `Separator`.
const bool NoMoreSeparatorsInFilePath = K == StringRef::npos;
if (I == EOP) // `Pattern` ends with a star.
- return NoMoreSeparatorsInFilePath;
- // `Pattern` ends with a lone backslash.
- if (Pattern[I] == '\\' && ++I == EOP)
- return false;
+ return Globstar || NoMoreSeparatorsInFilePath;
+ if (Pattern[I] != Separator) {
+ // `Pattern` ends with a lone backslash.
+ if (Pattern[I] == '\\' && ++I == EOP)
+ return false;
+ Globstar = false;
+ }
// The star is followed by a (possibly escaped) `Separator`.
if (Pattern[I] == Separator) {
- if (NoMoreSeparatorsInFilePath)
- return false;
- J = K; // Skip to next `Separator` in `FilePath`.
- break;
+ if (!Globstar) {
+ if (NoMoreSeparatorsInFilePath)
+ return false;
+ J = K; // Skip to next `Separator` in `FilePath`.
+ break;
+ }
+ if (++I == EOP)
+ return FilePathBack == Separator;
}
// Recurse.
- for (auto Pat = Pattern.substr(I); J < End && FilePath[J] != Separator;
- ++J) {
+ for (auto Pat = Pattern.substr(I);
+ J < End && (Globstar || FilePath[J] != Separator); ++J) {
if (matchFilePath(Pat, FilePath.substr(J)))
return true;
}
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index f2cfa7f..bf5ee28 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -137,12 +137,12 @@ public:
private:
ScopeType getScopeType(const FormatToken &Token) const {
switch (Token.getType()) {
- case TT_LambdaLBrace:
- return ST_ChildBlock;
case TT_ClassLBrace:
case TT_StructLBrace:
case TT_UnionLBrace:
return ST_Class;
+ case TT_CompoundRequirementLBrace:
+ return ST_CompoundRequirement;
default:
return ST_Other;
}
@@ -1580,7 +1580,10 @@ private:
return false;
break;
case tok::l_brace:
- if (Style.Language == FormatStyle::LK_TextProto) {
+ if (IsCpp) {
+ if (Tok->is(TT_RequiresExpressionLBrace))
+ Line.Type = LT_RequiresExpression;
+ } else if (Style.Language == FormatStyle::LK_TextProto) {
FormatToken *Previous = Tok->getPreviousNonComment();
if (Previous && Previous->isNot(TT_DictLiteral))
Previous->setType(TT_SelectorName);
@@ -2022,8 +2025,11 @@ public:
if (!consumeToken())
return LT_Invalid;
}
- if (Line.Type == LT_AccessModifier)
- return LT_AccessModifier;
+ if (const auto Type = Line.Type; Type == LT_AccessModifier ||
+ Type == LT_RequiresExpression ||
+ Type == LT_SimpleRequirement) {
+ return Type;
+ }
if (KeywordVirtualFound)
return LT_VirtualFunctionDecl;
if (ImportStatement)
@@ -2076,7 +2082,7 @@ private:
TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,
TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,
TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,
- TT_BracedListLBrace)) {
+ TT_CompoundRequirementLBrace, TT_BracedListLBrace)) {
CurrentToken->setType(TT_Unknown);
}
CurrentToken->Role.reset();
@@ -2792,6 +2798,16 @@ private:
return true;
}
+ auto IsNonVariableTemplate = [](const FormatToken &Tok) {
+ if (Tok.isNot(TT_TemplateCloser))
+ return false;
+ const auto *Less = Tok.MatchingParen;
+ if (!Less)
+ return false;
+ const auto *BeforeLess = Less->getPreviousNonComment();
+ return BeforeLess && BeforeLess->isNot(TT_VariableTemplate);
+ };
+
// Heuristically try to determine whether the parentheses contain a type.
auto IsQualifiedPointerOrReference = [](const FormatToken *T,
const LangOptions &LangOpts) {
@@ -2825,10 +2841,11 @@ private:
}
return T && T->is(TT_PointerOrReference);
};
- bool ParensAreType =
- BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
- BeforeRParen->isTypeName(LangOpts) ||
- IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
+
+ bool ParensAreType = IsNonVariableTemplate(*BeforeRParen) ||
+ BeforeRParen->is(TT_TypeDeclarationParen) ||
+ BeforeRParen->isTypeName(LangOpts) ||
+ IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
bool ParensCouldEndDecl =
AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
if (ParensAreType && !ParensCouldEndDecl)
@@ -3089,6 +3106,11 @@ private:
}
}
+ if (Line.Type == LT_SimpleRequirement ||
+ (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) {
+ return TT_BinaryOperator;
+ }
+
return TT_PointerOrReference;
}
@@ -3371,13 +3393,13 @@ private:
/// Parse unary operator expressions and surround them with fake
/// parentheses if appropriate.
void parseUnaryOperator() {
- llvm::SmallVector<FormatToken *, 2> Tokens;
+ SmallVector<FormatToken *, 2> Tokens;
while (Current && Current->is(TT_UnaryOperator)) {
Tokens.push_back(Current);
next();
}
parse(PrecedenceArrowAndPeriod);
- for (FormatToken *Token : llvm::reverse(Tokens)) {
+ for (FormatToken *Token : reverse(Tokens)) {
// The actual precedence doesn't matter.
addFakeParenthesis(Token, prec::Unknown);
}
@@ -3555,7 +3577,7 @@ private:
void TokenAnnotator::setCommentLineLevels(
SmallVectorImpl<AnnotatedLine *> &Lines) const {
const AnnotatedLine *NextNonCommentLine = nullptr;
- for (AnnotatedLine *Line : llvm::reverse(Lines)) {
+ for (AnnotatedLine *Line : reverse(Lines)) {
assert(Line->First);
// If the comment is currently aligned with the line immediately following
@@ -3676,9 +3698,16 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
Line.Type = Parser.parseLine();
if (!Line.Children.empty()) {
- ScopeStack.push_back(ST_ChildBlock);
- for (auto &Child : Line.Children)
+ ScopeStack.push_back(ST_Other);
+ const bool InRequiresExpression = Line.Type == LT_RequiresExpression;
+ for (auto &Child : Line.Children) {
+ if (InRequiresExpression &&
+ !Child->First->isOneOf(tok::kw_typename, tok::kw_requires,
+ TT_CompoundRequirementLBrace)) {
+ Child->Type = LT_SimpleRequirement;
+ }
annotate(*Child);
+ }
// ScopeStack can become empty if Child has an unmatched `}`.
if (!ScopeStack.empty())
ScopeStack.pop_back();
@@ -4930,6 +4959,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Right.is(TT_ModulePartitionColon)) {
return true;
}
+
+ if (Right.is(TT_AfterPPDirective))
+ return true;
+
// No space between import foo:bar but keep a space between import :bar;
if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
return false;
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 9117ca3..16e920e 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -33,14 +33,16 @@ enum LineType {
LT_VirtualFunctionDecl,
LT_ArrayOfStructInitializer,
LT_CommentAbovePPDirective,
+ LT_RequiresExpression,
+ LT_SimpleRequirement,
};
enum ScopeType {
- // Contained in child block.
- ST_ChildBlock,
// Contained in class declaration/definition.
ST_Class,
- // Contained within other scope block (function, loop, if/else, etc).
+ // Contained in compound requirement.
+ ST_CompoundRequirement,
+ // Contained in other blocks (function, lambda, loop, if/else, child, etc).
ST_Other,
};
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 1804c14..ec65fea 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -183,9 +183,9 @@ private:
unsigned Indent = 0;
};
-const FormatToken *getMatchingNamespaceToken(
- const AnnotatedLine *Line,
- const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+const FormatToken *
+getMatchingNamespaceToken(const AnnotatedLine *Line,
+ const ArrayRef<AnnotatedLine *> &AnnotatedLines) {
if (!Line->startsWith(tok::r_brace))
return nullptr;
size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;
@@ -200,9 +200,9 @@ StringRef getNamespaceTokenText(const AnnotatedLine *Line) {
return NamespaceToken ? NamespaceToken->TokenText : StringRef();
}
-StringRef getMatchingNamespaceTokenText(
- const AnnotatedLine *Line,
- const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+StringRef
+getMatchingNamespaceTokenText(const AnnotatedLine *Line,
+ const ArrayRef<AnnotatedLine *> &AnnotatedLines) {
const FormatToken *NamespaceToken =
getMatchingNamespaceToken(Line, AnnotatedLines);
return NamespaceToken ? NamespaceToken->TokenText : StringRef();
@@ -241,8 +241,8 @@ private:
/// Calculates how many lines can be merged into 1 starting at \p I.
unsigned
tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
- SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
+ ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E) {
const unsigned Indent = IndentTracker.getIndent();
// Can't join the last line with anything.
@@ -361,9 +361,18 @@ private:
const auto *FirstNonComment = TheLine->getFirstNonComment();
if (!FirstNonComment)
return 0;
+
// FIXME: There are probably cases where we should use FirstNonComment
// instead of TheLine->First.
+ if (Style.AllowShortNamespacesOnASingleLine &&
+ TheLine->First->is(tok::kw_namespace) &&
+ TheLine->Last->is(tok::l_brace)) {
+ const auto result = tryMergeNamespace(I, E, Limit);
+ if (result > 0)
+ return result;
+ }
+
if (Style.CompactNamespaces) {
if (const auto *NSToken = TheLine->First->getNamespaceToken()) {
int J = 1;
@@ -373,7 +382,7 @@ private:
ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
I[J]->Last->TotalLength < Limit;
++J, --ClosingLineIndex) {
- Limit -= I[J]->Last->TotalLength;
+ Limit -= I[J]->Last->TotalLength + 1;
// Reduce indent level for bodies of namespaces which were compacted,
// but only if their content was indented in the first place.
@@ -420,6 +429,7 @@ private:
TheLine->First != LastNonComment) {
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
}
+
// Try to merge a control statement block with left brace unwrapped.
if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
@@ -525,7 +535,7 @@ private:
// Try to merge records.
if (TheLine->Last->is(TT_EnumLBrace)) {
ShouldMerge = Style.AllowShortEnumsOnASingleLine;
- } else if (TheLine->Last->is(TT_RequiresExpressionLBrace)) {
+ } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
} else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) {
// NOTE: We use AfterClass (whereas AfterStruct exists) for both classes
@@ -604,8 +614,8 @@ private:
}
unsigned
- tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
+ tryMergeSimplePPDirective(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
unsigned Limit) {
if (Limit == 0)
return 0;
@@ -616,9 +626,76 @@ private:
return 1;
}
- unsigned tryMergeSimpleControlStatement(
- SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
+ unsigned tryMergeNamespace(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
+ if (Limit == 0)
+ return 0;
+
+ assert(I[1]);
+ const auto &L1 = *I[1];
+ if (L1.InPPDirective != (*I)->InPPDirective ||
+ (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
+ return 0;
+ }
+
+ if (std::distance(I, E) <= 2)
+ return 0;
+
+ assert(I[2]);
+ const auto &L2 = *I[2];
+ if (L2.Type == LT_Invalid)
+ return 0;
+
+ Limit = limitConsideringMacros(I + 1, E, Limit);
+
+ if (!nextTwoLinesFitInto(I, Limit))
+ return 0;
+
+ // Check if it's a namespace inside a namespace, and call recursively if so.
+ // '3' is the sizes of the whitespace and closing brace for " _inner_ }".
+ if (L1.First->is(tok::kw_namespace)) {
+ if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
+ return 0;
+
+ assert(Limit >= L1.Last->TotalLength + 3);
+ const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
+ const auto MergedLines = tryMergeNamespace(I + 1, E, InnerLimit);
+ if (MergedLines == 0)
+ return 0;
+ const auto N = MergedLines + 2;
+ // Check if there is even a line after the inner result.
+ if (std::distance(I, E) <= N)
+ return 0;
+ // Check that the line after the inner result starts with a closing brace
+ // which we are permitted to merge into one line.
+ if (I[N]->First->is(tok::r_brace) && !I[N]->First->MustBreakBefore &&
+ I[MergedLines + 1]->Last->isNot(tok::comment) &&
+ nextNLinesFitInto(I, I + N + 1, Limit)) {
+ return N;
+ }
+ return 0;
+ }
+
+ // There's no inner namespace, so we are considering to merge at most one
+ // line.
+
+ // The line which is in the namespace should end with semicolon.
+ if (L1.Last->isNot(tok::semi))
+ return 0;
+
+ // Last, check that the third line starts with a closing brace.
+ if (L2.First->isNot(tok::r_brace) || L2.First->MustBreakBefore)
+ return 0;
+
+ // If so, merge all three lines.
+ return 2;
+ }
+
+ unsigned
+ tryMergeSimpleControlStatement(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (Limit == 0)
return 0;
if (Style.BraceWrapping.AfterControlStatement ==
@@ -658,10 +735,9 @@ private:
return 1;
}
- unsigned
- tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
- unsigned Limit) {
+ unsigned tryMergeShortCaseLabels(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (Limit == 0 || I + 1 == E ||
I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) {
return 0;
@@ -692,7 +768,7 @@ private:
if (Line->First->is(tok::comment)) {
if (Level != Line->Level)
return 0;
- SmallVectorImpl<AnnotatedLine *>::const_iterator J = I + 2 + NumStmts;
+ const auto *J = I + 2 + NumStmts;
for (; J != E; ++J) {
Line = *J;
if (Line->InPPDirective != InPPDirective)
@@ -713,10 +789,9 @@ private:
return NumStmts;
}
- unsigned
- tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
- unsigned Limit) {
+ unsigned tryMergeSimpleBlock(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
// Don't merge with a preprocessor directive.
if (I[1]->Type == LT_PreprocessorDirective)
return 0;
@@ -898,10 +973,9 @@ private:
/// Returns the modified column limit for \p I if it is inside a macro and
/// needs a trailing '\'.
- unsigned
- limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
- unsigned Limit) {
+ unsigned limitConsideringMacros(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (I[0]->InPPDirective && I + 1 != E &&
!I[1]->First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
return Limit < 2 ? 0 : Limit - 2;
@@ -909,13 +983,28 @@ private:
return Limit;
}
- bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
+ bool nextTwoLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,
unsigned Limit) {
if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
return false;
return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
}
+ bool nextNLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
+ unsigned JoinedLength = 0;
+ for (const auto *J = I + 1; J != E; ++J) {
+ if ((*J)->First->MustBreakBefore)
+ return false;
+
+ JoinedLength += 1 + (*J)->Last->TotalLength;
+ if (JoinedLength > Limit)
+ return false;
+ }
+ return true;
+ }
+
bool containsMustBreak(const AnnotatedLine *Line) {
assert(Line->First);
// Ignore the first token, because in this situation, it applies more to the
@@ -943,9 +1032,9 @@ private:
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
- const SmallVectorImpl<AnnotatedLine *>::const_iterator End;
+ const ArrayRef<AnnotatedLine *>::const_iterator End;
- SmallVectorImpl<AnnotatedLine *>::const_iterator Next;
+ ArrayRef<AnnotatedLine *>::const_iterator Next;
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
};
@@ -1493,6 +1582,23 @@ static auto computeNewlines(const AnnotatedLine &Line,
Newlines = 1;
}
+ if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
+ // Modify empty lines after TT_NamespaceLBrace.
+ if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) {
+ if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
+ Newlines = 1;
+ else if (!Line.startsWithNamespace())
+ Newlines = std::max(Newlines, 2u);
+ }
+ // Modify empty lines before TT_NamespaceRBrace.
+ if (Line.startsWith(TT_NamespaceRBrace)) {
+ if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
+ Newlines = 1;
+ else if (!PreviousLine->startsWith(TT_NamespaceRBrace))
+ Newlines = std::max(Newlines, 2u);
+ }
+ }
+
// Insert or remove empty line before access specifiers.
if (PreviousLine && RootToken.isAccessSpecifier()) {
switch (Style.EmptyLineBeforeAccessModifier) {
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 654148a..3177172 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -51,9 +51,7 @@ void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,
<< "T=" << (unsigned)I->Tok->getType()
<< ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText
<< "\"] ";
- for (SmallVectorImpl<UnwrappedLine>::const_iterator
- CI = I->Children.begin(),
- CE = I->Children.end();
+ for (const auto *CI = I->Children.begin(), *CE = I->Children.end();
CI != CE; ++CI) {
OS << "\n";
printLine(OS, *CI, (Prefix + " ").str());
@@ -394,7 +392,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
break;
case tok::l_brace:
if (InRequiresExpression) {
- FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
+ FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);
} else if (FormatTok->Previous &&
FormatTok->Previous->ClosesRequiresClause) {
// We need the 'default' case here to correctly parse a function
@@ -1032,6 +1030,12 @@ void UnwrappedLineParser::parsePPDirective() {
case tok::pp_pragma:
parsePPPragma();
break;
+ case tok::pp_error:
+ case tok::pp_warning:
+ nextToken();
+ if (!eof() && Style.isCpp())
+ FormatTok->setFinalizedType(TT_AfterPPDirective);
+ [[fallthrough]];
default:
parsePPUnknown();
break;
@@ -1211,9 +1215,8 @@ void UnwrappedLineParser::parsePPPragma() {
}
void UnwrappedLineParser::parsePPUnknown() {
- do {
+ while (!eof())
nextToken();
- } while (!eof());
if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
@@ -1702,7 +1705,8 @@ void UnwrappedLineParser::parseStructuralElement(
}
for (const bool InRequiresExpression =
- OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
+ OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
+ TT_CompoundRequirementLBrace);
!eof();) {
if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) {
if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true);
@@ -2041,7 +2045,9 @@ void UnwrappedLineParser::parseStructuralElement(
? FormatTok->NewlinesBefore > 0
: CommentsBeforeNextToken.front()->NewlinesBefore > 0;
- if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
+ if (FollowedByNewline &&
+ (Text.size() >= 5 ||
+ (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) {
if (PreviousToken->isNot(TT_UntouchableMacroFunc))
PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
@@ -4788,8 +4794,7 @@ void UnwrappedLineParser::nextToken(int LevelDifference) {
}
void UnwrappedLineParser::distributeComments(
- const SmallVectorImpl<FormatToken *> &Comments,
- const FormatToken *NextTok) {
+ const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok) {
// Whether or not a line comment token continues a line is controlled by
// the method continuesLineCommentSection, with the following caveat:
//
@@ -5011,7 +5016,7 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
namespace {
template <typename Iterator>
void pushTokens(Iterator Begin, Iterator End,
- llvm::SmallVectorImpl<FormatToken *> &Into) {
+ SmallVectorImpl<FormatToken *> &Into) {
for (auto I = Begin; I != End; ++I) {
Into.push_back(I->Tok);
for (const auto &Child : I->Children)
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index b7daf8d..8160d5e 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -228,7 +228,7 @@ private:
// NextTok specifies the next token. A null pointer NextTok is supported, and
// signifies either the absence of a next token, or that the next token
// shouldn't be taken into account for the analysis.
- void distributeComments(const SmallVectorImpl<FormatToken *> &Comments,
+ void distributeComments(const ArrayRef<FormatToken *> &Comments,
const FormatToken *NextTok);
// Adds the comment preceding the next token to unwrapped lines.