forked from OSchip/llvm-project
[clang-format] Add new option BeforeLambdaBody in Allman style.
This option add a line break then a lambda is inside a function call. Reviewers : djasper, klimek, krasimir, MyDeveloperDay Reviewed By: MyDeveloperDay Differential Revision: https://reviews.llvm.org/D44609
This commit is contained in:
parent
ef7488ef20
commit
fa0118e6e5
|
@ -968,6 +968,24 @@ the configuration (without a prefix: ``Auto``).
|
|||
} else {
|
||||
}
|
||||
|
||||
* ``bool BeforeLambdaBody`` Wrap lambda block.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
true:
|
||||
connect(
|
||||
[]()
|
||||
{
|
||||
foo();
|
||||
bar();
|
||||
});
|
||||
|
||||
false:
|
||||
connect([]() {
|
||||
foo();
|
||||
bar();
|
||||
});
|
||||
|
||||
* ``bool IndentBraces`` Indent the wrapped braces themselves.
|
||||
|
||||
* ``bool SplitEmptyFunction`` If ``false``, empty function body can be put on a single line.
|
||||
|
|
|
@ -1,272 +1,291 @@
|
|||
========================================
|
||||
Clang 11.0.0 (In-Progress) Release Notes
|
||||
========================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Written by the `LLVM Team <https://llvm.org/>`_
|
||||
|
||||
.. warning::
|
||||
|
||||
These are in-progress notes for the upcoming Clang 11 release.
|
||||
Release notes for previous releases can be found on
|
||||
`the Download Page <https://releases.llvm.org/download.html>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document contains the release notes for the Clang C/C++/Objective-C
|
||||
frontend, part of the LLVM Compiler Infrastructure, release 11.0.0. Here we
|
||||
describe the status of Clang in some detail, including major
|
||||
improvements from the previous release and new feature work. For the
|
||||
general LLVM release notes, see `the LLVM
|
||||
documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM
|
||||
releases may be downloaded from the `LLVM releases web
|
||||
site <https://llvm.org/releases/>`_.
|
||||
|
||||
For more information about Clang or LLVM, including information about the
|
||||
latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
|
||||
`LLVM Web Site <https://llvm.org>`_.
|
||||
|
||||
Note that if you are reading this file from a Git checkout or the
|
||||
main Clang web page, this document applies to the *next* release, not
|
||||
the current one. To see the release notes for a specific release, please
|
||||
see the `releases page <https://llvm.org/releases/>`_.
|
||||
|
||||
What's New in Clang 11.0.0?
|
||||
===========================
|
||||
|
||||
Some of the major new features and improvements to Clang are listed
|
||||
here. Generic improvements to Clang as a whole or to its underlying
|
||||
infrastructure are described first, followed by language-specific
|
||||
sections with improvements to Clang's support for those languages.
|
||||
|
||||
Major New Features
|
||||
------------------
|
||||
|
||||
- ...
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- ...
|
||||
|
||||
Non-comprehensive list of changes in this release
|
||||
-------------------------------------------------
|
||||
|
||||
|
||||
New Compiler Flags
|
||||
------------------
|
||||
|
||||
|
||||
- -fstack-clash-protection will provide a protection against the stack clash
|
||||
attack for x86 architecture through automatic probing of each page of
|
||||
allocated stack.
|
||||
|
||||
Deprecated Compiler Flags
|
||||
-------------------------
|
||||
|
||||
The following options are deprecated and ignored. They will be removed in
|
||||
future versions of Clang.
|
||||
|
||||
- ...
|
||||
|
||||
Modified Compiler Flags
|
||||
-----------------------
|
||||
|
||||
|
||||
New Pragmas in Clang
|
||||
--------------------
|
||||
|
||||
- ...
|
||||
|
||||
Attribute Changes in Clang
|
||||
--------------------------
|
||||
|
||||
- ...
|
||||
|
||||
Windows Support
|
||||
---------------
|
||||
|
||||
C Language Changes in Clang
|
||||
---------------------------
|
||||
|
||||
- ...
|
||||
|
||||
C11 Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
...
|
||||
|
||||
C++ Language Changes in Clang
|
||||
-----------------------------
|
||||
|
||||
- Clang now implements a restriction on giving non-C-compatible anonymous
|
||||
structs a typedef name for linkage purposes, as described in C++ committee
|
||||
paper `P1766R1 <http://wg21.link/p1766r1>`. This paper was adopted by the
|
||||
C++ committee as a Defect Report resolution, so it is applied retroactively
|
||||
to all C++ standard versions. This affects code such as:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
typedef struct {
|
||||
int f() { return 0; }
|
||||
} S;
|
||||
|
||||
Previous versions of Clang rejected some constructs of this form
|
||||
(specifically, where the linkage of the type happened to be computed
|
||||
before the parser reached the typedef name); those cases are still rejected
|
||||
in Clang 11. In addition, cases that previous versions of Clang did not
|
||||
reject now produce an extension warning. This warning can be disabled with
|
||||
the warning flag ``-Wno-non-c-typedef-for-linkage``.
|
||||
|
||||
Affected code should be updated to provide a tag name for the anonymous
|
||||
struct:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
struct S {
|
||||
int f() { return 0; }
|
||||
};
|
||||
|
||||
If the code is shared with a C compilation (for example, if the parts that
|
||||
are not C-compatible are guarded with ``#ifdef __cplusplus``), the typedef
|
||||
declaration should be retained, but a tag name should still be provided:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
typedef struct S {
|
||||
int f() { return 0; }
|
||||
} S;
|
||||
|
||||
C++1z Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
...
|
||||
|
||||
Objective-C Language Changes in Clang
|
||||
-------------------------------------
|
||||
|
||||
|
||||
OpenCL C Language Changes in Clang
|
||||
----------------------------------
|
||||
|
||||
...
|
||||
|
||||
ABI Changes in Clang
|
||||
--------------------
|
||||
|
||||
|
||||
OpenMP Support in Clang
|
||||
-----------------------
|
||||
|
||||
- ...
|
||||
|
||||
CUDA Support in Clang
|
||||
---------------------
|
||||
|
||||
- ...
|
||||
|
||||
Internal API Changes
|
||||
--------------------
|
||||
|
||||
These are major API changes that have happened since the 10.0.0 release of
|
||||
Clang. If upgrading an external codebase that uses Clang as a library,
|
||||
this section should help get you past the largest hurdles of upgrading.
|
||||
|
||||
|
||||
Build System Changes
|
||||
--------------------
|
||||
|
||||
These are major changes to the build system that have happened since the 10.0.0
|
||||
release of Clang. Users of the build system should adjust accordingly.
|
||||
|
||||
- ...
|
||||
|
||||
AST Matchers
|
||||
------------
|
||||
|
||||
- ...
|
||||
|
||||
clang-format
|
||||
------------
|
||||
|
||||
|
||||
- Option ``IndentCaseBlocks`` has been added to support treating the block
|
||||
following a switch case label as a scope block which gets indented itself.
|
||||
It helps avoid having the closing bracket align with the switch statement's
|
||||
closing bracket (when ``IndentCaseLabels`` is ``false``).
|
||||
|
||||
- Option ``ObjCBreakBeforeNestedBlockParam`` has been added to optionally apply
|
||||
linebreaks for function arguments declarations before nested blocks.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
switch (fool) { vs. switch (fool) {
|
||||
case 1: case 1: {
|
||||
{ bar();
|
||||
bar(); } break;
|
||||
} default: {
|
||||
break; plop();
|
||||
default: }
|
||||
{ }
|
||||
plop();
|
||||
}
|
||||
}
|
||||
|
||||
- Option ``InsertTrailingCommas`` can be set to ``TCS_Wrapped`` to insert
|
||||
trailing commas in container literals (arrays and objects) that wrap across
|
||||
multiple lines. It is currently only available for JavaScript and disabled by
|
||||
default (``TCS_None``).
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
||||
- ...
|
||||
|
||||
Static Analyzer
|
||||
---------------
|
||||
|
||||
- ...
|
||||
|
||||
.. _release-notes-ubsan:
|
||||
|
||||
Undefined Behavior Sanitizer (UBSan)
|
||||
------------------------------------
|
||||
|
||||
|
||||
Core Analysis Improvements
|
||||
==========================
|
||||
|
||||
- ...
|
||||
|
||||
New Issues Found
|
||||
================
|
||||
|
||||
- ...
|
||||
|
||||
Python Binding Changes
|
||||
----------------------
|
||||
|
||||
The following methods have been added:
|
||||
|
||||
- ...
|
||||
|
||||
Significant Known Problems
|
||||
==========================
|
||||
|
||||
Additional Information
|
||||
======================
|
||||
|
||||
A wide variety of additional information is available on the `Clang web
|
||||
page <https://clang.llvm.org/>`_. The web page contains versions of the
|
||||
API documentation which are up-to-date with the Subversion version of
|
||||
the source code. You can access versions of these documents specific to
|
||||
this release by going into the "``clang/docs/``" directory in the Clang
|
||||
tree.
|
||||
|
||||
If you have any questions or comments about Clang, please feel free to
|
||||
contact us via the `mailing
|
||||
list <https://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
|
||||
========================================
|
||||
Clang 11.0.0 (In-Progress) Release Notes
|
||||
========================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Written by the `LLVM Team <https://llvm.org/>`_
|
||||
|
||||
.. warning::
|
||||
|
||||
These are in-progress notes for the upcoming Clang 11 release.
|
||||
Release notes for previous releases can be found on
|
||||
`the Download Page <https://releases.llvm.org/download.html>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document contains the release notes for the Clang C/C++/Objective-C
|
||||
frontend, part of the LLVM Compiler Infrastructure, release 11.0.0. Here we
|
||||
describe the status of Clang in some detail, including major
|
||||
improvements from the previous release and new feature work. For the
|
||||
general LLVM release notes, see `the LLVM
|
||||
documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM
|
||||
releases may be downloaded from the `LLVM releases web
|
||||
site <https://llvm.org/releases/>`_.
|
||||
|
||||
For more information about Clang or LLVM, including information about the
|
||||
latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
|
||||
`LLVM Web Site <https://llvm.org>`_.
|
||||
|
||||
Note that if you are reading this file from a Git checkout or the
|
||||
main Clang web page, this document applies to the *next* release, not
|
||||
the current one. To see the release notes for a specific release, please
|
||||
see the `releases page <https://llvm.org/releases/>`_.
|
||||
|
||||
What's New in Clang 11.0.0?
|
||||
===========================
|
||||
|
||||
Some of the major new features and improvements to Clang are listed
|
||||
here. Generic improvements to Clang as a whole or to its underlying
|
||||
infrastructure are described first, followed by language-specific
|
||||
sections with improvements to Clang's support for those languages.
|
||||
|
||||
Major New Features
|
||||
------------------
|
||||
|
||||
- ...
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- ...
|
||||
|
||||
Non-comprehensive list of changes in this release
|
||||
-------------------------------------------------
|
||||
|
||||
|
||||
New Compiler Flags
|
||||
------------------
|
||||
|
||||
|
||||
- -fstack-clash-protection will provide a protection against the stack clash
|
||||
attack for x86 architecture through automatic probing of each page of
|
||||
allocated stack.
|
||||
|
||||
Deprecated Compiler Flags
|
||||
-------------------------
|
||||
|
||||
The following options are deprecated and ignored. They will be removed in
|
||||
future versions of Clang.
|
||||
|
||||
- ...
|
||||
|
||||
Modified Compiler Flags
|
||||
-----------------------
|
||||
|
||||
|
||||
New Pragmas in Clang
|
||||
--------------------
|
||||
|
||||
- ...
|
||||
|
||||
Attribute Changes in Clang
|
||||
--------------------------
|
||||
|
||||
- ...
|
||||
|
||||
Windows Support
|
||||
---------------
|
||||
|
||||
C Language Changes in Clang
|
||||
---------------------------
|
||||
|
||||
- ...
|
||||
|
||||
C11 Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
...
|
||||
|
||||
C++ Language Changes in Clang
|
||||
-----------------------------
|
||||
|
||||
- Clang now implements a restriction on giving non-C-compatible anonymous
|
||||
structs a typedef name for linkage purposes, as described in C++ committee
|
||||
paper `P1766R1 <http://wg21.link/p1766r1>`. This paper was adopted by the
|
||||
C++ committee as a Defect Report resolution, so it is applied retroactively
|
||||
to all C++ standard versions. This affects code such as:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
typedef struct {
|
||||
int f() { return 0; }
|
||||
} S;
|
||||
|
||||
Previous versions of Clang rejected some constructs of this form
|
||||
(specifically, where the linkage of the type happened to be computed
|
||||
before the parser reached the typedef name); those cases are still rejected
|
||||
in Clang 11. In addition, cases that previous versions of Clang did not
|
||||
reject now produce an extension warning. This warning can be disabled with
|
||||
the warning flag ``-Wno-non-c-typedef-for-linkage``.
|
||||
|
||||
Affected code should be updated to provide a tag name for the anonymous
|
||||
struct:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
struct S {
|
||||
int f() { return 0; }
|
||||
};
|
||||
|
||||
If the code is shared with a C compilation (for example, if the parts that
|
||||
are not C-compatible are guarded with ``#ifdef __cplusplus``), the typedef
|
||||
declaration should be retained, but a tag name should still be provided:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
typedef struct S {
|
||||
int f() { return 0; }
|
||||
} S;
|
||||
|
||||
C++1z Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
...
|
||||
|
||||
Objective-C Language Changes in Clang
|
||||
-------------------------------------
|
||||
|
||||
|
||||
OpenCL C Language Changes in Clang
|
||||
----------------------------------
|
||||
|
||||
...
|
||||
|
||||
ABI Changes in Clang
|
||||
--------------------
|
||||
|
||||
|
||||
OpenMP Support in Clang
|
||||
-----------------------
|
||||
|
||||
- ...
|
||||
|
||||
CUDA Support in Clang
|
||||
---------------------
|
||||
|
||||
- ...
|
||||
|
||||
Internal API Changes
|
||||
--------------------
|
||||
|
||||
These are major API changes that have happened since the 10.0.0 release of
|
||||
Clang. If upgrading an external codebase that uses Clang as a library,
|
||||
this section should help get you past the largest hurdles of upgrading.
|
||||
|
||||
|
||||
Build System Changes
|
||||
--------------------
|
||||
|
||||
These are major changes to the build system that have happened since the 10.0.0
|
||||
release of Clang. Users of the build system should adjust accordingly.
|
||||
|
||||
- ...
|
||||
|
||||
AST Matchers
|
||||
------------
|
||||
|
||||
- ...
|
||||
|
||||
clang-format
|
||||
------------
|
||||
|
||||
|
||||
- Option ``IndentCaseBlocks`` has been added to support treating the block
|
||||
following a switch case label as a scope block which gets indented itself.
|
||||
It helps avoid having the closing bracket align with the switch statement's
|
||||
closing bracket (when ``IndentCaseLabels`` is ``false``).
|
||||
|
||||
- Option ``ObjCBreakBeforeNestedBlockParam`` has been added to optionally apply
|
||||
linebreaks for function arguments declarations before nested blocks.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
switch (fool) { vs. switch (fool) {
|
||||
case 1: case 1: {
|
||||
{ bar();
|
||||
bar(); } break;
|
||||
} default: {
|
||||
break; plop();
|
||||
default: }
|
||||
{ }
|
||||
plop();
|
||||
}
|
||||
}
|
||||
|
||||
- Option ``InsertTrailingCommas`` can be set to ``TCS_Wrapped`` to insert
|
||||
trailing commas in container literals (arrays and objects) that wrap across
|
||||
multiple lines. It is currently only available for JavaScript and disabled by
|
||||
default (``TCS_None``).
|
||||
|
||||
- Option ``BraceWrapping.BeforeLambdaBody`` has been added to manage lambda
|
||||
line break inside function parameter call in Allman style.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
true:
|
||||
connect(
|
||||
[]()
|
||||
{
|
||||
foo();
|
||||
bar();
|
||||
});
|
||||
|
||||
false:
|
||||
connect([]() {
|
||||
foo();
|
||||
bar();
|
||||
});
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
||||
- ...
|
||||
|
||||
Static Analyzer
|
||||
---------------
|
||||
|
||||
- ...
|
||||
|
||||
.. _release-notes-ubsan:
|
||||
|
||||
Undefined Behavior Sanitizer (UBSan)
|
||||
------------------------------------
|
||||
|
||||
|
||||
Core Analysis Improvements
|
||||
==========================
|
||||
|
||||
- ...
|
||||
|
||||
New Issues Found
|
||||
================
|
||||
|
||||
- ...
|
||||
|
||||
Python Binding Changes
|
||||
----------------------
|
||||
|
||||
The following methods have been added:
|
||||
|
||||
- ...
|
||||
|
||||
Significant Known Problems
|
||||
==========================
|
||||
|
||||
Additional Information
|
||||
======================
|
||||
|
||||
A wide variety of additional information is available on the `Clang web
|
||||
page <https://clang.llvm.org/>`_. The web page contains versions of the
|
||||
API documentation which are up-to-date with the Subversion version of
|
||||
the source code. You can access versions of these documents specific to
|
||||
this release by going into the "``clang/docs/``" directory in the Clang
|
||||
tree.
|
||||
|
||||
If you have any questions or comments about Clang, please feel free to
|
||||
contact us via the `mailing
|
||||
list <https://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
|
||||
|
|
|
@ -992,6 +992,23 @@ struct FormatStyle {
|
|||
/// }
|
||||
/// \endcode
|
||||
bool BeforeElse;
|
||||
/// Wrap lambda block.
|
||||
/// \code
|
||||
/// true:
|
||||
/// connect(
|
||||
/// []()
|
||||
/// {
|
||||
/// foo();
|
||||
/// bar();
|
||||
/// });
|
||||
///
|
||||
/// false:
|
||||
/// connect([]() {
|
||||
/// foo();
|
||||
/// bar();
|
||||
/// });
|
||||
/// \endcode
|
||||
bool BeforeLambdaBody;
|
||||
/// Indent the wrapped braces themselves.
|
||||
bool IndentBraces;
|
||||
/// If ``false``, empty function body can be put on a single line.
|
||||
|
|
|
@ -329,6 +329,11 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
|
|||
bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
const FormatToken &Current = *State.NextToken;
|
||||
const FormatToken &Previous = *Current.Previous;
|
||||
if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
|
||||
Current.is(TT_LambdaLBrace)) {
|
||||
auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
|
||||
return (LambdaBodyLength > getColumnLimit(State));
|
||||
}
|
||||
if (Current.MustBreakBefore || Current.is(TT_InlineASMColon))
|
||||
return true;
|
||||
if (State.Stack.back().BreakBeforeClosingBrace &&
|
||||
|
@ -1081,6 +1086,18 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
|
|||
return State.Stack.back().Indent;
|
||||
}
|
||||
|
||||
static bool hasNestedBlockInlined(const FormatToken *Previous,
|
||||
const FormatToken &Current,
|
||||
const FormatStyle &Style) {
|
||||
if (Previous->isNot(tok::l_paren))
|
||||
return true;
|
||||
if (Previous->ParameterCount > 1)
|
||||
return true;
|
||||
|
||||
// Also a nested block if contains a lambda inside function with 1 parameter
|
||||
return (Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLSquare));
|
||||
}
|
||||
|
||||
unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
|
||||
bool DryRun, bool Newline) {
|
||||
assert(State.Stack.size());
|
||||
|
@ -1183,8 +1200,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
|
|||
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) &&
|
||||
!Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
|
||||
State.Stack.back().NestedBlockInlined =
|
||||
!Newline &&
|
||||
(Previous->isNot(tok::l_paren) || Previous->ParameterCount > 1);
|
||||
!Newline && hasNestedBlockInlined(Previous, Current, Style);
|
||||
}
|
||||
|
||||
moveStatePastFakeLParens(State, Newline);
|
||||
|
@ -1421,7 +1437,21 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
|
|||
ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
|
||||
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
|
||||
State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
|
||||
State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1;
|
||||
State.Stack.back().HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
|
||||
|
||||
if (Style.BraceWrapping.BeforeLambdaBody &&
|
||||
Current.Next != nullptr && Current.Tok.is(tok::l_paren)) {
|
||||
// Search for any parameter that is a lambda
|
||||
FormatToken const *next = Current.Next;
|
||||
while (next != nullptr) {
|
||||
if (next->is(TT_LambdaLSquare)) {
|
||||
State.Stack.back().HasMultipleNestedBlocks = true;
|
||||
break;
|
||||
}
|
||||
next = next->Next;
|
||||
}
|
||||
}
|
||||
|
||||
State.Stack.back().IsInsideObjCArrayLiteral =
|
||||
Current.is(TT_ArrayInitializerLSquare) && Current.Previous &&
|
||||
Current.Previous->is(tok::at);
|
||||
|
|
|
@ -581,6 +581,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
|
|||
IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
|
||||
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
|
||||
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
|
||||
IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
|
||||
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
|
||||
IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
|
||||
IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
|
||||
|
@ -668,8 +669,8 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
|
|||
false, false, false,
|
||||
false, false, false,
|
||||
false, false, false,
|
||||
false, true, true,
|
||||
true};
|
||||
false, false, true,
|
||||
true, true};
|
||||
switch (Style.BreakBeforeBraces) {
|
||||
case FormatStyle::BS_Linux:
|
||||
Expanded.BraceWrapping.AfterClass = true;
|
||||
|
@ -717,14 +718,15 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
|
|||
Expanded.BraceWrapping.AfterExternBlock = true;
|
||||
Expanded.BraceWrapping.BeforeCatch = true;
|
||||
Expanded.BraceWrapping.BeforeElse = true;
|
||||
Expanded.BraceWrapping.BeforeLambdaBody = true;
|
||||
break;
|
||||
case FormatStyle::BS_GNU:
|
||||
Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always,
|
||||
true, true, true,
|
||||
true, true, true,
|
||||
true, true, true,
|
||||
true, true, true,
|
||||
true};
|
||||
Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always,
|
||||
true, true, true,
|
||||
true, true, true,
|
||||
true, true, true,
|
||||
false, true, true,
|
||||
true, true};
|
||||
break;
|
||||
case FormatStyle::BS_WebKit:
|
||||
Expanded.BraceWrapping.AfterFunction = true;
|
||||
|
@ -768,8 +770,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
|||
false, false, false,
|
||||
false, false, false,
|
||||
false, false, false,
|
||||
false, true, true,
|
||||
true};
|
||||
false, false, true,
|
||||
true, true};
|
||||
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
|
||||
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
|
||||
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
|
||||
|
|
|
@ -3122,6 +3122,56 @@ static bool isAllmanBrace(const FormatToken &Tok) {
|
|||
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);
|
||||
}
|
||||
|
||||
// Returns 'true' if 'Tok' is an function argument.
|
||||
static bool IsFunctionArgument(const FormatToken &Tok) {
|
||||
return Tok.MatchingParen && Tok.MatchingParen->Next &&
|
||||
Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren);
|
||||
}
|
||||
|
||||
static bool
|
||||
isItAnEmptyLambdaAllowed(const FormatToken &Tok,
|
||||
FormatStyle::ShortLambdaStyle ShortLambdaOption) {
|
||||
return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;
|
||||
}
|
||||
|
||||
static bool
|
||||
isItAInlineLambdaAllowed(const FormatToken &Tok,
|
||||
FormatStyle::ShortLambdaStyle ShortLambdaOption) {
|
||||
return (ShortLambdaOption == FormatStyle::SLS_Inline &&
|
||||
IsFunctionArgument(Tok)) ||
|
||||
(ShortLambdaOption == FormatStyle::SLS_All);
|
||||
}
|
||||
|
||||
static bool isOneChildWithoutMustBreakBefore(const FormatToken &Tok) {
|
||||
if (Tok.Children.size() != 1)
|
||||
return false;
|
||||
FormatToken *curElt = Tok.Children[0]->First;
|
||||
while (curElt) {
|
||||
if (curElt->MustBreakBefore)
|
||||
return false;
|
||||
curElt = curElt->Next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool
|
||||
isAllmanLambdaBrace(const FormatToken &Tok) {
|
||||
return (Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block &&
|
||||
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral));
|
||||
}
|
||||
|
||||
static bool
|
||||
isAllmanBraceIncludedBreakableLambda(const FormatToken &Tok,
|
||||
FormatStyle::ShortLambdaStyle ShortLambdaOption) {
|
||||
if (!isAllmanLambdaBrace(Tok))
|
||||
return false;
|
||||
|
||||
if (isItAnEmptyLambdaAllowed(Tok, ShortLambdaOption))
|
||||
return false;
|
||||
|
||||
return !isItAInlineLambdaAllowed(Tok, ShortLambdaOption) ||
|
||||
!isOneChildWithoutMustBreakBefore(Tok);
|
||||
}
|
||||
|
||||
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
||||
const FormatToken &Right) {
|
||||
const FormatToken &Left = *Right.Previous;
|
||||
|
@ -3257,6 +3307,14 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
|||
}
|
||||
if (Right.is(TT_InlineASMBrace))
|
||||
return Right.HasUnescapedNewline;
|
||||
|
||||
auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
|
||||
if (Style.BraceWrapping.BeforeLambdaBody &&
|
||||
(isAllmanBraceIncludedBreakableLambda(Left, ShortLambdaOption) ||
|
||||
isAllmanBraceIncludedBreakableLambda(Right, ShortLambdaOption))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isAllmanBrace(Left) || isAllmanBrace(Right))
|
||||
return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
|
||||
(Line.startsWith(tok::kw_typedef, tok::kw_enum) &&
|
||||
|
@ -3268,8 +3326,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
|||
return true;
|
||||
|
||||
if (Left.is(TT_LambdaLBrace)) {
|
||||
if (Left.MatchingParen && Left.MatchingParen->Next &&
|
||||
Left.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren) &&
|
||||
if (IsFunctionArgument(Left) &&
|
||||
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline)
|
||||
return false;
|
||||
|
||||
|
@ -3667,11 +3724,21 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
|||
if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||
|
||||
(Left.is(tok::r_square) && Right.is(TT_AttributeSquare)))
|
||||
return false;
|
||||
|
||||
auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
|
||||
if (Style.BraceWrapping.BeforeLambdaBody) {
|
||||
if (isAllmanLambdaBrace(Left))
|
||||
return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
|
||||
if (isAllmanLambdaBrace(Right))
|
||||
return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
|
||||
}
|
||||
|
||||
return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
|
||||
tok::kw_class, tok::kw_struct, tok::comment) ||
|
||||
Right.isMemberAccess() ||
|
||||
Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
|
||||
tok::colon, tok::l_square, tok::at) ||
|
||||
(Style.BraceWrapping.BeforeLambdaBody && Right.is(tok::l_brace)) ||
|
||||
(Left.is(tok::r_paren) &&
|
||||
Right.isOneOf(tok::identifier, tok::kw_const)) ||
|
||||
(Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
|
||||
|
|
|
@ -12673,6 +12673,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
|
|||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterExternBlock);
|
||||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
|
||||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
|
||||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeLambdaBody);
|
||||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
|
||||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);
|
||||
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord);
|
||||
|
@ -13962,6 +13963,245 @@ TEST_F(FormatTest, FormatsLambdas) {
|
|||
"function([]() { return b; }, a)", MergeInline);
|
||||
verifyFormat("function(a, []() { return b; })",
|
||||
"function(a, []() { return b; })", MergeInline);
|
||||
|
||||
// Check option "BraceWrapping.BeforeLambdaBody" and different state of
|
||||
// AllowShortLambdasOnASingleLine
|
||||
FormatStyle LLVMWithBeforeLambdaBody = getLLVMStyle();
|
||||
LLVMWithBeforeLambdaBody.BreakBeforeBraces = FormatStyle::BS_Custom;
|
||||
LLVMWithBeforeLambdaBody.BraceWrapping.BeforeLambdaBody = true;
|
||||
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
|
||||
FormatStyle::ShortLambdaStyle::SLS_None;
|
||||
verifyFormat("FctWithOneNestedLambdaInline_SLS_None(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return 17;\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneNestedLambdaEmpty_SLS_None(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("auto fct_SLS_None = []()\n"
|
||||
"{\n"
|
||||
" return 17;\n"
|
||||
"};",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_None(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return Call(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return 17;\n"
|
||||
" });\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("void Fct()\n"
|
||||
"{\n"
|
||||
" return {[]()\n"
|
||||
" {\n"
|
||||
" return 17;\n"
|
||||
" }};\n"
|
||||
"}",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
|
||||
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
|
||||
FormatStyle::ShortLambdaStyle::SLS_Empty;
|
||||
verifyFormat("FctWithOneNestedLambdaInline_SLS_Empty(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return 17;\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneNestedLambdaEmpty_SLS_Empty([]() {});",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneNestedLambdaEmptyInsideAVeryVeryVeryVeryVeryVeryVeryL"
|
||||
"ongFunctionName_SLS_Empty(\n"
|
||||
" []() {});",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithMultipleParams_SLS_Empty(A, B,\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return 17;\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("auto fct_SLS_Empty = []()\n"
|
||||
"{\n"
|
||||
" return 17;\n"
|
||||
"};",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_Empty(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return Call([]() {});\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_Empty(A,\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return Call([]() {});\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithLongLineInLambda_SLS_Empty(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
|
||||
" AndShouldNotBeConsiderAsInline,\n"
|
||||
" LambdaBodyMustBeBreak);\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
|
||||
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
|
||||
FormatStyle::ShortLambdaStyle::SLS_Inline;
|
||||
verifyFormat("FctWithOneNestedLambdaInline_SLS_Inline([]() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneNestedLambdaEmpty_SLS_Inline([]() {});",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("auto fct_SLS_Inline = []()\n"
|
||||
"{\n"
|
||||
" return 17;\n"
|
||||
"};",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_Inline([]() { return Call([]() { return "
|
||||
"17; }); });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithLongLineInLambda_SLS_Inline(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
|
||||
" AndShouldNotBeConsiderAsInline,\n"
|
||||
" LambdaBodyMustBeBreak);\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithMultipleParams_SLS_Inline("
|
||||
"VeryLongParameterThatShouldAskToBeOnMultiLine,\n"
|
||||
" []() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithMultipleParams_SLS_Inline(FirstParam, []() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
|
||||
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
|
||||
FormatStyle::ShortLambdaStyle::SLS_All;
|
||||
verifyFormat("FctWithOneNestedLambdaInline_SLS_All([]() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneNestedLambdaEmpty_SLS_All([]() {});",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("auto fct_SLS_All = []() { return 17; };",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneParam_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" // A cool function...\n"
|
||||
" return 43;\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithMultipleParams_SLS_All("
|
||||
"VeryLongParameterThatShouldAskToBeOnMultiLine,\n"
|
||||
" []() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithMultipleParams_SLS_All(A, []() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithMultipleParams_SLS_All(A, B, []() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithLongLineInLambda_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
|
||||
" AndShouldNotBeConsiderAsInline,\n"
|
||||
" LambdaBodyMustBeBreak);\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"auto fct_SLS_All = []()\n"
|
||||
"{\n"
|
||||
" return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
|
||||
" AndShouldNotBeConsiderAsInline,\n"
|
||||
" LambdaBodyMustBeBreak);\n"
|
||||
"};",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
LLVMWithBeforeLambdaBody.BinPackParameters = false;
|
||||
verifyFormat("FctAllOnSameLine_SLS_All([]() { return S; }, Fst, Second);",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithLongLineInLambda_SLS_All([]() { return SomeValueNotSoLong; },\n"
|
||||
" FirstParam,\n"
|
||||
" SecondParam,\n"
|
||||
" ThirdParam,\n"
|
||||
" FourthParam);",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithLongLineInLambda_SLS_All(\n"
|
||||
" []() { return "
|
||||
"SomeValueVeryVeryVeryVeryVeryVeryVeryVeryVeryLong; },\n"
|
||||
" FirstParam,\n"
|
||||
" SecondParam,\n"
|
||||
" ThirdParam,\n"
|
||||
" FourthParam);",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithLongLineInLambda_SLS_All(FirstParam,\n"
|
||||
" SecondParam,\n"
|
||||
" ThirdParam,\n"
|
||||
" FourthParam,\n"
|
||||
" []() { return SomeValueNotSoLong; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithLongLineInLambda_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return "
|
||||
"HereAVeryLongLineThatWillBeFormattedOnMultipleLineAndShouldNotB"
|
||||
"eConsiderAsInline;\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"FctWithLongLineInLambda_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return HereAVeryLongLine(ThatWillBeFormatted, OnMultipleLine,\n"
|
||||
" AndShouldNotBeConsiderAsInline,\n"
|
||||
" LambdaBodyMustBeBreak);\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithTwoParams_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" // A cool function...\n"
|
||||
" return 43;\n"
|
||||
" },\n"
|
||||
" 87);",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithTwoParams_SLS_All([]() { return 43; }, 87);",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("FctWithOneNestedLambdas_SLS_All([]() { return 17; });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat(
|
||||
"TwoNestedLambdas_SLS_All([]() { return Call([]() { return 17; }); });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_All([]() { return Call([]() { return 17; "
|
||||
"}); }, x);",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" // A cool function...\n"
|
||||
" return Call([]() { return 17; });\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
verifyFormat("TwoNestedLambdas_SLS_All(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" return Call(\n"
|
||||
" []()\n"
|
||||
" {\n"
|
||||
" // A cool function...\n"
|
||||
" return 17;\n"
|
||||
" });\n"
|
||||
" });",
|
||||
LLVMWithBeforeLambdaBody);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, EmptyLinesInLambdas) {
|
||||
|
|
Loading…
Reference in New Issue