diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -762,6 +762,130 @@ bbb >>= 2; +**AlignConsecutiveTrailingComments** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 16` + Style of aligning consecutive trailing comments. + This option existed as ``AlignTrailingComments`` since version 3.7. + + ``Consecutive`` will align the trailing comments of consecutive lines. + This will result in formattings like: + + .. code-block:: c++ + + true: false: + int a; // My comment a vs. int a; // My comment a + int b = 2; // comment b int b = 2; // comment about b + + Nested configuration flags: + + Alignment options. + + They can also be read as a whole for compatibility. The choices are: + - None + - Consecutive + - AcrossEmptyLines + - AcrossComments + - AcrossEmptyLinesAndComments + + For example, to align across empty lines and not across comments, either + of these work. + + .. code-block:: c++ + + AlignConsecutiveMacros: AcrossEmptyLines + + AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false + + * ``bool Enabled`` Whether aligning is enabled. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + #define foo(x) (x * x) + #define bar(y, z) (y + z) + + int a = 1; + int somelongname = 2; + double c = 3; + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int aaaa = 12; + float b = 23; + std::string ccc; + + * ``bool AcrossEmptyLines`` Whether to align across empty lines. + + .. code-block:: c++ + + true: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + false: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + * ``bool AcrossComments`` Whether to align across comments. + + .. code-block:: c++ + + true: + int d = 3; + /* A comment. */ + double e = 4; + + false: + int d = 3; + /* A comment. */ + double e = 4; + + * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``. Whether compound assignments + like ``+=`` are aligned along with ``=``. + + .. code-block:: c++ + + true: + a &= 2; + bbb = 2; + + false: + a &= 2; + bbb = 2; + + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment + operators are left-padded to the same length as long ones in order to + put all assignment operators to the right of the left hand side. + + .. code-block:: c++ + + true: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + false: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + **AlignEscapedNewlines** (``EscapedNewlineAlignmentStyle``) :versionbadge:`clang-format 5` Options for aligning backslashes in escaped newlines. @@ -847,13 +971,7 @@ **AlignTrailingComments** (``Boolean``) :versionbadge:`clang-format 3.7` - If ``true``, aligns trailing comments. - - .. code-block:: c++ - - true: false: - int a; // My comment a vs. int a; // My comment a - int b = 2; // comment b int b = 2; // comment about b + This option is **deprecated**. See ``AlignConsecutiveTrailingComments``. **AllowAllArgumentsOnNextLine** (``Boolean``) :versionbadge:`clang-format 9` If a function call or braced initializer list doesn't fit on a @@ -3567,7 +3685,7 @@ .. code-block:: yaml - QualifierOrder: ['inline', 'static', 'type', 'const'] + QualifierOrder: ['inline', 'static' , 'type', 'const'] .. code-block:: c++ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -294,6 +294,18 @@ /// \endcode /// \version 3.8 AlignConsecutiveStyle AlignConsecutiveDeclarations; + /// Style of aligning consecutive trailing comments. + /// This option existed as ``AlignTrailingComments`` since version 3.7. + /// + /// ``Consecutive`` will align the trailing comments of consecutive lines. + /// This will result in formattings like: + /// \code + /// true: false: + /// int a; // My comment a vs. int a; // My comment a + /// int b = 2; // comment b int b = 2; // comment about b + /// \endcode + /// \version 16 + AlignConsecutiveStyle AlignConsecutiveTrailingComments; /// Different styles for aligning escaped newlines. enum EscapedNewlineAlignmentStyle : int8_t { @@ -369,14 +381,9 @@ /// \version 3.5 OperandAlignmentStyle AlignOperands; - /// If ``true``, aligns trailing comments. - /// \code - /// true: false: - /// int a; // My comment a vs. int a; // My comment a - /// int b = 2; // comment b int b = 2; // comment about b - /// \endcode + /// This option is **deprecated**. See ``AlignConsecutiveTrailingComments``. /// \version 3.7 - bool AlignTrailingComments; + // bool AlignTrailingComments; /// \brief If a function call or braced initializer list doesn't fit on a /// line, allow putting all arguments onto the next line, even if @@ -3854,9 +3861,10 @@ AlignConsecutiveBitFields == R.AlignConsecutiveBitFields && AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations && AlignConsecutiveMacros == R.AlignConsecutiveMacros && + AlignConsecutiveTrailingComments == + R.AlignConsecutiveTrailingComments && AlignEscapedNewlines == R.AlignEscapedNewlines && AlignOperands == R.AlignOperands && - AlignTrailingComments == R.AlignTrailingComments && AllowAllArgumentsOnNextLine == R.AllowAllArgumentsOnNextLine && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -625,6 +625,8 @@ // For backward compatibility. if (!IO.outputting()) { IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); + IO.mapOptional("AlignTrailingComments", + Style.AlignConsecutiveTrailingComments.Enabled); IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); IO.mapOptional("IndentFunctionDeclarationAfterType", Style.IndentWrappedFunctionNames); @@ -644,9 +646,10 @@ IO.mapOptional("AlignConsecutiveDeclarations", Style.AlignConsecutiveDeclarations); IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); + IO.mapOptional("AlignConsecutiveTrailingComments", + Style.AlignConsecutiveTrailingComments); IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); IO.mapOptional("AlignOperands", Style.AlignOperands); - IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllArgumentsOnNextLine", Style.AllowAllArgumentsOnNextLine); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", @@ -1181,7 +1184,6 @@ LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; LLVMStyle.AlignOperands = FormatStyle::OAS_Align; - LLVMStyle.AlignTrailingComments = true; LLVMStyle.AlignConsecutiveAssignments = {}; LLVMStyle.AlignConsecutiveAssignments.Enabled = false; LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false; @@ -1191,6 +1193,8 @@ LLVMStyle.AlignConsecutiveBitFields = {}; LLVMStyle.AlignConsecutiveDeclarations = {}; LLVMStyle.AlignConsecutiveMacros = {}; + LLVMStyle.AlignConsecutiveTrailingComments = {}; + LLVMStyle.AlignConsecutiveTrailingComments.Enabled = true; LLVMStyle.AllowAllArgumentsOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortEnumsOnASingleLine = true; @@ -1447,7 +1451,7 @@ if (Language == FormatStyle::LK_Java) { GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; - GoogleStyle.AlignTrailingComments = false; + GoogleStyle.AlignConsecutiveTrailingComments.Enabled = false; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; @@ -1595,7 +1599,7 @@ Style.AccessModifierOffset = -4; Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; Style.AlignOperands = FormatStyle::OAS_DontAlign; - Style.AlignTrailingComments = false; + Style.AlignConsecutiveTrailingComments.Enabled = false; Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 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 @@ -927,6 +927,10 @@ unsigned StartOfSequence = 0; bool BreakBeforeNext = false; unsigned Newlines = 0; + unsigned int NewLineThreshold = + Style.AlignConsecutiveTrailingComments.AcrossEmptyLines + ? Style.MaxEmptyLinesToKeep + 1 + : 1; for (unsigned i = 0, e = Changes.size(); i != e; ++i) { if (Changes[i].StartOfBlockComment) continue; @@ -957,7 +961,7 @@ Changes[i - 1].Tok->is(tok::r_brace) && Changes[i - 1].StartOfTokenColumn == 0; bool WasAlignedWithStartOfNextLine = false; - if (Changes[i].NewlinesBefore == 1) { // A comment on its own line. + if (Changes[i].NewlinesBefore >= 1) { // A comment on its own line. unsigned CommentColumn = SourceMgr.getSpellingColumnNumber( Changes[i].OriginalWhitespaceRange.getEnd()); for (unsigned j = i + 1; j != e; ++j) { @@ -974,12 +978,13 @@ break; } } - if (!Style.AlignTrailingComments || FollowsRBraceInColumn0) { + if (!Style.AlignConsecutiveTrailingComments.Enabled || + FollowsRBraceInColumn0) { alignTrailingComments(StartOfSequence, i, MinColumn); MinColumn = ChangeMinColumn; MaxColumn = ChangeMinColumn; StartOfSequence = i; - } else if (BreakBeforeNext || Newlines > 1 || + } else if (BreakBeforeNext || Newlines > NewLineThreshold || (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) || // Break the comment sequence if the previous line did not end // in a trailing comment. 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 @@ -20041,7 +20041,6 @@ TEST_F(FormatTest, ParsesConfigurationBools) { FormatStyle Style = {}; Style.Language = FormatStyle::LK_Cpp; - CHECK_PARSE_BOOL(AlignTrailingComments); CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); @@ -20212,6 +20211,12 @@ CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveBitFields); CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveMacros); CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveDeclarations); + CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveTrailingComments); + // For backwards compatibility + CHECK_PARSE("AlignTrailingComments: true", + AlignConsecutiveTrailingComments.Enabled, true); + CHECK_PARSE("AlignTrailingComments: false", + AlignConsecutiveTrailingComments.Enabled, false); #undef CHECK_ALIGN_CONSECUTIVE diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -2858,6 +2858,182 @@ "int a; //\n"); } +TEST_F(FormatTestComments, AlignTrailingCommentsAcrossEmptyLines) { + FormatStyle Style = getLLVMStyle(); + Style.AlignConsecutiveTrailingComments.AcrossEmptyLines = true; + verifyFormat("#include \"a.h\" // simple\n" + "\n" + "#include \"aa.h\" // example case\n", + Style); + + verifyFormat("#include \"a.h\" // align across\n" + "\n" + "#include \"aa.h\" // two empty lines\n" + "\n" + "#include \"aaa.h\" // in a row\n", + Style); + + verifyFormat("#include \"a.h\" // align\n" + "#include \"aa.h\" // comment\n" + "#include \"aaa.h\" // blocks\n" + "\n" + "#include \"aaaa.h\" // across\n" + "#include \"aaaaa.h\" // one\n" + "#include \"aaaaaa.h\" // empty line\n", + Style); + + verifyFormat("#include \"a.h\" // align trailing comments\n" + "#include \"a.h\"\n" + "#include \"aa.h\" // across a line without comment\n", + Style); + + verifyFormat("#include \"a.h\" // align across\n" + "#include \"a.h\"\n" + "#include \"aa.h\" // two lines without comment\n" + "#include \"a.h\"\n" + "#include \"aaa.h\" // in a row\n", + Style); + + verifyFormat("#include \"a.h\" // align\n" + "#include \"aa.h\" // comment\n" + "#include \"aaa.h\" // blocks\n" + "#include \"a.h\"\n" + "#include \"aaaa.h\" // across\n" + "#include \"aaaaa.h\" // a line without\n" + "#include \"aaaaaa.h\" // comment\n", + Style); + + // Start of testing the combination with MaxEmptyLinesToKeep + Style.MaxEmptyLinesToKeep = 0; + verifyFormat("#include \"a.h\" // comment\n" + "#include \"aa.h\" // comment\n", + Style); + + Style.MaxEmptyLinesToKeep = 1; + verifyFormat("#include \"a.h\" // comment\n" + "\n" + "#include \"aa.h\" // comment\n", + Style); + + Style.MaxEmptyLinesToKeep = 2; + verifyFormat("#include \"a.h\" // comment\n" + "\n" + "\n" + "#include \"aa.h\" // comment\n", + Style); + + // Reset the setting + Style.MaxEmptyLinesToKeep = 1; + // End of testing the combination with MaxEmptyLinesToKeep + + Style.ColumnLimit = 15; + EXPECT_EQ("int ab; // line\n" + "int a; // long\n" + " // long\n" + "\n" + " // long", + format("int ab; // line\n" + "int a; // long long\n" + "\n" + "// long", + Style)); + + Style.ColumnLimit = 15; + EXPECT_EQ("int ab; // line\n" + "\n" + "int a; // long\n" + " // long\n", + format("int ab; // line\n" + "\n" + "int a; // long long\n", + Style)); + + Style.ColumnLimit = 30; + EXPECT_EQ("int foo = 12345; // comment\n" + "int bar =\n" + " 1234; // This is a very\n" + " // long comment\n" + " // which is wrapped\n" + " // arround.\n" + "\n" + "int x = 2; // Is this still\n" + " // aligned?\n", + format("int foo = 12345; // comment\n" + "int bar = 1234; // This is a very long comment\n" + " // which is wrapped arround.\n" + "\n" + "int x = 2; // Is this still aligned?\n", + Style)); + + Style.ColumnLimit = 35; + EXPECT_EQ("int foo = 12345; // comment\n" + "int bar =\n" + " 1234; // This is a very long\n" + " // comment which is\n" + " // wrapped arround.\n" + "\n" + "int x =\n" + " 2; // Is this still aligned?\n", + format("int foo = 12345; // comment\n" + "int bar = 1234; // This is a very long comment\n" + " // which is wrapped arround.\n" + "\n" + "int x = 2; // Is this still aligned?\n", + Style)); + + Style.ColumnLimit = 40; + EXPECT_EQ("int foo = 12345; // comment\n" + "int bar =\n" + " 1234; // This is a very long comment\n" + " // which is wrapped arround.\n" + "\n" + "int x = 2; // Is this still aligned?\n", + format("int foo = 12345; // comment\n" + "int bar = 1234; // This is a very long comment\n" + " // which is wrapped arround.\n" + "\n" + "int x = 2; // Is this still aligned?\n", + Style)); + + Style.ColumnLimit = 45; + EXPECT_EQ("int foo = 12345; // comment\n" + "int bar =\n" + " 1234; // This is a very long comment\n" + " // which is wrapped arround.\n" + "\n" + "int x = 2; // Is this still aligned?\n", + format("int foo = 12345; // comment\n" + "int bar = 1234; // This is a very long comment\n" + " // which is wrapped arround.\n" + "\n" + "int x = 2; // Is this still aligned?\n", + Style)); + + Style.ColumnLimit = 80; + EXPECT_EQ("int a; // line about a\n" + "\n" + "// line about b\n" + "long b;", + format("int a; // line about a\n" + "\n" + " // line about b\n" + " long b;", + Style)); + + Style.ColumnLimit = 80; + EXPECT_EQ("int a; // line about a\n" + "\n" + "// line 1 about b\n" + "// line 2 about b\n" + "long b;", + format("int a; // line about a\n" + "\n" + " // line 1 about b\n" + " // line 2 about b\n" + " long b;", + Style)); +} + TEST_F(FormatTestComments, AlignsBlockCommentDecorations) { EXPECT_EQ("/*\n" " */",