diff options
| -rw-r--r-- | clang/lib/Format/WhitespaceManager.cpp | 54 | ||||
| -rw-r--r-- | clang/unittests/Format/FormatTestComments.cpp | 24 | 
2 files changed, 70 insertions, 8 deletions
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index c48883351c7..4b4fd13145f 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -100,14 +100,52 @@ void WhitespaceManager::calculateLineBreakInformation() {    Changes[0].PreviousEndOfTokenColumn = 0;    Change *LastOutsideTokenChange = &Changes[0];    for (unsigned i = 1, e = Changes.size(); i != e; ++i) { -    unsigned OriginalWhitespaceStart = -        SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin()); -    unsigned PreviousOriginalWhitespaceEnd = SourceMgr.getFileOffset( -        Changes[i - 1].OriginalWhitespaceRange.getEnd()); -    Changes[i - 1].TokenLength = OriginalWhitespaceStart - -                                 PreviousOriginalWhitespaceEnd + -                                 Changes[i].PreviousLinePostfix.size() + -                                 Changes[i - 1].CurrentLinePrefix.size(); +    SourceLocation OriginalWhitespaceStart = +        Changes[i].OriginalWhitespaceRange.getBegin(); +    SourceLocation PreviousOriginalWhitespaceEnd = +        Changes[i - 1].OriginalWhitespaceRange.getEnd(); +    unsigned OriginalWhitespaceStartOffset = +        SourceMgr.getFileOffset(OriginalWhitespaceStart); +    unsigned PreviousOriginalWhitespaceEndOffset = +        SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd); +    assert(PreviousOriginalWhitespaceEndOffset <= +           OriginalWhitespaceStartOffset); +    const char *const PreviousOriginalWhitespaceEndData = +        SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd); +    StringRef Text(PreviousOriginalWhitespaceEndData, +                   SourceMgr.getCharacterData(OriginalWhitespaceStart) - +                       PreviousOriginalWhitespaceEndData); +    // Usually consecutive changes would occur in consecutive tokens. This is +    // not the case however when analyzing some preprocessor runs of the +    // annotated lines. For example, in this code: +    // +    // #if A // line 1 +    // int i = 1; +    // #else B // line 2 +    // int i = 2; +    // #endif // line 3 +    // +    // one of the runs will produce the sequence of lines marked with line 1, 2 +    // and 3. So the two consecutive whitespace changes just before '// line 2' +    // and before '#endif // line 3' span multiple lines and tokens: +    // +    // #else B{change X}[// line 2 +    // int i = 2; +    // ]{change Y}#endif // line 3 +    // +    // For this reason, if the text between consecutive changes spans multiple +    // newlines, the token length must be adjusted to the end of the original +    // line of the token. +    auto NewlinePos = Text.find_first_of('\n'); +    if (NewlinePos == StringRef::npos) { +      Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset - +                                   PreviousOriginalWhitespaceEndOffset + +                                   Changes[i].PreviousLinePostfix.size() + +                                   Changes[i - 1].CurrentLinePrefix.size(); +    } else { +      Changes[i - 1].TokenLength = +          NewlinePos + Changes[i - 1].CurrentLinePrefix.size(); +    }      // If there are multiple changes in this token, sum up all the changes until      // the end of the line. diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index 09ee4645f59..fdb5a08e7a2 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -1052,6 +1052,30 @@ TEST_F(FormatTestComments, KeepsTrailingPPCommentsAndSectionCommentsSeparate) {                 "}", getLLVMStyleWithColumns(80));  } +TEST_F(FormatTestComments, AlignsPPElseEndifComments) { +  verifyFormat("#if A\n" +               "#else  // A\n" +               "int iiii;\n" +               "#endif // B", +               getLLVMStyleWithColumns(20)); +  verifyFormat("#if A\n" +               "#else  // A\n" +               "int iiii; // CC\n" +               "#endif // B", +               getLLVMStyleWithColumns(20)); +  EXPECT_EQ("#if A\n" +            "#else  // A1\n" +            "       // A2\n" +            "int ii;\n" +            "#endif // B", +            format("#if A\n" +                   "#else  // A1\n" +                   "       // A2\n" +                   "int ii;\n" +                   "#endif // B", +                   getLLVMStyleWithColumns(20))); +} +  TEST_F(FormatTestComments, CommentsInStaticInitializers) {    EXPECT_EQ(        "static SomeType type = {aaaaaaaaaaaaaaaaaaaa, /* comment */\n"  | 

