Skip to content

Commit

Permalink
[clang-format] Add support for DanglingParenthesis
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Stringham authored and stringham committed Jul 21, 2017
1 parent e06c4a4 commit aa54b20
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 7 deletions.
14 changes: 14 additions & 0 deletions docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,20 @@ the configuration (without a prefix: ``Auto``).
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.
Expand Down
14 changes: 14 additions & 0 deletions include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,20 @@ struct FormatStyle {
/// \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;
Expand Down
11 changes: 11 additions & 0 deletions lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
State.Stack.back().NoLineBreakInOperand)
return false;

if(Current.is(tok::r_paren) && !State.Stack.back().BreakBeforeClosingParen)
return false;

return !State.Stack.back().NoLineBreak;
}

Expand All @@ -174,6 +177,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (State.Stack.back().BreakBeforeClosingBrace &&
Current.closesBlockOrBlockTypeList(Style))
return true;
if(State.Stack.back().BreakBeforeClosingParen && Current.is(tok::r_paren))
return true;
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
return true;
if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) ||
Expand Down Expand Up @@ -666,6 +671,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
PreviousNonComment->opensScope())))
State.Stack.back().BreakBeforeClosingBrace = true;

if (PreviousNonComment && PreviousNonComment->is(tok::l_paren))
State.Stack.back().BreakBeforeClosingParen = Style.DanglingParenthesis;

if (State.Stack.back().AvoidBinPacking) {
// If we are breaking after '(', '{', '<', this is not bin packing
// unless AllowAllParametersOfDeclarationOnNextLine is false or this is a
Expand Down Expand Up @@ -728,6 +736,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
(!Current.Next || Current.Next->isOneOf(tok::semi, tok::l_brace)))
return State.Stack[State.Stack.size() - 2].LastSpace;
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 &&
Expand Down
22 changes: 16 additions & 6 deletions lib/Format/ContinuationIndenter.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,13 @@ struct ParenState {
ParenState(unsigned Indent, unsigned LastSpace, bool AvoidBinPacking,
bool NoLineBreak)
: Indent(Indent), LastSpace(LastSpace), NestedBlockIndent(Indent),
BreakBeforeClosingBrace(false), AvoidBinPacking(AvoidBinPacking),
BreakBeforeParameter(false), NoLineBreak(NoLineBreak),
NoLineBreakInOperand(false), LastOperatorWrapped(true),
ContainsLineBreak(false), ContainsUnwrappedBuilder(false),
AlignColons(true), ObjCSelectorNameFound(false),
HasMultipleNestedBlocks(false), NestedBlockInlined(false) {}
BreakBeforeClosingBrace(false), BreakBeforeClosingParen(false),
AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
NoLineBreak(NoLineBreak), NoLineBreakInOperand(false),
LastOperatorWrapped(true), ContainsLineBreak(false),
ContainsUnwrappedBuilder(false), AlignColons(true),
ObjCSelectorNameFound(false), HasMultipleNestedBlocks(false),
NestedBlockInlined(false) {}

/// \brief The position to which a specific parenthesis level needs to be
/// indented.
Expand Down Expand Up @@ -210,6 +211,13 @@ struct ParenState {
/// was a newline after the beginning left brace.
bool BreakBeforeClosingBrace : 1;

/// \brief Whether a newline needs to be inserted before the block's closing
/// paren.
///
/// We only want to insert a newline before the closing paren if there also
/// was a newline after the beginning left paren.
bool BreakBeforeClosingParen : 1;

/// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
/// lines, in this context.
bool AvoidBinPacking : 1;
Expand Down Expand Up @@ -275,6 +283,8 @@ struct ParenState {
return FirstLessLess < Other.FirstLessLess;
if (BreakBeforeClosingBrace != Other.BreakBeforeClosingBrace)
return BreakBeforeClosingBrace;
if (BreakBeforeClosingParen != Other.BreakBeforeClosingParen)
return BreakBeforeClosingParen;
if (QuestionColumn != Other.QuestionColumn)
return QuestionColumn < Other.QuestionColumn;
if (AvoidBinPacking != Other.AvoidBinPacking)
Expand Down
3 changes: 3 additions & 0 deletions lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
IO.mapOptional("DanglingParenthesis", Style.DanglingParenthesis);
IO.mapOptional("ConstructorInitializerIndentWidth",
Style.ConstructorInitializerIndentWidth);
IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
Expand Down Expand Up @@ -575,6 +576,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.CommentPragmas = "^ IWYU pragma:";
LLVMStyle.CompactNamespaces = false;
LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
LLVMStyle.DanglingParenthesis = false;
LLVMStyle.ConstructorInitializerIndentWidth = 4;
LLVMStyle.ContinuationIndentWidth = 4;
LLVMStyle.Cpp11BracedListStyle = true;
Expand Down Expand Up @@ -648,6 +650,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
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))?$";
Expand Down
5 changes: 4 additions & 1 deletion lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2750,7 +2750,10 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
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))
Expand Down
1 change: 1 addition & 0 deletions unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9544,6 +9544,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(BreakBeforeInheritanceComma)
CHECK_PARSE_BOOL(CompactNamespaces);
CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine);
CHECK_PARSE_BOOL(DanglingParenthesis);
CHECK_PARSE_BOOL(DerivePointerAlignment);
CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding");
CHECK_PARSE_BOOL(DisableFormat);
Expand Down

0 comments on commit aa54b20

Please sign in to comment.