[clang] [clang-tools-extra] [clang-format] Aggregate options regarding empty lines (PR #96770)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 26 07:16:22 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: None (sstwcw)
<details>
<summary>Changes</summary>
The new option is `KeepEmptyLines`.
This patch was initially part of 9267f8f19a2e502e. I neglected to check the server builds before I added it. It broke clangd. Jie Fu fixed the problem in 4c91b49bab0728d4. I was unaware of it. I thought the main branch was still broken. I reverted the first patch in 70cfece24d6cbb57. It broke his fix. He reverted it in c69ea04fb9738db2. Because of all this mess, I believe this change is complicated enough to have its own patch.
---
Full diff: https://github.com/llvm/llvm-project/pull/96770.diff
8 Files Affected:
- (modified) clang-tools-extra/clangd/Format.cpp (+4-1)
- (modified) clang/docs/ClangFormatStyleOptions.rst (+35-10)
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/include/clang/Format/Format.h (+36-15)
- (modified) clang/lib/Format/Format.cpp (+16-6)
- (modified) clang/lib/Format/UnwrappedLineFormatter.cpp (+4-4)
- (modified) clang/unittests/Format/ConfigParseTest.cpp (+5-2)
- (modified) clang/unittests/Format/FormatTest.cpp (+3-3)
``````````diff
diff --git a/clang-tools-extra/clangd/Format.cpp b/clang-tools-extra/clangd/Format.cpp
index 272a34d4ed797..bd5e31b538d87 100644
--- a/clang-tools-extra/clangd/Format.cpp
+++ b/clang-tools-extra/clangd/Format.cpp
@@ -281,7 +281,10 @@ formatIncremental(llvm::StringRef OriginalCode, unsigned OriginalCursor,
// Never *remove* lines in response to pressing enter! This annoys users.
if (InsertedText == "\n") {
Style.MaxEmptyLinesToKeep = 1000;
- Style.KeepEmptyLinesAtTheStartOfBlocks = true;
+ Style.KeepEmptyLines = {
+ /*AtEndOfFile=*/true,
+ /*AtStartOfBlock=*/true,
+ };
}
// Compute the code we want to format:
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index bb00c20922d36..0480bd97a145f 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4443,23 +4443,48 @@ the configuration (without a prefix: ``Auto``).
false:
import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js"
+.. _KeepEmptyLines:
+
+**KeepEmptyLines** (``KeepEmptyLinesStyle``) :versionbadge:`clang-format 19` :ref:`¶ <KeepEmptyLines>`
+ Which empty lines are kept. See ``MaxEmptyLinesToKeep`` for how many
+ consecutive empty lines are kept.
+
+ Nested configuration flags:
+
+ Options regarding which empty lines are kept.
+
+ For example, the config below will remove empty lines at the end of the
+ file, and the start of blocks.
+
+
+ .. code-block:: c++
+
+ KeepEmptyLines:
+ AtEndOfFile: false
+ AtStartOfBlock: false
+
+ * ``bool AtEndOfFile`` Keep empty lines at end of file.
+
+ * ``bool AtStartOfBlock`` Keep empty lines at start of a block.
+
+ .. code-block:: c++
+
+ true: false:
+ if (foo) { vs. if (foo) {
+ bar();
+ bar(); }
+ }
+
+
.. _KeepEmptyLinesAtEOF:
**KeepEmptyLinesAtEOF** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ <KeepEmptyLinesAtEOF>`
- Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
+ This option is deprecated. See ``AtEndOfFile`` of ``KeepEmptyLines``.
.. _KeepEmptyLinesAtTheStartOfBlocks:
**KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <KeepEmptyLinesAtTheStartOfBlocks>`
- If true, the empty line at the start of blocks is kept.
-
- .. code-block:: c++
-
- true: false:
- if (foo) { vs. if (foo) {
- bar();
- bar(); }
- }
+ This option is deprecated. See ``AtStartOfBlock`` of ``KeepEmptyLines``.
.. _LambdaBodyIndentation:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index df579ae398c5e..9ed3ff4507671 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1110,6 +1110,8 @@ clang-format
- Adds ``AllowShortCaseExpressionOnASingleLine`` option.
- Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``.
- Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``.
+- Adds ``KeepEmptyLines`` option to deprecate ``KeepEmptyLinesAtEOF``
+ and ``KeepEmptyLinesAtTheStartOfBlocks``.
libclang
--------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 7d257be10af42..d6c1d75570557 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3095,20 +3095,44 @@ struct FormatStyle {
bool JavaScriptWrapImports;
// clang-format on
- /// Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
- /// \version 17
- bool KeepEmptyLinesAtEOF;
-
- /// If true, the empty line at the start of blocks is kept.
+ /// Options regarding which empty lines are kept.
+ ///
+ /// For example, the config below will remove empty lines at the end of the
+ /// file, and the start of blocks.
+ ///
/// \code
- /// true: false:
- /// if (foo) { vs. if (foo) {
- /// bar();
- /// bar(); }
- /// }
+ /// KeepEmptyLines:
+ /// AtEndOfFile: false
+ /// AtStartOfBlock: false
/// \endcode
+ struct KeepEmptyLinesStyle {
+ /// Keep empty lines at end of file.
+ bool AtEndOfFile;
+ /// Keep empty lines at start of a block.
+ /// \code
+ /// true: false:
+ /// if (foo) { vs. if (foo) {
+ /// bar();
+ /// bar(); }
+ /// }
+ /// \endcode
+ bool AtStartOfBlock;
+ bool operator==(const KeepEmptyLinesStyle &R) const {
+ return AtEndOfFile == R.AtEndOfFile && AtStartOfBlock == R.AtStartOfBlock;
+ }
+ };
+ /// Which empty lines are kept. See ``MaxEmptyLinesToKeep`` for how many
+ /// consecutive empty lines are kept.
+ /// \version 19
+ KeepEmptyLinesStyle KeepEmptyLines;
+
+ /// This option is deprecated. See ``AtEndOfFile`` of ``KeepEmptyLines``.
+ /// \version 17
+ // bool KeepEmptyLinesAtEOF;
+
+ /// This option is deprecated. See ``AtStartOfBlock`` of ``KeepEmptyLines``.
/// \version 3.7
- bool KeepEmptyLinesAtTheStartOfBlocks;
+ // bool KeepEmptyLinesAtTheStartOfBlocks;
/// Indentation logic for lambda bodies.
enum LambdaBodyIndentationKind : int8_t {
@@ -5033,10 +5057,7 @@ struct FormatStyle {
JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&
- KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF &&
- KeepEmptyLinesAtTheStartOfBlocks ==
- R.KeepEmptyLinesAtTheStartOfBlocks &&
- Language == R.Language &&
+ KeepEmptyLines == R.KeepEmptyLines && Language == R.Language &&
LambdaBodyIndentation == R.LambdaBodyIndentation &&
LineEnding == R.LineEnding && MacroBlockBegin == R.MacroBlockBegin &&
MacroBlockEnd == R.MacroBlockEnd && Macros == R.Macros &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index cd21fbb2221ac..c1e76ff391873 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -369,6 +369,13 @@ template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {
+ static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {
+ IO.mapOptional("AtEndOfFile", Value.AtEndOfFile);
+ IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
@@ -869,6 +876,9 @@ template <> struct MappingTraits<FormatStyle> {
OnCurrentLine);
IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
+ IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile);
+ IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
+ Style.KeepEmptyLines.AtStartOfBlock);
IO.mapOptional("IndentFunctionDeclarationAfterType",
Style.IndentWrappedFunctionNames);
IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
@@ -1004,9 +1014,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
- IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
- Style.KeepEmptyLinesAtTheStartOfBlocks);
- IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
+ IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines);
IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
IO.mapOptional("LineEnding", Style.LineEnding);
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
@@ -1517,8 +1525,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
/*Hex=*/0, /*HexMinDigits=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
- LLVMStyle.KeepEmptyLinesAtEOF = false;
- LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
+ LLVMStyle.KeepEmptyLines = {
+ /*AtEndOfFile=*/false,
+ /*AtStartOfBlock=*/true,
+ };
LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
LLVMStyle.Language = Language;
LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
@@ -1641,7 +1651,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
{".*", 3, 0, false}};
GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
GoogleStyle.IndentCaseLabels = true;
- GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
+ GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;
GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
GoogleStyle.ObjCSpaceAfterProperty = false;
GoogleStyle.ObjCSpaceBeforeProtocolList = true;
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 729f3d78f4a35..9f9623b5c5ef8 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1482,7 +1482,7 @@ static auto computeNewlines(const AnnotatedLine &Line,
Newlines = 0;
// Remove empty lines after "{".
- if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
+ if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
PreviousLine->Last->is(tok::l_brace) &&
!PreviousLine->startsWithNamespace() &&
!(PrevPrevLine && PrevPrevLine->startsWithNamespace() &&
@@ -1554,9 +1554,9 @@ void UnwrappedLineFormatter::formatFirstToken(
unsigned NewlineIndent) {
FormatToken &RootToken = *Line.First;
if (RootToken.is(tok::eof)) {
- unsigned Newlines =
- std::min(RootToken.NewlinesBefore,
- Style.KeepEmptyLinesAtEOF ? Style.MaxEmptyLinesToKeep + 1 : 1);
+ unsigned Newlines = std::min(
+ RootToken.NewlinesBefore,
+ Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
unsigned TokenIndent = Newlines ? NewlineIndent : 0;
Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
TokenIndent);
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index aded3ed2a6596..216bda508f924 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -178,8 +178,9 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(IndentWrappedFunctionNames);
CHECK_PARSE_BOOL(InsertBraces);
CHECK_PARSE_BOOL(InsertNewlineAtEOF);
- CHECK_PARSE_BOOL(KeepEmptyLinesAtEOF);
- CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks);
+ CHECK_PARSE_BOOL_FIELD(KeepEmptyLines.AtEndOfFile, "KeepEmptyLinesAtEOF");
+ CHECK_PARSE_BOOL_FIELD(KeepEmptyLines.AtStartOfBlock,
+ "KeepEmptyLinesAtTheStartOfBlocks");
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
@@ -226,6 +227,8 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyNamespace);
+ CHECK_PARSE_NESTED_BOOL(KeepEmptyLines, AtEndOfFile);
+ CHECK_PARSE_NESTED_BOOL(KeepEmptyLines, AtStartOfBlock);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterControlStatements);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterForeachMacros);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions,
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index db1decb20d626..6b42844133561 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -163,7 +163,7 @@ TEST_F(FormatTest, RemovesEmptyLines) {
auto CustomStyle = getLLVMStyle();
CustomStyle.BreakBeforeBraces = FormatStyle::BS_Custom;
CustomStyle.BraceWrapping.AfterNamespace = true;
- CustomStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
+ CustomStyle.KeepEmptyLines.AtStartOfBlock = false;
verifyFormat("namespace N\n"
"{\n"
"\n"
@@ -389,7 +389,7 @@ TEST_F(FormatTest, RemovesEmptyLines) {
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterClass = true;
Style.BraceWrapping.AfterFunction = true;
- Style.KeepEmptyLinesAtTheStartOfBlocks = false;
+ Style.KeepEmptyLines.AtStartOfBlock = false;
verifyFormat("class Foo\n"
"{\n"
@@ -27230,7 +27230,7 @@ TEST_F(FormatTest, InsertNewlineAtEOF) {
TEST_F(FormatTest, KeepEmptyLinesAtEOF) {
FormatStyle Style = getLLVMStyle();
- Style.KeepEmptyLinesAtEOF = true;
+ Style.KeepEmptyLines.AtEndOfFile = true;
const StringRef Code{"int i;\n\n"};
verifyNoChange(Code, Style);
``````````
</details>
https://github.com/llvm/llvm-project/pull/96770
More information about the cfe-commits
mailing list