Index: lib/Format/BreakableToken.cpp =================================================================== --- lib/Format/BreakableToken.cpp +++ lib/Format/BreakableToken.cpp @@ -40,9 +40,15 @@ } } -static StringRef getLineCommentIndentPrefix(StringRef Comment) { - static const char *const KnownPrefixes[] = {"///<", "//!<", "///", "//", - "//!"}; +static StringRef getLineCommentIndentPrefix(StringRef Comment, + const FormatStyle &Style) { + static const SmallVector KnownCStylePrefixes{ + "///<", "//!<", "///", "//", "//!"}; + static const SmallVector KnownTextProtoPrefixes{"//", "#"}; + const SmallVectorImpl &KnownPrefixes = + (Style.Language == FormatStyle::LK_TextProto) ? KnownTextProtoPrefixes + : KnownCStylePrefixes; + StringRef LongestPrefix; for (StringRef KnownPrefix : KnownPrefixes) { if (Comment.startswith(KnownPrefix)) { @@ -732,7 +738,8 @@ CurrentTok = CurrentTok->Next) { LastLineTok = LineTok; StringRef TokenText(CurrentTok->TokenText); - assert(TokenText.startswith("//")); + assert((TokenText.startswith("//") || TokenText.startswith("#")) && + "unsupported line comment prefix, '//' and '#' are supported"); size_t FirstLineIndex = Lines.size(); TokenText.split(Lines, "\n"); Content.resize(Lines.size()); @@ -745,8 +752,9 @@ // We need to trim the blanks in case this is not the first line in a // multiline comment. Then the indent is included in Lines[i]. StringRef IndentPrefix = - getLineCommentIndentPrefix(Lines[i].ltrim(Blanks)); - assert(IndentPrefix.startswith("//")); + getLineCommentIndentPrefix(Lines[i].ltrim(Blanks), Style); + assert((TokenText.startswith("//") || TokenText.startswith("#")) && + "unsupported line comment prefix, '//' and '#' are supported"); OriginalPrefix[i] = Prefix[i] = IndentPrefix; if (Lines[i].size() > Prefix[i].size() && isAlphanumeric(Lines[i][Prefix[i].size()])) { @@ -760,6 +768,9 @@ Prefix[i] = "///< "; else if (Prefix[i] == "//!<") Prefix[i] = "//!< "; + else if (Prefix[i] == "#" && + Style.Language == FormatStyle::LK_TextProto) + Prefix[i] = "# "; } Tokens[i] = LineTok; Index: lib/Format/FormatTokenLexer.h =================================================================== --- lib/Format/FormatTokenLexer.h +++ lib/Format/FormatTokenLexer.h @@ -73,6 +73,8 @@ // nested template parts by balancing curly braces. void handleTemplateStrings(); + void tryParsePythonComment(); + bool tryMerge_TMacro(); bool tryMergeConflictMarkers(); Index: lib/Format/FormatTokenLexer.cpp =================================================================== --- lib/Format/FormatTokenLexer.cpp +++ lib/Format/FormatTokenLexer.cpp @@ -50,6 +50,9 @@ tryParseJSRegexLiteral(); handleTemplateStrings(); } + if (Style.Language == FormatStyle::LK_TextProto) { + tryParsePythonComment(); + } tryMergePreviousTokens(); if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline) FirstInLineIndex = Tokens.size() - 1; @@ -330,6 +333,27 @@ resetLexer(SourceMgr.getFileOffset(loc)); } +void FormatTokenLexer::tryParsePythonComment() { + FormatToken *HashToken = Tokens.back(); + if (HashToken->isNot(tok::hash)) + return; + // Turn the remainder of this line into a comment. + const char *CommentBegin = + Lex->getBufferLocation() - HashToken->TokenText.size(); // at "#" + size_t From = CommentBegin - Lex->getBuffer().begin(); + size_t To = Lex->getBuffer().find_first_of('\n', From); + if (To == StringRef::npos) To = Lex->getBuffer().size(); + size_t Len = To - From; + const char *CommentEnd = CommentBegin + Len; + HashToken->Type = TT_LineComment; + HashToken->Tok.setKind(tok::comment); + HashToken->TokenText = Lex->getBuffer().substr(From, Len); + SourceLocation Loc = To < Lex->getBuffer().size() + ? Lex->getSourceLocation(CommentEnd) + : SourceMgr.getLocForEndOfFile(ID); + resetLexer(SourceMgr.getFileOffset(Loc)); +} + bool FormatTokenLexer::tryMerge_TMacro() { if (Tokens.size() < 4) return false; Index: unittests/Format/FormatTestComments.cpp =================================================================== --- unittests/Format/FormatTestComments.cpp +++ unittests/Format/FormatTestComments.cpp @@ -62,6 +62,12 @@ return Style; } + FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) { + FormatStyle Style = getGoogleStyle(FormatStyle::FormatStyle::LK_TextProto); + Style.ColumnLimit = ColumnLimit; + return Style; + } + void verifyFormat(llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle()) { EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); @@ -2872,6 +2878,38 @@ " A = B;", getLLVMStyleWithColumns(40))); } + +TEST_F(FormatTestComments, TODO) { + EXPECT_EQ("# comment\n" + "key: value", + format("# comment\n" + "key: value", + getTextProtoStyleWithColumns(20))); + EXPECT_EQ("# comment comment\n" + "# comment\n" + "key: value", + format("# comment comment comment\n" + "key: value", + getTextProtoStyleWithColumns(20))); + EXPECT_EQ("data {\n" + " # comment comment\n" + " # comment\n" + " key: value\n" + "}", + format("data {\n" + "# comment comment comment\n" + "key: value}", + getTextProtoStyleWithColumns(20))); + EXPECT_EQ("data {\n" + " # comment comment\n" + " # comment\n" + " key: value\n" + "}", + format("data {# comment comment comment\n" + "key: value}", + getTextProtoStyleWithColumns(20))); + +} } // end namespace } // end namespace format } // end namespace clang