forked from OSchip/llvm-project
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. llvm-svn: 193167
This commit is contained in:
parent
69f531065c
commit
1db6c38687
|
@ -92,8 +92,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
|
|||
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(const LineState &State) {
|
|||
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(const LineState &State) {
|
|||
!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::addTokenOnNewLine(LineState &State,
|
|||
|
||||
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::addTokenOnNewLine(LineState &State,
|
|||
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::addTokenOnNewLine(LineState &State,
|
|||
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::moveStateToNextToken(LineState &State,
|
|||
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::moveStateToNextToken(LineState &State,
|
|||
(!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::moveStateToNextToken(LineState &State,
|
|||
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::moveStateToNextToken(LineState &State,
|
|||
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::moveStateToNextToken(LineState &State,
|
|||
}
|
||||
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::moveStateToNextToken(LineState &State,
|
|||
(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::moveStateToNextToken(LineState &State,
|
|||
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 &&
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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::spaceRequiredBetween(const AnnotatedLine &Line,
|
|||
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(const AnnotatedLine &Line,
|
|||
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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue