clang-format: Improve line wrapping behavior in call sequences.

r256750 has been leading to an undesired behavior:

  aaaaaaaaaa
      .aaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);

This change increases penalty for wrapping before member accesses that aren't
calls. Thus, this is again formatted as (as it has been before r256750):

  aaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa(
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);

llvm-svn: 256830
This commit is contained in:
Daniel Jasper 2016-01-05 13:03:50 +00:00
parent 50d9c156dd
commit 00492f96bf
4 changed files with 29 additions and 14 deletions

View File

@ -378,7 +378,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
TT_CtorInitializerColon)) &&
((Previous.getPrecedence() != prec::Assignment &&
(Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 ||
!Previous.LastOperator)) ||
Previous.NextOperator)) ||
Current.StartsBinaryExpression)) {
// Always indent relative to the RHS of the expression unless this is a
// simple assignment without binary expression on the RHS. Also indent
@ -693,7 +693,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
std::min(State.LowestLevelOnLine, Current.NestingLevel);
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
Current.LastOperator ? 0 : State.Column;
!Current.NextOperator ? 0 : State.Column;
if (Current.is(TT_SelectorName)) {
State.Stack.back().ObjCSelectorNameFound = true;
if (Style.IndentWrappedFunctionNames) {

View File

@ -248,9 +248,9 @@ struct FormatToken {
/// with the same precedence, contains the 0-based operator index.
unsigned OperatorIndex = 0;
/// \brief Is this the last operator (or "."/"->") in a sequence of operators
/// with the same precedence?
bool LastOperator = false;
/// \brief If this is an operator (or "."/"->") in a sequence of operators
/// with the same precedence, points to the next operator.
FormatToken *NextOperator = nullptr;
/// \brief Is this token part of a \c DeclStmt defining multiple variables?
///

View File

@ -1330,6 +1330,8 @@ public:
} else {
// Operator found.
if (CurrentPrecedence == Precedence) {
if (LatestOperator)
LatestOperator->NextOperator = Current;
LatestOperator = Current;
Current->OperatorIndex = OperatorIndex;
++OperatorIndex;
@ -1339,7 +1341,7 @@ public:
}
if (LatestOperator && (Current || Precedence > 0)) {
LatestOperator->LastOperator = true;
// LatestOperator->LastOperator = true;
if (Precedence == PrecedenceArrowAndPeriod) {
// Call expressions don't have a binary operator precedence.
addFakeParenthesis(Start, prec::Unknown);
@ -1771,7 +1773,15 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
// which might otherwise be blown up onto many lines. Here, clang-format
// won't produce "hanging" indents anyway as there is no other trailing
// call.
return Right.LastOperator ? 150 : 35;
//
// Also apply higher penalty is not a call as that might lead to a wrapping
// like:
//
// aaaaaaa
// .aaaaaaaaa.bbbbbbbb(cccccccc);
return !Right.NextOperator || !Right.NextOperator->Previous->closesScope()
? 150
: 35;
}
if (Right.is(TT_TrailingAnnotation) &&
@ -1823,7 +1833,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(tok::lessless)) {
if (Left.is(tok::string_literal) &&
(!Right.LastOperator || Right.OperatorIndex != 1)) {
(Right.NextOperator || Right.OperatorIndex != 1)) {
StringRef Content = Left.TokenText;
if (Content.startswith("\""))
Content = Content.drop_front(1);

View File

@ -4164,10 +4164,6 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
"aaaaaaa->aaaaaaa\n"
" ->aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
" ->aaaaaaaa(aaaaaaaaaaaaaaa);");
verifyFormat(
"return aaaaaaaaaaaaaaaa\n"
" .aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa)\n"
" .aaaa(aaaaaaaaaaaaaa);");
verifyFormat(
"aaaaaaaaaaaaaaaaaaa()->aaaaaa(bbbbb)->aaaaaaaaaaaaaaaaaaa( // break\n"
" aaaaaaaaaaaaaa);");
@ -4238,6 +4234,15 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
"return !soooooooooooooome_map\n"
" .insert(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
" .second;");
verifyFormat(
"return aaaaaaaaaaaaaaaa\n"
" .aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa)\n"
" .aaaa(aaaaaaaaaaaaaa);");
// No hanging indent here.
verifyFormat("aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaa.aaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
verifyFormat("aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaa().aaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
}
TEST_F(FormatTest, BreaksAccordingToOperatorPrecedence) {
@ -7487,8 +7492,8 @@ TEST_F(FormatTest, FormatObjCMethodExpr) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa[aaaaaaaaaaaaaaaaaaaaa]\n"
" aaaaaaaaaaaaaaaaaaaaaa];");
verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n"
" .aaaaaaaa.aaaaaaaa];", // FIXME: Indentation seems off.
verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n"
" .aaaaaaaa];", // FIXME: Indentation seems off.
getLLVMStyleWithColumns(60));
verifyFormat(