diff options
-rw-r--r-- | docs/ClangFormatStyleOptions.rst | 38 | ||||
-rwxr-xr-x | docs/tools/dump_format_style.py | 54 | ||||
-rw-r--r-- | include/clang/Format/Format.h | 36 | ||||
-rw-r--r-- | lib/Format/Format.cpp | 78 | ||||
-rw-r--r-- | lib/Format/TokenAnnotator.cpp | 7 | ||||
-rw-r--r-- | lib/Format/UnwrappedLineFormatter.cpp | 7 | ||||
-rw-r--r-- | lib/Format/UnwrappedLineParser.cpp | 63 | ||||
-rw-r--r-- | unittests/Format/FormatTest.cpp | 31 |
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", |