clang-format: Enable formatting of nested blocks.
Among other things, this enables (better) formatting lambdas and
constructs like:
MACRO({
long_statement();
long_statement_2();
},
{
long_statement();
long_statement_2();
},
{ short_statement(); }, "");
This fixes llvm.org/PR15381.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190038 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 9891cb2..f9219cb 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -55,20 +55,20 @@
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
SourceManager &SourceMgr,
- const AnnotatedLine &Line,
- unsigned FirstIndent,
WhitespaceManager &Whitespaces,
encoding::Encoding Encoding,
bool BinPackInconclusiveFunctions)
- : Style(Style), SourceMgr(SourceMgr), Line(Line), FirstIndent(FirstIndent),
- Whitespaces(Whitespaces), Encoding(Encoding),
+ : Style(Style), SourceMgr(SourceMgr), Whitespaces(Whitespaces),
+ Encoding(Encoding),
BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {}
-LineState ContinuationIndenter::getInitialState() {
- // Initialize state dependent on indent.
+LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
+ const AnnotatedLine *Line) {
LineState State;
+ State.FirstIndent = FirstIndent;
State.Column = FirstIndent;
- State.NextToken = Line.First;
+ State.Line = Line;
+ State.NextToken = Line->First;
State.Stack.push_back(ParenState(FirstIndent, FirstIndent,
/*AvoidBinPacking=*/false,
/*NoLineBreak=*/false));
@@ -95,7 +95,7 @@
// The opening "{" of a braced list has to be on the same line as the first
// element if it is nested in another braced init list or function call.
if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&
- Previous.Previous &&
+ Previous.BlockKind == BK_BracedInit && Previous.Previous &&
Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
return false;
// This prevents breaks like:
@@ -183,8 +183,8 @@
return true;
if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
- Line.MightBeFunctionDecl && State.Stack.back().BreakBeforeParameter &&
- State.ParenLevel == 0)
+ State.Line->MightBeFunctionDecl &&
+ State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0)
return true;
if (startsSegmentOfBuilderTypeCall(Current) &&
(State.Stack.back().CallContinuation != 0 ||
@@ -234,10 +234,7 @@
Penalty += Style.PenaltyBreakFirstLessLess;
if (Current.is(tok::r_brace)) {
- if (Current.BlockKind == BK_BracedInit)
- State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
- else
- State.Column = FirstIndent;
+ State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
} else if (Current.is(tok::string_literal) &&
State.StartOfStringLiteral != 0) {
State.Column = State.StartOfStringLiteral;
@@ -261,7 +258,7 @@
Current.is(tok::kw_operator)) &&
State.ParenLevel == 0 &&
(!Style.IndentFunctionDeclarationAfterType ||
- Line.StartsDefinition))) {
+ State.Line->StartsDefinition))) {
State.Column = State.Stack.back().Indent;
} else if (Current.Type == TT_ObjCSelectorName) {
if (State.Stack.back().ColonPos > Current.CodePointCount) {
@@ -280,14 +277,15 @@
Previous.Type == TT_ObjCMethodExpr) {
State.Column = ContinuationIndent;
} else if (Current.Type == TT_CtorInitializerColon) {
- State.Column = FirstIndent + Style.ConstructorInitializerIndentWidth;
+ State.Column =
+ State.FirstIndent + Style.ConstructorInitializerIndentWidth;
} else if (Current.Type == TT_CtorInitializerComma) {
State.Column = State.Stack.back().Indent;
} else {
State.Column = State.Stack.back().Indent;
// Ensure that we fall back to indenting 4 spaces instead of just
// flushing continuations left.
- if (State.Column == FirstIndent)
+ if (State.Column == State.FirstIndent)
State.Column += 4;
}
@@ -306,7 +304,7 @@
NewLines = std::max(NewLines, std::min(Current.NewlinesBefore,
Style.MaxEmptyLinesToKeep + 1));
Whitespaces.replaceWhitespace(Current, NewLines, State.Column,
- State.Column, Line.InPPDirective);
+ State.Column, State.Line->InPPDirective);
}
if (!Current.isTrailingComment())
@@ -337,13 +335,13 @@
if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||
Previous.Type == TT_BinaryOperator) ||
(!Style.AllowAllParametersOfDeclarationOnNextLine &&
- Line.MustBeDeclaration))
+ State.Line->MustBeDeclaration))
State.Stack.back().BreakBeforeParameter = true;
}
} else {
if (Current.is(tok::equal) &&
- (Line.First->is(tok::kw_for) || State.ParenLevel == 0) &&
+ (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) &&
State.Stack.back().VariablePos == 0) {
State.Stack.back().VariablePos = State.Column;
// Move over * and & if they are bound to the variable name.
@@ -403,21 +401,18 @@
else if (Previous.Type == TT_InheritanceColon)
State.Stack.back().Indent = State.Column;
else if (Previous.opensScope()) {
- // If a function has multiple parameters (including a single parameter
- // that is a binary expression) or a trailing call, indent all
- // parameters from the opening parenthesis. This avoids confusing
- // indents like:
- // OuterFunction(InnerFunctionCall(
- // ParameterToInnerFunction),
- // SecondParameterToOuterFunction);
+ // If a function has a trailing call, indent all parameters from the
+ // opening parenthesis. This avoids confusing indents like:
+ // OuterFunction(InnerFunctionCall( // break
+ // ParameterToInnerFunction)) // break
+ // .SecondInnerFunctionCall();
bool HasTrailingCall = false;
if (Previous.MatchingParen) {
const FormatToken *Next = Previous.MatchingParen->getNextNonComment();
HasTrailingCall = Next && Next->isMemberAccess();
}
- if (startsBinaryExpression(Current) ||
- (HasTrailingCall &&
- State.Stack[State.Stack.size() - 2].CallContinuation == 0))
+ if (HasTrailingCall &&
+ State.Stack[State.Stack.size() - 2].CallContinuation == 0)
State.Stack.back().LastSpace = State.Column;
}
}
@@ -434,7 +429,7 @@
State.Stack.back().AvoidBinPacking = true;
if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0)
State.Stack.back().FirstLessLess = State.Column;
- if (Current.is(tok::l_square) &&
+ if (Current.is(tok::l_square) && Current.Type != TT_LambdaLSquare &&
State.Stack.back().StartOfArraySubscripts == 0)
State.Stack.back().StartOfArraySubscripts = State.Column;
if (Current.is(tok::question))
@@ -485,6 +480,14 @@
NewParenState.Indent =
std::max(std::max(State.Column, NewParenState.Indent),
State.Stack.back().LastSpace);
+ // Do not indent relative to the fake parentheses inserted for "." or "->".
+ // This is a special case to make the following to statements consistent:
+ // OuterFunction(InnerFunctionCall( // break
+ // ParameterToInnerFunction));
+ // OuterFunction(SomeObject.InnerFunctionCall( // break
+ // ParameterToInnerFunction));
+ if (*I > prec::Unknown)
+ NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
// Always indent conditional expressions. Never indent expression where
// the 'operator' is ',', ';' or an assignment (i.e. *I <=
@@ -504,17 +507,22 @@
// prepare for the following tokens.
if (Current.opensScope()) {
unsigned NewIndent;
- unsigned LastSpace = State.Stack.back().LastSpace;
bool AvoidBinPacking;
if (Current.is(tok::l_brace)) {
- NewIndent =
- LastSpace + (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);
+ if (Current.MatchingParen && Current.BlockKind == BK_Block) {
+ for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i)
+ State.Stack.pop_back();
+ NewIndent = State.Stack.back().LastSpace;
+ } else {
+ NewIndent = State.Stack.back().LastSpace +
+ (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);
+ }
const FormatToken *NextNoComment = Current.getNextNonComment();
AvoidBinPacking = NextNoComment &&
NextNoComment->Type == TT_DesignatedInitializerPeriod;
} else {
- NewIndent =
- 4 + std::max(LastSpace, State.Stack.back().StartOfFunctionCall);
+ NewIndent = 4 + std::max(State.Stack.back().LastSpace,
+ State.Stack.back().StartOfFunctionCall);
AvoidBinPacking = !Style.BinPackParameters ||
(Style.ExperimentalAutoDetectBinPacking &&
(Current.PackingKind == PPK_OnePerLine ||
@@ -522,7 +530,8 @@
Current.PackingKind == PPK_Inconclusive)));
}
- State.Stack.push_back(ParenState(NewIndent, LastSpace, AvoidBinPacking,
+ State.Stack.push_back(ParenState(NewIndent, State.Stack.back().LastSpace,
+ AvoidBinPacking,
State.Stack.back().NoLineBreak));
++State.ParenLevel;
}
@@ -531,7 +540,8 @@
// one line and put one per line if they don't.
if (Current.is(tok::l_square) && Current.Type == TT_ObjCMethodExpr &&
Current.MatchingParen != NULL) {
- if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit())
+ if (getLengthToMatchingParen(Current) + State.Column >
+ getColumnLimit(State))
State.Stack.back().BreakBeforeParameter = true;
}
@@ -539,7 +549,7 @@
// stacks.
if (State.Stack.size() > 1 &&
(Current.isOneOf(tok::r_paren, tok::r_square) ||
- (Current.is(tok::r_brace) && State.NextToken != Line.First) ||
+ (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
State.NextToken->Type == TT_TemplateCloser)) {
State.Stack.pop_back();
--State.ParenLevel;
@@ -552,10 +562,13 @@
}
// Remove scopes created by fake parenthesis.
- for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
- unsigned VariablePos = State.Stack.back().VariablePos;
- State.Stack.pop_back();
- State.Stack.back().VariablePos = VariablePos;
+ if (Current.isNot(tok::r_brace) ||
+ (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) {
+ for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
+ unsigned VariablePos = State.Stack.back().VariablePos;
+ State.Stack.pop_back();
+ State.Stack.back().VariablePos = VariablePos;
+ }
}
if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) {
@@ -568,6 +581,10 @@
State.Column += Current.CodePointCount;
State.NextToken = State.NextToken->Next;
unsigned Penalty = breakProtrudingToken(Current, State, DryRun);
+ if (State.Column > getColumnLimit(State)) {
+ unsigned ExcessCharacters = State.Column - getColumnLimit(State);
+ Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
+ }
// If the previous has a special role, let it consume tokens as appropriate.
// It is necessary to start at the previous token for the only implemented
@@ -593,8 +610,8 @@
// for all other lines is constant, and we ignore it.
State.Column = Current.CodePointsInLastLine;
- if (ColumnsUsed > getColumnLimit())
- return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());
+ if (ColumnsUsed > getColumnLimit(State))
+ return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit(State));
return 0;
}
@@ -623,15 +640,15 @@
if (Current.IsUnterminatedLiteral)
return 0;
- Token.reset(new BreakableStringLiteral(Current, StartColumn,
- Line.InPPDirective, Encoding));
+ Token.reset(new BreakableStringLiteral(
+ Current, StartColumn, State.Line->InPPDirective, Encoding));
} else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) {
unsigned OriginalStartColumn =
SourceMgr.getSpellingColumnNumber(Current.getStartOfNonWhitespace()) -
1;
Token.reset(new BreakableBlockComment(
Style, Current, StartColumn, OriginalStartColumn, !Current.Previous,
- Line.InPPDirective, Encoding));
+ State.Line->InPPDirective, Encoding));
} else if (Current.Type == TT_LineComment &&
(Current.Previous == NULL ||
Current.Previous->Type != TT_ImplicitStringLiteral)) {
@@ -648,14 +665,15 @@
}
Token.reset(new BreakableLineComment(Current, StartColumn,
- Line.InPPDirective, Encoding));
+ State.Line->InPPDirective, Encoding));
} else {
return 0;
}
- if (Current.UnbreakableTailLength >= getColumnLimit())
+ if (Current.UnbreakableTailLength >= getColumnLimit(State))
return 0;
- unsigned RemainingSpace = getColumnLimit() - Current.UnbreakableTailLength;
+ unsigned RemainingSpace =
+ getColumnLimit(State) - Current.UnbreakableTailLength;
bool BreakInserted = false;
unsigned Penalty = 0;
unsigned RemainingTokenColumns = 0;
@@ -668,7 +686,7 @@
Token->getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
while (RemainingTokenColumns > RemainingSpace) {
BreakableToken::Split Split =
- Token->getSplit(LineIndex, TailOffset, getColumnLimit());
+ Token->getSplit(LineIndex, TailOffset, getColumnLimit(State));
if (Split.first == StringRef::npos) {
// The last line's penalty is handled in addNextStateToQueue().
if (LineIndex < EndIndex - 1)
@@ -685,9 +703,9 @@
Penalty += Current.SplitPenalty;
unsigned ColumnsUsed =
Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first);
- if (ColumnsUsed > getColumnLimit()) {
- Penalty +=
- Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());
+ if (ColumnsUsed > getColumnLimit(State)) {
+ Penalty += Style.PenaltyExcessCharacter *
+ (ColumnsUsed - getColumnLimit(State));
}
TailOffset += Split.first + Split.second;
RemainingTokenColumns = NewRemainingTokenColumns;
@@ -714,9 +732,9 @@
return Penalty;
}
-unsigned ContinuationIndenter::getColumnLimit() const {
+unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {
// In preprocessor directives reserve two chars for trailing " \"
- return Style.ColumnLimit - (Line.InPPDirective ? 2 : 0);
+ return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
}
bool ContinuationIndenter::NextIsMultilineString(const LineState &State) {