diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 74aa8a2795150..92530cd232a01 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -1000,14 +1000,19 @@ void WhitespaceManager::alignTrailingComments() { bool BreakBeforeNext = false; bool IsInPP = Changes.front().Tok->Tok.is(tok::hash); int NewLineThreshold = 1; + const Change *LastChangeToCompare = nullptr; + const Change *LastNewlineChange = nullptr; if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always) NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1; for (int I = 0, MaxColumn = INT_MAX, Newlines = 0; I < Size; ++I) { auto &C = Changes[I]; + if (LastNewlineChange) + LastChangeToCompare = std::exchange(LastNewlineChange, nullptr); if (C.StartOfBlockComment) continue; if (C.NewlinesBefore != 0) { + LastNewlineChange = &C; Newlines += C.NewlinesBefore; const bool WasInPP = std::exchange( IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) || @@ -1036,7 +1041,19 @@ void WhitespaceManager::alignTrailingComments() { if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0) break; - int Spaces = + const auto *NextChange = I + 1 < Size ? &Changes[I + 1] : nullptr; + assert(!NextChange || NextChange->NewlinesBefore > 0 || + NextChange->Tok->is(tok::eof)); + auto ChangeIsMoved = [&C](const Change *ChangeToCompare) { + return ChangeToCompare && + C.Tok->OriginalColumn == ChangeToCompare->Tok->OriginalColumn && + C.Spaces == ChangeToCompare->Spaces; + }; + if (C.NewlinesBefore > 0 && + (ChangeIsMoved(LastChangeToCompare) || ChangeIsMoved(NextChange))) { + continue; + } + const int Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces; setChangeSpaces(I, Spaces); continue; diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index 707016096f7d2..a8620d6e9af40 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -3060,6 +3060,42 @@ TEST_F(FormatTestComments, AlignTrailingCommentsLeave) { "}", Style); + // Move comments along, when it appears, that the indentation changed when a + // scope has been added or removed. + verifyFormat("void func() {\n" + " int i;\n" + " // comment\n" + " // comment 2\n" + "}", + "void func() {\n" + " int i;\n" + " // comment\n" + " // comment 2\n" + "}", + Style); + + verifyFormat("void func() {\n" + " // comment\n" + " // comment 2\n" + " int i;\n" + "}", + "void func() {\n" + " // comment\n" + " // comment 2\n" + " int i;\n" + "}", + Style); + + verifyFormat("void func() {\n" + " // not moved, was not at normal indentation\n" + " int i;\n" + "}", + "void func() {\n" + " // not moved, was not at normal indentation\n" + " int i;\n" + "}", + Style); + Style.AlignEscapedNewlines = FormatStyle::ENAS_Left; verifyNoChange("#define FOO \\\n" " /* foo(); */ \\\n"