Adds an option KeepEmptyLinesAtEOF to keep empty lines (up to
MaxEmptyLinesToKeep) before EOF. This remedies the probably unintentional
change in behavior introduced in
3d3ea84a4f8f, which started to always
remove empty lines before EOF.
Fixes #56054.
Fixes #63150.
Differential Revision: https://reviews.llvm.org/
D152305
false:
import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js"
+.. _KeepEmptyLinesAtEOF:
+
+**KeepEmptyLinesAtEOF** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ <KeepEmptyLinesAtEOF>`
+ Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
+
.. _KeepEmptyLinesAtTheStartOfBlocks:
**KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <KeepEmptyLinesAtTheStartOfBlocks>`
- Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``.
- Add ``BracedInitializerIndentWidth`` which can be used to configure
the indentation level of the contents of braced init lists.
+- Add ``KeepEmptyLinesAtEOF`` to keep empty lines at end of file.
libclang
--------
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.
/// \code
/// true: false:
JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&
+ KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF &&
KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks &&
Language == R.Language &&
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks);
+ IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
IO.mapOptional("LineEnding", Style.LineEnding);
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
/*Hex=*/0, /*HexMinDigits=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
+ LLVMStyle.KeepEmptyLinesAtEOF = false;
LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
unsigned NewlineIndent) {
FormatToken &RootToken = *Line.First;
if (RootToken.is(tok::eof)) {
- unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u);
+ unsigned Newlines =
+ std::min(RootToken.NewlinesBefore,
+ Style.KeepEmptyLinesAtEOF ? Style.MaxEmptyLinesToKeep + 1 : 1);
unsigned TokenIndent = Newlines ? NewlineIndent : 0;
Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
TokenIndent);
CHECK_PARSE_BOOL(IndentWrappedFunctionNames);
CHECK_PARSE_BOOL(InsertBraces);
CHECK_PARSE_BOOL(InsertNewlineAtEOF);
+ CHECK_PARSE_BOOL(KeepEmptyLinesAtEOF);
CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks);
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
verifyFormat("int i;\n", "int i;", Style);
}
+TEST_F(FormatTest, KeepEmptyLinesAtEOF) {
+ FormatStyle Style = getLLVMStyle();
+ Style.KeepEmptyLinesAtEOF = true;
+
+ const StringRef Code{"int i;\n\n"};
+ verifyFormat(Code, Code, Style);
+ verifyFormat(Code, "int i;\n\n\n", Style);
+}
+
TEST_F(FormatTest, SpaceAfterUDL) {
verifyFormat("auto c = (4s).count();");
verifyFormat("auto x = 5s .count() == 5;");