Skip to content

Commit b4bd206

Browse files
[clang-format] Add option to separate comment alignment between ...
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 228a353 commit b4bd206

File tree

7 files changed

+100
-12
lines changed

7 files changed

+100
-12
lines changed

clang/docs/ClangFormatStyleOptions.rst

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

17021702
int abcdef; // but this isn't
17031703

1704+
* ``bool AlignPPAndNotPP`` If comments following preprocessor directive should be aligned with
1705+
comments that don't.
1706+
1707+
.. code-block:: c++
1708+
1709+
true: false:
1710+
#define A // Comment vs. #define A // Comment
1711+
#define AB // Aligned #define AB // Aligned
1712+
int i; // Aligned int i; // Not aligned
1713+
17041714

17051715
.. _AllowAllArgumentsOnNextLine:
17061716

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ clang-format
609609
literals.
610610
- Add ``Leave`` suboption to ``IndentPPDirectives``.
611611
- Add ``AllowBreakBeforeQtProperty`` option.
612+
- Add ``AlignPPAndNotPP`` suboption to ``AlignTrailingComments``.
612613

613614
libclang
614615
--------

clang/include/clang/Format/Format.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,19 @@ struct FormatStyle {
622622
/// int abcdef; // but this isn't
623623
/// \endcode
624624
unsigned OverEmptyLines;
625+
/// If comments following preprocessor directive should be aligned with
626+
/// comments that don't.
627+
/// \code
628+
/// true: false:
629+
/// #define A // Comment vs. #define A // Comment
630+
/// #define AB // Aligned #define AB // Aligned
631+
/// int i; // Aligned int i; // Not aligned
632+
/// \endcode
633+
bool AlignPPAndNotPP;
625634

626635
bool operator==(const TrailingCommentsAlignmentStyle &R) const {
627-
return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines;
636+
return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines &&
637+
AlignPPAndNotPP == R.AlignPPAndNotPP;
628638
}
629639
bool operator!=(const TrailingCommentsAlignmentStyle &R) const {
630640
return !(*this == R);

clang/lib/Format/Format.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -869,27 +869,28 @@ template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
869869
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
870870
IO.enumCase(Value, "Leave",
871871
FormatStyle::TrailingCommentsAlignmentStyle(
872-
{FormatStyle::TCAS_Leave, 0}));
872+
{FormatStyle::TCAS_Leave, 0, true}));
873873

874874
IO.enumCase(Value, "Always",
875875
FormatStyle::TrailingCommentsAlignmentStyle(
876-
{FormatStyle::TCAS_Always, 0}));
876+
{FormatStyle::TCAS_Always, 0, true}));
877877

878878
IO.enumCase(Value, "Never",
879879
FormatStyle::TrailingCommentsAlignmentStyle(
880-
{FormatStyle::TCAS_Never, 0}));
880+
{FormatStyle::TCAS_Never, 0, true}));
881881

882882
// For backwards compatibility
883883
IO.enumCase(Value, "true",
884884
FormatStyle::TrailingCommentsAlignmentStyle(
885-
{FormatStyle::TCAS_Always, 0}));
885+
{FormatStyle::TCAS_Always, 0, true}));
886886
IO.enumCase(Value, "false",
887887
FormatStyle::TrailingCommentsAlignmentStyle(
888-
{FormatStyle::TCAS_Never, 0}));
888+
{FormatStyle::TCAS_Never, 0, true}));
889889
}
890890

891891
static void mapping(IO &IO,
892892
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
893+
IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);
893894
IO.mapOptional("Kind", Value.Kind);
894895
IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
895896
}
@@ -1578,6 +1579,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
15781579
LLVMStyle.AlignTrailingComments = {};
15791580
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
15801581
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
1582+
LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
15811583
LLVMStyle.AllowAllArgumentsOnNextLine = true;
15821584
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
15831585
LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;

clang/lib/Format/WhitespaceManager.cpp

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

999999
const int Size = Changes.size();
1000+
if (Size == 0)
1001+
return;
1002+
10001003
int MinColumn = 0;
10011004
int StartOfSequence = 0;
10021005
bool BreakBeforeNext = false;
1006+
bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
10031007
int NewLineThreshold = 1;
10041008
if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
10051009
NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
@@ -1008,7 +1012,19 @@ void WhitespaceManager::alignTrailingComments() {
10081012
auto &C = Changes[I];
10091013
if (C.StartOfBlockComment)
10101014
continue;
1011-
Newlines += C.NewlinesBefore;
1015+
if (C.NewlinesBefore != 0) {
1016+
Newlines += C.NewlinesBefore;
1017+
const bool WasInPP = std::exchange(
1018+
IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||
1019+
C.ContinuesPPDirective);
1020+
if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
1021+
alignTrailingComments(StartOfSequence, I, MinColumn);
1022+
MinColumn = 0;
1023+
MaxColumn = INT_MAX;
1024+
StartOfSequence = I;
1025+
Newlines = 0;
1026+
}
1027+
}
10121028
if (!C.IsTrailingComment)
10131029
continue;
10141030

clang/unittests/Format/ConfigParseTest.cpp

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

577577
CHECK_PARSE("AlignTrailingComments: Leave", AlignTrailingComments,
578578
FormatStyle::TrailingCommentsAlignmentStyle(
579-
{FormatStyle::TCAS_Leave, 0}));
579+
{FormatStyle::TCAS_Leave, 0, true}));
580580
CHECK_PARSE("AlignTrailingComments: Always", AlignTrailingComments,
581581
FormatStyle::TrailingCommentsAlignmentStyle(
582-
{FormatStyle::TCAS_Always, 0}));
582+
{FormatStyle::TCAS_Always, 0, true}));
583583
CHECK_PARSE("AlignTrailingComments: Never", AlignTrailingComments,
584584
FormatStyle::TrailingCommentsAlignmentStyle(
585-
{FormatStyle::TCAS_Never, 0}));
585+
{FormatStyle::TCAS_Never, 0, true}));
586586
// For backwards compatibility
587587
CHECK_PARSE("AlignTrailingComments: true", AlignTrailingComments,
588588
FormatStyle::TrailingCommentsAlignmentStyle(
589-
{FormatStyle::TCAS_Always, 0}));
589+
{FormatStyle::TCAS_Always, 0, true}));
590590
CHECK_PARSE("AlignTrailingComments: false", AlignTrailingComments,
591591
FormatStyle::TrailingCommentsAlignmentStyle(
592-
{FormatStyle::TCAS_Never, 0}));
592+
{FormatStyle::TCAS_Never, 0, true}));
593593
CHECK_PARSE_NESTED_VALUE("Kind: Always", AlignTrailingComments, Kind,
594594
FormatStyle::TCAS_Always);
595595
CHECK_PARSE_NESTED_VALUE("Kind: Never", AlignTrailingComments, Kind,
@@ -598,6 +598,7 @@ TEST(ConfigParseTest, ParsesConfiguration) {
598598
FormatStyle::TCAS_Leave);
599599
CHECK_PARSE_NESTED_VALUE("OverEmptyLines: 1234", AlignTrailingComments,
600600
OverEmptyLines, 1234u);
601+
CHECK_PARSE_NESTED_BOOL(AlignTrailingComments, AlignPPAndNotPP);
601602

602603
Style.UseTab = FormatStyle::UT_ForIndentation;
603604
CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);

clang/unittests/Format/FormatTestComments.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,6 +3501,54 @@ TEST_F(FormatTestComments, DontAlignOverScope) {
35013501
"int foobar; // group");
35023502
}
35033503

3504+
TEST_F(FormatTestComments, DontAlignOverPPDirective) {
3505+
auto Style = getLLVMStyle();
3506+
Style.AlignTrailingComments.AlignPPAndNotPP = false;
3507+
3508+
verifyFormat("int i; // Aligned\n"
3509+
"int long; // with this\n"
3510+
"#define FOO // only aligned\n"
3511+
"#define LOOONG // with other pp directives\n"
3512+
"int loooong; // new alignment",
3513+
"int i;//Aligned\n"
3514+
"int long;//with this\n"
3515+
"#define FOO //only aligned\n"
3516+
"#define LOOONG //with other pp directives\n"
3517+
"int loooong; //new alignment",
3518+
Style);
3519+
3520+
verifyFormat("#define A // Comment\n"
3521+
"#define AB // Comment",
3522+
Style);
3523+
3524+
Style.ColumnLimit = 30;
3525+
verifyNoChange("#define A // Comment\n"
3526+
" // Continued\n"
3527+
"int i = 0; // New Stuff\n"
3528+
" // Continued\n"
3529+
"#define Func(X) \\\n"
3530+
" X(); \\\n"
3531+
" X(); // Comment\n"
3532+
" // Continued\n"
3533+
"long loong = 1; // Dont align",
3534+
Style);
3535+
3536+
Style.AlignTrailingComments.OverEmptyLines = 1;
3537+
verifyNoChange("#define A // Comment\n"
3538+
"\n"
3539+
" // Continued\n"
3540+
"int i = 0; // New Stuff\n"
3541+
"\n"
3542+
" // Continued\n"
3543+
"#define Func(X) \\\n"
3544+
" X(); \\\n"
3545+
" X(); // Comment\n"
3546+
"\n"
3547+
" // Continued\n"
3548+
"long loong = 1; // Dont align",
3549+
Style);
3550+
}
3551+
35043552
TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
35053553
EXPECT_EQ("/*\n"
35063554
" */",

0 commit comments

Comments
 (0)