Updated to Clang 3.5a.
Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 971acc2..5a3dee6 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -63,7 +63,8 @@
bool BinPackInconclusiveFunctions)
: Style(Style), SourceMgr(SourceMgr), Whitespaces(Whitespaces),
Encoding(Encoding),
- BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {}
+ BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
+ CommentPragmasRegex(Style.CommentPragmas) {}
LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
const AnnotatedLine *Line,
@@ -107,7 +108,8 @@
// SomeParameter, OtherParameter).DoSomething(
// ...
// As they hide "DoSomething" and are generally bad for readability.
- if (Previous.opensScope() && State.LowestLevelOnLine < State.StartOfLineLevel)
+ if (Previous.opensScope() && Previous.isNot(tok::l_brace) &&
+ State.LowestLevelOnLine < State.StartOfLineLevel)
return false;
if (Current.isMemberAccess() && State.Stack.back().ContainsUnwrappedBuilder)
return false;
@@ -136,13 +138,19 @@
if (Style.AlwaysBreakBeforeMultilineStrings &&
State.Column > State.Stack.back().Indent && // Breaking saves columns.
!Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
- Previous.Type != TT_InlineASMColon && NextIsMultilineString(State))
+ Previous.Type != TT_InlineASMColon && nextIsMultilineString(State))
return true;
if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) ||
Previous.Type == TT_ArrayInitializerLSquare) &&
getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State))
return true;
+ if (Current.Type == TT_CtorInitializerColon &&
+ (!Style.AllowShortFunctionsOnASingleLine ||
+ Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0))
+ return true;
+ if (State.Column < getNewLineColumn(State))
+ return false;
if (!Style.BreakBeforeBinaryOperators) {
// If we need to break somewhere inside the LHS of a binary expression, we
// should also break after the operator. Otherwise, the formatting would
@@ -173,19 +181,17 @@
}
// Same as above, but for the first "<<" operator.
- if (Current.is(tok::lessless) && State.Stack.back().BreakBeforeParameter &&
+ if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator &&
+ State.Stack.back().BreakBeforeParameter &&
State.Stack.back().FirstLessLess == 0)
return true;
- // FIXME: Comparing LongestObjCSelectorName to 0 is a hacky way of finding
- // out whether it is the first parameter. Clean this up.
if (Current.Type == TT_ObjCSelectorName &&
- Current.LongestObjCSelectorName == 0 &&
+ State.Stack.back().ObjCSelectorNameFound &&
State.Stack.back().BreakBeforeParameter)
return true;
- if ((Current.Type == TT_CtorInitializerColon ||
- (Previous.ClosesTemplateDeclaration && State.ParenLevel == 0 &&
- !Current.isTrailingComment())))
+ if (Previous.ClosesTemplateDeclaration && State.ParenLevel == 0 &&
+ !Current.isTrailingComment())
return true;
if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
@@ -197,6 +203,14 @@
(State.Stack.back().BreakBeforeParameter &&
State.Stack.back().ContainsUnwrappedBuilder)))
return true;
+
+ // The following could be precomputed as they do not depend on the state.
+ // However, as they should take effect only if the UnwrappedLine does not fit
+ // into the ColumnLimit, they are checked here in the ContinuationIndenter.
+ if (Previous.BlockKind == BK_Block && Previous.is(tok::l_brace) &&
+ !Current.isOneOf(tok::r_brace, tok::comment))
+ return true;
+
return false;
}
@@ -205,8 +219,8 @@
unsigned ExtraSpaces) {
const FormatToken &Current = *State.NextToken;
- if (State.Stack.size() == 0 ||
- (Current.Type == TT_ImplicitStringLiteral &&
+ assert(!State.Stack.empty());
+ if ((Current.Type == TT_ImplicitStringLiteral &&
(Current.Previous->Tok.getIdentifierInfo() == NULL ||
Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_not_keyword))) {
@@ -215,8 +229,8 @@
State.NextToken->WhitespaceRange.getEnd()) -
SourceMgr.getSpellingColumnNumber(
State.NextToken->WhitespaceRange.getBegin());
- State.Column += WhitespaceLength + State.NextToken->ColumnWidth;
- State.NextToken = State.NextToken->Next;
+ State.Column += WhitespaceLength;
+ moveStateToNextToken(State, DryRun, /*Newline=*/false);
return 0;
}
@@ -255,9 +269,12 @@
Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0,
Spaces, State.Column + Spaces);
- if (Current.Type == TT_ObjCSelectorName && State.Stack.back().ColonPos == 0) {
- if (State.Stack.back().Indent + Current.LongestObjCSelectorName >
- State.Column + Spaces + Current.ColumnWidth)
+ if (Current.Type == TT_ObjCSelectorName &&
+ !State.Stack.back().ObjCSelectorNameFound) {
+ if (Current.LongestObjCSelectorName == 0)
+ State.Stack.back().AlignColons = false;
+ else if (State.Stack.back().Indent + Current.LongestObjCSelectorName >
+ State.Column + Spaces + Current.ColumnWidth)
State.Stack.back().ColonPos =
State.Stack.back().Indent + Current.LongestObjCSelectorName;
else
@@ -265,7 +282,7 @@
}
if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr &&
- Current.Type != TT_LineComment)
+ (Current.Type != TT_LineComment || Previous.BlockKind == BK_BracedInit))
State.Stack.back().Indent = State.Column + Spaces;
if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style))
State.Stack.back().NoLineBreak = true;
@@ -277,11 +294,12 @@
// Treat the condition inside an if as if it was a second function
// parameter, i.e. let nested calls have a continuation indent.
State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(".
- else if (Previous.is(tok::comma) || Previous.Type == TT_ObjCMethodExpr)
+ else if (Current.isNot(tok::comment) &&
+ (Previous.is(tok::comma) ||
+ (Previous.is(tok::colon) && Previous.Type == TT_ObjCMethodExpr)))
State.Stack.back().LastSpace = State.Column;
else if ((Previous.Type == TT_BinaryOperator ||
Previous.Type == TT_ConditionalExpr ||
- Previous.Type == TT_UnaryOperator ||
Previous.Type == TT_CtorInitializerColon) &&
(Previous.getPrecedence() != prec::Assignment ||
Current.StartsBinaryExpression))
@@ -313,16 +331,15 @@
bool DryRun) {
FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *State.NextToken->Previous;
- // If we are continuing an expression, we want to use the continuation indent.
- unsigned ContinuationIndent =
- std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) +
- Style.ContinuationIndentWidth;
+
// Extra penalty that needs to be added because of the way certain line
// breaks are chosen.
unsigned Penalty = 0;
- const FormatToken *PreviousNonComment =
- State.NextToken->getPreviousNonComment();
+ const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
+ const FormatToken *NextNonComment = Previous.getNextNonComment();
+ if (!NextNonComment)
+ NextNonComment = &Current;
// The first line break on any ParenLevel causes an extra penalty in order
// prefer similar line breaks.
if (!State.Stack.back().ContainsLineBreak)
@@ -332,79 +349,46 @@
Penalty += State.NextToken->SplitPenalty;
// Breaking before the first "<<" is generally not desirable if the LHS is
- // short.
- if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0 &&
- State.Column <= Style.ColumnLimit / 2)
+ // short. Also always add the penalty if the LHS is split over mutliple lines
+ // to avoid unnecessary line breaks that just work around this penalty.
+ if (NextNonComment->is(tok::lessless) &&
+ State.Stack.back().FirstLessLess == 0 &&
+ (State.Column <= Style.ColumnLimit / 3 ||
+ State.Stack.back().BreakBeforeParameter))
Penalty += Style.PenaltyBreakFirstLessLess;
- if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) {
- State.Column = State.FirstIndent;
- } else if (Current.isOneOf(tok::r_brace, tok::r_square)) {
- if (Current.closesBlockTypeList(Style) ||
- (Current.MatchingParen &&
- Current.MatchingParen->BlockKind == BK_BracedInit))
- State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
- else
- State.Column = State.FirstIndent;
- } else if (Current.is(tok::string_literal) &&
- State.StartOfStringLiteral != 0) {
- State.Column = State.StartOfStringLiteral;
- State.Stack.back().BreakBeforeParameter = true;
- } else if (Current.is(tok::lessless) &&
- State.Stack.back().FirstLessLess != 0) {
- State.Column = State.Stack.back().FirstLessLess;
- } else if (Current.isMemberAccess()) {
- if (State.Stack.back().CallContinuation == 0) {
- State.Column = ContinuationIndent;
+ State.Column = getNewLineColumn(State);
+ if (NextNonComment->isMemberAccess()) {
+ if (State.Stack.back().CallContinuation == 0)
State.Stack.back().CallContinuation = State.Column;
- } else {
- State.Column = State.Stack.back().CallContinuation;
+ } else if (NextNonComment->Type == TT_ObjCSelectorName) {
+ if (!State.Stack.back().ObjCSelectorNameFound) {
+ if (NextNonComment->LongestObjCSelectorName == 0) {
+ State.Stack.back().AlignColons = false;
+ } else {
+ State.Stack.back().ColonPos =
+ State.Stack.back().Indent + NextNonComment->LongestObjCSelectorName;
+ }
+ } else if (State.Stack.back().AlignColons &&
+ State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) {
+ State.Stack.back().ColonPos = State.Column + NextNonComment->ColumnWidth;
}
- } else if (State.Stack.back().QuestionColumn != 0 &&
- (Current.Type == TT_ConditionalExpr ||
- Previous.Type == TT_ConditionalExpr)) {
- State.Column = State.Stack.back().QuestionColumn;
- } else if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) {
- State.Column = State.Stack.back().VariablePos;
- } else if ((PreviousNonComment &&
- PreviousNonComment->ClosesTemplateDeclaration) ||
- ((Current.Type == TT_StartOfName ||
- Current.is(tok::kw_operator)) &&
- State.ParenLevel == 0 &&
- (!Style.IndentFunctionDeclarationAfterType ||
- State.Line->StartsDefinition))) {
- State.Column = State.Stack.back().Indent;
- } else if (Current.Type == TT_ObjCSelectorName) {
- if (State.Stack.back().ColonPos == 0) {
- State.Stack.back().ColonPos =
- State.Stack.back().Indent + Current.LongestObjCSelectorName;
- State.Column = State.Stack.back().ColonPos - Current.ColumnWidth;
- } else if (State.Stack.back().ColonPos > Current.ColumnWidth) {
- State.Column = State.Stack.back().ColonPos - Current.ColumnWidth;
- } else {
- State.Column = State.Stack.back().Indent;
- State.Stack.back().ColonPos = State.Column + Current.ColumnWidth;
- }
- } else if (Current.Type == TT_ArraySubscriptLSquare) {
- if (State.Stack.back().StartOfArraySubscripts != 0)
- State.Column = State.Stack.back().StartOfArraySubscripts;
- else
- State.Column = ContinuationIndent;
- } else if (Current.Type == TT_StartOfName ||
- Previous.isOneOf(tok::coloncolon, tok::equal) ||
- Previous.Type == TT_ObjCMethodExpr) {
- State.Column = ContinuationIndent;
- } else if (Current.Type == TT_CtorInitializerColon) {
- 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 the continuation indent width instead of just
- // flushing continuations left.
- if (State.Column == State.FirstIndent &&
- PreviousNonComment->isNot(tok::r_brace))
- State.Column += Style.ContinuationIndentWidth;
+ } else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
+ (PreviousNonComment->Type == TT_ObjCMethodExpr ||
+ PreviousNonComment->Type == TT_DictLiteral)) {
+ // FIXME: This is hacky, find a better way. The problem is that in an ObjC
+ // method expression, the block should be aligned to the line starting it,
+ // e.g.:
+ // [aaaaaaaaaaaaaaa aaaaaaaaa: \\ break for some reason
+ // ^(int *i) {
+ // // ...
+ // }];
+ // Thus, we set LastSpace of the next higher ParenLevel, to which we move
+ // when we consume all of the "}"'s FakeRParens at the "{".
+ if (State.Stack.size() > 1)
+ State.Stack[State.Stack.size() - 2].LastSpace =
+ std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) +
+ Style.ContinuationIndentWidth;
}
if ((Previous.isOneOf(tok::comma, tok::semi) &&
@@ -413,7 +397,7 @@
State.Stack.back().BreakBeforeParameter = false;
if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0)
State.Stack.back().BreakBeforeParameter = false;
- if (Current.is(tok::question) ||
+ if (NextNonComment->is(tok::question) ||
(PreviousNonComment && PreviousNonComment->is(tok::question)))
State.Stack.back().BreakBeforeParameter = true;
@@ -429,8 +413,6 @@
if (!Current.isTrailingComment())
State.Stack.back().LastSpace = State.Column;
- if (Current.isMemberAccess())
- State.Stack.back().LastSpace += Current.ColumnWidth;
State.StartOfLineLevel = State.ParenLevel;
State.LowestLevelOnLine = State.ParenLevel;
@@ -443,7 +425,7 @@
!PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
PreviousNonComment->Type != TT_TemplateCloser &&
PreviousNonComment->Type != TT_BinaryOperator &&
- Current.Type != TT_BinaryOperator &&
+ Current.Type != TT_BinaryOperator &&
!PreviousNonComment->opensScope())
State.Stack.back().BreakBeforeParameter = true;
@@ -465,6 +447,99 @@
return Penalty;
}
+unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
+ if (!State.NextToken || !State.NextToken->Previous)
+ return 0;
+ FormatToken &Current = *State.NextToken;
+ const FormatToken &Previous = *State.NextToken->Previous;
+ // If we are continuing an expression, we want to use the continuation indent.
+ unsigned ContinuationIndent =
+ std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) +
+ Style.ContinuationIndentWidth;
+ const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
+ const FormatToken *NextNonComment = Previous.getNextNonComment();
+ if (!NextNonComment)
+ NextNonComment = &Current;
+ if (NextNonComment->is(tok::l_brace) &&
+ NextNonComment->BlockKind == BK_Block)
+ return State.ParenLevel == 0 ? State.FirstIndent
+ : State.Stack.back().Indent;
+ if (Current.isOneOf(tok::r_brace, tok::r_square)) {
+ if (Current.closesBlockTypeList(Style) ||
+ (Current.MatchingParen &&
+ Current.MatchingParen->BlockKind == BK_BracedInit))
+ return State.Stack[State.Stack.size() - 2].LastSpace;
+ else
+ return State.FirstIndent;
+ }
+ if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
+ return State.StartOfStringLiteral;
+ if (NextNonComment->is(tok::lessless) &&
+ State.Stack.back().FirstLessLess != 0)
+ return State.Stack.back().FirstLessLess;
+ if (NextNonComment->isMemberAccess()) {
+ if (State.Stack.back().CallContinuation == 0) {
+ return ContinuationIndent;
+ } else {
+ return State.Stack.back().CallContinuation;
+ }
+ }
+ if (State.Stack.back().QuestionColumn != 0 &&
+ (NextNonComment->Type == TT_ConditionalExpr ||
+ Previous.Type == TT_ConditionalExpr))
+ return State.Stack.back().QuestionColumn;
+ if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0)
+ return State.Stack.back().VariablePos;
+ if ((PreviousNonComment && (PreviousNonComment->ClosesTemplateDeclaration ||
+ PreviousNonComment->Type == TT_AttributeParen)) ||
+ ((NextNonComment->Type == TT_StartOfName ||
+ NextNonComment->is(tok::kw_operator)) &&
+ State.ParenLevel == 0 && (!Style.IndentFunctionDeclarationAfterType ||
+ State.Line->StartsDefinition)))
+ return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
+ if (NextNonComment->Type == TT_ObjCSelectorName) {
+ if (!State.Stack.back().ObjCSelectorNameFound) {
+ if (NextNonComment->LongestObjCSelectorName == 0) {
+ return State.Stack.back().Indent;
+ } else {
+ return State.Stack.back().Indent +
+ NextNonComment->LongestObjCSelectorName -
+ NextNonComment->ColumnWidth;
+ }
+ } else if (!State.Stack.back().AlignColons) {
+ return State.Stack.back().Indent;
+ } else if (State.Stack.back().ColonPos > NextNonComment->ColumnWidth) {
+ return State.Stack.back().ColonPos - NextNonComment->ColumnWidth;
+ } else {
+ return State.Stack.back().Indent;
+ }
+ }
+ if (NextNonComment->Type == TT_ArraySubscriptLSquare) {
+ if (State.Stack.back().StartOfArraySubscripts != 0)
+ return State.Stack.back().StartOfArraySubscripts;
+ else
+ return ContinuationIndent;
+ }
+ if (NextNonComment->Type == TT_StartOfName ||
+ Previous.isOneOf(tok::coloncolon, tok::equal)) {
+ return ContinuationIndent;
+ }
+ if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
+ (PreviousNonComment->Type == TT_ObjCMethodExpr ||
+ PreviousNonComment->Type == TT_DictLiteral))
+ return ContinuationIndent;
+ if (NextNonComment->Type == TT_CtorInitializerColon)
+ return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
+ if (NextNonComment->Type == TT_CtorInitializerComma)
+ return State.Stack.back().Indent;
+ if (State.Stack.back().Indent == State.FirstIndent && PreviousNonComment &&
+ PreviousNonComment->isNot(tok::r_brace))
+ // Ensure that we fall back to the continuation indent width instead of
+ // just flushing continuations left.
+ return State.Stack.back().Indent + Style.ContinuationIndentWidth;
+ return State.Stack.back().Indent;
+}
+
unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
bool DryRun, bool Newline) {
const FormatToken &Current = *State.NextToken;
@@ -472,7 +547,8 @@
if (Current.Type == TT_InheritanceColon)
State.Stack.back().AvoidBinPacking = true;
- if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0)
+ if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator &&
+ State.Stack.back().FirstLessLess == 0)
State.Stack.back().FirstLessLess = State.Column;
if (Current.Type == TT_ArraySubscriptLSquare &&
State.Stack.back().StartOfArraySubscripts == 0)
@@ -488,6 +564,8 @@
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
Current.LastInChainOfCalls ? 0 : State.Column + Current.ColumnWidth;
+ if (Current.Type == TT_ObjCSelectorName)
+ State.Stack.back().ObjCSelectorNameFound = true;
if (Current.Type == TT_CtorInitializerColon) {
// Indent 2 from the column, so:
// SomeClass::SomeClass()
@@ -531,6 +609,18 @@
std::max(std::max(State.Column, NewParenState.Indent),
State.Stack.back().LastSpace);
+ // Don't allow the RHS of an operator to be split over multiple lines unless
+ // there is a line-break right after the operator.
+ // Exclude relational operators, as there, it is always more desirable to
+ // have the LHS 'left' of the RHS.
+ // FIXME: Implement this for '<<' and BreakBeforeBinaryOperators.
+ if (!Newline && Previous && Previous->Type == TT_BinaryOperator &&
+ !Previous->isOneOf(tok::lessless, tok::question, tok::colon) &&
+ Previous->getPrecedence() > prec::Assignment &&
+ Previous->getPrecedence() != prec::Relational &&
+ !Style.BreakBeforeBinaryOperators)
+ NewParenState.NoLineBreak = true;
+
// 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
@@ -539,6 +629,7 @@
// ParameterToInnerFunction));
if (*I > prec::Unknown)
NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
+ NewParenState.StartOfFunctionCall = State.Column;
// Always indent conditional expressions. Never indent expression where
// the 'operator' is ',', ';' or an assignment (i.e. *I <=
@@ -566,7 +657,7 @@
if (Current.MatchingParen && Current.BlockKind == BK_Block) {
// If this is an l_brace starting a nested block, we pretend (wrt. to
// indentation) that we already consumed the corresponding r_brace.
- // Thus, we remove all ParenStates caused bake fake parentheses that end
+ // Thus, we remove all ParenStates caused by fake parentheses that end
// at the r_brace. The net effect of this is that we don't indent
// relative to the l_brace, if the nested block is the last parameter of
// a function. For example, this formats:
@@ -577,20 +668,32 @@
//
// instead of:
// SomeFunction(a, [] {
- // f(); // break
- // });
- for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i)
+ // f(); // break
+ // });
+ for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) {
+ assert(State.Stack.size() > 1);
+ if (State.Stack.size() == 1) {
+ // Do not pop the last element.
+ break;
+ }
State.Stack.pop_back();
- NewIndent = State.Stack.back().LastSpace + Style.IndentWidth;
+ }
+ // For some reason, ObjC blocks are indented like continuations.
+ NewIndent =
+ State.Stack.back().LastSpace + (Current.Type == TT_ObjCBlockLBrace
+ ? Style.ContinuationIndentWidth
+ : Style.IndentWidth);
++NewIndentLevel;
BreakBeforeParameter = true;
} else {
NewIndent = State.Stack.back().LastSpace;
if (Current.opensBlockTypeList(Style)) {
NewIndent += Style.IndentWidth;
+ NewIndent = std::min(State.Column + 2, NewIndent);
++NewIndentLevel;
} else {
NewIndent += Style.ContinuationIndentWidth;
+ NewIndent = std::min(State.Column + 1, NewIndent);
}
}
const FormatToken *NextNoComment = Current.getNextNonComment();
@@ -649,15 +752,20 @@
// as they will have been removed early (see above).
for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
unsigned VariablePos = State.Stack.back().VariablePos;
+ assert(State.Stack.size() > 1);
+ if (State.Stack.size() == 1) {
+ // Do not pop the last element.
+ break;
+ }
State.Stack.pop_back();
State.Stack.back().VariablePos = VariablePos;
}
}
- if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) {
+ if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
State.StartOfStringLiteral = State.Column;
- } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash,
- tok::string_literal)) {
+ } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
+ !Current.isStringLiteral()) {
State.StartOfStringLiteral = 0;
}
@@ -669,13 +777,15 @@
Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
}
+ if (Current.Role)
+ Current.Role->formatFromToken(State, this, DryRun);
// 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
// role (comma separated list). That way, the decision whether or not to break
// after the "{" is already done and both options are tried and evaluated.
// FIXME: This is ugly, find a better way.
if (Previous && Previous->Role)
- Penalty += Previous->Role->format(State, this, DryRun);
+ Penalty += Previous->Role->formatAfterToken(State, this, DryRun);
return Penalty;
}
@@ -727,19 +837,14 @@
if (Current.Type == TT_ImplicitStringLiteral)
return 0;
- if (!Current.isOneOf(tok::string_literal, tok::wide_string_literal,
- tok::utf8_string_literal, tok::utf16_string_literal,
- tok::utf32_string_literal, tok::comment))
+ if (!Current.isStringLiteral() && !Current.is(tok::comment))
return 0;
- llvm::OwningPtr<BreakableToken> Token;
+ std::unique_ptr<BreakableToken> Token;
unsigned StartColumn = State.Column - Current.ColumnWidth;
unsigned ColumnLimit = getColumnLimit(State);
- if (Current.isOneOf(tok::string_literal, tok::wide_string_literal,
- tok::utf8_string_literal, tok::utf16_string_literal,
- tok::utf32_string_literal) &&
- Current.Type != TT_ImplicitStringLiteral) {
+ if (Current.isStringLiteral()) {
// Don't break string literals inside preprocessor directives (except for
// #define directives, as their contents are stored in separate lines and
// are not affected by this check).
@@ -755,13 +860,20 @@
StringRef Text = Current.TokenText;
StringRef Prefix;
StringRef Postfix;
+ bool IsNSStringLiteral = false;
// FIXME: Handle whitespace between '_T', '(', '"..."', and ')'.
// FIXME: Store Prefix and Suffix (or PrefixLength and SuffixLength to
// reduce the overhead) for each FormatToken, which is a string, so that we
// don't run multiple checks here on the hot path.
+ if (Text.startswith("\"") && Current.Previous &&
+ Current.Previous->is(tok::at)) {
+ IsNSStringLiteral = true;
+ Prefix = "@\"";
+ }
if ((Text.endswith(Postfix = "\"") &&
- (Text.startswith(Prefix = "\"") || Text.startswith(Prefix = "u\"") ||
- Text.startswith(Prefix = "U\"") || Text.startswith(Prefix = "u8\"") ||
+ (IsNSStringLiteral || Text.startswith(Prefix = "\"") ||
+ Text.startswith(Prefix = "u\"") || Text.startswith(Prefix = "U\"") ||
+ Text.startswith(Prefix = "u8\"") ||
Text.startswith(Prefix = "L\""))) ||
(Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")")) ||
getRawStringLiteralPrefixPostfix(Text, Prefix, Postfix)) {
@@ -772,12 +884,16 @@
return 0;
}
} else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) {
+ if (CommentPragmasRegex.match(Current.TokenText.substr(2)))
+ return 0;
Token.reset(new BreakableBlockComment(
Current, State.Line->Level, StartColumn, Current.OriginalColumn,
!Current.Previous, State.Line->InPPDirective, Encoding, Style));
} else if (Current.Type == TT_LineComment &&
(Current.Previous == NULL ||
Current.Previous->Type != TT_ImplicitStringLiteral)) {
+ if (CommentPragmasRegex.match(Current.TokenText.substr(2)))
+ return 0;
Token.reset(new BreakableLineComment(Current, State.Line->Level,
StartColumn, /*InPPDirective=*/false,
Encoding, Style));
@@ -848,8 +964,8 @@
State.Stack[i].BreakBeforeParameter = true;
}
- Penalty += Current.is(tok::string_literal) ? Style.PenaltyBreakString
- : Style.PenaltyBreakComment;
+ Penalty += Current.isStringLiteral() ? Style.PenaltyBreakString
+ : Style.PenaltyBreakComment;
State.Stack.back().LastSpace = StartColumn;
}
@@ -861,18 +977,19 @@
return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
}
-bool ContinuationIndenter::NextIsMultilineString(const LineState &State) {
+bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {
const FormatToken &Current = *State.NextToken;
- if (!Current.is(tok::string_literal))
+ if (!Current.isStringLiteral())
return false;
// We never consider raw string literals "multiline" for the purpose of
- // AlwaysBreakBeforeMultilineStrings implementation.
+ // AlwaysBreakBeforeMultilineStrings implementation as they are special-cased
+ // (see TokenAnnotator::mustBreakBefore().
if (Current.TokenText.startswith("R\""))
return false;
if (Current.IsMultiline)
return true;
if (Current.getNextNonComment() &&
- Current.getNextNonComment()->is(tok::string_literal))
+ Current.getNextNonComment()->isStringLiteral())
return true; // Implicit concatenation.
if (State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
Style.ColumnLimit)