[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-10-02 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

@djasper should I move forward with extending the BracketAlignmentStyle option? 
I'm happy to do it, but I'd like to get the idea signed off on before I spend 
more time working on it. We've been using a version of clang-format with these 
changes since May, and we've been happy with it.

Does my current approach seem reasonable, or should I follow a different 
pattern?


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2018-08-25 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

@djasper can you give some direction here?

Would you be okay with me extending the BracketAlignmentStyle option?
What do I need to do to get this change merged?


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-30 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added inline comments.



Comment at: include/clang/Format/Format.h:793
+  /// \endcode
+  bool DanglingParenthesis;
+

djasper wrote:
> stringham wrote:
> > djasper wrote:
> > > I don't think this is a name that anyone will intuitively understand. I 
> > > understand that the naming is hard here. One thing I am wondering is 
> > > whether this might ever make sense unless AlignAfterOpenBracket is set to 
> > > AlwaysBreak?
> > > 
> > > Unless that option is set, we could have both in the same file:
> > > 
> > >   someFunction(,
> > >);
> > > 
> > > and
> > > 
> > >   someFunction(
> > >   , 
> > >   );
> > > 
> > > Is that intended, i.e. are you actively using that? Answering this is 
> > > important, because it influence whether or not we actually need to add 
> > > another style option and even how to implement this.
> > The name was based on the configuration option that scalafmt has for their 
> > automatic scala formatter, they also have an option to have the closing 
> > paren on its own line and they call it `danglingParentheses`. I don't love 
> > the name and am open to other options.
> > 
> > That's a good point about AlignAfterOpenBracket being set to AlwaysBreak. 
> > In our usage we have that option set, and I'm also unsure if it makes sense 
> > without AlwaysBreak.
> Hm. I am not sure either. What do you think of extending the 
> BracketAlignmentStyle enum with an AlwaysBreakWithDanglingParenthesis? Or 
> AlwaysBreakAndWrapRParen?
Sorry for the delay in the reply!

That seems like a reasonable solution to me. I believe the structure of the 
patch would be the same, just changing out the configuration option.

Can you point me to where I should look to figure out how to run the unit tests 
and let me know if there are other changes you would recommend besides updating 
configuration options?


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2019-03-09 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

@MyDeveloperDay I am happy to write unit tests and clean up the change set but 
I don't want to spend more time on this if it has no chance of being merged.

I am looking for some agreement that this feature is worth adding to clang 
format and then I'd like to know that my general solution is reasonable and 
agree on what we should call the option.

Currently, we're just using a fork with this patch applied. It would be nice to 
get the changes merged upstream, but I don't know how to make that happen.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D33029/new/

https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2019-10-06 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

@MyDeveloperDay done


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D33029/new/

https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2020-03-26 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

@bbassi, I don't have plans to address this, and am supportive of you finishing 
it up.

The plan was to move this as one of the options in the `BracketAlignmentStyle` 
configuration (value of `AlwaysBreakWithDanglingParenthesis`) rather than have 
it be a brand new config property.

So we need to do that switch, and write new tests for this feature.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D33029/new/

https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2020-03-27 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

Here's a commit rebased as of yesterday that is still adding 
DanglingParenthesis option instead of extending the BracketAlignmentStyle 
configuration.

https://github.com/lucidsoftware/llvm-project/commit/3c04de1feffaa9787234da8fe3cf288eebc979d6


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D33029/new/

https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2020-03-27 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

I think that adding `AlwaysBreakWithDanglingParenthesis` as an option to 
`BracketAlignmentStyle` should not impact any of the binpacking settings - they 
should be distinct configuration.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D33029/new/

https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-09 Thread Ryan Stringham via Phabricator via cfe-commits
stringham created this revision.
stringham added a project: clang-tools-extra.
Herald added a subscriber: klimek.

This adds an option to clang-format to support dangling parenthesis.

If you have a parameter list like

Foo(

  param1,
  param2,
  param3,

);

clang-format currently only supports putting the closing paren on the same line 
as param3:

Foo(

  param1,
  param2,
  param3, );

This makes it difficult to see the change from the function signature to the 
function body, for example:

class Foo extends Bar {

  constructor(
  param1,
  param2,
  param3, ) {
  super(param1, 'x');
  this.param2 = param2;
  }

}

would now be formatted like:

class Foo extends Bar {

  constructor(
  param1,
  param2,
  param3, 
  ) {
  super(param1, 'x');
  this.param2 = param2;
  }

}

and it is much easier to see the difference between the parameter list and the 
function body.


https://reviews.llvm.org/D33029

Files:
  docs/ClangFormatStyleOptions.rst
  include/clang/Format/Format.h
  lib/Format/ContinuationIndenter.cpp
  lib/Format/Format.cpp
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTest.cpp

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);
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: 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/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) {
+r

[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-10 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

1. be used in a project of significant size (have dozens of contributors)
  - We are using this at Lucid Software (https://www.lucidchart.com & 
https://www.lucidpress.com) to format our JS and TS (we are using clang-format 
to automatically style over 650,000 lines of code)
  - It's not open source, but we do have dozens of contributors

2. have a publicly accessible style guide
  - We don't have a publicly available style guide, but here is Airbnb's 
Javascript Style guide's style definition which uses the dangling parens:
- 
https://github.com/airbnb/javascript#functions--signature-invocation-indentation
- I think this counts as a project of significant size with a publicly 
available style guide which would use this style rule.

3. have a person willing to contribute and maintain patches
  - Me
  - We currently have a fork of clang on github 
(https://github.com/lucidsoftware/clang) with this patch applied


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-10 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

I think we should have the option whether or not a trailing comma is preset for 
a few reasons:

1. clang-format doesn't support enforcing adding trailing commas
2. trailing commas aren't always supported (if you use the rest operator)
  - `Uncaught SyntaxError: Rest parameter must be last formal parameter`
3. if you break before the opening paren, treating the surrounding parens as a 
"block" helps the developer match up the parens.

false:

  longFunctionCall(new longClassNameBeingInitialized(
  param1,
  param2,
  param3,
  param4,
  param5));

true:

  longFunctionCall(new longClassNameBeingInitialized(
  param1,
  param2,
  param3,
  param4,
  param5
  ));

also happens for function calls like this:

false:

  this.myList = [
  param1,
  functionCall(param)
  .chainedCall(
  longparam1,
  function(foo) {
  return calculateSomething(foo);
  }),
  param3,
  ];

true:

  this.myList = [
  param1,
  functionCall(param)
  .chainedCall(
  longparam1,
  function(foo) {
  return calculateSomething(foo);
  }
  ),
  param3,
  ];

can't put a trailing comma with the rest operator
false:

  class MyClass {
  constructor(
  param1,
  param2,
  ...args) {
  this.p1 = param1;
  }
  }

true:

  class MyClass {
  constructor(
  param1,
  param2,
  ...args
  ) {
  this.p1 = param1;
  }
  }


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-10 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

If the parameter list fits within the column limit, and there are no trailing 
commas, then we don't end up wrapping the closing paren.

If it is long enough that it causes wrapping (regardless of trailing commas), 
and the wrapping happens directly after the opening paren, we break before the 
closing paren.


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-12 Thread Ryan Stringham via Phabricator via cfe-commits
stringham updated this revision to Diff 98873.

https://reviews.llvm.org/D33029

Files:
  docs/ClangFormatStyleOptions.rst
  include/clang/Format/Format.h
  lib/Format/ContinuationIndenter.cpp
  lib/Format/ContinuationIndenter.h
  lib/Format/Format.cpp
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTest.cpp

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);
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: 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/ContinuationIndenter.h
===
--- lib/Format/ContinuationIndenter.h
+++ lib/Format/ContinuationIndenter.h
@@ -149,12 +149,13 @@
   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.
@@ -210,6 +211,13 @@
   /// 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;
@@ -275,6 +283,8 @@
   return FirstLessLess < Other.FirstLessLess;
 if (BreakBeforeClosingBrace != Other.BreakBeforeClosingBrace)
   return BreakBeforeClosingBrace;
+if (BreakBeforeClosingParen != Other.BreakBeforeClosingParen)
+  return BreakBeforeClosingParen;
 if (Q

[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-15 Thread Ryan Stringham via Phabricator via cfe-commits
stringham added a comment.

> Probably all of the examples from the original patch description and later 
> comments should be turned into unit tests.

I would like to add some unit tests for this, but was not able to figure out 
how to run the unit test suite. Where can I find instructions on how to run the 
unit tests?

I found out how to build clang-format from a combination of 
https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang_format_binaries.md
 and https://github.com/angular/clang-format#compiling-clang-format

I saw step 10 on http://clang.llvm.org/get_started.html says to run `make 
check-clang` from my build directory, but when I try that I get "No rule to 
make target" errors.




Comment at: docs/ClangFormatStyleOptions.rst:953
 
+**DanglingParenthesis** (``bool``)
+  If there is a break after the opening parenthesis, also break before the 
closing parenthesis

djasper wrote:
> Have you auto-generated this with docs/tools/dump_format_style.py? There seem 
> to be subtle differences.
I was not aware the dump_format_style.py existed. I created this manually based 
on the code around it. I will try running that script.



Comment at: include/clang/Format/Format.h:793
+  /// \endcode
+  bool DanglingParenthesis;
+

djasper wrote:
> I don't think this is a name that anyone will intuitively understand. I 
> understand that the naming is hard here. One thing I am wondering is whether 
> this might ever make sense unless AlignAfterOpenBracket is set to AlwaysBreak?
> 
> Unless that option is set, we could have both in the same file:
> 
>   someFunction(,
>);
> 
> and
> 
>   someFunction(
>   , 
>   );
> 
> Is that intended, i.e. are you actively using that? Answering this is 
> important, because it influence whether or not we actually need to add 
> another style option and even how to implement this.
The name was based on the configuration option that scalafmt has for their 
automatic scala formatter, they also have an option to have the closing paren 
on its own line and they call it `danglingParentheses`. I don't love the name 
and am open to other options.

That's a good point about AlignAfterOpenBracket being set to AlwaysBreak. In 
our usage we have that option set, and I'm also unsure if it makes sense 
without AlwaysBreak.


https://reviews.llvm.org/D33029



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33029: [clang-format] add option for dangling parenthesis

2017-05-15 Thread Ryan Stringham via Phabricator via cfe-commits
stringham updated this revision to Diff 99010.
stringham added a comment.

Generated the documentation using dump_format_style.py

removed some unnecessary braces.


https://reviews.llvm.org/D33029

Files:
  docs/ClangFormatStyleOptions.rst
  include/clang/Format/Format.h
  lib/Format/ContinuationIndenter.cpp
  lib/Format/ContinuationIndenter.h
  lib/Format/Format.cpp
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTest.cpp

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);
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2652,7 +2652,9 @@
   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: 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/ContinuationIndenter.h
===
--- lib/Format/ContinuationIndenter.h
+++ lib/Format/ContinuationIndenter.h
@@ -149,12 +149,13 @@
   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.
@@ -210,6 +211,13 @@
   /// 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;
@@ -275,6 +283,8 @@
   return FirstLessLess < Other.FirstLessLess;
 if (BreakBeforeClosingBrace != Other.BreakBeforeClosingBrace)
   return BreakBeforeClosingBrace;
+i