diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3162,6 +3162,9 @@ --i; --i; while (i); } while (i); +**InsertNewlineAtEOF** (``Boolean``) :versionbadge:`clang-format 16` + Insert a newline at end of file if missing. + **InsertTrailingCommas** (``TrailingCommaStyle``) :versionbadge:`clang-format 11` If set to ``TCS_Wrapped`` will insert trailing commas in container literals (arrays and objects) that wrap across multiple lines. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -876,6 +876,7 @@ in C++, C#, Java, and JavaScript. - Add ``BreakAfterAttributes`` option for breaking after a group of C++11 attributes before a function declaration/definition name. +- Add ``InsertNewlineAtEOF`` option for inserting a newline at EOF if missing. clang-extdef-mapping -------------------- 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 @@ -2450,6 +2450,10 @@ /// \version 15 bool InsertBraces; + /// Insert a newline at end of file if missing. + /// \version 16 + bool InsertNewlineAtEOF; + /// The style of inserting trailing commas into container literals. enum TrailingCommaStyle : int8_t { /// Do not insert trailing commas. @@ -4151,6 +4155,7 @@ IndentWidth == R.IndentWidth && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && InsertBraces == R.InsertBraces && + InsertNewlineAtEOF == R.InsertNewlineAtEOF && IntegerLiteralSeparator.Binary == R.IntegerLiteralSeparator.Binary && IntegerLiteralSeparator.Decimal == R.IntegerLiteralSeparator.Decimal && 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 @@ -899,6 +899,7 @@ IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); IO.mapOptional("InsertBraces", Style.InsertBraces); + IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF); IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas); IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator); IO.mapOptional("JavaImportGroups", Style.JavaImportGroups); @@ -1355,6 +1356,7 @@ LLVMStyle.IndentWidth = 2; LLVMStyle.IndentWrappedFunctionNames = false; LLVMStyle.InsertBraces = false; + LLVMStyle.InsertNewlineAtEOF = false; LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; LLVMStyle.IntegerLiteralSeparator = {/*Binary=*/0, /*Decimal=*/0, /*Hex=*/0}; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1289,6 +1289,10 @@ Tok->setType(TT_TrailingReturnArrow); } break; + case tok::eof: + if (Style.InsertNewlineAtEOF && Tok->NewlinesBefore == 0) + Tok->NewlinesBefore = 1; + break; default: break; } diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -167,6 +167,7 @@ CHECK_PARSE_BOOL(IndentRequiresClause); CHECK_PARSE_BOOL(IndentWrappedFunctionNames); CHECK_PARSE_BOOL(InsertBraces); + CHECK_PARSE_BOOL(InsertNewlineAtEOF); 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 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -25171,6 +25171,14 @@ EXPECT_EQ(Code, format(Code, Style)); } +TEST_F(FormatTest, InsertNewlineAtEOF) { + FormatStyle Style = getLLVMStyle(); + Style.InsertNewlineAtEOF = true; + + verifyFormat("int i;\n", Style); + verifyFormat("int i;\n", "int i;", Style); +} + } // namespace } // namespace format } // namespace clang