summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorFrancois Ferrand <thetypz@gmail.com>2017-06-30 20:25:55 +0000
committerFrancois Ferrand <thetypz@gmail.com>2017-06-30 20:25:55 +0000
commitad72256daa2d8e20334bd29e2e7364c07840f250 (patch)
treebc01f401cea04368fb4a103bf3d5bae7b001600a /clang
parent1fec6cbeba6042286ec2060e12f9a4a2e8ccec44 (diff)
downloadbcm5719-llvm-ad72256daa2d8e20334bd29e2e7364c07840f250.tar.gz
bcm5719-llvm-ad72256daa2d8e20334bd29e2e7364c07840f250.zip
clang-format: add options to merge empty record body
Summary: This patch introduces a few extra BraceWrapping options, similar to `SplitEmptyFunction`, to allow merging empty 'record' bodies (e.g. class, struct, union and namespace): * SplitEmptyClass * SplitEmptyStruct * SplitEmptyUnion * SplitEmptyNamespace The `SplitEmptyFunction` option name has also been simplified/ shortened (from `SplitEmptyFunctionBody`). These options are helpful when the correspond AfterXXX option is enabled, to allow merging the empty record: class Foo {}; In addition, this fixes an unexpected merging of short records, when the AfterXXXX options are used, which caused to be formatted like this: class Foo { void Foo(); }; This is now properly formatted as: class Foo { void Foo(); }; Reviewers: djasper, krasimir Reviewed By: djasper Subscribers: cfe-commits, klimek Differential Revision: https://reviews.llvm.org/D34395 llvm-svn: 306874
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Format/Format.h24
-rw-r--r--clang/lib/Format/Format.cpp16
-rw-r--r--clang/lib/Format/FormatToken.h13
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.cpp28
-rw-r--r--clang/unittests/Format/FormatTest.cpp180
5 files changed, 247 insertions, 14 deletions
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 5b587a4db09..ee24c55fef6 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -717,7 +717,29 @@ struct FormatStyle {
/// }
/// \endcode
///
- bool SplitEmptyFunctionBody;
+ bool SplitEmptyFunction;
+ /// \brief If ``false``, empty record (e.g. class, struct or union) body
+ /// can be put on a single line. This option is used only if the opening
+ /// brace of the record has already been wrapped, i.e. the `AfterClass`
+ /// (for classes) brace wrapping mode is set.
+ /// \code
+ /// class Foo vs. class Foo
+ /// {} {
+ /// }
+ /// \endcode
+ ///
+ bool SplitEmptyRecord;
+ /// \brief If ``false``, empty namespace body can be put on a single line.
+ /// This option is used only if the opening brace of the namespace has
+ /// already been wrapped, i.e. the `AfterNamespace` brace wrapping mode is
+ /// set.
+ /// \code
+ /// namespace Foo vs. namespace Foo
+ /// {} {
+ /// }
+ /// \endcode
+ ///
+ bool SplitEmptyNamespace;
};
/// \brief Control of individual brace wrapping cases.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 94147fcbd2a..e6657eb26a6 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -414,7 +414,9 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
- IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody);
+ IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
+ IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
+ IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
}
};
@@ -490,7 +492,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
return Style;
FormatStyle Expanded = Style;
Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true};
+ false, false, false, false, false, true,
+ true, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -503,7 +506,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterStruct = true;
Expanded.BraceWrapping.AfterUnion = true;
- Expanded.BraceWrapping.SplitEmptyFunctionBody = false;
+ Expanded.BraceWrapping.SplitEmptyFunction = false;
+ Expanded.BraceWrapping.SplitEmptyRecord = false;
break;
case FormatStyle::BS_Stroustrup:
Expanded.BraceWrapping.AfterFunction = true;
@@ -523,7 +527,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
break;
case FormatStyle::BS_GNU:
Expanded.BraceWrapping = {true, true, true, true, true, true,
- true, true, true, true, true, true};
+ true, true, true, true, true, true,
+ true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -560,7 +565,8 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true};
+ false, false, false, false, false, true,
+ true, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index ddec578f89a..0fe91adcd47 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -476,6 +476,19 @@ struct FormatToken {
return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);
}
+ /// \brief Return the actual namespace token, if this token starts a namespace
+ /// block.
+ const FormatToken *getNamespaceToken() const {
+ const FormatToken *NamespaceTok = this;
+ if (is(tok::comment))
+ NamespaceTok = NamespaceTok->getNextNonComment();
+ // Detect "(inline)? namespace" in the beginning of a line.
+ if (NamespaceTok && NamespaceTok->is(tok::kw_inline))
+ NamespaceTok = NamespaceTok->getNextNonComment();
+ return NamespaceTok && NamespaceTok->is(tok::kw_namespace) ? NamespaceTok
+ : nullptr;
+ }
+
private:
// Disallow copying.
FormatToken(const FormatToken &) = delete;
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 8836c07cac7..2005a282292 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -136,10 +136,7 @@ private:
bool isNamespaceDeclaration(const AnnotatedLine *Line) {
const FormatToken *NamespaceTok = Line->First;
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok->is(tok::kw_inline))
- NamespaceTok = NamespaceTok->getNextNonComment();
- return NamespaceTok && NamespaceTok->is(tok::kw_namespace);
+ return NamespaceTok && NamespaceTok->getNamespaceToken();
}
bool isEndOfNamespace(const AnnotatedLine *Line,
@@ -216,10 +213,31 @@ private:
if (TheLine->Last->is(TT_FunctionLBrace) &&
TheLine->First == TheLine->Last &&
- !Style.BraceWrapping.SplitEmptyFunctionBody &&
+ !Style.BraceWrapping.SplitEmptyFunction &&
I[1]->First->is(tok::r_brace))
return tryMergeSimpleBlock(I, E, Limit);
+ // Handle empty record blocks where the brace has already been wrapped
+ if (TheLine->Last->is(tok::l_brace) && TheLine->First == TheLine->Last &&
+ I != AnnotatedLines.begin()) {
+ bool EmptyBlock = I[1]->First->is(tok::r_brace);
+
+ const FormatToken *Tok = I[-1]->First;
+ if (Tok && Tok->is(tok::comment))
+ Tok = Tok->getNextNonComment();
+
+ if (Tok && Tok->getNamespaceToken())
+ return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
+ ? tryMergeSimpleBlock(I, E, Limit) : 0;
+
+ if (Tok && Tok->is(tok::kw_typedef))
+ Tok = Tok->getNextNonComment();
+ if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
+ Keywords.kw_interface))
+ return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
+ ? tryMergeSimpleBlock(I, E, Limit) : 0;
+ }
+
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
// If necessary, change to something smarter.
bool MergeShortFunctions =
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index e070396ac05..b5f959f9c1f 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -6571,12 +6571,12 @@ TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) {
MergeInlineOnly);
}
-TEST_F(FormatTest, SplitEmptyFunctionBody) {
+TEST_F(FormatTest, SplitEmptyFunction) {
FormatStyle Style = getLLVMStyle();
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterFunction = true;
- Style.BraceWrapping.SplitEmptyFunctionBody = false;
+ Style.BraceWrapping.SplitEmptyFunction = false;
Style.ColumnLimit = 40;
verifyFormat("int f()\n"
@@ -6639,6 +6639,178 @@ TEST_F(FormatTest, SplitEmptyFunctionBody) {
Style);
}
+TEST_F(FormatTest, SplitEmptyClass) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterClass = true;
+ Style.BraceWrapping.SplitEmptyRecord = false;
+
+ verifyFormat("class Foo\n"
+ "{};",
+ Style);
+ verifyFormat("/* something */ class Foo\n"
+ "{};",
+ Style);
+ verifyFormat("template <typename X> class Foo\n"
+ "{};",
+ Style);
+ verifyFormat("class Foo\n"
+ "{\n"
+ " Foo();\n"
+ "};",
+ Style);
+ verifyFormat("typedef class Foo\n"
+ "{\n"
+ "} Foo_t;",
+ Style);
+}
+
+TEST_F(FormatTest, SplitEmptyStruct) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterStruct = true;
+ Style.BraceWrapping.SplitEmptyRecord = false;
+
+ verifyFormat("struct Foo\n"
+ "{};",
+ Style);
+ verifyFormat("/* something */ struct Foo\n"
+ "{};",
+ Style);
+ verifyFormat("template <typename X> struct Foo\n"
+ "{};",
+ Style);
+ verifyFormat("struct Foo\n"
+ "{\n"
+ " Foo();\n"
+ "};",
+ Style);
+ verifyFormat("typedef struct Foo\n"
+ "{\n"
+ "} Foo_t;",
+ Style);
+ //typedef struct Bar {} Bar_t;
+}
+
+TEST_F(FormatTest, SplitEmptyUnion) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterUnion = true;
+ Style.BraceWrapping.SplitEmptyRecord = false;
+
+ verifyFormat("union Foo\n"
+ "{};",
+ Style);
+ verifyFormat("/* something */ union Foo\n"
+ "{};",
+ Style);
+ verifyFormat("union Foo\n"
+ "{\n"
+ " A,\n"
+ "};",
+ Style);
+ verifyFormat("typedef union Foo\n"
+ "{\n"
+ "} Foo_t;",
+ Style);
+}
+
+TEST_F(FormatTest, SplitEmptyNamespace) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterNamespace = true;
+ Style.BraceWrapping.SplitEmptyNamespace = false;
+
+ verifyFormat("namespace Foo\n"
+ "{};",
+ Style);
+ verifyFormat("/* something */ namespace Foo\n"
+ "{};",
+ Style);
+ verifyFormat("inline namespace Foo\n"
+ "{};",
+ Style);
+ verifyFormat("namespace Foo\n"
+ "{\n"
+ "void Bar();\n"
+ "};",
+ Style);
+}
+
+TEST_F(FormatTest, NeverMergeShortRecords) {
+ FormatStyle Style = getLLVMStyle();
+
+ verifyFormat("class Foo {\n"
+ " Foo();\n"
+ "};",
+ Style);
+ verifyFormat("typedef class Foo {\n"
+ " Foo();\n"
+ "} Foo_t;",
+ Style);
+ verifyFormat("struct Foo {\n"
+ " Foo();\n"
+ "};",
+ Style);
+ verifyFormat("typedef struct Foo {\n"
+ " Foo();\n"
+ "} Foo_t;",
+ Style);
+ verifyFormat("union Foo {\n"
+ " A,\n"
+ "};",
+ Style);
+ verifyFormat("typedef union Foo {\n"
+ " A,\n"
+ "} Foo_t;",
+ Style);
+ verifyFormat("namespace Foo {\n"
+ "void Bar();\n"
+ "};",
+ Style);
+
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterClass = true;
+ Style.BraceWrapping.AfterStruct = true;
+ Style.BraceWrapping.AfterUnion = true;
+ Style.BraceWrapping.AfterNamespace = true;
+ verifyFormat("class Foo\n"
+ "{\n"
+ " Foo();\n"
+ "};",
+ Style);
+ verifyFormat("typedef class Foo\n"
+ "{\n"
+ " Foo();\n"
+ "} Foo_t;",
+ Style);
+ verifyFormat("struct Foo\n"
+ "{\n"
+ " Foo();\n"
+ "};",
+ Style);
+ verifyFormat("typedef struct Foo\n"
+ "{\n"
+ " Foo();\n"
+ "} Foo_t;",
+ Style);
+ verifyFormat("union Foo\n"
+ "{\n"
+ " A,\n"
+ "};",
+ Style);
+ verifyFormat("typedef union Foo\n"
+ "{\n"
+ " A,\n"
+ "} Foo_t;",
+ Style);
+ verifyFormat("namespace Foo\n"
+ "{\n"
+ "void Bar();\n"
+ "};",
+ Style);
+}
+
TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
// Elaborate type variable declarations.
verifyFormat("struct foo a = {bar};\nint n;");
@@ -9371,7 +9543,9 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
- CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunctionBody);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyNamespace);
}
#undef CHECK_PARSE_BOOL
OpenPOWER on IntegriCloud