From 79d6c72e0ede4ab816c46727326985d6547f826b Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Fri, 15 Mar 2013 13:42:02 +0000 Subject: [PATCH] Indent all lines in a multi-line comment by the same amount. Summary: Do this to avoid spoling nicely formatted multi-line comments (e.g. with code examples or similar stuff). Reviewers: djasper Reviewed By: djasper CC: cfe-commits, klimek Differential Revision: http://llvm-reviews.chandlerc.com/D544 llvm-svn: 177153 --- clang/lib/Format/Format.cpp | 36 +++++++++++++-------------- clang/unittests/Format/FormatTest.cpp | 24 ++++++++++++------ 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 777d5e8f72ac..aa715e692d17 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -193,36 +193,34 @@ public: } private: - void indentBlockComment(const FormatToken &Tok, int BaseIndent) { + void indentBlockComment(const FormatToken &Tok, int Indent) { SourceLocation TokenLoc = Tok.Tok.getLocation(); + int IndentDelta = Indent - SourceMgr.getSpellingColumnNumber(TokenLoc) + 1; const char *Start = SourceMgr.getCharacterData(TokenLoc); const char *Current = Start; const char *TokEnd = Current + Tok.TokenLength; + llvm::SmallVector LineStarts; 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, "")); + LineStarts.push_back(TokenLoc.getLocWithOffset(Current - Start)); + // If we need to outdent the line, check that it's indented enough. + for (int i = 0; i < -IndentDelta; ++i, ++Current) + if (Current >= TokEnd || *Current != ' ') + return; } else { ++Current; } } + + for (size_t i = 0; i < LineStarts.size(); ++i) { + if (IndentDelta > 0) + Replaces.insert(tooling::Replacement(SourceMgr, LineStarts[i], 0, + std::string(IndentDelta, ' '))); + else if (IndentDelta < 0) + Replaces.insert( + tooling::Replacement(SourceMgr, LineStarts[i], -IndentDelta, "")); + } } std::string getNewLineText(unsigned NewLines, unsigned Spaces) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index ca7ed62ed1ec..4034d1a7b80b 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -619,14 +619,6 @@ TEST_F(FormatTest, AlignsMultiLineComments) { " * 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" @@ -641,6 +633,22 @@ TEST_F(FormatTest, AlignsMultiLineComments) { " */\n" "void f() {}\n" "};")); + EXPECT_EQ("/*\n" + " 1. This is a comment with non-trivial formatting.\n" + " 1.1. We have to indent/outdent all lines equally\n" + " 1.1.1. to keep the formatting.\n" + " */", + format(" /*\n" + " 1. This is a comment with non-trivial formatting.\n" + " 1.1. We have to indent/outdent all lines equally\n" + " 1.1.1. to keep the formatting.\n" + " */")); + EXPECT_EQ("/*\n" + " Don't try to outdent if there's not enough inentation.\n" + " */", + format(" /*\n" + " Don't try to outdent if there's not enough inentation.\n" + " */")); } TEST_F(FormatTest, CommentsInStaticInitializers) {