r193167 - clang-format: Improve formatting of ObjC array literals.
Daniel Jasper
djasper at google.com
Tue Oct 22 08:30:28 PDT 2013
Author: djasper
Date: Tue Oct 22 10:30:28 2013
New Revision: 193167
URL: http://llvm.org/viewvc/llvm-project?rev=193167&view=rev
Log:
clang-format: Improve formatting of ObjC array literals.
Before:
NSArray *arguments =
@[ kind == kUserTicket ? @"--user-store" : @"--system-store",
@"--print-tickets", @"--productid", @"com.google.Chrome" ];
After:
NSArray *arguments = @[
kind == kUserTicket ? @"--user-store" : @"--system-store",
@"--print-tickets",
@"--productid",
@"com.google.Chrome"
];
This fixes llvm.org/PR15231.
Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=193167&r1=193166&r2=193167&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Tue Oct 22 10:30:28 2013
@@ -92,8 +92,8 @@ bool ContinuationIndenter::canBreak(cons
const FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *Current.Previous;
assert(&Previous == Current.Previous);
- if (!Current.CanBreakBefore &&
- !(Current.is(tok::r_brace) && State.Stack.back().BreakBeforeClosingBrace))
+ if (!Current.CanBreakBefore && !(State.Stack.back().BreakBeforeClosingBrace &&
+ Current.closesBlockTypeList(Style)))
return false;
// 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.
@@ -118,10 +118,8 @@ bool ContinuationIndenter::mustBreak(con
const FormatToken &Previous = *Current.Previous;
if (Current.MustBreakBefore || Current.Type == TT_InlineASMColon)
return true;
- if ((!Style.Cpp11BracedListStyle ||
- (Current.MatchingParen &&
- Current.MatchingParen->BlockKind == BK_Block)) &&
- Current.is(tok::r_brace) && State.Stack.back().BreakBeforeClosingBrace)
+ if (State.Stack.back().BreakBeforeClosingBrace &&
+ Current.closesBlockTypeList(Style))
return true;
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
return true;
@@ -136,7 +134,8 @@ bool ContinuationIndenter::mustBreak(con
!Previous.isOneOf(tok::kw_return, tok::lessless) &&
Previous.Type != TT_InlineASMColon && NextIsMultilineString(State))
return true;
- if (Previous.Type == TT_ObjCDictLiteral && Previous.is(tok::l_brace) &&
+ if (((Previous.Type == TT_ObjCDictLiteral && Previous.is(tok::l_brace)) ||
+ Previous.Type == TT_ArrayInitializerLSquare) &&
getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State))
return true;
@@ -332,10 +331,8 @@ unsigned ContinuationIndenter::addTokenO
if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) {
State.Column = State.FirstIndent;
- } else if (Current.is(tok::r_brace)) {
- if (Current.MatchingParen &&
- (Current.MatchingParen->BlockKind == BK_BracedInit ||
- !Current.MatchingParen->Children.empty()))
+ } else if (Current.isOneOf(tok::r_brace, tok::r_square)) {
+ if (Current.closesBlockTypeList(Style))
State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
else
State.Column = State.FirstIndent;
@@ -372,8 +369,7 @@ unsigned ContinuationIndenter::addTokenO
State.Column = State.Stack.back().Indent;
State.Stack.back().ColonPos = State.Column + Current.ColumnWidth;
}
- } else if (Current.is(tok::l_square) && Current.Type != TT_ObjCMethodExpr &&
- Current.Type != TT_LambdaLSquare) {
+ } else if (Current.Type == TT_ArraySubscriptLSquare) {
if (State.Stack.back().StartOfArraySubscripts != 0)
State.Column = State.Stack.back().StartOfArraySubscripts;
else
@@ -431,8 +427,9 @@ unsigned ContinuationIndenter::addTokenO
TokenBefore->Type != TT_BinaryOperator && !TokenBefore->opensScope())
State.Stack.back().BreakBeforeParameter = true;
- // If we break after {, we should also break before the corresponding }.
- if (Previous.is(tok::l_brace))
+ // If we break after { or the [ of an array initializer, we should also break
+ // before the corresponding } or ].
+ if (Previous.is(tok::l_brace) || Previous.Type == TT_ArrayInitializerLSquare)
State.Stack.back().BreakBeforeClosingBrace = true;
if (State.Stack.back().AvoidBinPacking) {
@@ -457,7 +454,7 @@ unsigned ContinuationIndenter::moveState
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) && Current.Type != TT_LambdaLSquare &&
+ if (Current.Type == TT_ArraySubscriptLSquare &&
State.Stack.back().StartOfArraySubscripts == 0)
State.Stack.back().StartOfArraySubscripts = State.Column;
if (Current.is(tok::question))
@@ -527,7 +524,7 @@ unsigned ContinuationIndenter::moveState
(!SkipFirstExtraIndent && *I > prec::Assignment &&
!Style.BreakBeforeBinaryOperators))
NewParenState.Indent += Style.ContinuationIndentWidth;
- if (Previous && !Previous->opensScope())
+ if ((Previous && !Previous->opensScope()) || *I > prec::Comma)
NewParenState.BreakBeforeParameter = false;
State.Stack.push_back(NewParenState);
SkipFirstExtraIndent = false;
@@ -539,7 +536,9 @@ unsigned ContinuationIndenter::moveState
unsigned NewIndent;
unsigned NewIndentLevel = State.Stack.back().IndentLevel;
bool AvoidBinPacking;
- if (Current.is(tok::l_brace)) {
+ bool BreakBeforeParameter = false;
+ if (Current.is(tok::l_brace) ||
+ Current.Type == TT_ArrayInitializerLSquare) {
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.
@@ -560,6 +559,7 @@ unsigned ContinuationIndenter::moveState
State.Stack.pop_back();
NewIndent = State.Stack.back().LastSpace + Style.IndentWidth;
++NewIndentLevel;
+ BreakBeforeParameter = true;
} else {
NewIndent = State.Stack.back().LastSpace;
if (Style.Cpp11BracedListStyle)
@@ -571,6 +571,8 @@ unsigned ContinuationIndenter::moveState
}
const FormatToken *NextNoComment = Current.getNextNonComment();
AvoidBinPacking = Current.BlockKind == BK_Block ||
+ Current.Type == TT_ArrayInitializerLSquare ||
+ Current.Type == TT_ObjCDictLiteral ||
(NextNoComment &&
NextNoComment->Type == TT_DesignatedInitializerPeriod);
} else {
@@ -582,6 +584,12 @@ unsigned ContinuationIndenter::moveState
(Current.PackingKind == PPK_OnePerLine ||
(!BinPackInconclusiveFunctions &&
Current.PackingKind == PPK_Inconclusive)));
+ // If this '[' opens an ObjC call, determine whether all parameters fit
+ // into one line and put one per line if they don't.
+ if (Current.Type == TT_ObjCMethodExpr &&
+ getLengthToMatchingParen(Current) + State.Column >
+ getColumnLimit(State))
+ BreakBeforeParameter = true;
}
bool NoLineBreak = State.Stack.back().NoLineBreak ||
@@ -590,23 +598,10 @@ unsigned ContinuationIndenter::moveState
State.Stack.push_back(ParenState(NewIndent, NewIndentLevel,
State.Stack.back().LastSpace,
AvoidBinPacking, NoLineBreak));
- State.Stack.back().BreakBeforeParameter = Current.BlockKind == BK_Block;
+ State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
++State.ParenLevel;
}
- // If this '[' opens an ObjC call, determine whether all parameters fit into
- // one line and put one per line if they don't.
- if (Current.isOneOf(tok::l_brace, tok::l_square) &&
- (Current.Type == TT_ObjCDictLiteral ||
- Current.Type == TT_ObjCMethodExpr) &&
- Current.MatchingParen != NULL) {
- if (getLengthToMatchingParen(Current) + State.Column >
- getColumnLimit(State)) {
- State.Stack.back().BreakBeforeParameter = true;
- State.Stack.back().AvoidBinPacking = true;
- }
- }
-
// If we encounter a closing ), ], } or >, we can remove a level from our
// stacks.
if (State.Stack.size() > 1 &&
Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=193167&r1=193166&r2=193167&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Tue Oct 22 10:30:28 2013
@@ -25,6 +25,8 @@ namespace clang {
namespace format {
enum TokenType {
+ TT_ArrayInitializerLSquare,
+ TT_ArraySubscriptLSquare,
TT_BinaryOperator,
TT_BitFieldColon,
TT_BlockComment,
@@ -39,7 +41,6 @@ enum TokenType {
TT_FunctionTypeLParen,
TT_LambdaLSquare,
TT_LineComment,
- TT_ObjCArrayLiteral,
TT_ObjCBlockLParen,
TT_ObjCDecl,
TT_ObjCDictLiteral,
@@ -338,6 +339,17 @@ struct FormatToken {
return Tok;
}
+ bool closesBlockTypeList(const FormatStyle &Style) const {
+ if (is(tok::r_brace) && MatchingParen &&
+ (MatchingParen->BlockKind == BK_Block ||
+ !Style.Cpp11BracedListStyle))
+ return true;
+ if (is(tok::r_square) && MatchingParen &&
+ MatchingParen->Type == TT_ArrayInitializerLSquare)
+ return true;
+ return false;
+ }
+
FormatToken *MatchingParen;
FormatToken *Previous;
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=193167&r1=193166&r2=193167&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Oct 22 10:30:28 2013
@@ -197,13 +197,14 @@ private:
getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
Contexts.back().IsExpression = true;
- bool StartsObjCArrayLiteral = Parent && Parent->is(tok::at);
if (StartsObjCMethodExpr) {
Contexts.back().ColonIsObjCMethodExpr = true;
Left->Type = TT_ObjCMethodExpr;
- } else if (StartsObjCArrayLiteral) {
- Left->Type = TT_ObjCArrayLiteral;
+ } else if (Parent && Parent->is(tok::at)) {
+ Left->Type = TT_ArrayInitializerLSquare;
+ } else if (Left->Type == TT_Unknown) {
+ Left->Type = TT_ArraySubscriptLSquare;
}
while (CurrentToken != NULL) {
@@ -222,8 +223,6 @@ private:
// binary operator.
if (Parent != NULL && Parent->Type == TT_PointerOrReference)
Parent->Type = TT_BinaryOperator;
- } else if (StartsObjCArrayLiteral) {
- CurrentToken->Type = TT_ObjCArrayLiteral;
}
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
@@ -235,6 +234,9 @@ private:
}
if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
return false;
+ if (CurrentToken->is(tok::comma) &&
+ Left->Type == TT_ArraySubscriptLSquare)
+ Left->Type = TT_ArrayInitializerLSquare;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
return false;
@@ -1263,9 +1265,11 @@ bool TokenAnnotator::spaceRequiredBetwee
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
if (Left.is(tok::l_square))
- return Left.Type == TT_ObjCArrayLiteral && Right.isNot(tok::r_square);
+ return Left.Type == TT_ArrayInitializerLSquare &&
+ Right.isNot(tok::r_square);
if (Right.is(tok::r_square))
- return Right.Type == TT_ObjCArrayLiteral;
+ return Right.MatchingParen &&
+ Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))
return false;
@@ -1481,15 +1485,17 @@ bool TokenAnnotator::canBreakBefore(cons
if (Left.is(tok::greater) && Right.is(tok::greater) &&
Left.Type != TT_TemplateCloser)
return false;
+ if (Left.Type == TT_ArrayInitializerLSquare)
+ return true;
return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
!Style.BreakBeforeBinaryOperators) ||
Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct) ||
- Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon) ||
+ Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon,
+ tok::l_square, tok::at) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const, tok::kw___attribute)) ||
- (Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
- Right.is(tok::l_square);
+ (Left.is(tok::l_paren) && !Right.is(tok::r_paren));
}
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=193167&r1=193166&r2=193167&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Oct 22 10:30:28 2013
@@ -5378,6 +5378,7 @@ TEST_F(FormatTest, ObjCLiterals) {
verifyFormat(
"NSArray *array = @[ @\" Hey \", NSApp, [NSNumber numberWithInt:42] ];");
verifyFormat("return @[ @3, @[], @[ @4, @5 ] ];");
+ verifyFormat("NSArray *array = @[ [foo description] ];");
verifyFormat("@{");
verifyFormat("@{}");
@@ -5408,6 +5409,13 @@ TEST_F(FormatTest, ObjCLiterals) {
" NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : "
"regularFont,\n"
"};");
+ verifyFormat(
+ "NSArray *arguments = @[\n"
+ " kind == kUserTicket ? @\"--user-store\" : @\"--system-store\",\n"
+ " @\"--print-tickets\",\n"
+ " @\"--productid\",\n"
+ " @\"com.google.Chrome\"\n"
+ "];");
}
TEST_F(FormatTest, ReformatRegionAdjustsIndent) {
More information about the cfe-commits
mailing list