Skip to content

Commit bcb1b77

Browse files
[clang-format] Add option to separate comment alignment between ... (#165033)
normal lines and PP directives. Handling PP directives differently can be desired, like in #161848. Changing the default is not an option, there are tests for exactly the current behaviour.
1 parent 21aa788 commit bcb1b77

File tree

7 files changed

+112
-12
lines changed

7 files changed

+112
-12
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,16 @@ the configuration (without a prefix: ``Auto``).
16731673

16741674
int abcdef; // but this isn't
16751675

1676+
* ``bool AlignPPAndNotPP`` If comments following preprocessor directive should be aligned with
1677+
comments that don't.
1678+
1679+
.. code-block:: c++
1680+
1681+
true: false:
1682+
#define A // Comment vs. #define A // Comment
1683+
#define AB // Aligned #define AB // Aligned
1684+
int i; // Aligned int i; // Not aligned
1685+
16761686

16771687
.. _AllowAllArgumentsOnNextLine:
16781688

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ clang-format
653653
- Deprecate ``AlwaysBreak`` and ``BlockIndent`` suboptions from the
654654
``AlignAfterOpenBracket`` option, and make ``AlignAfterOpenBracket`` a
655655
``bool`` type.
656+
- Add ``AlignPPAndNotPP`` suboption to ``AlignTrailingComments``.
656657

657658
libclang
658659
--------

clang/include/clang/Format/Format.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,9 +601,19 @@ struct FormatStyle {
601601
/// int abcdef; // but this isn't
602602
/// \endcode
603603
unsigned OverEmptyLines;
604+
/// If comments following preprocessor directive should be aligned with
605+
/// comments that don't.
606+
/// \code
607+
/// true: false:
608+
/// #define A // Comment vs. #define A // Comment
609+
/// #define AB // Aligned #define AB // Aligned
610+
/// int i; // Aligned int i; // Not aligned
611+
/// \endcode
612+
bool AlignPPAndNotPP;
604613

605614
bool operator==(const TrailingCommentsAlignmentStyle &R) const {
606-
return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines;
615+
return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines &&
616+
AlignPPAndNotPP == R.AlignPPAndNotPP;
607617
}
608618
bool operator!=(const TrailingCommentsAlignmentStyle &R) const {
609619
return !(*this == R);

clang/lib/Format/Format.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -876,27 +876,28 @@ template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
876876
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
877877
IO.enumCase(Value, "Leave",
878878
FormatStyle::TrailingCommentsAlignmentStyle(
879-
{FormatStyle::TCAS_Leave, 0}));
879+
{FormatStyle::TCAS_Leave, 0, true}));
880880

881881
IO.enumCase(Value, "Always",
882882
FormatStyle::TrailingCommentsAlignmentStyle(
883-
{FormatStyle::TCAS_Always, 0}));
883+
{FormatStyle::TCAS_Always, 0, true}));
884884

885885
IO.enumCase(Value, "Never",
886886
FormatStyle::TrailingCommentsAlignmentStyle(
887-
{FormatStyle::TCAS_Never, 0}));
887+
{FormatStyle::TCAS_Never, 0, true}));
888888

889889
// For backwards compatibility
890890
IO.enumCase(Value, "true",
891891
FormatStyle::TrailingCommentsAlignmentStyle(
892-
{FormatStyle::TCAS_Always, 0}));
892+
{FormatStyle::TCAS_Always, 0, true}));
893893
IO.enumCase(Value, "false",
894894
FormatStyle::TrailingCommentsAlignmentStyle(
895-
{FormatStyle::TCAS_Never, 0}));
895+
{FormatStyle::TCAS_Never, 0, true}));
896896
}
897897

898898
static void mapping(IO &IO,
899899
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
900+
IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);
900901
IO.mapOptional("Kind", Value.Kind);
901902
IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
902903
}
@@ -1651,6 +1652,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
16511652
LLVMStyle.AlignTrailingComments = {};
16521653
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
16531654
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
1655+
LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
16541656
LLVMStyle.AllowAllArgumentsOnNextLine = true;
16551657
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
16561658
LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;

clang/lib/Format/WhitespaceManager.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,9 +1007,13 @@ void WhitespaceManager::alignTrailingComments() {
10071007
return;
10081008

10091009
const int Size = Changes.size();
1010+
if (Size == 0)
1011+
return;
1012+
10101013
int MinColumn = 0;
10111014
int StartOfSequence = 0;
10121015
bool BreakBeforeNext = false;
1016+
bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
10131017
int NewLineThreshold = 1;
10141018
if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
10151019
NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
@@ -1018,7 +1022,19 @@ void WhitespaceManager::alignTrailingComments() {
10181022
auto &C = Changes[I];
10191023
if (C.StartOfBlockComment)
10201024
continue;
1021-
Newlines += C.NewlinesBefore;
1025+
if (C.NewlinesBefore != 0) {
1026+
Newlines += C.NewlinesBefore;
1027+
const bool WasInPP = std::exchange(
1028+
IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||
1029+
C.ContinuesPPDirective);
1030+
if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
1031+
alignTrailingComments(StartOfSequence, I, MinColumn);
1032+
MinColumn = 0;
1033+
MaxColumn = INT_MAX;
1034+
StartOfSequence = I;
1035+
Newlines = 0;
1036+
}
1037+
}
10221038
if (!C.IsTrailingComment)
10231039
continue;
10241040

clang/unittests/Format/ConfigParseTest.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -589,20 +589,20 @@ TEST(ConfigParseTest, ParsesConfiguration) {
589589

590590
CHECK_PARSE("AlignTrailingComments: Leave", AlignTrailingComments,
591591
FormatStyle::TrailingCommentsAlignmentStyle(
592-
{FormatStyle::TCAS_Leave, 0}));
592+
{FormatStyle::TCAS_Leave, 0, true}));
593593
CHECK_PARSE("AlignTrailingComments: Always", AlignTrailingComments,
594594
FormatStyle::TrailingCommentsAlignmentStyle(
595-
{FormatStyle::TCAS_Always, 0}));
595+
{FormatStyle::TCAS_Always, 0, true}));
596596
CHECK_PARSE("AlignTrailingComments: Never", AlignTrailingComments,
597597
FormatStyle::TrailingCommentsAlignmentStyle(
598-
{FormatStyle::TCAS_Never, 0}));
598+
{FormatStyle::TCAS_Never, 0, true}));
599599
// For backwards compatibility
600600
CHECK_PARSE("AlignTrailingComments: true", AlignTrailingComments,
601601
FormatStyle::TrailingCommentsAlignmentStyle(
602-
{FormatStyle::TCAS_Always, 0}));
602+
{FormatStyle::TCAS_Always, 0, true}));
603603
CHECK_PARSE("AlignTrailingComments: false", AlignTrailingComments,
604604
FormatStyle::TrailingCommentsAlignmentStyle(
605-
{FormatStyle::TCAS_Never, 0}));
605+
{FormatStyle::TCAS_Never, 0, true}));
606606
CHECK_PARSE_NESTED_VALUE("Kind: Always", AlignTrailingComments, Kind,
607607
FormatStyle::TCAS_Always);
608608
CHECK_PARSE_NESTED_VALUE("Kind: Never", AlignTrailingComments, Kind,
@@ -611,6 +611,7 @@ TEST(ConfigParseTest, ParsesConfiguration) {
611611
FormatStyle::TCAS_Leave);
612612
CHECK_PARSE_NESTED_VALUE("OverEmptyLines: 1234", AlignTrailingComments,
613613
OverEmptyLines, 1234u);
614+
CHECK_PARSE_NESTED_BOOL(AlignTrailingComments, AlignPPAndNotPP);
614615

615616
Style.UseTab = FormatStyle::UT_ForIndentation;
616617
CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);

clang/unittests/Format/FormatTestComments.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3378,6 +3378,66 @@ TEST_F(FormatTestComments, DontAlignOverScope) {
33783378
"int foobar; // group");
33793379
}
33803380

3381+
TEST_F(FormatTestComments, DontAlignOverPPDirective) {
3382+
auto Style = getLLVMStyle();
3383+
Style.AlignTrailingComments.AlignPPAndNotPP = false;
3384+
3385+
verifyFormat("int i; // Aligned\n"
3386+
"int long; // with this\n"
3387+
"#define FOO // only aligned\n"
3388+
"#define LOOONG // with other pp directives\n"
3389+
"int loooong; // new alignment",
3390+
"int i;//Aligned\n"
3391+
"int long;//with this\n"
3392+
"#define FOO //only aligned\n"
3393+
"#define LOOONG //with other pp directives\n"
3394+
"int loooong; //new alignment",
3395+
Style);
3396+
3397+
verifyFormat("#define A // Comment\n"
3398+
"#define AB // Comment",
3399+
Style);
3400+
3401+
Style.ColumnLimit = 30;
3402+
verifyNoChange("#define A // Comment\n"
3403+
" // Continued\n"
3404+
"int i = 0; // New Stuff\n"
3405+
" // Continued\n"
3406+
"#define Func(X) \\\n"
3407+
" X(); \\\n"
3408+
" X(); // Comment\n"
3409+
" // Continued\n"
3410+
"long loong = 1; // Dont align",
3411+
Style);
3412+
3413+
verifyFormat("#define A // Comment that\n"
3414+
" // would wrap\n"
3415+
"#define FOO // For the\n"
3416+
" // alignment\n"
3417+
"#define B // Also\n"
3418+
" // aligned",
3419+
"#define A // Comment that would wrap\n"
3420+
"#define FOO // For the alignment\n"
3421+
"#define B // Also\n"
3422+
" // aligned",
3423+
Style);
3424+
3425+
Style.AlignTrailingComments.OverEmptyLines = 1;
3426+
verifyNoChange("#define A // Comment\n"
3427+
"\n"
3428+
" // Continued\n"
3429+
"int i = 0; // New Stuff\n"
3430+
"\n"
3431+
" // Continued\n"
3432+
"#define Func(X) \\\n"
3433+
" X(); \\\n"
3434+
" X(); // Comment\n"
3435+
"\n"
3436+
" // Continued\n"
3437+
"long loong = 1; // Dont align",
3438+
Style);
3439+
}
3440+
33813441
TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
33823442
verifyFormat("/*\n"
33833443
" */",

0 commit comments

Comments
 (0)