summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/ClangFormatStyleOptions.rst38
-rwxr-xr-xdocs/tools/dump_format_style.py54
-rw-r--r--include/clang/Format/Format.h36
-rw-r--r--lib/Format/Format.cpp78
-rw-r--r--lib/Format/TokenAnnotator.cpp7
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp7
-rw-r--r--lib/Format/UnwrappedLineParser.cpp63
-rw-r--r--unittests/Format/FormatTest.cpp31
8 files changed, 254 insertions, 60 deletions
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index 1d61197c7d..e10c3521f6 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -252,6 +252,27 @@ the configuration (without a prefix: ``Auto``).
If ``false``, a function declaration's or function definition's
parameters will either all be on the same line or will have one line each.
+**BraceWrapping** (``BraceWrappingFlags``)
+ Control of individual brace wrapping cases.
+
+ If ``BreakBeforeBraces`` is set to ``custom``, use this to specify how each
+ individual brace case should be handled. Otherwise, this is ignored.
+
+ Nested configuration flags:
+
+ * ``bool AfterClass`` Wrap class definitions.
+ * ``bool AfterControlStatement`` Wrap control statements (if/for/while/switch/..).
+ * ``bool AfterEnum`` Wrap enum definitions.
+ * ``bool AfterFunction`` Wrap function definitions.
+ * ``bool AfterNamespace`` Wrap namespace definitions.
+ * ``bool AfterObjCDeclaration`` Wrap ObjC definitions (@autoreleasepool, interfaces, ..).
+ * ``bool AfterStruct`` Wrap struct definitions.
+ * ``bool AfterUnion`` Wrap union definitions.
+ * ``bool BeforeCatch`` Wrap before ``catch``.
+ * ``bool BeforeElse`` Wrap before ``else``.
+ * ``bool IndentBraces`` Indent the wrapped braces themselves.
+
+
**BreakBeforeBinaryOperators** (``BinaryOperatorStyle``)
The way to wrap binary operators.
@@ -288,6 +309,8 @@ the configuration (without a prefix: ``Auto``).
or other definitions.
* ``BS_WebKit`` (in configuration: ``WebKit``)
Like ``Attach``, but break before functions.
+ * ``BS_Custom`` (in configuration: ``Custom``)
+ Configure each individual brace in ``BraceWrapping``.
**BreakBeforeTernaryOperators** (``bool``)
@@ -365,6 +388,21 @@ the configuration (without a prefix: ``Auto``).
For example: BOOST_FOREACH.
+**IncludeCategories** (``std::vector<std::pair<std::string, unsigned>>``)
+ Regular expressions denoting the different #include categories used
+ for ordering #includes.
+
+ These regular expressions are matched against the filename of an include
+ (including the <> or "") in order. The value belonging to the first
+ matching regular expression is assigned and #includes are sorted first
+ according to increasing category number and then alphabetically within
+ each category.
+
+ If none of the regular expressions match, UINT_MAX is assigned as
+ category. The main header for a source file automatically gets category 0,
+ so that it is kept at the beginning of the #includes
+ (http://llvm.org/docs/CodingStandards.html#include-style).
+
**IndentCaseLabels** (``bool``)
Indent case labels one level from the switch statement.
diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py
index fdf03c6244..308f47fb0c 100755
--- a/docs/tools/dump_format_style.py
+++ b/docs/tools/dump_format_style.py
@@ -36,14 +36,35 @@ class Option:
self.type = type
self.comment = comment.strip()
self.enum = None
+ self.nested_struct = None
def __str__(self):
s = '**%s** (``%s``)\n%s' % (self.name, self.type,
doxygen2rst(indent(self.comment, 2)))
if self.enum:
s += indent('\n\nPossible values:\n\n%s\n' % self.enum, 2)
+ if self.nested_struct:
+ s += indent('\n\nNested configuration flags:\n\n%s\n' %self.nested_struct,
+ 2)
return s
+class NestedStruct:
+ def __init__(self, name, comment):
+ self.name = name
+ self.comment = comment.strip()
+ self.values = []
+
+ def __str__(self):
+ return '\n'.join(map(str, self.values))
+
+class NestedField:
+ def __init__(self, name, comment):
+ self.name = name
+ self.comment = comment.strip()
+
+ def __str__(self):
+ return '* ``%s`` %s' % (self.name, doxygen2rst(self.comment))
+
class Enum:
def __init__(self, name, comment):
self.name = name
@@ -69,14 +90,16 @@ def clean_comment_line(line):
def read_options(header):
class State:
- BeforeStruct, Finished, InStruct, InFieldComment, InEnum, \
- InEnumMemberComment = range(6)
+ BeforeStruct, Finished, InStruct, InNestedStruct, InNestedFieldComent, \
+ InFieldComment, InEnum, InEnumMemberComment = range(8)
state = State.BeforeStruct
options = []
enums = {}
+ nested_structs = {}
comment = ''
enum = None
+ nested_struct = None
for line in header:
line = line.strip()
@@ -97,13 +120,33 @@ def read_options(header):
state = State.InEnum
name = re.sub(r'enum\s+(\w+)\s*\{', '\\1', line)
enum = Enum(name, comment)
+ elif line.startswith('struct'):
+ state = State.InNestedStruct
+ name = re.sub(r'struct\s+(\w+)\s*\{', '\\1', line)
+ nested_struct = NestedStruct(name, comment)
elif line.endswith(';'):
state = State.InStruct
- field_type, field_name = re.match(r'([<>:\w]+)\s+(\w+);', line).groups()
+ field_type, field_name = re.match(r'([<>:\w(,\s)]+)\s+(\w+);',
+ line).groups()
option = Option(str(field_name), str(field_type), comment)
options.append(option)
else:
raise Exception('Invalid format, expected comment, field or enum')
+ elif state == State.InNestedStruct:
+ if line.startswith('///'):
+ state = State.InNestedFieldComent
+ comment = clean_comment_line(line)
+ elif line == '};':
+ state = State.InStruct
+ nested_structs[nested_struct.name] = nested_struct
+ else:
+ raise Exception('Invalid format, expected struct field comment or };')
+ elif state == State.InNestedFieldComent:
+ if line.startswith('///'):
+ comment += clean_comment_line(line)
+ else:
+ state = State.InNestedStruct
+ nested_struct.values.append(NestedField(line.replace(';', ''), comment))
elif state == State.InEnum:
if line.startswith('///'):
state = State.InEnumMemberComment
@@ -124,9 +167,12 @@ def read_options(header):
for option in options:
if not option.type in ['bool', 'unsigned', 'int', 'std::string',
- 'std::vector<std::string>']:
+ 'std::vector<std::string>',
+ 'std::vector<std::pair<std::string, unsigned>>']:
if enums.has_key(option.type):
option.enum = enums[option.type]
+ elif nested_structs.has_key(option.type):
+ option.nested_struct = nested_structs[option.type];
else:
raise Exception('Unknown type: %s' % option.type)
return options
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index bed131d80c..19d32f90b8 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -178,12 +178,46 @@ struct FormatStyle {
/// or other definitions.
BS_GNU,
/// Like ``Attach``, but break before functions.
- BS_WebKit
+ BS_WebKit,
+ /// Configure each individual brace in \c BraceWrapping.
+ BS_Custom
};
/// \brief The brace breaking style to use.
BraceBreakingStyle BreakBeforeBraces;
+ /// \brief Precise control over the wrapping of braces.
+ struct BraceWrappingFlags {
+ /// \brief Wrap class definitions.
+ bool AfterClass;
+ /// \brief Wrap control statements (if/for/while/switch/..).
+ bool AfterControlStatement;
+ /// \brief Wrap enum definitions.
+ bool AfterEnum;
+ /// \brief Wrap function definitions.
+ bool AfterFunction;
+ /// \brief Wrap namespace definitions.
+ bool AfterNamespace;
+ /// \brief Wrap ObjC definitions (@autoreleasepool, interfaces, ..).
+ bool AfterObjCDeclaration;
+ /// \brief Wrap struct definitions.
+ bool AfterStruct;
+ /// \brief Wrap union definitions.
+ bool AfterUnion;
+ /// \brief Wrap before \c catch.
+ bool BeforeCatch;
+ /// \brief Wrap before \c else.
+ bool BeforeElse;
+ /// \brief Indent the wrapped braces themselves.
+ bool IndentBraces;
+ };
+
+ /// \brief Control of individual brace wrapping cases.
+ ///
+ /// If \c BreakBeforeBraces is set to \c custom, use this to specify how each
+ /// individual brace case should be handled. Otherwise, this is ignored.
+ BraceWrappingFlags BraceWrapping;
+
/// \brief If \c true, ternary operators will be placed after line breaks.
bool BreakBeforeTernaryOperators;
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 64c06f19d0..aa227a1f00 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -99,11 +99,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
+ IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
- static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
+template <>
+struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
@@ -221,6 +224,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.AlwaysBreakTemplateDeclarations);
IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
+ IO.mapOptional("BraceWrapping", Style.BraceWrapping);
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
@@ -285,6 +289,22 @@ template <> struct MappingTraits<FormatStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
+ static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
+ IO.mapOptional("AfterClass", Wrapping.AfterClass);
+ IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
+ IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
+ IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
+ IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
+ IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
+ IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
+ IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
+ IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
+ IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
+ IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
+ }
+};
+
// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
@@ -340,6 +360,53 @@ std::string ParseErrorCategory::message(int EV) const {
llvm_unreachable("unexpected parse error");
}
+static FormatStyle expandPresets(const FormatStyle &Style) {
+ FormatStyle Expanded = Style;
+ Expanded.BraceWrapping = {false, false, false, false, false, false,
+ false, false, false, false, false};
+ switch (Style.BreakBeforeBraces) {
+ case FormatStyle::BS_Linux:
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterNamespace = true;
+ Expanded.BraceWrapping.BeforeElse = true;
+ break;
+ case FormatStyle::BS_Mozilla:
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterEnum = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.AfterUnion = true;
+ break;
+ case FormatStyle::BS_Stroustrup:
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.BeforeCatch = true;
+ Expanded.BraceWrapping.BeforeElse = true;
+ break;
+ case FormatStyle::BS_Allman:
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterControlStatement = true;
+ Expanded.BraceWrapping.AfterEnum = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterNamespace = true;
+ Expanded.BraceWrapping.AfterObjCDeclaration = true;
+ Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.BeforeCatch = true;
+ Expanded.BraceWrapping.BeforeElse = true;
+ break;
+ case FormatStyle::BS_GNU:
+ Expanded.BraceWrapping = {true, true, true, true, true, true,
+ true, true, true, true, true};
+ break;
+ case FormatStyle::BS_WebKit:
+ Expanded.BraceWrapping.AfterFunction = true;
+ break;
+ default:
+ break;
+ }
+ return Expanded;
+}
+
FormatStyle getLLVMStyle() {
FormatStyle LLVMStyle;
LLVMStyle.Language = FormatStyle::LK_Cpp;
@@ -615,7 +682,7 @@ std::string configurationAsText(const FormatStyle &Style) {
llvm::yaml::Output Output(Stream);
// We use the same mapping method for input and output, so we need a non-const
// reference here.
- FormatStyle NonConstStyle = Style;
+ FormatStyle NonConstStyle = expandPresets(Style);
Output << NonConstStyle;
return Stream.str();
}
@@ -1709,9 +1776,10 @@ tooling::Replacements reformat(const FormatStyle &Style,
SourceManager &SourceMgr, FileID ID,
ArrayRef<CharSourceRange> Ranges,
bool *IncompleteFormat) {
- if (Style.DisableFormat)
+ FormatStyle Expanded = expandPresets(Style);
+ if (Expanded.DisableFormat)
return tooling::Replacements();
- Formatter formatter(Style, SourceMgr, ID, Ranges);
+ Formatter formatter(Expanded, SourceMgr, ID, Ranges);
return formatter.format(IncompleteFormat);
}
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index a569f6c56b..f6a80342dc 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -2158,10 +2158,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.is(TT_InlineASMBrace))
return Right.HasUnescapedNewline;
if (isAllmanBrace(Left) || isAllmanBrace(Right))
- return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
- (Style.BreakBeforeBraces == FormatStyle::BS_Mozilla &&
- Line.startsWith(tok::kw_enum));
+ return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
+ (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
+ (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
if (Style.Language == FormatStyle::LK_Proto && Left.isNot(tok::l_brace) &&
Right.is(TT_SelectorName))
return true;
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 7e1fc3b1dd..6d9b1da49b 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -199,12 +199,12 @@ private:
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
}
if (TheLine->Last->is(tok::l_brace)) {
- return Style.BreakBeforeBraces == FormatStyle::BS_Attach
+ return !Style.BraceWrapping.AfterFunction
? tryMergeSimpleBlock(I, E, Limit)
: 0;
}
if (I[1]->First->is(TT_FunctionLBrace) &&
- Style.BreakBeforeBraces != FormatStyle::BS_Attach) {
+ Style.BraceWrapping.AfterFunction) {
if (I[1]->Last->is(TT_LineComment))
return 0;
@@ -263,8 +263,7 @@ private:
SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
if (Limit == 0)
return 0;
- if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
+ if (Style.BraceWrapping.AfterControlStatement &&
(I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
return 0;
if (I[1]->InPPDirective != (*I)->InPPDirective ||
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 08115036cd..159e60bfe1 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -154,12 +154,10 @@ public:
CompoundStatementIndenter(UnwrappedLineParser *Parser,
const FormatStyle &Style, unsigned &LineLevel)
: LineLevel(LineLevel), OldLineLevel(LineLevel) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) {
- Parser->addUnwrappedLine();
- } else if (Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
+ if (Style.BraceWrapping.AfterControlStatement)
Parser->addUnwrappedLine();
+ if (Style.BraceWrapping.IndentBraces)
++LineLevel;
- }
}
~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
@@ -456,17 +454,15 @@ static bool isGoogScope(const UnwrappedLine &Line) {
static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
const FormatToken &InitialToken) {
- switch (Style.BreakBeforeBraces) {
- case FormatStyle::BS_Linux:
- return InitialToken.isOneOf(tok::kw_namespace, tok::kw_class);
- case FormatStyle::BS_Mozilla:
- return InitialToken.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union);
- case FormatStyle::BS_Allman:
- case FormatStyle::BS_GNU:
- return true;
- default:
- return false;
- }
+ if (InitialToken.is(tok::kw_namespace))
+ return Style.BraceWrapping.AfterNamespace;
+ if (InitialToken.is(tok::kw_class))
+ return Style.BraceWrapping.AfterClass;
+ if (InitialToken.is(tok::kw_union))
+ return Style.BraceWrapping.AfterUnion;
+ if (InitialToken.is(tok::kw_struct))
+ return Style.BraceWrapping.AfterStruct;
+ return false;
}
void UnwrappedLineParser::parseChildBlock() {
@@ -681,8 +677,7 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::objc_autoreleasepool:
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ if (Style.BraceWrapping.AfterObjCDeclaration)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
}
@@ -876,7 +871,7 @@ void UnwrappedLineParser::parseStructuralElement() {
// structural element.
// FIXME: Figure out cases where this is not true, and add projections
// for them (the one we know is missing are lambdas).
- if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
+ if (Style.BraceWrapping.AfterFunction)
addUnwrappedLine();
FormatTok->Type = TT_FunctionLBrace;
parseBlock(/*MustBeDeclaration=*/false);
@@ -1264,12 +1259,10 @@ void UnwrappedLineParser::parseIfThenElse() {
if (FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
+ if (Style.BraceWrapping.BeforeElse)
addUnwrappedLine();
- } else {
+ else
NeedsUnwrappedLine = true;
- }
} else {
addUnwrappedLine();
++Line->Level;
@@ -1277,8 +1270,6 @@ void UnwrappedLineParser::parseIfThenElse() {
--Line->Level;
}
if (FormatTok->Tok.is(tok::kw_else)) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup)
- addUnwrappedLine();
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
@@ -1319,9 +1310,7 @@ void UnwrappedLineParser::parseTryCatch() {
if (FormatTok->is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
- Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) {
+ if (Style.BraceWrapping.BeforeCatch) {
addUnwrappedLine();
} else {
NeedsUnwrappedLine = true;
@@ -1359,17 +1348,13 @@ void UnwrappedLineParser::parseTryCatch() {
NeedsUnwrappedLine = false;
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
- Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) {
+ if (Style.BraceWrapping.BeforeCatch)
addUnwrappedLine();
- } else {
+ else
NeedsUnwrappedLine = true;
- }
}
- if (NeedsUnwrappedLine) {
+ if (NeedsUnwrappedLine)
addUnwrappedLine();
- }
}
void UnwrappedLineParser::parseNamespace() {
@@ -1445,7 +1430,7 @@ void UnwrappedLineParser::parseDoWhile() {
if (FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ if (Style.BraceWrapping.IndentBraces)
addUnwrappedLine();
} else {
addUnwrappedLine();
@@ -1473,11 +1458,8 @@ void UnwrappedLineParser::parseLabel() {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
if (FormatTok->Tok.is(tok::kw_break)) {
- // "break;" after "}" on its own line only for BS_Allman and BS_GNU
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
+ if (Style.BraceWrapping.AfterControlStatement)
addUnwrappedLine();
- }
parseStructuralElement();
}
addUnwrappedLine();
@@ -1741,8 +1723,7 @@ void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
parseObjCProtocolList();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ if (Style.BraceWrapping.AfterObjCDeclaration)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/true);
}
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 8549ec6ef4..b0c9d46b1a 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -9263,6 +9263,20 @@ TEST_F(FormatTest, GetsCorrectBasedOnStyle) {
#define CHECK_PARSE_BOOL(FIELD) CHECK_PARSE_BOOL_FIELD(FIELD, #FIELD)
+#define CHECK_PARSE_NESTED_BOOL_FIELD(STRUCT, FIELD, CONFIG_NAME) \
+ Style.STRUCT.FIELD = false; \
+ EXPECT_EQ(0, \
+ parseConfiguration(#STRUCT ":\n " CONFIG_NAME ": true", &Style) \
+ .value()); \
+ EXPECT_TRUE(Style.STRUCT.FIELD); \
+ EXPECT_EQ(0, \
+ parseConfiguration(#STRUCT ":\n " CONFIG_NAME ": false", &Style) \
+ .value()); \
+ EXPECT_FALSE(Style.STRUCT.FIELD);
+
+#define CHECK_PARSE_NESTED_BOOL(STRUCT, FIELD) \
+ CHECK_PARSE_NESTED_BOOL_FIELD(STRUCT, FIELD, #FIELD)
+
#define CHECK_PARSE(TEXT, FIELD, VALUE) \
EXPECT_NE(VALUE, Style.FIELD); \
EXPECT_EQ(0, parseConfiguration(TEXT, &Style).value()); \
@@ -9303,6 +9317,18 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses);
CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
+
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterEnum);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterFunction);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterNamespace);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterObjCDeclaration);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterStruct);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterUnion);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
}
#undef CHECK_PARSE_BOOL
@@ -9414,7 +9440,10 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("BreakBeforeBraces: Allman", BreakBeforeBraces,
FormatStyle::BS_Allman);
CHECK_PARSE("BreakBeforeBraces: GNU", BreakBeforeBraces, FormatStyle::BS_GNU);
- CHECK_PARSE("BreakBeforeBraces: WebKit", BreakBeforeBraces, FormatStyle::BS_WebKit);
+ CHECK_PARSE("BreakBeforeBraces: WebKit", BreakBeforeBraces,
+ FormatStyle::BS_WebKit);
+ CHECK_PARSE("BreakBeforeBraces: Custom", BreakBeforeBraces,
+ FormatStyle::BS_Custom);
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None",