forked from OSchip/llvm-project
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
This commit is contained in:
parent
1fec6cbeba
commit
ad72256daa
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue