You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
7.3 KiB
186 lines
7.3 KiB
From fa1b9053729ec6a4425a44ec5502dd388928274a Mon Sep 17 00:00:00 2001
|
|
From: Ivan Donchevskii <ivan.donchevskii@qt.io>
|
|
Date: Fri, 12 Oct 2018 08:19:25 +0200
|
|
Subject: [PATCH] [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 <CR> 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.
|
|
|
|
This is a cherry pick from commits b748c82e3664c2e2e3d29645ede472d87b8cde63
|
|
and 1817513d4f3a2e4e26be124dbe395340f798fd51.
|
|
|
|
Change-Id: I9d2935b937bb68ea8dc59fac8463718475e9c080
|
|
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
|
|
---
|
|
include/clang/Format/Format.h | 13 +++++++++++++
|
|
lib/Format/Format.cpp | 4 ++++
|
|
lib/Format/UnwrappedLineFormatter.cpp | 9 +++++----
|
|
lib/Format/UnwrappedLineParser.cpp | 2 ++
|
|
unittests/Format/FormatTest.cpp | 16 ++++++++++++++++
|
|
5 files changed, 40 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
|
|
index cb37b0c890c..b9c4df3d1af 100644
|
|
--- a/include/clang/Format/Format.h
|
|
+++ b/include/clang/Format/Format.h
|
|
@@ -22,6 +22,8 @@
|
|
#include "llvm/Support/Regex.h"
|
|
#include <system_error>
|
|
|
|
+#define KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
|
|
+
|
|
namespace llvm {
|
|
namespace vfs {
|
|
class FileSystem;
|
|
@@ -1200,6 +1202,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:
|
|
@@ -1767,6 +1779,7 @@ struct FormatStyle {
|
|
JavaImportGroups == R.JavaImportGroups &&
|
|
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 2c4f8760540..61ea88626ee 100644
|
|
--- a/lib/Format/Format.cpp
|
|
+++ b/lib/Format/Format.cpp
|
|
@@ -417,6 +417,8 @@ template <> struct MappingTraits<FormatStyle> {
|
|
IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
|
|
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);
|
|
@@ -678,6 +680,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;
|
|
@@ -745,6 +748,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
|
{"^<ext/.*\\.h>", 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 6b6a9aff461..c88efbc6867 100644
|
|
--- a/lib/Format/UnwrappedLineFormatter.cpp
|
|
+++ b/lib/Format/UnwrappedLineFormatter.cpp
|
|
@@ -684,7 +684,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() {}
|
|
|
|
@@ -727,7 +727,8 @@ protected:
|
|
// assert so that we can simply call this function for all tokens.
|
|
return true;
|
|
|
|
- if (NewLine) {
|
|
+ if (NewLine || (Previous.Children[0]->First->MustBreakBefore &&
|
|
+ Style.KeepLineBreaksForNonEmptyLines)) {
|
|
int AdditionalIndent = State.Stack.back().Indent -
|
|
Previous.Children[0]->Level * Style.IndentWidth;
|
|
|
|
@@ -772,10 +773,10 @@ protected:
|
|
}
|
|
|
|
ContinuationIndenter *Indenter;
|
|
+ const FormatStyle &Style;
|
|
|
|
private:
|
|
WhitespaceManager *Whitespaces;
|
|
- const FormatStyle &Style;
|
|
UnwrappedLineFormatter *BlockFormatter;
|
|
};
|
|
|
|
@@ -798,7 +799,7 @@ public:
|
|
while (State.NextToken) {
|
|
bool Newline =
|
|
Indenter->mustBreak(State) ||
|
|
- (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
|
|
+ (State.NextToken->NewlinesBefore > 0 && Indenter->canBreak(State));
|
|
unsigned Penalty = 0;
|
|
formatChildren(State, Newline, /*DryRun=*/false, Penalty);
|
|
Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
|
|
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
|
|
index 3cd3c8f9cdf..3aa30c7cb3f 100644
|
|
--- a/lib/Format/UnwrappedLineParser.cpp
|
|
+++ b/lib/Format/UnwrappedLineParser.cpp
|
|
@@ -2554,6 +2554,8 @@ void UnwrappedLineParser::nextToken(int LevelDifference) {
|
|
else
|
|
readTokenWithJavaScriptASI();
|
|
FormatTok->Previous = Previous;
|
|
+ if (FormatTok->NewlinesBefore && Style.KeepLineBreaksForNonEmptyLines)
|
|
+ FormatTok->MustBreakBefore = true;
|
|
}
|
|
|
|
void UnwrappedLineParser::distributeComments(
|
|
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
|
|
index c05fceb4766..38906d9ee31 100644
|
|
--- a/unittests/Format/FormatTest.cpp
|
|
+++ b/unittests/Format/FormatTest.cpp
|
|
@@ -385,6 +385,22 @@ TEST_F(FormatTest, RemovesEmptyLines) {
|
|
" void funk() {}\n"
|
|
"};",
|
|
Style));
|
|
+
|
|
+ Style.KeepLineBreaksForNonEmptyLines = true;
|
|
+ Style.ColumnLimit = 0;
|
|
+ EXPECT_EQ("int foo(int a,\n"
|
|
+ " int b)\n"
|
|
+ "{\n"
|
|
+ "}",
|
|
+ format("int foo(int a,\n"
|
|
+ "int b) {}",
|
|
+ Style));
|
|
+
|
|
+ EXPECT_EQ("[]() {\n"
|
|
+ " foo(); }",
|
|
+ format("[]() {\n"
|
|
+ "foo(); }",
|
|
+ Style));
|
|
}
|
|
|
|
TEST_F(FormatTest, RecognizesBinaryOperatorKeywords) {
|
|
--
|
|
2.26.2
|
|
|