From: Owen Pan Date: Tue, 13 Jun 2023 16:52:34 +0000 (-0700) Subject: Reland [clang-format] Add the KeepEmptyLinesAtEOF option X-Git-Tag: upstream/17.0.6~5248 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=829ed96b779c10cb023d7e3dbcfad22413979ec4;p=platform%2Fupstream%2Fllvm.git Reland [clang-format] Add the KeepEmptyLinesAtEOF option --- diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 8f23a4a..fa552d6 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3555,6 +3555,11 @@ the configuration (without a prefix: ``Auto``). false: import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js" +.. _KeepEmptyLinesAtEOF: + +**KeepEmptyLinesAtEOF** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ ` + Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file. + .. _KeepEmptyLinesAtTheStartOfBlocks: **KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ ` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a6b4a79..6bfd77c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -719,6 +719,7 @@ clang-format - 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 -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 6a9d435..74b3e15 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2675,6 +2675,10 @@ 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. /// \code /// true: false: @@ -4364,6 +4368,7 @@ struct FormatStyle { JavaImportGroups == R.JavaImportGroups && JavaScriptQuotes == R.JavaScriptQuotes && JavaScriptWrapImports == R.JavaScriptWrapImports && + KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF && KeepEmptyLinesAtTheStartOfBlocks == R.KeepEmptyLinesAtTheStartOfBlocks && Language == R.Language && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 6e2b6a6..5fee5e6 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -942,6 +942,7 @@ template <> struct MappingTraits { 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); @@ -1410,6 +1411,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { /*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; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 33be74d..5172deb 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -1425,7 +1425,9 @@ void UnwrappedLineFormatter::formatFirstToken( 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); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 169c93d..6c720ec 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -167,6 +167,7 @@ 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(ObjCSpaceAfterProperty); CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index fa53cbd..ee64b3a 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -25728,6 +25728,15 @@ TEST_F(FormatTest, InsertNewlineAtEOF) { 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;");