From 94b748ff16172f0da2b842fe0d5bae438f07034f Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Wed, 27 Mar 2013 17:08:02 +0000 Subject: [PATCH] Insert extra new line before access specifiers. Summary: Insert extra new line before access specifiers. Reviewers: djasper Reviewed By: djasper CC: cfe-commits, klimek Differential Revision: http://llvm-reviews.chandlerc.com/D581 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178149 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/Format.cpp | 33 +++++++++++++++------------------ lib/Format/TokenAnnotator.h | 14 ++++++++++++++ unittests/Format/FormatTest.cpp | 22 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 1ff3036eb9..245b7f60a6 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -442,8 +442,7 @@ private: while (I != E) { if (!I->Untouchable) { unsigned Spaces = I->Spaces + Column - I->MinColumn; - storeReplacement( - I->Tok, std::string(I->NewLines, '\n') + std::string(Spaces, ' ')); + storeReplacement(I->Tok, getNewLineText(I->NewLines, Spaces)); } ++I; } @@ -1350,6 +1349,7 @@ public: } std::vector IndentForLevel; bool PreviousLineWasTouched = false; + const AnnotatedToken *PreviousLineLastToken = 0; for (std::vector::iterator I = AnnotatedLines.begin(), E = AnnotatedLines.end(); I != E; ++I) { @@ -1376,8 +1376,8 @@ public: Indent = LevelIndent = SourceMgr.getSpellingColumnNumber(FirstTok.Tok.getLocation()) - 1; } else { - formatFirstToken(TheLine.First, Indent, TheLine.InPPDirective, - PreviousEndOfLineColumn); + formatFirstToken(TheLine.First, PreviousLineLastToken, Indent, + TheLine.InPPDirective, PreviousEndOfLineColumn); } tryFitMultipleLinesInOne(Indent, I, E); UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine, Indent, @@ -1399,8 +1399,8 @@ public: // Remove trailing whitespace of the previous line if it was touched. if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) - formatFirstToken(TheLine.First, Indent, TheLine.InPPDirective, - PreviousEndOfLineColumn); + formatFirstToken(TheLine.First, PreviousLineLastToken, Indent, + TheLine.InPPDirective, PreviousEndOfLineColumn); } // If we did not reformat this unwrapped line, the column at the end of // the last token is unchanged - thus, we can calculate the end of the @@ -1414,6 +1414,7 @@ public: Whitespaces.addUntouchableComment(SourceMgr.getSpellingColumnNumber( TheLine.Last->FormatTok.Tok.getLocation()) - 1); } + PreviousLineLastToken = I->Last; } return Whitespaces.generateReplacements(); } @@ -1474,17 +1475,7 @@ private: /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. int getIndentOffset(const AnnotatedToken &RootToken) { - bool IsAccessModifier = false; - if (RootToken.isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private)) - IsAccessModifier = true; - else if (RootToken.is(tok::at) && !RootToken.Children.empty() && - (RootToken.Children[0].isObjCAtKeyword(tok::objc_public) || - RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) || - RootToken.Children[0].isObjCAtKeyword(tok::objc_package) || - RootToken.Children[0].isObjCAtKeyword(tok::objc_private))) - IsAccessModifier = true; - - if (IsAccessModifier) + if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier()) return Style.AccessModifierOffset; return 0; } @@ -1662,7 +1653,8 @@ private: /// \brief Add a new line and the required indent before the first Token /// of the \c UnwrappedLine if there was no structural parsing error. /// Returns the indent level of the \c UnwrappedLine. - void formatFirstToken(const AnnotatedToken &RootToken, unsigned Indent, + void formatFirstToken(const AnnotatedToken &RootToken, + const AnnotatedToken *PreviousToken, unsigned Indent, bool InPPDirective, unsigned PreviousEndOfLineColumn) { const FormatToken &Tok = RootToken.FormatTok; @@ -1672,6 +1664,11 @@ private: Newlines = 1; if (!InPPDirective || Tok.HasUnescapedNewline) { + // Insert extra new line before access specifiers. + if (PreviousToken && PreviousToken->isOneOf(tok::semi, tok::r_brace) && + RootToken.isAccessSpecifier() && Tok.NewlinesBefore == 1) + ++Newlines; + Whitespaces.replaceWhitespace(RootToken, Newlines, Indent, 0); } else { Whitespaces.replacePPWhitespace(RootToken, Newlines, Indent, diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h index 929684400b..013dd2d27c 100644 --- a/lib/Format/TokenAnnotator.h +++ b/lib/Format/TokenAnnotator.h @@ -107,6 +107,20 @@ public: return FormatTok.Tok.isObjCAtKeyword(Kind); } + bool isAccessSpecifier(bool ColonRequired = true) const { + return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) && + (!ColonRequired || + (!Children.empty() && Children[0].is(tok::colon))); + } + + bool isObjCAccessSpecifier() const { + return is(tok::at) && !Children.empty() && + (Children[0].isObjCAtKeyword(tok::objc_public) || + Children[0].isObjCAtKeyword(tok::objc_protected) || + Children[0].isObjCAtKeyword(tok::objc_package) || + Children[0].isObjCAtKeyword(tok::objc_private)); + } + FormatToken FormatTok; TokenType Type; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index daeb1dbaf0..7fbb9f3ac4 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -937,6 +937,28 @@ TEST_F(FormatTest, UnderstandsAccessSpecifiers) { "};"); } +TEST_F(FormatTest, SeparatesLogicalBlocks) { + EXPECT_EQ("class A {\n" + "public:\n" + " void f();\n" + "\n" + "private:\n" + " void g() {}\n" + " // test\n" + "protected:\n" + " int h;\n" + "};", + format("class A {\n" + "public:\n" + "void f();\n" + "private:\n" + "void g() {}\n" + "// test\n" + "protected:\n" + "int h;\n" + "};")); +} + TEST_F(FormatTest, FormatsDerivedClass) { verifyFormat("class A : public B {\n};"); verifyFormat("class A : public ::B {\n};"); -- 2.40.0