Index: docs/ClangFormatStyleOptions.rst =================================================================== --- docs/ClangFormatStyleOptions.rst +++ docs/ClangFormatStyleOptions.rst @@ -950,6 +950,20 @@ return 0; } +**DanglingParenthesis** (``bool``) + If there is a break after the opening parenthesis, also break before the closing parenthesis + + .. code-block:: c++ + + true: + someLongFunction( + argument1, argument2 + ); + + false: + someLongFunction( + argument1, argument2); + **ConstructorInitializerIndentWidth** (``unsigned``) The number of characters to use for indentation of constructor initializer lists. Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -778,6 +778,20 @@ /// \endcode bool ConstructorInitializerAllOnOneLineOrOnePerLine; + /// \brief If there is a break after the opening parenthesis, also break + /// before the closing parenthesis + /// \code + /// true: + /// someLongFunction( + /// argument1, argument2 + /// ); + /// + /// false: + /// someLongFunction( + /// argument1, argument2); + /// \endcode + bool DanglingParenthesis; + /// \brief The number of characters to use for indentation of constructor /// initializer lists. unsigned ConstructorInitializerIndentWidth; Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -143,6 +143,12 @@ State.Stack.back().NoLineBreakInOperand) return false; + if (Style.DanglingParenthesis && Current.is(tok::r_paren) && + Current.MatchingParen && + Current.MatchingParen->LastNewlineOffset == + Current.MatchingParen->Next->LastNewlineOffset) + return false; + return !State.Stack.back().NoLineBreak; } @@ -156,6 +162,11 @@ return true; if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) return true; + if (Style.DanglingParenthesis && Current.is(tok::r_paren) && + Current.MatchingParen && + Current.MatchingParen->LastNewlineOffset < + Current.MatchingParen->Next->LastNewlineOffset) + return true; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) && Style.isCpp() && @@ -674,6 +685,9 @@ return State.Stack[State.Stack.size() - 2].LastSpace; return State.FirstIndent; } + if (Style.DanglingParenthesis && Current.is(tok::r_paren) && State.Stack.size() > 1) { + return State.Stack[State.Stack.size() - 2].LastSpace; + } if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope()) return State.Stack[State.Stack.size() - 2].LastSpace; if (Current.is(tok::identifier) && Current.Next && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -315,6 +315,7 @@ Style.BreakBeforeInheritanceComma); IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", Style.ConstructorInitializerAllOnOneLineOrOnePerLine); + IO.mapOptional("DanglingParenthesis", Style.DanglingParenthesis); IO.mapOptional("ConstructorInitializerIndentWidth", Style.ConstructorInitializerIndentWidth); IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); @@ -541,6 +542,7 @@ LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; + LLVMStyle.DanglingParenthesis = false; LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; @@ -606,6 +608,7 @@ GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; GoogleStyle.AlwaysBreakTemplateDeclarations = true; GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + GoogleStyle.DanglingParenthesis = false; GoogleStyle.DerivePointerAlignment = true; GoogleStyle.IncludeCategories = {{"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}}; GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -2652,7 +2652,10 @@ if (Right.is(TT_ImplicitStringLiteral)) return false; - if (Right.is(tok::r_paren) || Right.is(TT_TemplateCloser)) + if (Right.is(tok::r_paren)) { + return Style.DanglingParenthesis; + } + if (Right.is(TT_TemplateCloser)) return false; if (Right.is(tok::r_square) && Right.MatchingParen && Right.MatchingParen->is(TT_LambdaLSquare)) Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -8757,6 +8757,7 @@ CHECK_PARSE_BOOL(BreakStringLiterals); CHECK_PARSE_BOOL(BreakBeforeInheritanceComma) CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); + CHECK_PARSE_BOOL(DanglingParenthesis); CHECK_PARSE_BOOL(DerivePointerAlignment); CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding"); CHECK_PARSE_BOOL(DisableFormat);