diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -262,7 +262,8 @@ // 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; @@ -365,9 +366,24 @@ Changes[i].Spaces += Shift; 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 && + Changes[previous].Tok->getType() == TT_PointerOrReference; + previous--) { + Changes[previous + 1].Spaces -= Shift; + Changes[previous].Spaces += Shift; + } + } } } @@ -437,8 +453,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; @@ -728,12 +744,6 @@ if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None) 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) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15039,9 +15039,11 @@ " double bar();\n" "};\n", 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" @@ -15062,6 +15064,140 @@ "int ll=10000;\n" "}", Alignment)); + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int **j = 2, ***k;\n" + " int &k = i;\n" + " int &&l = i + j;\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;\n" + "int &k=i;\n" + "int &&l=i+j;\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)); + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int** j = 2;\n" + " int& k = i;\n" + " int&& l = i + j;\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 &k=i;\n" + "int &&l=i+j;\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)); + EXPECT_EQ("void SomeFunction(int parameter = 0) {\n" + " int const i = 1;\n" + " int ** j = 2, ***k;\n" + " int & k = i;\n" + " int && l = i + j;\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;\n" + "int &k=i;\n" + "int &&l=i+j;\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 = FormatStyle::ACS_None; Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; verifyFormat("#define A \\\n"