Index: lib/Format/WhitespaceManager.cpp =================================================================== --- lib/Format/WhitespaceManager.cpp +++ lib/Format/WhitespaceManager.cpp @@ -155,10 +155,15 @@ } } +static bool IsPointerOrReference(tok::TokenKind Kind) { + return Kind == tok::star || Kind == tok::amp || Kind == tok::ampamp; +} + // Align a single sequence of tokens, see AlignTokens below. template static void -AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches, +AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, + unsigned Column, F &&Matches, SmallVector &Changes) { bool FoundMatchOnLine = false; int Shift = 0; @@ -178,9 +183,23 @@ } assert(Shift >= 0); + if (Shift == 0) + continue; + Changes[i].StartOfTokenColumn += Shift; if (i + 1 != Changes.size()) Changes[i + 1].PreviousEndOfTokenColumn += Shift; + + // If PointerAlignment is PAS_Right, keep *s or &s next to the token + if (Style.PointerAlignment == FormatStyle::PAS_Right && + Changes[i].Spaces != 0) { + for (int previous = i - 1; + previous >= 0 && IsPointerOrReference(Changes[previous].Kind); + previous--) { + Changes[previous + 1].Spaces -= Shift; + Changes[previous].Spaces += Shift; + } + } } } @@ -227,8 +246,8 @@ // containing any matching token to be aligned and located after such token. auto AlignCurrentSequence = [&] { if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) - AlignTokenSequence(StartOfSequence, EndOfSequence, MinColumn, Matches, - Changes); + AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn, + Matches, Changes); MinColumn = 0; MaxColumn = UINT_MAX; StartOfSequence = 0; @@ -323,13 +342,6 @@ if (!Style.AlignConsecutiveDeclarations) return; - // FIXME: Currently we don't handle properly the PointerAlignment: Right - // The * and & are not aligned and are left dangling. Something has to be done - // about it, but it raises the question of alignment of code like: - // const char* const* v1; - // float const* v2; - // SomeVeryLongType const& v3; - AlignTokens(Style, [](Change const &C) { return C.IsStartOfDeclName; }, Changes); } @@ -367,8 +379,7 @@ unsigned CommentColumn = SourceMgr.getSpellingColumnNumber( Changes[i].OriginalWhitespaceRange.getEnd()); for (unsigned j = i + 1; j != e; ++j) { - if (Changes[j].Kind == tok::comment || - Changes[j].Kind == tok::unknown) + if (Changes[j].Kind == tok::comment || Changes[j].Kind == tok::unknown) // Skip over comments and unknown tokens. "unknown tokens are used for // the continuation of multiline comments. continue; @@ -489,8 +500,7 @@ } } -void WhitespaceManager::storeReplacement(SourceRange Range, - StringRef Text) { +void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) { unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) - SourceMgr.getFileOffset(Range.getBegin()); // Don't create a replacement, if it does not change anything. Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -8769,9 +8769,11 @@ verifyFormat("int oneTwoThree = {0}; // comment\n" "unsigned oneTwo = 0; // comment", Alignment); + + // PAS_RIGHT EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" " int const i = 1;\n" - " int * j = 2;\n" + " int *j = 2;\n" " int big = 10000;\n" "\n" " unsigned oneTwoThree = 123;\n" @@ -8792,6 +8794,131 @@ "int ll=10000;\n" "}", Alignment)); + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int **j = 2, ***k = 3;\n" + " int big = 10000;\n" + "\n" + " unsigned oneTwoThree = 123;\n" + " int oneTwo = 12;\n" + " method();\n" + " float k = 2;\n" + " int ll = 10000;\n" + "}", + format("void SomeFunction(int parameter= 0) {\n" + " int const i= 1;\n" + " int **j=2,***k=3;\n" + " int big = 10000;\n" + "\n" + "unsigned oneTwoThree =123;\n" + "int oneTwo = 12;\n" + " method();\n" + "float k= 2;\n" + "int ll=10000;\n" + "}", + Alignment)); + + // PAS_LEFT + FormatStyle AlignmentLeft = Alignment; + AlignmentLeft.PointerAlignment = FormatStyle::PAS_Left; + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int* j = 2;\n" + " int big = 10000;\n" + "\n" + " unsigned oneTwoThree = 123;\n" + " int oneTwo = 12;\n" + " method();\n" + " float k = 2;\n" + " int ll = 10000;\n" + "}", + format("void SomeFunction(int parameter= 0) {\n" + " int const i= 1;\n" + " int *j=2;\n" + " int big = 10000;\n" + "\n" + "unsigned oneTwoThree =123;\n" + "int oneTwo = 12;\n" + " method();\n" + "float k= 2;\n" + "int ll=10000;\n" + "}", + AlignmentLeft)); + // FIXME: one would expect " int** j = 2, *** k = 3;\n" + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int ** j = 2, ***k = 3;\n" + " int big = 10000;\n" + "\n" + " unsigned oneTwoThree = 123;\n" + " int oneTwo = 12;\n" + " method();\n" + " float k = 2;\n" + " int ll = 10000;\n" + "}", + format("void SomeFunction(int parameter= 0) {\n" + " int const i= 1;\n" + " int **j=2,***k=3;\n" + " int big = 10000;\n" + "\n" + "unsigned oneTwoThree =123;\n" + "int oneTwo = 12;\n" + " method();\n" + "float k= 2;\n" + "int ll=10000;\n" + "}", + AlignmentLeft)); + // PAS_MIDDLE + FormatStyle AlignmentMiddle = Alignment; + AlignmentMiddle.PointerAlignment = FormatStyle::PAS_Middle; + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int * j = 2;\n" + " int big = 10000;\n" + "\n" + " unsigned oneTwoThree = 123;\n" + " int oneTwo = 12;\n" + " method();\n" + " float k = 2;\n" + " int ll = 10000;\n" + "}", + format("void SomeFunction(int parameter= 0) {\n" + " int const i= 1;\n" + " int *j=2;\n" + " int big = 10000;\n" + "\n" + "unsigned oneTwoThree =123;\n" + "int oneTwo = 12;\n" + " method();\n" + "float k= 2;\n" + "int ll=10000;\n" + "}", + AlignmentMiddle)); + // FIXME: one would expect " int ** j = 2, *** k = 3;\n" + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int ** j = 2, ***k = 3;\n" + " int big = 10000;\n" + "\n" + " unsigned oneTwoThree = 123;\n" + " int oneTwo = 12;\n" + " method();\n" + " float k = 2;\n" + " int ll = 10000;\n" + "}", + format("void SomeFunction(int parameter= 0) {\n" + " int const i= 1;\n" + " int **j=2,***k=3;\n" + " int big = 10000;\n" + "\n" + "unsigned oneTwoThree =123;\n" + "int oneTwo = 12;\n" + " method();\n" + "float k= 2;\n" + "int ll=10000;\n" + "}", + AlignmentMiddle)); + Alignment.AlignConsecutiveAssignments = false; Alignment.AlignEscapedNewlinesLeft = true; verifyFormat("#define A \\\n" @@ -8818,7 +8945,7 @@ Alignment); verifyFormat("void SomeFunction(int parameter = 0) {\n" " int const i = 1;\n" - " int * j = 2;\n" + " int *j = 2;\n" " int big = 10000;\n" "}", Alignment); @@ -8922,7 +9049,7 @@ " float b,\n" " int c,\n" " uint32_t *d) {\n" - " int * e = 0;\n" + " int *e = 0;\n" " float f = 0;\n" " double g = 0;\n" "}\n"