From f753615897c86928517e48e4d106e669d59618c5 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Thu, 14 Mar 2013 16:10:54 +0000 Subject: [PATCH] Multi-line comment alignment Summary: Aligns continuation lines of multi-line comments to the base indentation level +1: class A { /* * test */ void f() {} }; The first revision is work in progress. The implementation is not yet complete. Reviewers: djasper Reviewed By: djasper CC: cfe-commits, klimek Differential Revision: http://llvm-reviews.chandlerc.com/D541 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177080 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/Format.cpp | 57 ++++++++++++++++++++++++++------- unittests/Format/FormatTest.cpp | 35 ++++++++++++++++++++ 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index ab895c7d1c..777d5e8f72 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -128,16 +128,14 @@ public: if (Tok.Parent != NULL || !Comments.empty()) { if (Style.ColumnLimit >= Spaces + WhitespaceStartColumn + Tok.FormatTok.TokenLength) { - Comments.push_back(StoredComment()); - Comments.back().Tok = Tok.FormatTok; - Comments.back().Spaces = Spaces; - Comments.back().NewLines = NewLines; - if (NewLines == 0) - Comments.back().MinColumn = WhitespaceStartColumn + Spaces; - else - Comments.back().MinColumn = Spaces; - Comments.back().MaxColumn = - Style.ColumnLimit - Tok.FormatTok.TokenLength; + StoredComment Comment; + Comment.Tok = Tok.FormatTok; + Comment.Spaces = Spaces; + Comment.NewLines = NewLines; + Comment.MinColumn = + NewLines > 0 ? Spaces : WhitespaceStartColumn + Spaces; + Comment.MaxColumn = Style.ColumnLimit - Tok.FormatTok.TokenLength; + Comments.push_back(Comment); return; } } @@ -146,6 +144,10 @@ public: // If this line does not have a trailing comment, align the stored comments. if (Tok.Children.empty() && !isTrailingComment(Tok)) alignComments(); + + if (Tok.Type == TT_BlockComment) + indentBlockComment(Tok.FormatTok, Spaces); + storeReplacement(Tok.FormatTok, getNewLineText(NewLines, Spaces)); } @@ -191,6 +193,38 @@ public: } private: + void indentBlockComment(const FormatToken &Tok, int BaseIndent) { + SourceLocation TokenLoc = Tok.Tok.getLocation(); + const char *Start = SourceMgr.getCharacterData(TokenLoc); + const char *Current = Start; + const char *TokEnd = Current + Tok.TokenLength; + while (Current < TokEnd) { + if (*Current == '\n') { + ++Current; + SourceLocation Loc = TokenLoc.getLocWithOffset(Current - Start); + int Indent = BaseIndent; + int Spaces = 0; + while (Current < TokEnd && *Current == ' ') { + ++Spaces; + ++Current; + } + if (Current < TokEnd && *Current == '*') + ++Indent; + else + Indent += 3; + + if (Spaces < Indent) + Replaces.insert(tooling::Replacement( + SourceMgr, Loc, 0, std::string(Indent - Spaces, ' '))); + else if (Spaces > Indent) + Replaces.insert( + tooling::Replacement(SourceMgr, Loc, Spaces - Indent, "")); + } else { + ++Current; + } + } + } + std::string getNewLineText(unsigned NewLines, unsigned Spaces) { return std::string(NewLines, '\n') + std::string(Spaces, ' '); } @@ -227,8 +261,7 @@ private: unsigned MinColumn = 0; unsigned MaxColumn = UINT_MAX; comment_iterator Start = Comments.begin(); - for (comment_iterator I = Comments.begin(), E = Comments.end(); I != E; - ++I) { + for (comment_iterator I = Start, E = Comments.end(); I != E; ++I) { if (I->MinColumn > MaxColumn || I->MaxColumn < MinColumn) { alignComments(Start, I, MinColumn); MinColumn = I->MinColumn; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 3044c69cd0..ca7ed62ed1 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -608,6 +608,41 @@ TEST_F(FormatTest, UnderstandsMultiLineComments) { NoBinPacking); } +TEST_F(FormatTest, AlignsMultiLineComments) { + EXPECT_EQ("/*\n" + " * Really multi-line\n" + " * comment.\n" + " */\n" + "void f() {}", + format(" /*\n" + " * Really multi-line\n" + " * comment.\n" + " */\n" + " void f() {}")); + EXPECT_EQ("/*\n" + " A comment.\n" + " */\n" + "void f() {}", + format(" /*\n" + " A comment.\n" + " */\n" + " void f() {}")); + EXPECT_EQ("class C {\n" + " /*\n" + " * Another multi-line\n" + " * comment.\n" + " */\n" + " void f() {}\n" + "};", + format("class C {\n" + "/*\n" + " * Another multi-line\n" + " * comment.\n" + " */\n" + "void f() {}\n" + "};")); +} + TEST_F(FormatTest, CommentsInStaticInitializers) { EXPECT_EQ( "static SomeType type = { aaaaaaaaaaaaaaaaaaaa, /* comment */\n" -- 2.40.0