diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-16 21:03:44 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-16 21:03:44 +0000 |
commit | 325377b57338e700317f5e423e5b0f1c08d99a39 (patch) | |
tree | acd401a9713562cf3e93d13fa6a70ad67eb5cd99 /lib/Format | |
parent | 1b08b196ac845675036ac78f3ac927d0a37f707c (diff) |
Notes
Diffstat (limited to 'lib/Format')
-rw-r--r-- | lib/Format/Format.cpp | 16 | ||||
-rw-r--r-- | lib/Format/NamespaceEndCommentsFixer.cpp | 64 | ||||
-rw-r--r-- | lib/Format/UnwrappedLineFormatter.cpp | 80 | ||||
-rw-r--r-- | lib/Format/UnwrappedLineParser.cpp | 5 | ||||
-rw-r--r-- | lib/Format/WhitespaceManager.h | 4 |
5 files changed, 142 insertions, 27 deletions
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 2ef6516e02ee4..39da87cf99888 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -310,6 +310,8 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); + IO.mapOptional("BreakBeforeInheritanceComma", + Style.BreakBeforeInheritanceComma); IO.mapOptional("BreakBeforeTernaryOperators", Style.BreakBeforeTernaryOperators); @@ -330,8 +332,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); - IO.mapOptional("BreakBeforeInheritanceComma", - Style.BreakBeforeInheritanceComma); + IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", Style.ConstructorInitializerAllOnOneLineOrOnePerLine); IO.mapOptional("ConstructorInitializerIndentWidth", @@ -410,6 +411,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); IO.mapOptional("BeforeElse", Wrapping.BeforeElse); IO.mapOptional("IndentBraces", Wrapping.IndentBraces); + IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody); } }; @@ -485,7 +487,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { return Style; FormatStyle Expanded = Style; Expanded.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false}; + false, false, false, false, false, true}; switch (Style.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; @@ -498,6 +500,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; + Expanded.BraceWrapping.SplitEmptyFunctionBody = false; break; case FormatStyle::BS_Stroustrup: Expanded.BraceWrapping.AfterFunction = true; @@ -517,7 +520,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { break; case FormatStyle::BS_GNU: Expanded.BraceWrapping = {true, true, true, true, true, true, - true, true, true, true, true}; + true, true, true, true, true, true}; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -548,19 +551,20 @@ FormatStyle getLLVMStyle() { LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = false; - LLVMStyle.BinPackParameters = true; LLVMStyle.BinPackArguments = true; + LLVMStyle.BinPackParameters = true; 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, false, false, false, true}; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakBeforeInheritanceComma = false; LLVMStyle.BreakStringLiterals = true; LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; + LLVMStyle.CompactNamespaces = false; LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp index 88cf123c18990..1bbb41f757ae2 100644 --- a/lib/Format/NamespaceEndCommentsFixer.cpp +++ b/lib/Format/NamespaceEndCommentsFixer.cpp @@ -107,6 +107,24 @@ void updateEndComment(const FormatToken *RBraceTok, StringRef EndCommentText, << llvm::toString(std::move(Err)) << "\n"; } } + +const FormatToken * +getNamespaceToken(const AnnotatedLine *line, + const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { + if (!line->Affected || line->InPPDirective || !line->startsWith(tok::r_brace)) + return nullptr; + size_t StartLineIndex = line->MatchingOpeningBlockLineIndex; + if (StartLineIndex == UnwrappedLine::kInvalidIndex) + return nullptr; + assert(StartLineIndex < AnnotatedLines.size()); + const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First; + // Detect "(inline)? namespace" in the beginning of a line. + if (NamespaceTok->is(tok::kw_inline)) + NamespaceTok = NamespaceTok->getNextNonComment(); + if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace)) + return nullptr; + return NamespaceTok; +} } // namespace NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env, @@ -120,20 +138,14 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end()); tooling::Replacements Fixes; + std::string AllNamespaceNames = ""; + size_t StartLineIndex = SIZE_MAX; + unsigned int CompactedNamespacesCount = 0; for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) { - if (!AnnotatedLines[I]->Affected || AnnotatedLines[I]->InPPDirective || - !AnnotatedLines[I]->startsWith(tok::r_brace)) - continue; const AnnotatedLine *EndLine = AnnotatedLines[I]; - size_t StartLineIndex = EndLine->MatchingOpeningBlockLineIndex; - if (StartLineIndex == UnwrappedLine::kInvalidIndex) - continue; - assert(StartLineIndex < E); - const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First; - // Detect "(inline)? namespace" in the beginning of a line. - if (NamespaceTok->is(tok::kw_inline)) - NamespaceTok = NamespaceTok->getNextNonComment(); - if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace)) + const FormatToken *NamespaceTok = + getNamespaceToken(EndLine, AnnotatedLines); + if (!NamespaceTok) continue; FormatToken *RBraceTok = EndLine->First; if (RBraceTok->Finalized) @@ -145,6 +157,27 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( if (RBraceTok->Next && RBraceTok->Next->is(tok::semi)) { EndCommentPrevTok = RBraceTok->Next; } + if (StartLineIndex == SIZE_MAX) + StartLineIndex = EndLine->MatchingOpeningBlockLineIndex; + std::string NamespaceName = computeName(NamespaceTok); + if (Style.CompactNamespaces) { + if ((I + 1 < E) && + getNamespaceToken(AnnotatedLines[I + 1], AnnotatedLines) && + StartLineIndex - CompactedNamespacesCount - 1 == + AnnotatedLines[I + 1]->MatchingOpeningBlockLineIndex && + !AnnotatedLines[I + 1]->First->Finalized) { + if (hasEndComment(EndCommentPrevTok)) { + // remove end comment, it will be merged in next one + updateEndComment(EndCommentPrevTok, std::string(), SourceMgr, &Fixes); + } + CompactedNamespacesCount++; + AllNamespaceNames = "::" + NamespaceName + AllNamespaceNames; + continue; + } + NamespaceName += std::move(AllNamespaceNames); + CompactedNamespacesCount = 0; + AllNamespaceNames = std::string(); + } // The next token in the token stream after the place where the end comment // token must be. This is either the next token on the current line or the // first token on the next line. @@ -156,17 +189,16 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( bool AddNewline = EndCommentNextTok && EndCommentNextTok->NewlinesBefore == 0 && EndCommentNextTok->isNot(tok::eof); - const std::string NamespaceName = computeName(NamespaceTok); const std::string EndCommentText = computeEndCommentText(NamespaceName, AddNewline); if (!hasEndComment(EndCommentPrevTok)) { bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1; if (!isShort) addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes); - continue; - } - if (!validEndComment(EndCommentPrevTok, NamespaceName)) + } else if (!validEndComment(EndCommentPrevTok, NamespaceName)) { updateEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes); + } + StartLineIndex = SIZE_MAX; } return Fixes; } diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index 01504da0a29ba..7f644651a6ab8 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -66,6 +66,13 @@ public: Indent += Offset; } + /// \brief Update the indent state given that \p Line indent should be + /// skipped. + void skipLine(const AnnotatedLine &Line) { + while (IndentForLevel.size() <= Line.Level) + IndentForLevel.push_back(Indent); + } + /// \brief Update the level indent to adapt to the given \p Line. /// /// When a line is not formatted, we move the subsequent lines on the same @@ -127,12 +134,31 @@ private: unsigned Indent = 0; }; +bool isNamespaceDeclaration(const AnnotatedLine *Line) { + const FormatToken *NamespaceTok = Line->First; + // Detect "(inline)? namespace" in the beginning of a line. + if (NamespaceTok->is(tok::kw_inline)) + NamespaceTok = NamespaceTok->getNextNonComment(); + return NamespaceTok && NamespaceTok->is(tok::kw_namespace); +} + +bool isEndOfNamespace(const AnnotatedLine *Line, + const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { + if (!Line->startsWith(tok::r_brace)) + return false; + size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex; + if (StartLineIndex == UnwrappedLine::kInvalidIndex) + return false; + assert(StartLineIndex < AnnotatedLines.size()); + return isNamespaceDeclaration(AnnotatedLines[StartLineIndex]); +} + class LineJoiner { public: LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords, const SmallVectorImpl<AnnotatedLine *> &Lines) - : Style(Style), Keywords(Keywords), End(Lines.end()), - Next(Lines.begin()) {} + : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()), + AnnotatedLines(Lines) {} /// \brief Returns the next line, merging multiple lines into one if possible. const AnnotatedLine *getNextMergedLine(bool DryRun, @@ -142,7 +168,7 @@ public: const AnnotatedLine *Current = *Next; IndentTracker.nextLine(*Current); unsigned MergedLines = - tryFitMultipleLinesInOne(IndentTracker.getIndent(), Next, End); + tryFitMultipleLinesInOne(IndentTracker, Next, End); if (MergedLines > 0 && Style.ColumnLimit == 0) // Disallow line merging if there is a break at the start of one of the // input lines. @@ -159,9 +185,11 @@ public: private: /// \brief Calculates how many lines can be merged into 1 starting at \p I. unsigned - tryFitMultipleLinesInOne(unsigned Indent, + tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker, SmallVectorImpl<AnnotatedLine *>::const_iterator I, SmallVectorImpl<AnnotatedLine *>::const_iterator E) { + const unsigned Indent = IndentTracker.getIndent(); + // Can't join the last line with anything. if (I + 1 == E) return 0; @@ -186,6 +214,12 @@ private: ? 0 : Limit - TheLine->Last->TotalLength; + if (TheLine->Last->is(TT_FunctionLBrace) && + TheLine->First == TheLine->Last && + !Style.BraceWrapping.SplitEmptyFunctionBody && + I[1]->First->is(tok::r_brace)) + return tryMergeSimpleBlock(I, E, Limit); + // FIXME: TheLine->Level != 0 might or might not be the right check to do. // If necessary, change to something smarter. bool MergeShortFunctions = @@ -195,6 +229,38 @@ private: (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline && TheLine->Level != 0); + if (Style.CompactNamespaces) { + if (isNamespaceDeclaration(TheLine)) { + int i = 0; + unsigned closingLine = TheLine->MatchingOpeningBlockLineIndex - 1; + for (; I + 1 + i != E && isNamespaceDeclaration(I[i + 1]) && + closingLine == I[i + 1]->MatchingOpeningBlockLineIndex && + I[i + 1]->Last->TotalLength < Limit; + i++, closingLine--) { + // No extra indent for compacted namespaces + IndentTracker.skipLine(*I[i + 1]); + + Limit -= I[i + 1]->Last->TotalLength; + } + return i; + } + + if (isEndOfNamespace(TheLine, AnnotatedLines)) { + int i = 0; + unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1; + for (; I + 1 + i != E && isEndOfNamespace(I[i + 1], AnnotatedLines) && + openingLine == I[i + 1]->MatchingOpeningBlockLineIndex; + i++, openingLine--) { + // No space between consecutive braces + I[i + 1]->First->SpacesRequiredBefore = !I[i]->Last->is(tok::r_brace); + + // Indent like the outer-most namespace + IndentTracker.nextLine(*I[i + 1]); + } + return i; + } + } + if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First != TheLine->Last) { return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; @@ -215,7 +281,10 @@ private: Limit -= 2; unsigned MergedLines = 0; - if (MergeShortFunctions) { + if (MergeShortFunctions || + (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + I[1]->First == I[1]->Last && I + 2 != E && + I[2]->First->is(tok::r_brace))) { MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); // If we managed to merge the block, count the function header, which is // on a separate line. @@ -449,6 +518,7 @@ private: const SmallVectorImpl<AnnotatedLine *>::const_iterator End; SmallVectorImpl<AnnotatedLine *>::const_iterator Next; + const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines; }; static void markFinalized(FormatToken *Tok) { diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index eda7ef36434df..27436dda67a7f 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -492,6 +492,11 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, nextToken(); Line->Level = InitialLevel; Line->MatchingOpeningBlockLineIndex = OpeningLineIndex; + if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) { + // Update the opening line to add the forward reference as well + (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex = + CurrentLines->size() - 1; + } } static bool isGoogScope(const UnwrappedLine &Line) { diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h index 6be4af2622766..50df59d09641d 100644 --- a/lib/Format/WhitespaceManager.h +++ b/lib/Format/WhitespaceManager.h @@ -43,6 +43,10 @@ public: /// \brief Replaces the whitespace in front of \p Tok. Only call once for /// each \c AnnotatedToken. + /// + /// \p StartOfTokenColumn is the column at which the token will start after + /// this replacement. It is needed for determining how \p Spaces is turned + /// into tabs and spaces for some format styles. void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces, unsigned StartOfTokenColumn, bool InPPDirective = false); |