/// }
/// \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.
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);
}
};
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;
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;
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;
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;
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;
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,
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 =
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"
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;");
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