}
-**BreakAfterAttributes** (``AttributeBreakingStyle``) :versionbadge:`clang-format 16`
- Break after a group of C++11 attributes before a function
- declaration/definition name.
-
- Possible values:
-
- * ``ABS_Always`` (in configuration: ``Always``)
- Always break after attributes.
-
- .. code-block:: c++
-
- [[nodiscard]]
- inline int f();
- [[gnu::const]] [[nodiscard]]
- int g();
-
- * ``ABS_Leave`` (in configuration: ``Leave``)
- Leave the line breaking after attributes as is.
-
- .. code-block:: c++
-
- [[nodiscard]] inline int f();
- [[gnu::const]] [[nodiscard]]
- int g();
-
- * ``ABS_Never`` (in configuration: ``Never``)
- Never break after attributes.
-
- .. code-block:: c++
-
- [[nodiscard]] inline int f();
- [[gnu::const]] [[nodiscard]] int g();
-
-
-
**BreakAfterJavaFieldAnnotations** (``Boolean``) :versionbadge:`clang-format 3.8`
Break after each annotation on a field in Java files.
To match the default behavior of clang-format 15, use the ``Keyword`` value.
- Add ``IntegerLiteralSeparator`` option for fixing integer literal separators
in C++, C#, Java, and JavaScript.
-- Add ``BreakAfterAttributes`` option for breaking after a group of C++11
- attributes before a function declaration/definition name.
- Add ``InsertNewlineAtEOF`` option for inserting a newline at EOF if missing.
clang-extdef-mapping
/// \version 3.8
BraceWrappingFlags BraceWrapping;
- /// Different ways to break after attributes.
- enum AttributeBreakingStyle : int8_t {
- /// Always break after attributes.
- /// \code
- /// [[nodiscard]]
- /// inline int f();
- /// [[gnu::const]] [[nodiscard]]
- /// int g();
- /// \endcode
- ABS_Always,
- /// Leave the line breaking after attributes as is.
- /// \code
- /// [[nodiscard]] inline int f();
- /// [[gnu::const]] [[nodiscard]]
- /// int g();
- /// \endcode
- ABS_Leave,
- /// Never break after attributes.
- /// \code
- /// [[nodiscard]] inline int f();
- /// [[gnu::const]] [[nodiscard]] int g();
- /// \endcode
- ABS_Never,
- };
-
- /// Break after a group of C++11 attributes before a function
- /// declaration/definition name.
- /// \version 16
- AttributeBreakingStyle BreakAfterAttributes;
-
/// If ``true``, clang-format will always break after a Json array `[`
/// otherwise it will scan until the closing `]` to determine if it should add
/// newlines between elements (prettier compatible).
BinPackArguments == R.BinPackArguments &&
BinPackParameters == R.BinPackParameters &&
BitFieldColonSpacing == R.BitFieldColonSpacing &&
- BreakAfterAttributes == R.BreakAfterAttributes &&
BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
BreakArrays == R.BreakArrays &&
BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators &&
// If the return type spans multiple lines, wrap before the function name.
if (((Current.is(TT_FunctionDeclarationName) &&
- !State.Line->ReturnTypeWrapped &&
// Don't break before a C# function when no break after return type.
(!Style.isCSharp() ||
Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) &&
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
- static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
- IO.enumCase(Value, "Always", FormatStyle::ABS_Always);
- IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);
- IO.enumCase(Value, "Never", FormatStyle::ABS_Never);
- }
-};
-
-template <>
struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
static void enumeration(IO &IO,
FormatStyle::ArrayInitializerAlignmentStyle &Value) {
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
IO.mapOptional("BraceWrapping", Style.BraceWrapping);
- IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
IO.mapOptional("BreakAfterJavaFieldAnnotations",
Style.BreakAfterJavaFieldAnnotations);
IO.mapOptional("BreakArrays", Style.BreakArrays);
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
/*SplitEmptyNamespace=*/true};
- LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Never;
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakArrays = true;
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
CanBreakBefore(false), ClosesTemplateDeclaration(false),
StartsBinaryExpression(false), EndsBinaryExpression(false),
PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false),
- Finalized(false), ClosesRequiresClause(false),
- EndsCppAttributeGroup(false), BlockKind(BK_Unknown),
+ Finalized(false), ClosesRequiresClause(false), BlockKind(BK_Unknown),
Decision(FD_Unformatted), PackingKind(PPK_Inconclusive),
TypeIsFinalized(false), Type(TT_Unknown) {}
/// \c true if this is the last token within requires clause.
unsigned ClosesRequiresClause : 1;
- /// \c true if this token ends a group of C++ attributes.
- unsigned EndsCppAttributeGroup : 1;
-
private:
/// Contains the kind of block if this token is a brace.
unsigned BlockKind : 2;
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().ContextType == Context::TemplateArgument);
- const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;
- const bool IsCpp11AttributeSpecifier =
- isCpp11AttributeSpecifier(*Left) || IsInnerSquare;
+ bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
+ Contexts.back().InCpp11AttributeSpecifier;
// Treat C# Attributes [STAThread] much like C++ attributes [[...]].
bool IsCSharpAttributeSpecifier =
Left->setType(TT_InlineASMSymbolicNameLSquare);
} else if (IsCpp11AttributeSpecifier) {
Left->setType(TT_AttributeSquare);
- if (!IsInnerSquare && Left->Previous)
- Left->Previous->EndsCppAttributeGroup = false;
} else if (Style.isJavaScript() && Parent &&
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
- if (IsCpp11AttributeSpecifier) {
+ if (IsCpp11AttributeSpecifier)
CurrentToken->setType(TT_AttributeSquare);
- if (!IsInnerSquare)
- CurrentToken->EndsCppAttributeGroup = true;
- }
if (IsCSharpAttributeSpecifier) {
CurrentToken->setType(TT_AttributeSquare);
} else if (((CurrentToken->Next &&
return false;
}
-static bool mustBreakAfterAttributes(const FormatToken &Tok,
- const FormatStyle &Style) {
- switch (Style.BreakAfterAttributes) {
- case FormatStyle::ABS_Always:
- return true;
- case FormatStyle::ABS_Leave:
- return Tok.NewlinesBefore > 0;
- default:
- return false;
- }
-}
-
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
for (AnnotatedLine *ChildLine : Line.Children)
calculateFormattingInformation(*ChildLine);
if (AlignArrayOfStructures)
calculateArrayInitializerColumnList(Line);
- for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
- Tok = Tok->Next) {
- if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line)) {
- Tok->setType(TT_FunctionDeclarationName);
- if (AfterLastAttribute &&
- mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
- AfterLastAttribute->MustBreakBefore = true;
- Line.ReturnTypeWrapped = true;
- }
- break;
- }
- if (Tok->Previous->EndsCppAttributeGroup)
- AfterLastAttribute = Tok;
- }
-
while (Current) {
+ if (isFunctionDeclarationName(Style.isCpp(), *Current, Line))
+ Current->setType(TT_FunctionDeclarationName);
const FormatToken *Prev = Current->Previous;
if (Current->is(TT_LineComment)) {
if (Prev->is(BK_BracedInit) && Prev->opensScope()) {
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
IsMultiVariableDeclStmt(false), Affected(false),
LeadingEmptyLinesAffected(false), ChildrenAffected(false),
- ReturnTypeWrapped(false), IsContinuation(Line.IsContinuation),
+ IsContinuation(Line.IsContinuation),
FirstStartColumn(Line.FirstStartColumn) {
assert(!Line.Tokens.empty());
/// \c True if one of this line's children intersects with an input range.
bool ChildrenAffected;
- /// \c True if breaking after last attribute group in function return type.
- bool ReturnTypeWrapped;
-
/// \c True if this line should be indented by ContinuationIndent in addition
/// to the normal indention level.
bool IsContinuation;
BreakBeforeConceptDeclarations, FormatStyle::BBCDS_Always);
CHECK_PARSE("BreakBeforeConceptDeclarations: false",
BreakBeforeConceptDeclarations, FormatStyle::BBCDS_Allowed);
-
- CHECK_PARSE("BreakAfterAttributes: Always", BreakAfterAttributes,
- FormatStyle::ABS_Always);
- CHECK_PARSE("BreakAfterAttributes: Leave", BreakAfterAttributes,
- FormatStyle::ABS_Leave);
- CHECK_PARSE("BreakAfterAttributes: Never", BreakAfterAttributes,
- FormatStyle::ABS_Never);
}
TEST(ConfigParseTest, ParsesConfigurationWithLanguages) {
#endif
}
-TEST_F(FormatTest, BreakAfterAttributes) {
- FormatStyle Style = getLLVMStyle();
- EXPECT_EQ(Style.BreakAfterAttributes, FormatStyle::ABS_Never);
-
- const StringRef Code("[[nodiscard]] inline int f(int &i);\n"
- "[[foo([[]])]] [[nodiscard]]\n"
- "int g(int &i);\n"
- "[[nodiscard]]\n"
- "inline int f(int &i) {\n"
- " i = 1;\n"
- " return 0;\n"
- "}\n"
- "[[foo([[]])]] [[nodiscard]] int g(int &i) {\n"
- " i = 0;\n"
- " return 1;\n"
- "}");
-
- verifyFormat("[[nodiscard]] inline int f(int &i);\n"
- "[[foo([[]])]] [[nodiscard]] int g(int &i);\n"
- "[[nodiscard]] inline int f(int &i) {\n"
- " i = 1;\n"
- " return 0;\n"
- "}\n"
- "[[foo([[]])]] [[nodiscard]] int g(int &i) {\n"
- " i = 0;\n"
- " return 1;\n"
- "}",
- Code, Style);
-
- Style.BreakAfterAttributes = FormatStyle::ABS_Always;
- verifyFormat("[[nodiscard]]\n"
- "inline int f(int &i);\n"
- "[[foo([[]])]] [[nodiscard]]\n"
- "int g(int &i);\n"
- "[[nodiscard]]\n"
- "inline int f(int &i) {\n"
- " i = 1;\n"
- " return 0;\n"
- "}\n"
- "[[foo([[]])]] [[nodiscard]]\n"
- "int g(int &i) {\n"
- " i = 0;\n"
- " return 1;\n"
- "}",
- Code, Style);
-
- Style.BreakAfterAttributes = FormatStyle::ABS_Leave;
- EXPECT_EQ(Code, format(Code, Style));
-}
-
TEST_F(FormatTest, InsertNewlineAtEOF) {
FormatStyle Style = getLLVMStyle();
Style.InsertNewlineAtEOF = true;