Index: lib/Format/WhitespaceManager.h =================================================================== --- lib/Format/WhitespaceManager.h +++ lib/Format/WhitespaceManager.h @@ -109,7 +109,8 @@ unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, unsigned NewlinesBefore, StringRef PreviousLinePostfix, StringRef CurrentLinePrefix, tok::TokenKind Kind, - bool ContinuesPPDirective, bool IsStartOfDeclName); + bool ContinuesPPDirective, bool IsStartOfDeclName, + bool IsInsideTrailingCommentToken); bool CreateReplacement; // Changes might be in the middle of a token, so we cannot just keep the @@ -139,6 +140,9 @@ // comments. Uncompensated negative offset is truncated to 0. int Spaces; + // If this change is inside of a token but not at the start of the token. + bool IsInsideToken; + // \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and // \c EscapedNewlineColumn will be calculated in // \c calculateLineBreakInformation. Index: lib/Format/WhitespaceManager.cpp =================================================================== --- lib/Format/WhitespaceManager.cpp +++ lib/Format/WhitespaceManager.cpp @@ -30,7 +30,7 @@ unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, unsigned NewlinesBefore, StringRef PreviousLinePostfix, StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective, - bool IsStartOfDeclName) + bool IsStartOfDeclName, bool IsInsideToken) : CreateReplacement(CreateReplacement), OriginalWhitespaceRange(OriginalWhitespaceRange), StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore), @@ -38,8 +38,8 @@ CurrentLinePrefix(CurrentLinePrefix), Kind(Kind), ContinuesPPDirective(ContinuesPPDirective), IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel), - Spaces(Spaces), IsTrailingComment(false), TokenLength(0), - PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0), + Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false), + TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0), StartOfBlockComment(nullptr), IndentationOffset(0) {} void WhitespaceManager::reset() { @@ -58,7 +58,8 @@ Change(/*CreateReplacement=*/true, Tok.WhitespaceRange, IndentLevel, Spaces, StartOfTokenColumn, Newlines, "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, - Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); + Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName), + /*IsInsideToken=*/false)); } void WhitespaceManager::addUntouchableToken(const FormatToken &Tok, @@ -69,7 +70,8 @@ /*CreateReplacement=*/false, Tok.WhitespaceRange, /*IndentLevel=*/0, /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst, - Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); + Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName), + /*IsInsideToken=*/false)); } void WhitespaceManager::replaceWhitespaceInToken( @@ -82,15 +84,10 @@ Changes.push_back(Change( true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)), IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix, - CurrentPrefix, - // If we don't add a newline this change doesn't start a comment. Thus, - // when we align line comments, we don't need to treat this change as one. - // FIXME: We still need to take this change in account to properly - // calculate the new length of the comment and to calculate the changes - // for which to do the alignment when aligning comments. - Tok.is(TT_LineComment) && Newlines > 0 ? tok::comment : tok::unknown, + CurrentPrefix, Tok.is(TT_LineComment) ? tok::comment : tok::unknown, InPPDirective && !Tok.IsFirst, - Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName))); + Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName), + /*IsInsideToken=*/true)); } const tooling::Replacements &WhitespaceManager::generateReplacements() { @@ -120,11 +117,28 @@ Changes[i].PreviousLinePostfix.size() + Changes[i - 1].CurrentLinePrefix.size(); + // If there are multiple changes in this token, sum up all the changes until + // the end of the line. + for (unsigned j = i; j != e; ++j) { + if (!Changes[j].IsInsideToken || Changes[j].NewlinesBefore > 0) + break; + + unsigned OriginalWhitespaceStart = SourceMgr.getFileOffset( + Changes[j].OriginalWhitespaceRange.getBegin()); + unsigned PreviousOriginalWhitespaceEnd = SourceMgr.getFileOffset( + Changes[j - 1].OriginalWhitespaceRange.getEnd()); + Changes[i - 1].TokenLength += + OriginalWhitespaceStart - PreviousOriginalWhitespaceEnd + + Changes[j].PreviousLinePostfix.size() + + Changes[j - 1].CurrentLinePrefix.size() + Changes[j].Spaces; + } + Changes[i].PreviousEndOfTokenColumn = Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength; Changes[i - 1].IsTrailingComment = - (Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof) && + (Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof || + (Changes[i].IsInsideToken && Changes[i].Kind == tok::comment)) && Changes[i - 1].Kind == tok::comment; } // FIXME: The last token is currently not always an eof token; in those @@ -134,6 +148,10 @@ const WhitespaceManager::Change *LastBlockComment = nullptr; for (auto &Change : Changes) { + // Reset the IsTrailingComment flag for changes inside of trailing comments + // so they don't get realigned later. + if (Change.IsInsideToken) + Change.IsTrailingComment = false; Change.StartOfBlockComment = nullptr; Change.IndentationOffset = 0; if (Change.Kind == tok::comment) { Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -1022,6 +1022,15 @@ " lineWith(); // comment\n" " // at start\n" "}")); + EXPECT_EQ("int xy; // a\n" + "int z; // b", + format("int xy; // a\n" + "int z; //b")); + EXPECT_EQ("int xy; // a\n" + "int z; // bb", + format("int xy; // a\n" + "int z; //bb", + getLLVMStyleWithColumns(12))); verifyFormat("#define A \\\n" " int i; /* iiiiiiiiiiiiiiiiiiiii */ \\\n"