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.
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``)
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.
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
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()
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
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
/// 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;
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);
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);
}
};
+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.
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;
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();
}
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);
}
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;
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;
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 ||
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; }
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() {
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);
}
// 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);
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;
--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);
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;
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() {
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();
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();
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);
}
#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()); \
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
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",