From b748c82e3664c2e2e3d29645ede472d87b8cde63 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 12 Oct 2018 08:19:25 +0200 Subject: [in review/clang-8][clang-format] Introduce the flag which allows not to shrink lines -------------------------------------------------------------------------- * https://reviews.llvm.org/D53072 -------------------------------------------------------------------------- Currently there's no way to prevent to lines optimization even if you have intentionally put to split the line. In general case it's fine. So I would prefer to have such option which you can enable in special cases (for me it's an IDE related use case). Revert this change if upstream clang-format offers better solution. Change-Id: I01993cc94820b87c61f3968a1a756f74041e2b4f Reviewed-by: Marco Bubke --- include/clang/Format/Format.h | 13 +++++++++++++ lib/Format/Format.cpp | 4 ++++ lib/Format/UnwrappedLineFormatter.cpp | 7 ++++--- unittests/Format/FormatTest.cpp | 8 ++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 85dda948c1..8ca6b3e31c 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -22,6 +22,8 @@ #include "llvm/Support/Regex.h" #include +#define KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED + namespace clang { class Lexer; @@ -1160,6 +1162,16 @@ struct FormatStyle { /// \endcode bool JavaScriptWrapImports; + /// If true, no line breaks are optimized out (works only with ColumnLimit = 0) + /// \code + /// true: false: + /// int foo(int a, vs. int foo(int a, int b) { + /// int b) { + /// bar(); bar(); + /// } } + /// \endcode + bool KeepLineBreaksForNonEmptyLines; + /// If true, the empty line at the start of blocks is kept. /// \code /// true: false: @@ -1726,6 +1738,7 @@ struct FormatStyle { IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && JavaScriptQuotes == R.JavaScriptQuotes && JavaScriptWrapImports == R.JavaScriptWrapImports && + KeepLineBreaksForNonEmptyLines == R.KeepLineBreaksForNonEmptyLines && KeepEmptyLinesAtTheStartOfBlocks == R.KeepEmptyLinesAtTheStartOfBlocks && MacroBlockBegin == R.MacroBlockBegin && diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 9a2da69e89..df93b21779 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -416,6 +416,8 @@ template <> struct MappingTraits { Style.IndentWrappedFunctionNames); IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); + IO.mapOptional("KeepLineBreaksForNonEmptyLines", + Style.KeepLineBreaksForNonEmptyLines); IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", Style.KeepEmptyLinesAtTheStartOfBlocks); IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); @@ -676,6 +678,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.JavaScriptWrapImports = true; LLVMStyle.TabWidth = 8; LLVMStyle.MaxEmptyLinesToKeep = 1; + LLVMStyle.KeepLineBreaksForNonEmptyLines = false; LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; @@ -741,6 +744,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { {"^", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}}; GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; GoogleStyle.IndentCaseLabels = true; + GoogleStyle.KeepLineBreaksForNonEmptyLines = false; GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; GoogleStyle.ObjCSpaceAfterProperty = false; diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index 906dae40cb..7e1d805a5f 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -672,7 +672,7 @@ public: LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces, const FormatStyle &Style, UnwrappedLineFormatter *BlockFormatter) - : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), + : Indenter(Indenter), Style(Style), Whitespaces(Whitespaces), BlockFormatter(BlockFormatter) {} virtual ~LineFormatter() {} @@ -760,10 +760,10 @@ protected: } ContinuationIndenter *Indenter; + const FormatStyle &Style; private: WhitespaceManager *Whitespaces; - const FormatStyle &Style; UnwrappedLineFormatter *BlockFormatter; }; @@ -786,7 +786,8 @@ public: while (State.NextToken) { bool Newline = Indenter->mustBreak(State) || - (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0); + (State.NextToken->NewlinesBefore > 0 && + (Style.KeepLineBreaksForNonEmptyLines || Indenter->canBreak(State))); unsigned Penalty = 0; formatChildren(State, Newline, /*DryRun=*/false, Penalty); Indenter->addTokenToState(State, Newline, /*DryRun=*/false); diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index f234e287cf..3c94e4c9af 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -349,6 +349,14 @@ TEST_F(FormatTest, RemovesEmptyLines) { " void funk() {}\n" "};", Style)); + + Style.KeepLineBreaksForNonEmptyLines = true; + Style.ColumnLimit = 0; + EXPECT_EQ("int foo(int a,\n" + " int b) {}", + format("int foo(int a,\n" + " int b) {}", + Style)); } TEST_F(FormatTest, RecognizesBinaryOperatorKeywords) { -- cgit v1.2.3