<div dir="ltr">Addressed in r190042.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Sep 5, 2013 at 12:33 PM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div class="h5">On Thu, Sep 5, 2013 at 11:29 AM, Daniel Jasper <span dir="ltr"><<a href="mailto:djasper@google.com" target="_blank">djasper@google.com</a>></span> wrote:<br>
</div></div><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: djasper<br>
Date: Thu Sep 5 04:29:45 2013<br>
New Revision: 190038<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=190038&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=190038&view=rev</a><br>
Log:<br>
clang-format: Enable formatting of nested blocks.<br>
<br>
Among other things, this enables (better) formatting lambdas and<br>
constructs like:<br>
MACRO({<br>
long_statement();<br>
long_statement_2();<br>
},<br>
{<br>
long_statement();<br>
long_statement_2();<br>
},<br>
{ short_statement(); }, "");<br>
<br>
This fixes <a href="http://llvm.org/PR15381" target="_blank">llvm.org/PR15381</a>.<br>
<br>
Modified:<br>
cfe/trunk/lib/Format/ContinuationIndenter.cpp<br>
cfe/trunk/lib/Format/ContinuationIndenter.h<br>
cfe/trunk/lib/Format/Format.cpp<br>
cfe/trunk/lib/Format/FormatToken.h<br>
cfe/trunk/lib/Format/TokenAnnotator.cpp<br>
cfe/trunk/lib/Format/TokenAnnotator.h<br>
cfe/trunk/lib/Format/UnwrappedLineParser.cpp<br>
cfe/trunk/lib/Format/UnwrappedLineParser.h<br>
cfe/trunk/unittests/Format/FormatTest.cpp<br>
<br>
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)<br>
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Thu Sep 5 04:29:45 2013<br>
@@ -55,20 +55,20 @@ static bool startsSegmentOfBuilderTypeCa<br>
<br>
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,<br>
SourceManager &SourceMgr,<br>
- const AnnotatedLine &Line,<br>
- unsigned FirstIndent,<br>
WhitespaceManager &Whitespaces,<br>
encoding::Encoding Encoding,<br>
bool BinPackInconclusiveFunctions)<br>
- : Style(Style), SourceMgr(SourceMgr), Line(Line), FirstIndent(FirstIndent),<br>
- Whitespaces(Whitespaces), Encoding(Encoding),<br>
+ : Style(Style), SourceMgr(SourceMgr), Whitespaces(Whitespaces),<br>
+ Encoding(Encoding),<br>
BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {}<br>
<br>
-LineState ContinuationIndenter::getInitialState() {<br>
- // Initialize state dependent on indent.<br>
+LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,<br>
+ const AnnotatedLine *Line) {<br>
LineState State;<br>
+ State.FirstIndent = FirstIndent;<br>
State.Column = FirstIndent;<br>
- State.NextToken = Line.First;<br>
+ State.Line = Line;<br>
+ State.NextToken = Line->First;<br>
State.Stack.push_back(ParenState(FirstIndent, FirstIndent,<br>
/*AvoidBinPacking=*/false,<br>
/*NoLineBreak=*/false));<br>
@@ -95,7 +95,7 @@ bool ContinuationIndenter::canBreak(cons<br>
// The opening "{" of a braced list has to be on the same line as the first<br>
// element if it is nested in another braced init list or function call.<br>
if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&<br>
- Previous.Previous &&<br>
+ Previous.BlockKind == BK_BracedInit && Previous.Previous &&<br>
Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))<br>
return false;<br>
// This prevents breaks like:<br>
@@ -183,8 +183,8 @@ bool ContinuationIndenter::mustBreak(con<br>
return true;<br>
<br>
if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&<br>
- Line.MightBeFunctionDecl && State.Stack.back().BreakBeforeParameter &&<br>
- State.ParenLevel == 0)<br>
+ State.Line->MightBeFunctionDecl &&<br>
+ State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0)<br>
return true;<br>
if (startsSegmentOfBuilderTypeCall(Current) &&<br>
(State.Stack.back().CallContinuation != 0 ||<br>
@@ -234,10 +234,7 @@ unsigned ContinuationIndenter::addTokenT<br>
Penalty += Style.PenaltyBreakFirstLessLess;<br>
<br>
if (Current.is(tok::r_brace)) {<br>
- if (Current.BlockKind == BK_BracedInit)<br>
- State.Column = State.Stack[State.Stack.size() - 2].LastSpace;<br>
- else<br>
- State.Column = FirstIndent;<br>
+ State.Column = State.Stack[State.Stack.size() - 2].LastSpace;<br>
} else if (Current.is(tok::string_literal) &&<br>
State.StartOfStringLiteral != 0) {<br>
State.Column = State.StartOfStringLiteral;<br>
@@ -261,7 +258,7 @@ unsigned ContinuationIndenter::addTokenT<br>
Current.is(tok::kw_operator)) &&<br>
State.ParenLevel == 0 &&<br>
(!Style.IndentFunctionDeclarationAfterType ||<br>
- Line.StartsDefinition))) {<br>
+ State.Line->StartsDefinition))) {<br>
State.Column = State.Stack.back().Indent;<br>
} else if (Current.Type == TT_ObjCSelectorName) {<br>
if (State.Stack.back().ColonPos > Current.CodePointCount) {<br>
@@ -280,14 +277,15 @@ unsigned ContinuationIndenter::addTokenT<br>
Previous.Type == TT_ObjCMethodExpr) {<br>
State.Column = ContinuationIndent;<br>
} else if (Current.Type == TT_CtorInitializerColon) {<br>
- State.Column = FirstIndent + Style.ConstructorInitializerIndentWidth;<br>
+ State.Column =<br>
+ State.FirstIndent + Style.ConstructorInitializerIndentWidth;<br>
} else if (Current.Type == TT_CtorInitializerComma) {<br>
State.Column = State.Stack.back().Indent;<br>
} else {<br>
State.Column = State.Stack.back().Indent;<br>
// Ensure that we fall back to indenting 4 spaces instead of just<br>
// flushing continuations left.<br>
- if (State.Column == FirstIndent)<br>
+ if (State.Column == State.FirstIndent)<br>
State.Column += 4;<br>
}<br>
<br>
@@ -306,7 +304,7 @@ unsigned ContinuationIndenter::addTokenT<br>
NewLines = std::max(NewLines, std::min(Current.NewlinesBefore,<br>
Style.MaxEmptyLinesToKeep + 1));<br>
Whitespaces.replaceWhitespace(Current, NewLines, State.Column,<br>
- State.Column, Line.InPPDirective);<br>
+ State.Column, State.Line->InPPDirective);<br>
}<br>
<br>
if (!Current.isTrailingComment())<br>
@@ -337,13 +335,13 @@ unsigned ContinuationIndenter::addTokenT<br>
if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||<br>
Previous.Type == TT_BinaryOperator) ||<br>
(!Style.AllowAllParametersOfDeclarationOnNextLine &&<br>
- Line.MustBeDeclaration))<br>
+ State.Line->MustBeDeclaration))<br>
State.Stack.back().BreakBeforeParameter = true;<br>
}<br>
<br>
} else {<br>
if (Current.is(tok::equal) &&<br>
- (Line.First->is(tok::kw_for) || State.ParenLevel == 0) &&<br>
+ (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) &&<br>
State.Stack.back().VariablePos == 0) {<br>
State.Stack.back().VariablePos = State.Column;<br>
// Move over * and & if they are bound to the variable name.<br>
@@ -403,21 +401,18 @@ unsigned ContinuationIndenter::addTokenT<br>
else if (Previous.Type == TT_InheritanceColon)<br>
State.Stack.back().Indent = State.Column;<br>
else if (Previous.opensScope()) {<br>
- // If a function has multiple parameters (including a single parameter<br>
- // that is a binary expression) or a trailing call, indent all<br>
- // parameters from the opening parenthesis. This avoids confusing<br>
- // indents like:<br>
- // OuterFunction(InnerFunctionCall(<br>
- // ParameterToInnerFunction),<br>
- // SecondParameterToOuterFunction);<br>
+ // If a function has a trailing call, indent all parameters from the<br>
+ // opening parenthesis. This avoids confusing indents like:<br>
+ // OuterFunction(InnerFunctionCall( // break<br>
+ // ParameterToInnerFunction)) // break<br>
+ // .SecondInnerFunctionCall();<br>
bool HasTrailingCall = false;<br>
if (Previous.MatchingParen) {<br>
const FormatToken *Next = Previous.MatchingParen->getNextNonComment();<br>
HasTrailingCall = Next && Next->isMemberAccess();<br>
}<br>
- if (startsBinaryExpression(Current) ||<br>
- (HasTrailingCall &&<br>
- State.Stack[State.Stack.size() - 2].CallContinuation == 0))<br>
+ if (HasTrailingCall &&<br>
+ State.Stack[State.Stack.size() - 2].CallContinuation == 0)<br>
State.Stack.back().LastSpace = State.Column;<br>
}<br>
}<br>
@@ -434,7 +429,7 @@ unsigned ContinuationIndenter::moveState<br>
State.Stack.back().AvoidBinPacking = true;<br>
if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0)<br>
State.Stack.back().FirstLessLess = State.Column;<br>
- if (Current.is(tok::l_square) &&<br>
+ if (Current.is(tok::l_square) && Current.Type != TT_LambdaLSquare &&<br>
State.Stack.back().StartOfArraySubscripts == 0)<br>
State.Stack.back().StartOfArraySubscripts = State.Column;<br>
if (Current.is(tok::question))<br>
@@ -485,6 +480,14 @@ unsigned ContinuationIndenter::moveState<br>
NewParenState.Indent =<br>
std::max(std::max(State.Column, NewParenState.Indent),<br>
State.Stack.back().LastSpace);<br>
+ // Do not indent relative to the fake parentheses inserted for "." or "->".<br>
+ // This is a special case to make the following to statements consistent:<br>
+ // OuterFunction(InnerFunctionCall( // break<br>
+ // ParameterToInnerFunction));<br>
+ // OuterFunction(SomeObject.InnerFunctionCall( // break<br>
+ // ParameterToInnerFunction));<br>
+ if (*I > prec::Unknown)<br>
+ NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);<br>
<br>
// Always indent conditional expressions. Never indent expression where<br>
// the 'operator' is ',', ';' or an assignment (i.e. *I <=<br>
@@ -504,17 +507,22 @@ unsigned ContinuationIndenter::moveState<br>
// prepare for the following tokens.<br>
if (Current.opensScope()) {<br>
unsigned NewIndent;<br>
- unsigned LastSpace = State.Stack.back().LastSpace;<br>
bool AvoidBinPacking;<br>
if (Current.is(tok::l_brace)) {<br>
- NewIndent =<br>
- LastSpace + (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);<br>
+ if (Current.MatchingParen && Current.BlockKind == BK_Block) {<br>
+ for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i)<br>
+ State.Stack.pop_back();<br></blockquote><div><br></div></div></div><div>Can you please add a comment why this is ok / necessary here :)</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ NewIndent = State.Stack.back().LastSpace;<br>
+ } else {<br>
+ NewIndent = State.Stack.back().LastSpace +<br>
+ (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);<br>
+ }<br>
const FormatToken *NextNoComment = Current.getNextNonComment();<br>
AvoidBinPacking = NextNoComment &&<br>
NextNoComment->Type == TT_DesignatedInitializerPeriod;<br>
} else {<br>
- NewIndent =<br>
- 4 + std::max(LastSpace, State.Stack.back().StartOfFunctionCall);<br>
+ NewIndent = 4 + std::max(State.Stack.back().LastSpace,<br>
+ State.Stack.back().StartOfFunctionCall);<br>
AvoidBinPacking = !Style.BinPackParameters ||<br>
(Style.ExperimentalAutoDetectBinPacking &&<br>
(Current.PackingKind == PPK_OnePerLine ||<br>
@@ -522,7 +530,8 @@ unsigned ContinuationIndenter::moveState<br>
Current.PackingKind == PPK_Inconclusive)));<br>
}<br>
<br>
- State.Stack.push_back(ParenState(NewIndent, LastSpace, AvoidBinPacking,<br>
+ State.Stack.push_back(ParenState(NewIndent, State.Stack.back().LastSpace,<br>
+ AvoidBinPacking,<br>
State.Stack.back().NoLineBreak));<br>
++State.ParenLevel;<br>
}<br>
@@ -531,7 +540,8 @@ unsigned ContinuationIndenter::moveState<br>
// one line and put one per line if they don't.<br>
if (Current.is(tok::l_square) && Current.Type == TT_ObjCMethodExpr &&<br>
Current.MatchingParen != NULL) {<br>
- if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit())<br>
+ if (getLengthToMatchingParen(Current) + State.Column ><br>
+ getColumnLimit(State))<br>
State.Stack.back().BreakBeforeParameter = true;<br>
}<br>
<br>
@@ -539,7 +549,7 @@ unsigned ContinuationIndenter::moveState<br>
// stacks.<br>
if (State.Stack.size() > 1 &&<br>
(Current.isOneOf(tok::r_paren, tok::r_square) ||<br>
- (Current.is(tok::r_brace) && State.NextToken != Line.First) ||<br>
+ (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||<br>
State.NextToken->Type == TT_TemplateCloser)) {<br>
State.Stack.pop_back();<br>
--State.ParenLevel;<br>
@@ -552,10 +562,13 @@ unsigned ContinuationIndenter::moveState<br>
}<br>
<br>
// Remove scopes created by fake parenthesis.<br>
- for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {<br>
- unsigned VariablePos = State.Stack.back().VariablePos;<br>
- State.Stack.pop_back();<br>
- State.Stack.back().VariablePos = VariablePos;<br>
+ if (Current.isNot(tok::r_brace) ||<br>
+ (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) {<br>
+ for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {<br>
+ unsigned VariablePos = State.Stack.back().VariablePos;<br>
+ State.Stack.pop_back();<br>
+ State.Stack.back().VariablePos = VariablePos;<br>
+ }<br>
}<br>
<br>
if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) {<br>
@@ -568,6 +581,10 @@ unsigned ContinuationIndenter::moveState<br>
State.Column += Current.CodePointCount;<br>
State.NextToken = State.NextToken->Next;<br>
unsigned Penalty = breakProtrudingToken(Current, State, DryRun);<br>
+ if (State.Column > getColumnLimit(State)) {<br>
+ unsigned ExcessCharacters = State.Column - getColumnLimit(State);<br>
+ Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;<br>
+ }<br>
<br>
// If the previous has a special role, let it consume tokens as appropriate.<br>
// It is necessary to start at the previous token for the only implemented<br>
@@ -593,8 +610,8 @@ ContinuationIndenter::addMultilineString<br>
// for all other lines is constant, and we ignore it.<br>
State.Column = Current.CodePointsInLastLine;<br>
<br>
- if (ColumnsUsed > getColumnLimit())<br>
- return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());<br>
+ if (ColumnsUsed > getColumnLimit(State))<br>
+ return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit(State));<br>
return 0;<br>
}<br>
<br>
@@ -623,15 +640,15 @@ unsigned ContinuationIndenter::breakProt<br>
if (Current.IsUnterminatedLiteral)<br>
return 0;<br>
<br>
- Token.reset(new BreakableStringLiteral(Current, StartColumn,<br>
- Line.InPPDirective, Encoding));<br>
+ Token.reset(new BreakableStringLiteral(<br>
+ Current, StartColumn, State.Line->InPPDirective, Encoding));<br>
} else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) {<br>
unsigned OriginalStartColumn =<br>
SourceMgr.getSpellingColumnNumber(Current.getStartOfNonWhitespace()) -<br>
1;<br>
Token.reset(new BreakableBlockComment(<br>
Style, Current, StartColumn, OriginalStartColumn, !Current.Previous,<br>
- Line.InPPDirective, Encoding));<br>
+ State.Line->InPPDirective, Encoding));<br>
} else if (Current.Type == TT_LineComment &&<br>
(Current.Previous == NULL ||<br>
Current.Previous->Type != TT_ImplicitStringLiteral)) {<br>
@@ -648,14 +665,15 @@ unsigned ContinuationIndenter::breakProt<br>
}<br>
<br>
Token.reset(new BreakableLineComment(Current, StartColumn,<br>
- Line.InPPDirective, Encoding));<br>
+ State.Line->InPPDirective, Encoding));<br>
} else {<br>
return 0;<br>
}<br>
- if (Current.UnbreakableTailLength >= getColumnLimit())<br>
+ if (Current.UnbreakableTailLength >= getColumnLimit(State))<br>
return 0;<br>
<br>
- unsigned RemainingSpace = getColumnLimit() - Current.UnbreakableTailLength;<br>
+ unsigned RemainingSpace =<br>
+ getColumnLimit(State) - Current.UnbreakableTailLength;<br>
bool BreakInserted = false;<br>
unsigned Penalty = 0;<br>
unsigned RemainingTokenColumns = 0;<br>
@@ -668,7 +686,7 @@ unsigned ContinuationIndenter::breakProt<br>
Token->getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);<br>
while (RemainingTokenColumns > RemainingSpace) {<br>
BreakableToken::Split Split =<br>
- Token->getSplit(LineIndex, TailOffset, getColumnLimit());<br>
+ Token->getSplit(LineIndex, TailOffset, getColumnLimit(State));<br>
if (Split.first == StringRef::npos) {<br>
// The last line's penalty is handled in addNextStateToQueue().<br>
if (LineIndex < EndIndex - 1)<br>
@@ -685,9 +703,9 @@ unsigned ContinuationIndenter::breakProt<br>
Penalty += Current.SplitPenalty;<br>
unsigned ColumnsUsed =<br>
Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first);<br>
- if (ColumnsUsed > getColumnLimit()) {<br>
- Penalty +=<br>
- Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());<br>
+ if (ColumnsUsed > getColumnLimit(State)) {<br>
+ Penalty += Style.PenaltyExcessCharacter *<br>
+ (ColumnsUsed - getColumnLimit(State));<br>
}<br>
TailOffset += Split.first + Split.second;<br>
RemainingTokenColumns = NewRemainingTokenColumns;<br>
@@ -714,9 +732,9 @@ unsigned ContinuationIndenter::breakProt<br>
return Penalty;<br>
}<br>
<br>
-unsigned ContinuationIndenter::getColumnLimit() const {<br>
+unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {<br>
// In preprocessor directives reserve two chars for trailing " \"<br>
- return Style.ColumnLimit - (Line.InPPDirective ? 2 : 0);<br>
+ return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);<br>
}<br>
<br>
bool ContinuationIndenter::NextIsMultilineString(const LineState &State) {<br>
<br>
Modified: cfe/trunk/lib/Format/ContinuationIndenter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/ContinuationIndenter.h (original)<br>
+++ cfe/trunk/lib/Format/ContinuationIndenter.h Thu Sep 5 04:29:45 2013<br>
@@ -35,14 +35,13 @@ public:<br>
/// \brief Constructs a \c ContinuationIndenter to format \p Line starting in<br>
/// column \p FirstIndent.<br>
ContinuationIndenter(const FormatStyle &Style, SourceManager &SourceMgr,<br>
- const AnnotatedLine &Line, unsigned FirstIndent,<br>
WhitespaceManager &Whitespaces,<br>
encoding::Encoding Encoding,<br>
bool BinPackInconclusiveFunctions);<br>
<br>
- /// \brief Get the initial state, i.e. the state after placing the line's<br>
- /// first token.<br>
- LineState getInitialState();<br>
+ /// \brief Get the initial state, i.e. the state after placing \p Line's<br>
+ /// first token at \p FirstIndent.<br>
+ LineState getInitialState(unsigned FirstIndent, const AnnotatedLine *Line);<br>
<br>
// FIXME: canBreak and mustBreak aren't strictly indentation-related. Find a<br>
// better home.<br>
@@ -65,7 +64,7 @@ public:<br>
<br>
/// \brief Get the column limit for this line. This is the style's column<br>
/// limit, potentially reduced for preprocessor definitions.<br>
- unsigned getColumnLimit() const;<br>
+ unsigned getColumnLimit(const LineState &State) const;<br>
<br>
private:<br>
/// \brief Mark the next token as consumed in \p State and modify its stacks<br>
@@ -101,8 +100,6 @@ private:<br>
<br>
FormatStyle Style;<br>
SourceManager &SourceMgr;<br>
- const AnnotatedLine &Line;<br>
- const unsigned FirstIndent;<br>
WhitespaceManager &Whitespaces;<br>
encoding::Encoding Encoding;<br>
bool BinPackInconclusiveFunctions;<br>
@@ -271,6 +268,14 @@ struct LineState {<br>
/// FIXME: Come up with a better algorithm instead.<br>
bool IgnoreStackForComparison;<br>
<br>
+ /// \brief The indent of the first token.<br>
+ unsigned FirstIndent;<br>
+<br>
+ /// \brief The line that is being formatted.<br>
+ ///<br>
+ /// Does not need to be considered for memoization because it doesn't change.<br>
+ const AnnotatedLine *Line;<br>
+<br>
/// \brief Comparison operator to be able to used \c LineState in \c map.<br>
bool operator<(const LineState &Other) const {<br>
if (NextToken != Other.NextToken)<br>
<br>
Modified: cfe/trunk/lib/Format/Format.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/Format.cpp (original)<br>
+++ cfe/trunk/lib/Format/Format.cpp Thu Sep 5 04:29:45 2013<br>
@@ -324,8 +324,8 @@ public:<br>
<br>
/// \brief Formats the line starting at \p State, simply keeping all of the<br>
/// input's line breaking decisions.<br>
- void format() {<br>
- LineState State = Indenter->getInitialState();<br>
+ void format(unsigned FirstIndent, const AnnotatedLine *Line) {<br>
+ LineState State = Indenter->getInitialState(FirstIndent, Line);<br>
while (State.NextToken != NULL) {<br>
bool Newline =<br>
Indenter->mustBreak(State) ||<br>
@@ -341,12 +341,16 @@ private:<br>
class UnwrappedLineFormatter {<br>
public:<br>
UnwrappedLineFormatter(ContinuationIndenter *Indenter,<br>
+ WhitespaceManager *Whitespaces,<br>
const FormatStyle &Style, const AnnotatedLine &Line)<br>
- : Indenter(Indenter), Style(Style), Line(Line), Count(0) {}<br>
+ : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), Line(Line),<br>
+ Count(0) {}<br>
<br>
- /// \brief Formats an \c UnwrappedLine.<br>
- void format() {<br>
- LineState State = Indenter->getInitialState();<br>
+ /// \brief Formats an \c UnwrappedLine and returns the penalty.<br>
+ ///<br>
+ /// If \p DryRun is \c false, directly applies the changes.<br>
+ unsigned format(unsigned FirstIndent, bool DryRun = false) {<br>
+ LineState State = Indenter->getInitialState(FirstIndent, &Line);<br>
<br>
// If the ObjC method declaration does not fit on a line, we should format<br>
// it with one arg per line.<br>
@@ -354,7 +358,7 @@ public:<br>
State.Stack.back().BreakBeforeParameter = true;<br>
<br>
// Find best solution in solution space.<br>
- analyzeSolutionSpace(State);<br>
+ return analyzeSolutionSpace(State, DryRun);<br>
}<br>
<br>
private:<br>
@@ -388,8 +392,10 @@ private:<br>
/// This implements a variant of Dijkstra's algorithm on the graph that spans<br>
/// the solution space (\c LineStates are the nodes). The algorithm tries to<br>
/// find the shortest path (the one with lowest penalty) from \p InitialState<br>
- /// to a state where all tokens are placed.<br>
- void analyzeSolutionSpace(LineState &InitialState) {<br>
+ /// to a state where all tokens are placed. Returns the penalty.<br>
+ ///<br>
+ /// If \p DryRun is \c false, directly applies the changes.<br>
+ unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false) {<br>
std::set<LineState> Seen;<br>
<br>
// Insert start element into queue.<br>
@@ -398,9 +404,11 @@ private:<br>
Queue.push(QueueItem(OrderedPenalty(0, Count), Node));<br>
++Count;<br>
<br>
+ unsigned Penalty = 0;<br>
+<br>
// While not empty, take first element and follow edges.<br>
while (!Queue.empty()) {<br>
- unsigned Penalty = Queue.top().first.first;<br>
+ Penalty = Queue.top().first.first;<br>
StateNode *Node = Queue.top().second;<br>
if (Node->State.NextToken == NULL) {<br>
DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");<br>
@@ -424,12 +432,16 @@ private:<br>
if (Queue.empty())<br>
// We were unable to find a solution, do nothing.<br>
// FIXME: Add diagnostic?<br>
- return;<br>
+ return 0;<br>
<br>
// Reconstruct the solution.<br>
- reconstructPath(InitialState, Queue.top().second);<br>
+ if (!DryRun)<br>
+ reconstructPath(InitialState, Queue.top().second);<br>
+<br>
DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");<br>
DEBUG(llvm::dbgs() << "---\n");<br>
+<br>
+ return Penalty;<br>
}<br>
<br>
void reconstructPath(LineState &State, StateNode *Current) {<br>
@@ -441,8 +453,10 @@ private:<br>
}<br>
for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();<br>
I != E; ++I) {<br>
- unsigned Penalty = Indenter->addTokenToState(State, (*I)->NewLine, false);<br>
- (void)Penalty;<br>
+ unsigned Penalty = 0;<br>
+ formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);<br>
+ Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);<br>
+<br>
DEBUG({<br>
if ((*I)->NewLine) {<br>
llvm::dbgs() << "Penalty for placing "<br>
@@ -466,18 +480,80 @@ private:<br>
<br>
StateNode *Node = new (Allocator.Allocate())<br>
StateNode(PreviousNode->State, NewLine, PreviousNode);<br>
+ if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))<br>
+ return;<br>
+<br>
Penalty += Indenter->addTokenToState(Node->State, NewLine, true);<br>
- if (Node->State.Column > Indenter->getColumnLimit()) {<br>
- unsigned ExcessCharacters =<br>
- Node->State.Column - Indenter->getColumnLimit();<br>
- Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;<br>
- }<br>
<br>
Queue.push(QueueItem(OrderedPenalty(Penalty, Count), Node));<br>
++Count;<br>
}<br>
<br>
+ /// \brief Format all children of \p Tok assuming the parent is indented to<br>
+ /// \p ParentIndent.<br></blockquote><div><br></div></div></div><div>ParentIndent is not a parameter...</div><div class="im"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ ///<br>
+ /// Returns \c true if all children could be placed successfully and adapts<br>
+ /// \p Penalty as well as \p State. If \p DryRun is false, also directly<br>
+ /// creates changes using \c Whitespaces.<br>
+ ///<br>
+ /// The crucial idea here is that children always get formatted upon<br>
+ /// encountering the closing brace right after the nested block. Now, if we<br>
+ /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is<br>
+ /// \c false), the entire block has to be kept on the same line (which is only<br>
+ /// possible if it fits on the line, only contains a single statement, etc.<br>
+ ///<br>
+ /// If \p NewLine is true, we format the nested block on separate lines, i.e.<br>
+ /// break after the "{", format all lines with correct indentation and the put<br>
+ /// the closing "}" on yet another new line.<br>
+ ///<br>
+ /// This enables us to keep the simple structure of the<br>
+ /// \c UnwrappedLineFormatter, where we only have two options for each token:<br>
+ /// break or don't break.<br>
+ bool formatChildren(LineState &State, bool NewLine, bool DryRun,<br>
+ unsigned &Penalty) {<br>
+ const FormatToken &LBrace = *State.NextToken->Previous;<br>
+ if (LBrace.isNot(tok::l_brace) || LBrace.BlockKind != BK_Block ||<br>
+ LBrace.Children.size() == 0)<br>
+ return true; // The previous token does not open a block. Nothing to do.<br></blockquote><div><br></div></div><div>Why's that not an assert?</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+ if (NewLine) {<br>
+ unsigned ParentIndent = State.Stack.back().Indent;<br>
+ for (SmallVector<AnnotatedLine *, 1>::const_iterator<br>
+ I = LBrace.Children.begin(),<br>
+ E = LBrace.Children.end();<br>
+ I != E; ++I) {<br>
+ unsigned Indent =<br>
+ ParentIndent + ((*I)->Level - Line.Level) * Style.IndentWidth;<br>
+ if (!DryRun)<br>
+ Whitespaces->replaceWhitespace(<br>
+ *(*I)->First, /*Newlines=*/1, /*Spaces=*/Indent,<br>
+ /*StartOfTokenColumn=*/Indent, Line.InPPDirective);<br>
+ UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style, **I);<br>
+ Penalty += Formatter.format(Indent, DryRun);<br>
+ }<br>
+ return true;<br>
+ }<br>
+<br>
+ if (LBrace.Children.size() > 1)<br>
+ return false; // Cannot merge multiple statements into a single line.<br>
+<br>
+ // We can't put the closing "}" on a line with a trailing comment.<br>
+ if (LBrace.Children[0]->Last->isTrailingComment())<br>
+ return false;<br>
+<br>
+ if (!DryRun) {<br>
+ Whitespaces->replaceWhitespace(*LBrace.Children[0]->First,<br>
+ /*Newlines=*/0, /*Spaces=*/1,<br>
+ /*StartOfTokenColumn=*/State.Column,<br>
+ State.Line->InPPDirective);<br>
+ }<br>
+<br>
+ State.Column += 1 + LBrace.Children[0]->Last->TotalLength;<br>
+ return true;<br>
+ }<br>
+<br>
ContinuationIndenter *Indenter;<br>
+ WhitespaceManager *Whitespaces;<br>
FormatStyle Style;<br>
const AnnotatedLine &Line;<br>
<br>
@@ -654,7 +730,12 @@ public:<br>
<< "\n");<br>
}<br>
<br>
- virtual ~Formatter() {}<br>
+ virtual ~Formatter() {<br>
+ for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>
+ delete AnnotatedLines[i];<br>
+ }<br>
+ AnnotatedLines.clear();<br></blockquote><div><br></div></div></div><div>I would not do the clear(), as the object is not reachable afterwards...</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ }<br>
<br>
tooling::Replacements format() {<br>
FormatTokenLexer Tokens(Lex, SourceMgr, Style, Encoding);<br>
@@ -663,23 +744,23 @@ public:<br>
bool StructuralError = Parser.parse();<br>
TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));<br>
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>
- Annotator.annotate(AnnotatedLines[i]);<br>
+ Annotator.annotate(*AnnotatedLines[i]);<br>
}<br>
deriveLocalStyle();<br>
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>
- Annotator.calculateFormattingInformation(AnnotatedLines[i]);<br>
+ Annotator.calculateFormattingInformation(*AnnotatedLines[i]);<br>
}<br>
<br>
// Adapt level to the next line if this is a comment.<br>
// FIXME: Can/should this be done in the UnwrappedLineParser?<br>
const AnnotatedLine *NextNonCommentLine = NULL;<br>
for (unsigned i = AnnotatedLines.size() - 1; i > 0; --i) {<br>
- if (NextNonCommentLine && AnnotatedLines[i].First->is(tok::comment) &&<br>
- !AnnotatedLines[i].First->Next)<br>
- AnnotatedLines[i].Level = NextNonCommentLine->Level;<br>
+ if (NextNonCommentLine && AnnotatedLines[i]->First->is(tok::comment) &&<br>
+ !AnnotatedLines[i]->First->Next)<br>
+ AnnotatedLines[i]->Level = NextNonCommentLine->Level;<br>
else<br>
- NextNonCommentLine = AnnotatedLines[i].First->isNot(tok::r_brace)<br>
- ? &AnnotatedLines[i]<br>
+ NextNonCommentLine = AnnotatedLines[i]->First->isNot(tok::r_brace)<br>
+ ? AnnotatedLines[i]<br>
: NULL;<br>
}<br>
<br>
@@ -687,10 +768,10 @@ public:<br>
bool PreviousLineWasTouched = false;<br>
const FormatToken *PreviousLineLastToken = 0;<br>
bool FormatPPDirective = false;<br>
- for (std::vector<AnnotatedLine>::iterator I = AnnotatedLines.begin(),<br>
- E = AnnotatedLines.end();<br>
+ for (std::vector<AnnotatedLine *>::iterator I = AnnotatedLines.begin(),<br>
+ E = AnnotatedLines.end();<br>
I != E; ++I) {<br>
- const AnnotatedLine &TheLine = *I;<br>
+ const AnnotatedLine &TheLine = **I;<br>
const FormatToken *FirstTok = TheLine.First;<br>
int Offset = getIndentOffset(*TheLine.First);<br>
<br>
@@ -729,26 +810,27 @@ public:<br>
} else {<br>
Indent = LevelIndent = FirstTok->OriginalColumn;<br>
}<br>
- ContinuationIndenter Indenter(Style, SourceMgr, TheLine, Indent,<br>
- Whitespaces, Encoding,<br>
+ ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,<br>
BinPackInconclusiveFunctions);<br>
<br>
// If everything fits on a single line, just put it there.<br>
unsigned ColumnLimit = Style.ColumnLimit;<br>
- if ((I + 1) != E && (I + 1)->InPPDirective &&<br>
- !(I + 1)->First->HasUnescapedNewline)<br>
- ColumnLimit = Indenter.getColumnLimit();<br>
+ AnnotatedLine *NextLine = *(I + 1);<br>
+ if ((I + 1) != E && NextLine->InPPDirective &&<br>
+ !NextLine->First->HasUnescapedNewline)<br>
+ ColumnLimit = getColumnLimit(TheLine.InPPDirective);<br>
<br>
- if (I->Last->TotalLength + Indent <= ColumnLimit) {<br>
- LineState State = Indenter.getInitialState();<br>
+ if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {<br>
+ LineState State = Indenter.getInitialState(Indent, &TheLine);<br>
while (State.NextToken != NULL)<br>
Indenter.addTokenToState(State, false, false);<br>
} else if (Style.ColumnLimit == 0) {<br>
NoColumnLimitFormatter Formatter(&Indenter);<br>
- Formatter.format();<br>
+ Formatter.format(Indent, &TheLine);<br>
} else {<br>
- UnwrappedLineFormatter Formatter(&Indenter, Style, TheLine);<br>
- Formatter.format();<br>
+ UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style,<br>
+ TheLine);<br>
+ Formatter.format(Indent);<br>
}<br>
<br>
IndentForLevel[TheLine.Level] = LevelIndent;<br>
@@ -783,7 +865,7 @@ public:<br>
// last token.<br>
PreviousLineWasTouched = false;<br>
}<br>
- PreviousLineLastToken = I->Last;<br>
+ PreviousLineLastToken = TheLine.Last;<br>
}<br>
return Whitespaces.generateReplacements();<br>
}<br>
@@ -796,9 +878,9 @@ private:<br>
bool HasBinPackedFunction = false;<br>
bool HasOnePerLineFunction = false;<br>
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>
- if (!AnnotatedLines[i].First->Next)<br>
+ if (!AnnotatedLines[i]->First->Next)<br>
continue;<br>
- FormatToken *Tok = AnnotatedLines[i].First->Next;<br>
+ FormatToken *Tok = AnnotatedLines[i]->First->Next;<br>
while (Tok->Next) {<br>
if (Tok->Type == TT_PointerOrReference) {<br>
bool SpacesBefore =<br>
@@ -866,10 +948,11 @@ private:<br>
/// This will change \c Line and \c AnnotatedLine to contain the merged line,<br>
/// if possible; note that \c I will be incremented when lines are merged.<br>
void tryFitMultipleLinesInOne(unsigned Indent,<br>
- std::vector<AnnotatedLine>::iterator &I,<br>
- std::vector<AnnotatedLine>::iterator E) {<br>
+ std::vector<AnnotatedLine *>::iterator &I,<br>
+ std::vector<AnnotatedLine *>::iterator E) {<br>
// We can never merge stuff if there are trailing line comments.<br>
- if (I->Last->Type == TT_LineComment)<br>
+ AnnotatedLine *TheLine = *I;<br>
+ if (TheLine->Last->Type == TT_LineComment)<br>
return;<br>
<br>
if (Indent > Style.ColumnLimit)<br>
@@ -878,70 +961,72 @@ private:<br>
unsigned Limit = Style.ColumnLimit - Indent;<br>
// If we already exceed the column limit, we set 'Limit' to 0. The different<br>
// tryMerge..() functions can then decide whether to still do merging.<br>
- Limit = I->Last->TotalLength > Limit ? 0 : Limit - I->Last->TotalLength;<br>
+ Limit = TheLine->Last->TotalLength > Limit<br>
+ ? 0<br>
+ : Limit - TheLine->Last->TotalLength;<br>
<br>
- if (I + 1 == E || (I + 1)->Type == LT_Invalid)<br>
+ if (I + 1 == E || (*(I + 1))->Type == LT_Invalid)<br>
return;<br>
<br>
- if (I->Last->is(tok::l_brace)) {<br>
+ if (TheLine->Last->is(tok::l_brace)) {<br>
tryMergeSimpleBlock(I, E, Limit);<br>
} else if (Style.AllowShortIfStatementsOnASingleLine &&<br>
- I->First->is(tok::kw_if)) {<br>
+ TheLine->First->is(tok::kw_if)) {<br>
tryMergeSimpleControlStatement(I, E, Limit);<br>
} else if (Style.AllowShortLoopsOnASingleLine &&<br>
- I->First->isOneOf(tok::kw_for, tok::kw_while)) {<br>
+ TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {<br>
tryMergeSimpleControlStatement(I, E, Limit);<br>
- } else if (I->InPPDirective &&<br>
- (I->First->HasUnescapedNewline || I->First->IsFirst)) {<br>
+ } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||<br>
+ TheLine->First->IsFirst)) {<br>
tryMergeSimplePPDirective(I, E, Limit);<br>
}<br>
}<br>
<br>
- void tryMergeSimplePPDirective(std::vector<AnnotatedLine>::iterator &I,<br>
- std::vector<AnnotatedLine>::iterator E,<br>
+ void tryMergeSimplePPDirective(std::vector<AnnotatedLine *>::iterator &I,<br>
+ std::vector<AnnotatedLine *>::iterator E,<br>
unsigned Limit) {<br>
if (Limit == 0)<br>
return;<br>
- AnnotatedLine &Line = *I;<br>
- if (!(I + 1)->InPPDirective || (I + 1)->First->HasUnescapedNewline)<br>
+ AnnotatedLine &Line = **I;<br>
+ if (!(*(I + 1))->InPPDirective || (*(I + 1))->First->HasUnescapedNewline)<br>
return;<br>
- if (I + 2 != E && (I + 2)->InPPDirective &&<br>
- !(I + 2)->First->HasUnescapedNewline)<br>
+ if (I + 2 != E && (*(I + 2))->InPPDirective &&<br>
+ !(*(I + 2))->First->HasUnescapedNewline)<br>
return;<br>
- if (1 + (I + 1)->Last->TotalLength > Limit)<br>
+ if (1 + (*(I + 1))->Last->TotalLength > Limit)<br>
return;<br>
- join(Line, *(++I));<br>
+ join(Line, **(++I));<br>
}<br>
<br>
- void tryMergeSimpleControlStatement(std::vector<AnnotatedLine>::iterator &I,<br>
- std::vector<AnnotatedLine>::iterator E,<br>
+ void tryMergeSimpleControlStatement(std::vector<AnnotatedLine *>::iterator &I,<br>
+ std::vector<AnnotatedLine *>::iterator E,<br>
unsigned Limit) {<br>
if (Limit == 0)<br>
return;<br>
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&<br>
- (I + 1)->First->is(tok::l_brace))<br>
+ (*(I + 1))->First->is(tok::l_brace))<br>
return;<br>
- if ((I + 1)->InPPDirective != I->InPPDirective ||<br>
- ((I + 1)->InPPDirective && (I + 1)->First->HasUnescapedNewline))<br>
+ if ((*(I + 1))->InPPDirective != (*I)->InPPDirective ||<br>
+ ((*(I + 1))->InPPDirective && (*(I + 1))->First->HasUnescapedNewline))<br>
return;<br>
- AnnotatedLine &Line = *I;<br>
+ AnnotatedLine &Line = **I;<br>
if (Line.Last->isNot(tok::r_paren))<br>
return;<br>
- if (1 + (I + 1)->Last->TotalLength > Limit)<br>
+ if (1 + (*(I + 1))->Last->TotalLength > Limit)<br>
return;<br>
- if ((I + 1)->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,<br>
- tok::kw_while) ||<br>
- (I + 1)->First->Type == TT_LineComment)<br>
+ if ((*(I + 1))->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,<br>
+ tok::kw_while) ||<br>
+ (*(I + 1))->First->Type == TT_LineComment)<br>
return;<br>
// Only inline simple if's (no nested if or else).<br>
if (I + 2 != E && Line.First->is(tok::kw_if) &&<br>
- (I + 2)->First->is(tok::kw_else))<br>
+ (*(I + 2))->First->is(tok::kw_else))<br>
return;<br>
- join(Line, *(++I));<br>
+ join(Line, **(++I));<br>
}<br>
<br>
- void tryMergeSimpleBlock(std::vector<AnnotatedLine>::iterator &I,<br>
- std::vector<AnnotatedLine>::iterator E,<br>
+ void tryMergeSimpleBlock(std::vector<AnnotatedLine *>::iterator &I,<br>
+ std::vector<AnnotatedLine *>::iterator E,<br>
unsigned Limit) {<br>
// No merging if the brace already is on the next line.<br>
if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)<br>
@@ -950,7 +1035,7 @@ private:<br>
// First, check that the current line allows merging. This is the case if<br>
// we're not in a control flow statement and the last token is an opening<br>
// brace.<br>
- AnnotatedLine &Line = *I;<br>
+ AnnotatedLine &Line = **I;<br>
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,<br>
tok::kw_else, tok::kw_try, tok::kw_catch,<br>
tok::kw_for,<br>
@@ -958,24 +1043,24 @@ private:<br>
tok::at, tok::minus, tok::plus))<br>
return;<br>
<br>
- FormatToken *Tok = (I + 1)->First;<br>
+ FormatToken *Tok = (*(I + 1))->First;<br>
if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&<br>
(Tok->getNextNonComment() == NULL ||<br>
Tok->getNextNonComment()->is(tok::semi))) {<br>
// We merge empty blocks even if the line exceeds the column limit.<br>
Tok->SpacesRequiredBefore = 0;<br>
Tok->CanBreakBefore = true;<br>
- join(Line, *(I + 1));<br>
+ join(Line, **(I + 1));<br>
I += 1;<br>
} else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {<br>
// Check that we still have three lines and they fit into the limit.<br>
- if (I + 2 == E || (I + 2)->Type == LT_Invalid ||<br>
+ if (I + 2 == E || (*(I + 2))->Type == LT_Invalid ||<br>
!nextTwoLinesFitInto(I, Limit))<br>
return;<br>
<br>
// Second, check that the next line does not contain any braces - if it<br>
// does, readability declines when putting it into a single line.<br>
- if ((I + 1)->Last->Type == TT_LineComment || Tok->MustBreakBefore)<br>
+ if ((*(I + 1))->Last->Type == TT_LineComment || Tok->MustBreakBefore)<br>
return;<br>
do {<br>
if (Tok->isOneOf(tok::l_brace, tok::r_brace))<br>
@@ -984,20 +1069,21 @@ private:<br>
} while (Tok != NULL);<br>
<br>
// Last, check that the third line contains a single closing brace.<br>
- Tok = (I + 2)->First;<br>
+ Tok = (*(I + 2))->First;<br>
if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||<br>
Tok->MustBreakBefore)<br>
return;<br>
<br>
- join(Line, *(I + 1));<br>
- join(Line, *(I + 2));<br>
+ join(Line, **(I + 1));<br>
+ join(Line, **(I + 2));<br>
I += 2;<br>
}<br>
}<br>
<br>
- bool nextTwoLinesFitInto(std::vector<AnnotatedLine>::iterator I,<br>
+ bool nextTwoLinesFitInto(std::vector<AnnotatedLine *>::iterator I,<br>
unsigned Limit) {<br>
- return 1 + (I + 1)->Last->TotalLength + 1 + (I + 2)->Last->TotalLength <=<br>
+ return 1 + (*(I + 1))->Last->TotalLength + 1 +<br>
+ (*(I + 2))->Last->TotalLength <=<br>
Limit;<br>
}<br>
<br>
@@ -1034,12 +1120,12 @@ private:<br>
return touchesRanges(LineRange);<br>
}<br>
<br>
- bool touchesPPDirective(std::vector<AnnotatedLine>::iterator I,<br>
- std::vector<AnnotatedLine>::iterator E) {<br>
+ bool touchesPPDirective(std::vector<AnnotatedLine *>::iterator I,<br>
+ std::vector<AnnotatedLine *>::iterator E) {<br>
for (; I != E; ++I) {<br>
- if (I->First->HasUnescapedNewline)<br>
+ if ((*I)->First->HasUnescapedNewline)<br>
return false;<br>
- if (touchesLine(*I))<br>
+ if (touchesLine(**I))<br>
return true;<br>
}<br>
return false;<br>
@@ -1055,7 +1141,7 @@ private:<br>
}<br>
<br>
virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {<br>
- AnnotatedLines.push_back(AnnotatedLine(TheLine));<br>
+ AnnotatedLines.push_back(new AnnotatedLine(TheLine));<br>
}<br>
<br>
/// \brief Add a new line and the required indent before the first Token<br>
@@ -1084,12 +1170,17 @@ private:<br>
InPPDirective && !RootToken.HasUnescapedNewline);<br>
}<br>
<br>
+ unsigned getColumnLimit(bool InPPDirective) const {<br>
+ // In preprocessor directives reserve two chars for trailing " \"<br>
+ return Style.ColumnLimit - (InPPDirective ? 2 : 0);<br>
+ }<br>
+<br>
FormatStyle Style;<br>
Lexer &Lex;<br>
SourceManager &SourceMgr;<br>
WhitespaceManager Whitespaces;<br>
std::vector<CharSourceRange> Ranges;<br>
- std::vector<AnnotatedLine> AnnotatedLines;<br>
+ std::vector<AnnotatedLine *> AnnotatedLines;<br>
<br>
encoding::Encoding Encoding;<br>
bool BinPackInconclusiveFunctions;<br>
<br>
Modified: cfe/trunk/lib/Format/FormatToken.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/FormatToken.h (original)<br>
+++ cfe/trunk/lib/Format/FormatToken.h Thu Sep 5 04:29:45 2013<br>
@@ -36,6 +36,7 @@ enum TokenType {<br>
TT_InlineASMColon,<br>
TT_InheritanceColon,<br>
TT_FunctionTypeLParen,<br>
+ TT_LambdaLSquare,<br>
TT_LineComment,<br>
TT_ObjCArrayLiteral,<br>
TT_ObjCBlockLParen,<br>
@@ -75,6 +76,7 @@ enum ParameterPackingKind {<br>
};<br>
<br>
class TokenRole;<br>
+class AnnotatedLine;<br>
<br>
/// \brief A wrapper around a \c Token storing information about the<br>
/// whitespace characters preceeding it.<br>
@@ -335,6 +337,8 @@ struct FormatToken {<br>
FormatToken *Previous;<br>
FormatToken *Next;<br>
<br>
+ SmallVector<AnnotatedLine *, 1> Children;<br>
+<br>
private:<br>
// Disallow copying.<br>
FormatToken(const FormatToken &) LLVM_DELETED_FUNCTION;<br>
<br>
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)<br>
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Thu Sep 5 04:29:45 2013<br>
@@ -182,7 +182,7 @@ private:<br>
FormatToken *Left = CurrentToken->Previous;<br>
FormatToken *Parent = Left->getPreviousNonComment();<br>
bool StartsObjCMethodExpr =<br>
- Contexts.back().CanBeExpression &&<br>
+ Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&<br>
(!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,<br>
tok::kw_return, tok::kw_throw) ||<br>
Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||<br>
@@ -522,7 +522,7 @@ private:<br>
<br>
// Reset token type in case we have already looked at it and then recovered<br>
// from an error (e.g. failure to find the matching >).<br>
- if (CurrentToken != NULL)<br>
+ if (CurrentToken != NULL && CurrentToken->Type != TT_LambdaLSquare)<br>
CurrentToken->Type = TT_Unknown;<br>
}<br>
<br>
@@ -974,6 +974,11 @@ private:<br>
} // end anonymous namespace<br>
<br>
void TokenAnnotator::annotate(AnnotatedLine &Line) {<br>
+ for (std::vector<AnnotatedLine *>::iterator I = Line.Children.begin(),<br>
+ E = Line.Children.end();<br>
+ I != E; ++I) {<br>
+ annotate(**I);<br>
+ }<br>
AnnotatingParser Parser(Style, Line, Ident_in);<br>
Line.Type = Parser.parseLine();<br>
if (Line.Type == LT_Invalid)<br>
@@ -1026,7 +1031,7 @@ void TokenAnnotator::calculateFormatting<br>
}<br>
Current->CanBreakBefore =<br>
Current->MustBreakBefore || canBreakBefore(Line, *Current);<br>
- if (Current->MustBreakBefore ||<br>
+ if (Current->MustBreakBefore || !Current->Children.empty() ||<br>
(Current->is(tok::string_literal) && Current->isMultiline()))<br>
Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;<br>
else<br>
@@ -1048,9 +1053,13 @@ void TokenAnnotator::calculateFormatting<br>
Current->Role->precomputeFormattingInfos(Current);<br>
}<br>
<br>
- DEBUG({<br>
- printDebugInfo(Line);<br>
- });<br>
+ DEBUG({ printDebugInfo(Line); });<br>
+<br>
+ for (std::vector<AnnotatedLine *>::iterator I = Line.Children.begin(),<br>
+ E = Line.Children.end();<br>
+ I != E; ++I) {<br>
+ calculateFormattingInformation(**I);<br>
+ }<br>
}<br>
<br>
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {<br>
@@ -1212,7 +1221,7 @@ bool TokenAnnotator::spaceRequiredBetwee<br>
if (Right.is(tok::r_square))<br>
return Right.Type == TT_ObjCArrayLiteral;<br>
if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&<br>
- Left.isNot(tok::numeric_constant))<br>
+ Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))<br>
return false;<br>
if (Left.is(tok::colon))<br>
return Left.Type != TT_ObjCMethodExpr;<br>
@@ -1233,7 +1242,7 @@ bool TokenAnnotator::spaceRequiredBetwee<br>
if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)<br>
return false;<br>
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))<br>
- return false; // No spaces in "{}".<br>
+ return !Left.Children.empty(); // No spaces in "{}".<br>
if (Left.is(tok::l_brace) || Right.is(tok::r_brace))<br>
return !Style.Cpp11BracedListStyle;<br>
if (Right.Type == TT_UnaryOperator)<br>
@@ -1355,11 +1364,13 @@ bool TokenAnnotator::canBreakBefore(cons<br>
// change the "binding" behavior of a comment.<br>
return false;<br>
<br>
+ if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)<br>
+ return false;<br>
+<br>
// We only break before r_brace if there was a corresponding break before<br>
// the l_brace, which is tracked by BreakBeforeClosingBrace.<br>
- if (Right.isOneOf(tok::r_brace, tok::r_paren) ||<br>
- Right.Type == TT_TemplateCloser)<br>
- return false;<br>
+ if (Right.is(tok::r_brace))<br>
+ return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;<br>
<br>
// Allow breaking after a trailing 'const', e.g. after a method declaration,<br>
// unless it is follow by ';', '{' or '='.<br>
<br>
Modified: cfe/trunk/lib/Format/TokenAnnotator.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.h?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.h?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/TokenAnnotator.h (original)<br>
+++ cfe/trunk/lib/Format/TokenAnnotator.h Thu Sep 5 04:29:45 2013<br>
@@ -38,31 +38,53 @@ enum LineType {<br>
class AnnotatedLine {<br>
public:<br>
AnnotatedLine(const UnwrappedLine &Line)<br>
- : First(Line.Tokens.front()), Level(Line.Level),<br>
+ : First(Line.Tokens.front().Tok), Level(Line.Level),<br>
InPPDirective(Line.InPPDirective),<br>
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),<br>
StartsDefinition(false) {<br>
assert(!Line.Tokens.empty());<br>
FormatToken *Current = First;<br>
- for (std::list<FormatToken *>::const_iterator I = ++Line.Tokens.begin(),<br>
- E = Line.Tokens.end();<br>
+ for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),<br>
+ E = Line.Tokens.end();<br>
I != E; ++I) {<br>
- Current->Next = *I;<br>
- (*I)->Previous = Current;<br>
+ const UnwrappedLineNode &Node = *I;<br>
+ Current->Next = I->Tok;<br>
+ I->Tok->Previous = Current;<br>
Current = Current->Next;<br>
+ for (SmallVectorImpl<UnwrappedLine>::const_iterator<br>
+ I = Node.Children.begin(),<br>
+ E = Node.Children.end();<br>
+ I != E; ++I) {<br>
+ Children.push_back(new AnnotatedLine(*I));<br>
+ Current->Children.push_back(Children.back());<br>
+ }<br>
}<br>
Last = Current;<br>
}<br>
<br>
+ ~AnnotatedLine() {<br>
+ for (unsigned i = 0, e = Children.size(); i != e; ++i) {<br>
+ delete Children[i];<br>
+ }<br>
+ Children.clear();<br></blockquote><div><br></div></div></div><div>Same here...</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ }<br>
+<br>
FormatToken *First;<br>
FormatToken *Last;<br>
<br>
+ std::vector<AnnotatedLine *> Children;<br>
+<br>
LineType Type;<br>
unsigned Level;<br>
bool InPPDirective;<br>
bool MustBeDeclaration;<br>
bool MightBeFunctionDecl;<br>
bool StartsDefinition;<br>
+<br>
+private:<br>
+ // Disallow copying.<br>
+ AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;<br>
+ void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;<br>
};<br>
<br>
/// \brief Determines extra information about the tokens comprising an<br>
<br>
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)<br>
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Thu Sep 5 04:29:45 2013<br>
@@ -122,9 +122,12 @@ class ScopedLineState {<br>
public:<br>
ScopedLineState(UnwrappedLineParser &Parser,<br>
bool SwitchToPreprocessorLines = false)<br>
- : Parser(Parser), SwitchToPreprocessorLines(SwitchToPreprocessorLines) {<br>
+ : Parser(Parser) {<br>
+ OriginalLines = Parser.CurrentLines;<br>
if (SwitchToPreprocessorLines)<br>
Parser.CurrentLines = &Parser.PreprocessorDirectives;<br>
+ else if (!Parser.Line->Tokens.empty())<br>
+ Parser.CurrentLines = &Parser.Line->Tokens.back().Children;<br>
PreBlockLine = Parser.Line.take();<br>
Parser.Line.reset(new UnwrappedLine());<br>
Parser.Line->Level = PreBlockLine->Level;<br>
@@ -137,16 +140,16 @@ public:<br>
}<br>
assert(Parser.Line->Tokens.empty());<br>
Parser.Line.reset(PreBlockLine);<br>
- Parser.MustBreakBeforeNextToken = true;<br>
- if (SwitchToPreprocessorLines)<br>
- Parser.CurrentLines = &Parser.Lines;<br>
+ if (Parser.CurrentLines == &Parser.PreprocessorDirectives)<br>
+ Parser.MustBreakBeforeNextToken = true;<br>
+ Parser.CurrentLines = OriginalLines;<br>
}<br>
<br>
private:<br>
UnwrappedLineParser &Parser;<br>
- const bool SwitchToPreprocessorLines;<br>
<br>
UnwrappedLine *PreBlockLine;<br>
+ SmallVectorImpl<UnwrappedLine> *OriginalLines;<br>
};<br>
<br>
namespace {<br>
@@ -191,7 +194,8 @@ bool UnwrappedLineParser::parse() {<br>
Tokens = &TokenSource;<br>
readToken();<br>
parseFile();<br>
- for (std::vector<UnwrappedLine>::iterator I = Lines.begin(), E = Lines.end();<br>
+ for (SmallVectorImpl<UnwrappedLine>::iterator I = Lines.begin(),<br>
+ E = Lines.end();<br>
I != E; ++I) {<br>
Callback.consumeUnwrappedLine(*I);<br>
}<br>
@@ -670,6 +674,8 @@ void UnwrappedLineParser::parseStructura<br>
}<br>
<br>
void UnwrappedLineParser::tryToParseLambda() {<br>
+ assert(FormatTok->is(tok::l_square));<br>
+ FormatToken &LSquare = *FormatTok;<br>
if (!tryToParseLambdaIntroducer()) {<br>
return;<br>
}<br>
@@ -681,7 +687,6 @@ void UnwrappedLineParser::tryToParseLamb<br>
switch (FormatTok->Tok.getKind()) {<br>
case tok::l_brace:<br>
break;<br>
- return;<br>
case tok::l_paren:<br>
parseParens();<br>
break;<br>
@@ -694,6 +699,7 @@ void UnwrappedLineParser::tryToParseLamb<br>
break;<br>
}<br>
}<br>
+ LSquare.Type = TT_LambdaLSquare;<br>
parseChildBlock();<br>
}<br>
<br>
@@ -1183,23 +1189,39 @@ void UnwrappedLineParser::parseObjCProto<br>
parseObjCUntilAtEnd();<br>
}<br>
<br>
+static void printDebugInfo(const UnwrappedLine &Line, StringRef Prefix = "") {<br>
+ llvm::dbgs() << Prefix << "Line(" << Line.Level << ")"<br>
+ << (Line.InPPDirective ? " MACRO" : "") << ": ";<br>
+ for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),<br>
+ E = Line.Tokens.end();<br>
+ I != E; ++I) {<br>
+ llvm::dbgs() << I->Tok->Tok.getName() << " ";<br>
+ }<br>
+ for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),<br>
+ E = Line.Tokens.end();<br>
+ I != E; ++I) {<br>
+ const UnwrappedLineNode &Node = *I;<br>
+ for (SmallVectorImpl<UnwrappedLine>::const_iterator<br>
+ I = Node.Children.begin(),<br>
+ E = Node.Children.end();<br>
+ I != E; ++I) {<br>
+ printDebugInfo(*I, "\nChild: ");<br>
+ }<br>
+ }<br>
+ llvm::dbgs() << "\n";<br>
+}<br>
+<br>
void UnwrappedLineParser::addUnwrappedLine() {<br>
if (Line->Tokens.empty())<br>
return;<br>
DEBUG({<br>
- llvm::dbgs() << "Line(" << Line->Level << ")"<br>
- << (Line->InPPDirective ? " MACRO" : "") << ": ";<br>
- for (std::list<FormatToken *>::iterator I = Line->Tokens.begin(),<br>
- E = Line->Tokens.end();<br>
- I != E; ++I) {<br>
- llvm::dbgs() << (*I)->Tok.getName() << " ";<br>
- }<br>
- llvm::dbgs() << "\n";<br>
+ if (CurrentLines == &Lines)<br>
+ printDebugInfo(*Line);<br>
});<br>
CurrentLines->push_back(*Line);<br>
Line->Tokens.clear();<br>
if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {<br>
- for (std::vector<UnwrappedLine>::iterator<br>
+ for (SmallVectorImpl<UnwrappedLine>::iterator<br>
I = PreprocessorDirectives.begin(),<br>
E = PreprocessorDirectives.end();<br>
I != E; ++I) {<br>
@@ -1273,9 +1295,9 @@ void UnwrappedLineParser::readToken() {<br>
}<br>
<br>
void UnwrappedLineParser::pushToken(FormatToken *Tok) {<br>
- Line->Tokens.push_back(Tok);<br>
+ Line->Tokens.push_back(UnwrappedLineNode(Tok));<br>
if (MustBreakBeforeNextToken) {<br>
- Line->Tokens.back()->MustBreakBefore = true;<br>
+ Line->Tokens.back().Tok->MustBreakBefore = true;<br>
MustBreakBeforeNextToken = false;<br>
}<br>
}<br>
<br>
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)<br>
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Thu Sep 5 04:29:45 2013<br>
@@ -24,6 +24,8 @@<br>
namespace clang {<br>
namespace format {<br>
<br>
+struct UnwrappedLineNode;<br>
+<br>
/// \brief An unwrapped line is a sequence of \c Token, that we would like to<br>
/// put on a single line if there was no column limit.<br>
///<br>
@@ -35,7 +37,7 @@ struct UnwrappedLine {<br>
<br>
// FIXME: Don't use std::list here.<br>
/// \brief The \c Tokens comprising this \c UnwrappedLine.<br>
- std::list<FormatToken *> Tokens;<br>
+ std::list<UnwrappedLineNode> Tokens;<br>
<br>
/// \brief The indent level of the \c UnwrappedLine.<br>
unsigned Level;<br>
@@ -119,18 +121,18 @@ private:<br>
bool MustBreakBeforeNextToken;<br>
<br>
// The parsed lines. Only added to through \c CurrentLines.<br>
- std::vector<UnwrappedLine> Lines;<br>
+ SmallVector<UnwrappedLine, 8> Lines;<br>
<br>
// Preprocessor directives are parsed out-of-order from other unwrapped lines.<br>
// Thus, we need to keep a list of preprocessor directives to be reported<br>
// after an unwarpped line that has been started was finished.<br>
- std::vector<UnwrappedLine> PreprocessorDirectives;<br>
+ SmallVector<UnwrappedLine, 4> PreprocessorDirectives;<br>
<br>
// New unwrapped lines are added via CurrentLines.<br>
// Usually points to \c &Lines. While parsing a preprocessor directive when<br>
// there is an unfinished previous unwrapped line, will point to<br>
// \c &PreprocessorDirectives.<br>
- std::vector<UnwrappedLine> *CurrentLines;<br>
+ SmallVectorImpl<UnwrappedLine> *CurrentLines;<br>
<br>
// We store for each line whether it must be a declaration depending on<br>
// whether we are in a compound statement or not.<br>
@@ -162,6 +164,14 @@ private:<br>
friend class ScopedLineState;<br>
};<br>
<br>
+struct UnwrappedLineNode {<br>
+ UnwrappedLineNode() : Tok(NULL) {}<br>
+ UnwrappedLineNode(FormatToken *Tok) : Tok(Tok) {}<br>
+<br>
+ FormatToken *Tok;<br>
+ SmallVector<UnwrappedLine, 0> Children;<br>
+};<br>
+<br>
} // end namespace format<br>
} // end namespace clang<br>
<br>
<br>
Modified: cfe/trunk/unittests/Format/FormatTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=190038&r1=190037&r2=190038&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=190038&r1=190037&r2=190038&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)<br>
+++ cfe/trunk/unittests/Format/FormatTest.cpp Thu Sep 5 04:29:45 2013<br>
@@ -110,7 +110,7 @@ TEST_F(FormatTest, MessUp) {<br>
// Basic function tests.<br>
//===----------------------------------------------------------------------===//<br>
<br>
-TEST_F(FormatTest, DoesNotChangeCorrectlyFormatedCode) {<br>
+TEST_F(FormatTest, DoesNotChangeCorrectlyFormattedCode) {<br>
EXPECT_EQ(";", format(";"));<br>
}<br>
<br>
@@ -1496,7 +1496,9 @@ TEST_F(FormatTest, FormatsClasses) {<br>
" public G {};");<br>
<br>
verifyFormat("class\n"<br>
- " ReallyReallyLongClassName {\n};",<br>
+ " ReallyReallyLongClassName {\n"<br>
+ " int i;\n"<br>
+ "};",<br>
getLLVMStyleWithColumns(32));<br>
}<br>
<br>
@@ -2184,23 +2186,37 @@ TEST_F(FormatTest, LayoutStatementsAroun<br>
}<br>
<br>
TEST_F(FormatTest, LayoutBlockInsideParens) {<br>
+ EXPECT_EQ("functionCall({ int i; });", format(" functionCall ( {int i;} );"));<br>
EXPECT_EQ("functionCall({\n"<br>
" int i;\n"<br>
+ " int j;\n"<br>
"});",<br>
- format(" functionCall ( {int i;} );"));<br>
-<br>
- // FIXME: This is bad, find a better and more generic solution.<br>
+ format(" functionCall ( {int i;int j;} );"));<br>
EXPECT_EQ("functionCall({\n"<br>
- " int i;\n"<br>
- "},\n"<br>
+ " int i;\n"<br>
+ " int j;\n"<br>
+ " },\n"<br>
" aaaa, bbbb, cccc);",<br>
- format(" functionCall ( {int i;}, aaaa, bbbb, cccc);"));<br>
+ format(" functionCall ( {int i;int j;}, aaaa, bbbb, cccc);"));<br>
+ EXPECT_EQ("functionCall(aaaa, bbbb, { int i; });",<br>
+ format(" functionCall (aaaa, bbbb, {int i;});"));<br>
+ EXPECT_EQ("functionCall(aaaa, bbbb, {\n"<br>
+ " int i;\n"<br>
+ " int j;\n"<br>
+ "});",<br>
+ format(" functionCall (aaaa, bbbb, {int i;int j;});"));<br>
+ EXPECT_EQ("functionCall(aaaa, bbbb, { int i; });",<br>
+ format(" functionCall (aaaa, bbbb, {int i;});"));<br>
verifyFormat(<br>
"Aaa({\n"<br>
- " int i;\n"<br>
- "},\n"<br>
+ " int i; // break\n"<br>
+ " },\n"<br>
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"<br>
" ccccccccccccccccc));");<br>
+ verifyFormat("DEBUG({\n"<br>
+ " if (a)\n"<br>
+ " f();\n"<br>
+ "});");<br>
}<br>
<br>
TEST_F(FormatTest, LayoutBlockInsideStatement) {<br>
@@ -3681,7 +3697,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStar<br>
verifyGoogleFormat("return sizeof(int**);");<br>
verifyIndependentOfContext("Type **A = static_cast<Type **>(P);");<br>
verifyGoogleFormat("Type** A = static_cast<Type**>(P);");<br>
- verifyFormat("auto a = [](int **&, int ***) {\n};");<br>
+ verifyFormat("auto a = [](int **&, int ***) {};");<br>
<br>
verifyIndependentOfContext("InvalidRegions[*R] = 0;");<br>
<br>
@@ -3865,7 +3881,7 @@ TEST_F(FormatTest, FormatsCasts) {<br>
verifyFormat("f(foo).b;");<br>
verifyFormat("f(foo)(b);");<br>
verifyFormat("f(foo)[b];");<br>
- verifyFormat("[](foo) {\n return 4;\n}(bar);");<br>
+ verifyFormat("[](foo) { return 4; }(bar);");<br>
verifyFormat("(*funptr)(foo)[4];");<br>
verifyFormat("funptrs[4](foo)[4];");<br>
verifyFormat("void f(int *);");<br>
@@ -6260,68 +6276,40 @@ TEST_F(FormatTest, FormatsProtocolBuffer<br>
}<br>
<br>
TEST_F(FormatTest, FormatsLambdas) {<br>
- verifyFormat(<br>
- "int c = [b]() mutable {\n"<br>
- " return [&b] {\n"<br>
- " return b++;\n"<br>
- " }();\n"<br>
- "}();\n");<br>
- verifyFormat(<br>
- "int c = [&] {\n"<br>
- " [=] {\n"<br>
- " return b++;\n"<br>
- " }();\n"<br>
- "}();\n");<br>
- verifyFormat(<br>
- "int c = [&, &a, a] {\n"<br>
- " [=, c, &d] {\n"<br>
- " return b++;\n"<br>
- " }();\n"<br>
- "}();\n");<br>
- verifyFormat(<br>
- "int c = [&a, &a, a] {\n"<br>
- " [=, a, b, &c] {\n"<br>
- " return b++;\n"<br>
- " }();\n"<br>
- "}();\n");<br>
- verifyFormat(<br>
- "auto c = {[&a, &a, a] {\n"<br>
- " [=, a, b, &c] {\n"<br>
- " return b++;\n"<br>
- " }();\n"<br>
- "} }\n");<br>
- verifyFormat(<br>
- "auto c = {[&a, &a, a] {\n"<br>
- " [=, a, b, &c] {\n"<br>
- " }();\n"<br>
- "} }\n");<br>
- verifyFormat(<br>
- "void f() {\n"<br>
- " other(x.begin(), x.end(), [&](int, int) {\n"<br>
- " return 1;\n"<br>
- " });\n"<br>
- "}\n");<br>
+ verifyFormat("int c = [b]() mutable {\n"<br>
+ " return [&b] { return b++; }();\n"<br>
+ "}();\n");<br>
+ verifyFormat("int c = [&] {\n"<br>
+ " [=] { return b++; }();\n"<br>
+ "}();\n");<br>
+ verifyFormat("int c = [&, &a, a] {\n"<br>
+ " [=, c, &d] { return b++; }();\n"<br>
+ "}();\n");<br>
+ verifyFormat("int c = [&a, &a, a] {\n"<br>
+ " [=, a, b, &c] { return b++; }();\n"<br>
+ "}();\n");<br>
+ verifyFormat("auto c = { [&a, &a, a] {\n"<br>
+ " [=, a, b, &c] { return b++; }();\n"<br>
+ "} }\n");<br>
+ verifyFormat("auto c = { [&a, &a, a] { [=, a, b, &c] { }(); } }\n");<br>
+ verifyFormat("void f() {\n"<br>
+ " other(x.begin(), x.end(), [&](int, int) { return 1; });\n"<br>
+ "}\n");<br>
// FIXME: The formatting is incorrect; this test currently checks that<br>
// parsing of the unwrapped lines doesn't regress.<br>
- verifyFormat(<br>
- "void f() {\n"<br>
- " other(x.begin(), //\n"<br>
- " x.end(), //\n"<br>
- " [&](int, int) {\n"<br>
- " return 1;\n"<br>
- " });\n"<br>
- "}\n");<br>
+ verifyFormat("void f() {\n"<br>
+ " other(x.begin(), //\n"<br>
+ " x.end(), //\n"<br>
+ " [&](int, int) { return 1; });\n"<br>
+ "}\n");<br>
}<br>
<br>
TEST_F(FormatTest, FormatsBlocks) {<br>
// FIXME: Make whitespace formatting consistent. Ask a ObjC dev how<br>
// it would ideally look.<br>
- verifyFormat("[operation setCompletionBlock:^{\n"<br>
- " [self onOperationDone];\n"<br>
- "}];\n");<br>
- verifyFormat("int i = {[operation setCompletionBlock : ^{\n"<br>
- " [self onOperationDone];\n"<br>
- "}] };\n");<br>
+ verifyFormat("[operation setCompletionBlock:^{ [self onOperationDone]; }];");<br>
+ verifyFormat("int i = {[operation setCompletionBlock : ^{ [self "<br>
+ "onOperationDone]; }] };");<br>
}<br>
<br>
} // end namespace tooling<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div>