2013-01-30 05:01:14 +08:00
|
|
|
//===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// \brief This file implements a token annotator, i.e. creates
|
|
|
|
/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "TokenAnnotator.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2013-04-09 04:33:42 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2013-01-30 05:01:14 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace format {
|
|
|
|
|
2013-07-01 12:03:19 +08:00
|
|
|
namespace {
|
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
/// \brief A parser that gathers additional information about tokens.
|
|
|
|
///
|
2013-03-13 00:28:18 +08:00
|
|
|
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
|
2013-01-30 05:01:14 +08:00
|
|
|
/// store a parenthesis levels. It also tries to resolve matching "<" and ">"
|
|
|
|
/// into template parameter lists.
|
|
|
|
class AnnotatingParser {
|
|
|
|
public:
|
clang-format: Add column layout formatting for braced lists
With this patch, braced lists (with more than 3 elements are formatted in a
column layout if possible). E.g.:
static const uint16_t CallerSavedRegs64Bit[] = {
X86::RAX, X86::RDX, X86::RCX, X86::RSI, X86::RDI,
X86::R8, X86::R9, X86::R10, X86::R11, 0
};
Required other changes:
- FormatTokens can now have a special role that contains extra data and can do
special formattings. A comma separated list is currently the only
implementation.
- Move penalty calculation entirely into ContinuationIndenter (there was a last
piece still in UnwrappedLineFormatter).
Review: http://llvm-reviews.chandlerc.com/D1457
llvm-svn: 189018
2013-08-22 23:00:41 +08:00
|
|
|
AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
|
|
|
|
IdentifierInfo &Ident_in)
|
|
|
|
: Style(Style), Line(Line), CurrentToken(Line.First),
|
2013-11-08 01:43:07 +08:00
|
|
|
KeywordVirtualFound(false), AutoFound(false), Ident_in(Ident_in) {
|
2013-06-26 08:30:14 +08:00
|
|
|
Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
Formatter: Correctly format stars in `sizeof(int**)` and similar places.
This redoes how '*' and '&' are classified as pointer / reference markers when
followed by ')', '>', or ','.
Previously, determineStarAmpUsage() marked a single '*' and '&' followed by
')', '>', or ',' as pointer or reference marker. Now, all '*'s and '&'s
preceding ')', '>', or ',' are marked as pointer / reference markers. Fixes
PR14884.
Since only the last '*' in 'int ***' was marked as pointer before (the rest
were unary operators, which don't reach spaceRequiredBetween()),
spaceRequiredBetween() now had to be thought about handing multiple '*'s in
sequence.
Before:
return sizeof(int * *);
Type **A = static_cast<Type * *>(P);
Now:
return sizeof(int**);
Type **A = static_cast<Type **>(P);
While here, also make all methods of AnnotatingParser except parseLine()
private.
Review URL: http://llvm-reviews.chandlerc.com/D384
llvm-svn: 174975
2013-02-13 00:17:07 +08:00
|
|
|
private:
|
2013-01-30 05:01:14 +08:00
|
|
|
bool parseAngle() {
|
|
|
|
if (CurrentToken == NULL)
|
|
|
|
return false;
|
2013-03-14 21:45:21 +08:00
|
|
|
ScopedContextCreator ContextCreator(*this, tok::less, 10);
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Left = CurrentToken->Previous;
|
2013-02-06 18:05:46 +08:00
|
|
|
Contexts.back().IsExpression = false;
|
2013-01-30 05:01:14 +08:00
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
if (CurrentToken->is(tok::greater)) {
|
|
|
|
Left->MatchingParen = CurrentToken;
|
|
|
|
CurrentToken->MatchingParen = Left;
|
|
|
|
CurrentToken->Type = TT_TemplateCloser;
|
|
|
|
next();
|
|
|
|
return true;
|
|
|
|
}
|
2013-03-13 22:41:29 +08:00
|
|
|
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
|
2013-05-15 21:46:48 +08:00
|
|
|
tok::question, tok::colon))
|
|
|
|
return false;
|
2013-06-02 02:56:00 +08:00
|
|
|
// If a && or || is found and interpreted as a binary operator, this set
|
2013-06-04 00:16:41 +08:00
|
|
|
// of angles is likely part of something like "a < b && c > d". If the
|
2013-06-02 02:56:00 +08:00
|
|
|
// angles are inside an expression, the ||/&& might also be a binary
|
|
|
|
// operator that was misinterpreted because we are parsing template
|
|
|
|
// parameters.
|
|
|
|
// FIXME: This is getting out of hand, write a decent parser.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
|
2013-06-02 02:56:00 +08:00
|
|
|
(CurrentToken->Previous->Type == TT_BinaryOperator ||
|
|
|
|
Contexts[Contexts.size() - 2].IsExpression) &&
|
2013-05-29 22:47:47 +08:00
|
|
|
Line.First->isNot(tok::kw_template))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-02-14 23:01:34 +08:00
|
|
|
updateParameterCount(Left, CurrentToken);
|
2013-01-30 05:01:14 +08:00
|
|
|
if (!consumeToken())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseParens(bool LookForDecls = false) {
|
|
|
|
if (CurrentToken == NULL)
|
|
|
|
return false;
|
2013-03-14 21:45:21 +08:00
|
|
|
ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
|
2013-02-06 18:05:46 +08:00
|
|
|
|
|
|
|
// FIXME: This is a bit of a hack. Do better.
|
|
|
|
Contexts.back().ColonIsForRangeExpr =
|
|
|
|
Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
|
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
bool StartsObjCMethodExpr = false;
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Left = CurrentToken->Previous;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (CurrentToken->is(tok::caret)) {
|
|
|
|
// ^( starts a block.
|
|
|
|
Left->Type = TT_ObjCBlockLParen;
|
2013-05-29 22:47:47 +08:00
|
|
|
} else if (FormatToken *MaybeSel = Left->Previous) {
|
2013-01-30 05:01:14 +08:00
|
|
|
// @selector( starts a selector.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
|
|
|
|
MaybeSel->Previous->is(tok::at)) {
|
2013-01-30 05:01:14 +08:00
|
|
|
StartsObjCMethodExpr = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-13 17:09:09 +08:00
|
|
|
if (Left->Previous && Left->Previous->isOneOf(tok::kw_static_assert,
|
2013-10-21 02:15:30 +08:00
|
|
|
tok::kw_if, tok::kw_while)) {
|
|
|
|
// static_assert, if and while usually contain expressions.
|
2013-08-02 01:58:23 +08:00
|
|
|
Contexts.back().IsExpression = true;
|
2013-10-21 02:15:30 +08:00
|
|
|
} else if (Left->Previous && Left->Previous->is(tok::r_square) &&
|
|
|
|
Left->Previous->MatchingParen &&
|
|
|
|
Left->Previous->MatchingParen->Type == TT_LambdaLSquare) {
|
|
|
|
// This is a parameter list of a lambda expression.
|
|
|
|
Contexts.back().IsExpression = false;
|
|
|
|
}
|
2013-08-02 01:58:23 +08:00
|
|
|
|
2013-02-06 18:05:46 +08:00
|
|
|
if (StartsObjCMethodExpr) {
|
|
|
|
Contexts.back().ColonIsObjCMethodExpr = true;
|
|
|
|
Left->Type = TT_ObjCMethodExpr;
|
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-05-28 16:33:00 +08:00
|
|
|
bool MightBeFunctionType = CurrentToken->is(tok::star);
|
2013-07-10 22:02:49 +08:00
|
|
|
bool HasMultipleLines = false;
|
|
|
|
bool HasMultipleParametersOnALine = false;
|
2013-01-30 05:01:14 +08:00
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
// LookForDecls is set when "if (" has been seen. Check for
|
|
|
|
// 'identifier' '*' 'identifier' followed by not '=' -- this
|
|
|
|
// '*' has to be a binary operator but determineStarAmpUsage() will
|
|
|
|
// categorize it as an unary operator, so set the right type here.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (LookForDecls && CurrentToken->Next) {
|
2013-07-04 22:47:51 +08:00
|
|
|
FormatToken *Prev = CurrentToken->getPreviousNonComment();
|
2013-06-08 00:02:52 +08:00
|
|
|
if (Prev) {
|
2013-07-04 22:47:51 +08:00
|
|
|
FormatToken *PrevPrev = Prev->getPreviousNonComment();
|
2013-06-08 00:02:52 +08:00
|
|
|
FormatToken *Next = CurrentToken->Next;
|
|
|
|
if (PrevPrev && PrevPrev->is(tok::identifier) &&
|
|
|
|
Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
|
|
|
|
CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
|
|
|
|
Prev->Type = TT_BinaryOperator;
|
|
|
|
LookForDecls = false;
|
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-12 20:16:34 +08:00
|
|
|
if (CurrentToken->Previous->Type == TT_PointerOrReference &&
|
|
|
|
CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
|
|
|
|
tok::coloncolon))
|
|
|
|
MightBeFunctionType = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (CurrentToken->is(tok::r_paren)) {
|
2013-05-29 22:47:47 +08:00
|
|
|
if (MightBeFunctionType && CurrentToken->Next &&
|
2013-07-16 19:37:21 +08:00
|
|
|
(CurrentToken->Next->is(tok::l_paren) ||
|
|
|
|
(CurrentToken->Next->is(tok::l_square) &&
|
|
|
|
!Contexts.back().IsExpression)))
|
2013-05-28 16:33:00 +08:00
|
|
|
Left->Type = TT_FunctionTypeLParen;
|
2013-01-30 05:01:14 +08:00
|
|
|
Left->MatchingParen = CurrentToken;
|
|
|
|
CurrentToken->MatchingParen = Left;
|
|
|
|
|
2013-02-05 18:07:47 +08:00
|
|
|
if (StartsObjCMethodExpr) {
|
2013-02-06 18:05:46 +08:00
|
|
|
CurrentToken->Type = TT_ObjCMethodExpr;
|
|
|
|
if (Contexts.back().FirstObjCSelectorName != NULL) {
|
|
|
|
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
|
|
|
|
Contexts.back().LongestObjCSelectorName;
|
2013-02-05 18:07:47 +08:00
|
|
|
}
|
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-07-10 22:02:49 +08:00
|
|
|
if (!HasMultipleLines)
|
|
|
|
Left->PackingKind = PPK_Inconclusive;
|
|
|
|
else if (HasMultipleParametersOnALine)
|
|
|
|
Left->PackingKind = PPK_BinPacked;
|
|
|
|
else
|
|
|
|
Left->PackingKind = PPK_OnePerLine;
|
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
next();
|
|
|
|
return true;
|
|
|
|
}
|
2013-03-13 22:41:29 +08:00
|
|
|
if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-02-14 23:01:34 +08:00
|
|
|
updateParameterCount(Left, CurrentToken);
|
2013-07-10 22:02:49 +08:00
|
|
|
if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
|
|
|
|
!CurrentToken->Next->HasUnescapedNewline &&
|
|
|
|
!CurrentToken->Next->isTrailingComment())
|
|
|
|
HasMultipleParametersOnALine = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (!consumeToken())
|
|
|
|
return false;
|
2013-07-10 22:02:49 +08:00
|
|
|
if (CurrentToken && CurrentToken->HasUnescapedNewline)
|
|
|
|
HasMultipleLines = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseSquare() {
|
|
|
|
if (!CurrentToken)
|
|
|
|
return false;
|
|
|
|
|
2013-06-17 21:19:53 +08:00
|
|
|
// A '[' could be an index subscript (after an identifier or after
|
2013-02-10 10:08:05 +08:00
|
|
|
// ')' or ']'), it could be the start of an Objective-C method
|
|
|
|
// expression, or it could the the start of an Objective-C array literal.
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Left = CurrentToken->Previous;
|
2013-07-04 22:47:51 +08:00
|
|
|
FormatToken *Parent = Left->getPreviousNonComment();
|
2013-01-30 05:01:14 +08:00
|
|
|
bool StartsObjCMethodExpr =
|
2013-09-05 17:29:45 +08:00
|
|
|
Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&
|
2013-03-13 22:41:29 +08:00
|
|
|
(!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
|
|
|
|
tok::kw_return, tok::kw_throw) ||
|
2013-04-10 17:49:49 +08:00
|
|
|
Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
|
2013-03-13 22:41:29 +08:00
|
|
|
Parent->Type == TT_CastRParen ||
|
2013-05-29 22:47:47 +08:00
|
|
|
getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
|
2013-03-14 21:45:21 +08:00
|
|
|
ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
|
2013-03-13 15:49:51 +08:00
|
|
|
Contexts.back().IsExpression = true;
|
2013-10-27 01:00:22 +08:00
|
|
|
bool ColonFound = false;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-02-06 18:05:46 +08:00
|
|
|
if (StartsObjCMethodExpr) {
|
|
|
|
Contexts.back().ColonIsObjCMethodExpr = true;
|
|
|
|
Left->Type = TT_ObjCMethodExpr;
|
2013-10-22 23:30:28 +08:00
|
|
|
} else if (Parent && Parent->is(tok::at)) {
|
|
|
|
Left->Type = TT_ArrayInitializerLSquare;
|
|
|
|
} else if (Left->Type == TT_Unknown) {
|
|
|
|
Left->Type = TT_ArraySubscriptLSquare;
|
2013-02-06 18:05:46 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
|
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
if (CurrentToken->is(tok::r_square)) {
|
2013-09-05 18:04:31 +08:00
|
|
|
if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
|
|
|
|
Left->Type == TT_ObjCMethodExpr) {
|
2013-02-06 14:20:11 +08:00
|
|
|
// An ObjC method call is rarely followed by an open parenthesis.
|
2013-01-30 05:01:14 +08:00
|
|
|
// FIXME: Do we incorrectly label ":" with this?
|
|
|
|
StartsObjCMethodExpr = false;
|
|
|
|
Left->Type = TT_Unknown;
|
|
|
|
}
|
2013-02-04 15:21:18 +08:00
|
|
|
if (StartsObjCMethodExpr) {
|
2013-02-06 18:05:46 +08:00
|
|
|
CurrentToken->Type = TT_ObjCMethodExpr;
|
2013-02-06 14:20:11 +08:00
|
|
|
// determineStarAmpUsage() thinks that '*' '[' is allocating an
|
|
|
|
// array of pointers, but if '[' starts a selector then '*' is a
|
|
|
|
// binary operator.
|
2013-03-13 00:28:18 +08:00
|
|
|
if (Parent != NULL && Parent->Type == TT_PointerOrReference)
|
2013-02-07 00:54:35 +08:00
|
|
|
Parent->Type = TT_BinaryOperator;
|
2013-02-04 15:21:18 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
Left->MatchingParen = CurrentToken;
|
|
|
|
CurrentToken->MatchingParen = Left;
|
2013-02-06 18:05:46 +08:00
|
|
|
if (Contexts.back().FirstObjCSelectorName != NULL)
|
|
|
|
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
|
|
|
|
Contexts.back().LongestObjCSelectorName;
|
2013-01-30 05:01:14 +08:00
|
|
|
next();
|
|
|
|
return true;
|
|
|
|
}
|
2013-03-13 22:41:29 +08:00
|
|
|
if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-10-27 01:00:22 +08:00
|
|
|
if (CurrentToken->is(tok::colon))
|
|
|
|
ColonFound = true;
|
2013-10-22 23:30:28 +08:00
|
|
|
if (CurrentToken->is(tok::comma) &&
|
2013-10-24 18:31:50 +08:00
|
|
|
(Left->Type == TT_ArraySubscriptLSquare ||
|
2013-10-27 01:00:22 +08:00
|
|
|
(Left->Type == TT_ObjCMethodExpr && !ColonFound)))
|
2013-10-22 23:30:28 +08:00
|
|
|
Left->Type = TT_ArrayInitializerLSquare;
|
2013-02-14 23:01:34 +08:00
|
|
|
updateParameterCount(Left, CurrentToken);
|
2013-01-30 05:01:14 +08:00
|
|
|
if (!consumeToken())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseBrace() {
|
2013-05-06 16:27:33 +08:00
|
|
|
if (CurrentToken != NULL) {
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Left = CurrentToken->Previous;
|
2013-10-24 18:31:50 +08:00
|
|
|
ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
|
|
|
|
Contexts.back().ColonIsDictLiteral = true;
|
2013-05-26 13:39:26 +08:00
|
|
|
|
2013-05-06 16:27:33 +08:00
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
if (CurrentToken->is(tok::r_brace)) {
|
|
|
|
Left->MatchingParen = CurrentToken;
|
|
|
|
CurrentToken->MatchingParen = Left;
|
|
|
|
next();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
|
|
|
|
return false;
|
|
|
|
updateParameterCount(Left, CurrentToken);
|
2013-10-24 18:31:50 +08:00
|
|
|
if (CurrentToken->is(tok::colon))
|
|
|
|
Left->Type = TT_DictLiteral;
|
2013-05-06 16:27:33 +08:00
|
|
|
if (!consumeToken())
|
|
|
|
return false;
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
}
|
2013-05-06 16:27:33 +08:00
|
|
|
// No closing "}" found, this probably starts a definition.
|
|
|
|
Line.StartsDefinition = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
|
|
|
}
|
2013-02-20 20:56:39 +08:00
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
void updateParameterCount(FormatToken *Left, FormatToken *Current) {
|
2013-07-10 22:02:49 +08:00
|
|
|
if (Current->is(tok::comma)) {
|
2013-02-14 23:01:34 +08:00
|
|
|
++Left->ParameterCount;
|
clang-format: Add column layout formatting for braced lists
With this patch, braced lists (with more than 3 elements are formatted in a
column layout if possible). E.g.:
static const uint16_t CallerSavedRegs64Bit[] = {
X86::RAX, X86::RDX, X86::RCX, X86::RSI, X86::RDI,
X86::R8, X86::R9, X86::R10, X86::R11, 0
};
Required other changes:
- FormatTokens can now have a special role that contains extra data and can do
special formattings. A comma separated list is currently the only
implementation.
- Move penalty calculation entirely into ContinuationIndenter (there was a last
piece still in UnwrappedLineFormatter).
Review: http://llvm-reviews.chandlerc.com/D1457
llvm-svn: 189018
2013-08-22 23:00:41 +08:00
|
|
|
if (!Left->Role)
|
|
|
|
Left->Role.reset(new CommaSeparatedList(Style));
|
|
|
|
Left->Role->CommaFound(Current);
|
2013-07-10 22:02:49 +08:00
|
|
|
} else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {
|
2013-02-14 23:01:34 +08:00
|
|
|
Left->ParameterCount = 1;
|
2013-07-10 22:02:49 +08:00
|
|
|
}
|
2013-02-14 23:01:34 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
|
|
|
|
bool parseConditional() {
|
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
if (CurrentToken->is(tok::colon)) {
|
|
|
|
CurrentToken->Type = TT_ConditionalExpr;
|
|
|
|
next();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!consumeToken())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseTemplateDeclaration() {
|
|
|
|
if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
|
|
|
|
CurrentToken->Type = TT_TemplateOpener;
|
|
|
|
next();
|
|
|
|
if (!parseAngle())
|
|
|
|
return false;
|
2013-02-20 01:14:38 +08:00
|
|
|
if (CurrentToken != NULL)
|
2013-05-29 22:47:47 +08:00
|
|
|
CurrentToken->Previous->ClosesTemplateDeclaration = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool consumeToken() {
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Tok = CurrentToken;
|
2013-01-30 05:01:14 +08:00
|
|
|
next();
|
2013-05-29 22:47:47 +08:00
|
|
|
switch (Tok->Tok.getKind()) {
|
2013-01-30 05:01:14 +08:00
|
|
|
case tok::plus:
|
|
|
|
case tok::minus:
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok->Previous == NULL && Line.MustBeDeclaration)
|
2013-01-30 05:01:14 +08:00
|
|
|
Tok->Type = TT_ObjCMethodSpecifier;
|
|
|
|
break;
|
|
|
|
case tok::colon:
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok->Previous == NULL)
|
2013-03-18 20:50:26 +08:00
|
|
|
return false;
|
2013-01-30 05:01:14 +08:00
|
|
|
// Colons from ?: are handled in parseConditional().
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) {
|
2013-01-30 05:01:14 +08:00
|
|
|
Tok->Type = TT_CtorInitializerColon;
|
2013-10-24 18:31:50 +08:00
|
|
|
} else if (Contexts.back().ColonIsDictLiteral) {
|
|
|
|
Tok->Type = TT_DictLiteral;
|
2013-02-06 18:05:46 +08:00
|
|
|
} else if (Contexts.back().ColonIsObjCMethodExpr ||
|
2013-05-29 22:47:47 +08:00
|
|
|
Line.First->Type == TT_ObjCMethodSpecifier) {
|
2013-01-30 05:01:14 +08:00
|
|
|
Tok->Type = TT_ObjCMethodExpr;
|
2013-05-29 22:47:47 +08:00
|
|
|
Tok->Previous->Type = TT_ObjCSelectorName;
|
2013-09-10 17:38:25 +08:00
|
|
|
if (Tok->Previous->ColumnWidth >
|
2013-06-05 22:09:10 +08:00
|
|
|
Contexts.back().LongestObjCSelectorName) {
|
2013-10-10 21:36:20 +08:00
|
|
|
Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
|
2013-06-05 22:09:10 +08:00
|
|
|
}
|
2013-02-06 18:05:46 +08:00
|
|
|
if (Contexts.back().FirstObjCSelectorName == NULL)
|
2013-05-29 22:47:47 +08:00
|
|
|
Contexts.back().FirstObjCSelectorName = Tok->Previous;
|
2013-02-06 18:05:46 +08:00
|
|
|
} else if (Contexts.back().ColonIsForRangeExpr) {
|
2013-01-30 05:01:14 +08:00
|
|
|
Tok->Type = TT_RangeBasedForLoopColon;
|
2013-10-10 21:36:20 +08:00
|
|
|
} else if (CurrentToken != NULL &&
|
|
|
|
CurrentToken->is(tok::numeric_constant)) {
|
|
|
|
Tok->Type = TT_BitFieldColon;
|
2013-10-09 00:24:07 +08:00
|
|
|
} else if (Contexts.size() == 1 && Line.First->isNot(tok::kw_enum)) {
|
2013-02-14 16:42:54 +08:00
|
|
|
Tok->Type = TT_InheritanceColon;
|
2013-03-14 21:45:21 +08:00
|
|
|
} else if (Contexts.back().ContextKind == tok::l_paren) {
|
|
|
|
Tok->Type = TT_InlineASMColon;
|
2013-02-05 18:07:47 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
break;
|
|
|
|
case tok::kw_if:
|
|
|
|
case tok::kw_while:
|
|
|
|
if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
|
|
|
|
next();
|
2013-06-26 08:30:14 +08:00
|
|
|
if (!parseParens(/*LookForDecls=*/true))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case tok::kw_for:
|
2013-02-06 18:05:46 +08:00
|
|
|
Contexts.back().ColonIsForRangeExpr = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
next();
|
|
|
|
if (!parseParens())
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case tok::l_paren:
|
|
|
|
if (!parseParens())
|
|
|
|
return false;
|
2013-11-08 01:43:07 +08:00
|
|
|
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
|
|
|
|
!Contexts.back().IsExpression)
|
Allow breaking between a type and name in variable declarations.
This fixes llvm.org/PR14967 and is generall necessary to avoid
situations where the column limit is exceeded. The challenge is
restricting such lines splits, otherwise clang-format suddenly starts
breaking at bad places.
Before:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string,
SomeOtherTemplateParameter> &ReallyReallyLongParameterName,
const SomeType<string,
SomeOtherTemplateParameter> &AnotherLongParameterName) {}
After:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string, SomeOtherTemplateParameter> &
ReallyReallyLongParameterName,
const SomeType<string, SomeOtherTemplateParameter> &
AnotherLongParameterName) {}
llvm-svn: 175999
2013-02-25 02:54:32 +08:00
|
|
|
Line.MightBeFunctionDecl = true;
|
2013-01-30 05:01:14 +08:00
|
|
|
break;
|
|
|
|
case tok::l_square:
|
|
|
|
if (!parseSquare())
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case tok::l_brace:
|
|
|
|
if (!parseBrace())
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case tok::less:
|
2013-07-31 06:37:19 +08:00
|
|
|
if (Tok->Previous && !Tok->Previous->Tok.isLiteral() && parseAngle())
|
2013-01-30 05:01:14 +08:00
|
|
|
Tok->Type = TT_TemplateOpener;
|
|
|
|
else {
|
|
|
|
Tok->Type = TT_BinaryOperator;
|
|
|
|
CurrentToken = Tok;
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case tok::r_paren:
|
|
|
|
case tok::r_square:
|
|
|
|
return false;
|
|
|
|
case tok::r_brace:
|
|
|
|
// Lines can start with '}'.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok->Previous != NULL)
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case tok::greater:
|
|
|
|
Tok->Type = TT_BinaryOperator;
|
|
|
|
break;
|
|
|
|
case tok::kw_operator:
|
2013-09-02 17:20:39 +08:00
|
|
|
while (CurrentToken &&
|
|
|
|
!CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
|
2013-03-13 22:41:29 +08:00
|
|
|
if (CurrentToken->isOneOf(tok::star, tok::amp))
|
2013-02-11 16:01:18 +08:00
|
|
|
CurrentToken->Type = TT_PointerOrReference;
|
|
|
|
consumeToken();
|
2013-09-02 17:20:39 +08:00
|
|
|
if (CurrentToken && CurrentToken->Previous->Type == TT_BinaryOperator)
|
2013-08-28 15:27:35 +08:00
|
|
|
CurrentToken->Previous->Type = TT_OverloadedOperator;
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
2013-05-10 15:59:58 +08:00
|
|
|
if (CurrentToken) {
|
2013-02-11 16:01:18 +08:00
|
|
|
CurrentToken->Type = TT_OverloadedOperatorLParen;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (CurrentToken->Previous->Type == TT_BinaryOperator)
|
|
|
|
CurrentToken->Previous->Type = TT_OverloadedOperator;
|
2013-05-10 15:59:58 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
break;
|
|
|
|
case tok::question:
|
|
|
|
parseConditional();
|
|
|
|
break;
|
|
|
|
case tok::kw_template:
|
|
|
|
parseTemplateDeclaration();
|
|
|
|
break;
|
2013-02-11 23:32:15 +08:00
|
|
|
case tok::identifier:
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Line.First->is(tok::kw_for) &&
|
|
|
|
Tok->Tok.getIdentifierInfo() == &Ident_in)
|
2013-02-11 23:32:15 +08:00
|
|
|
Tok->Type = TT_ObjCForIn;
|
|
|
|
break;
|
2013-04-03 21:36:17 +08:00
|
|
|
case tok::comma:
|
|
|
|
if (Contexts.back().FirstStartOfName)
|
|
|
|
Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
|
2013-07-27 00:56:36 +08:00
|
|
|
if (Contexts.back().InCtorInitializer)
|
|
|
|
Tok->Type = TT_CtorInitializerComma;
|
2013-04-03 21:36:17 +08:00
|
|
|
break;
|
2013-01-30 05:01:14 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseIncludeDirective() {
|
|
|
|
next();
|
|
|
|
if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
|
|
|
|
next();
|
|
|
|
while (CurrentToken != NULL) {
|
2013-05-29 22:47:47 +08:00
|
|
|
if (CurrentToken->isNot(tok::comment) || CurrentToken->Next)
|
2013-01-30 05:01:14 +08:00
|
|
|
CurrentToken->Type = TT_ImplicitStringLiteral;
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (CurrentToken != NULL) {
|
2013-02-23 15:46:38 +08:00
|
|
|
if (CurrentToken->is(tok::string_literal))
|
|
|
|
// Mark these string literals as "implicit" literals, too, so that
|
|
|
|
// they are not split or line-wrapped.
|
|
|
|
CurrentToken->Type = TT_ImplicitStringLiteral;
|
2013-01-30 05:01:14 +08:00
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parseWarningOrError() {
|
|
|
|
next();
|
|
|
|
// We still want to format the whitespace left of the first token of the
|
|
|
|
// warning or error.
|
|
|
|
next();
|
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
CurrentToken->Type = TT_ImplicitStringLiteral;
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void parsePreprocessorDirective() {
|
|
|
|
next();
|
|
|
|
if (CurrentToken == NULL)
|
|
|
|
return;
|
2013-10-12 05:43:05 +08:00
|
|
|
if (CurrentToken->Tok.is(tok::numeric_constant)) {
|
|
|
|
CurrentToken->SpacesRequiredBefore = 1;
|
|
|
|
return;
|
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
// Hashes in the middle of a line can lead to any strange token
|
|
|
|
// sequence.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (CurrentToken->Tok.getIdentifierInfo() == NULL)
|
2013-01-30 05:01:14 +08:00
|
|
|
return;
|
2013-05-29 22:47:47 +08:00
|
|
|
switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
|
2013-01-30 05:01:14 +08:00
|
|
|
case tok::pp_include:
|
|
|
|
case tok::pp_import:
|
|
|
|
parseIncludeDirective();
|
|
|
|
break;
|
|
|
|
case tok::pp_error:
|
|
|
|
case tok::pp_warning:
|
|
|
|
parseWarningOrError();
|
|
|
|
break;
|
2013-04-23 21:54:04 +08:00
|
|
|
case tok::pp_if:
|
|
|
|
case tok::pp_elif:
|
|
|
|
parseLine();
|
|
|
|
break;
|
2013-01-30 05:01:14 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-02-05 17:34:14 +08:00
|
|
|
while (CurrentToken != NULL)
|
|
|
|
next();
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
Formatter: Correctly format stars in `sizeof(int**)` and similar places.
This redoes how '*' and '&' are classified as pointer / reference markers when
followed by ')', '>', or ','.
Previously, determineStarAmpUsage() marked a single '*' and '&' followed by
')', '>', or ',' as pointer or reference marker. Now, all '*'s and '&'s
preceding ')', '>', or ',' are marked as pointer / reference markers. Fixes
PR14884.
Since only the last '*' in 'int ***' was marked as pointer before (the rest
were unary operators, which don't reach spaceRequiredBetween()),
spaceRequiredBetween() now had to be thought about handing multiple '*'s in
sequence.
Before:
return sizeof(int * *);
Type **A = static_cast<Type * *>(P);
Now:
return sizeof(int**);
Type **A = static_cast<Type **>(P);
While here, also make all methods of AnnotatingParser except parseLine()
private.
Review URL: http://llvm-reviews.chandlerc.com/D384
llvm-svn: 174975
2013-02-13 00:17:07 +08:00
|
|
|
public:
|
2013-01-30 05:01:14 +08:00
|
|
|
LineType parseLine() {
|
|
|
|
if (CurrentToken->is(tok::hash)) {
|
|
|
|
parsePreprocessorDirective();
|
|
|
|
return LT_PreprocessorDirective;
|
|
|
|
}
|
|
|
|
while (CurrentToken != NULL) {
|
|
|
|
if (CurrentToken->is(tok::kw_virtual))
|
|
|
|
KeywordVirtualFound = true;
|
|
|
|
if (!consumeToken())
|
|
|
|
return LT_Invalid;
|
|
|
|
}
|
|
|
|
if (KeywordVirtualFound)
|
|
|
|
return LT_VirtualFunctionDecl;
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Line.First->Type == TT_ObjCMethodSpecifier) {
|
2013-02-06 18:05:46 +08:00
|
|
|
if (Contexts.back().FirstObjCSelectorName != NULL)
|
|
|
|
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
|
|
|
|
Contexts.back().LongestObjCSelectorName;
|
2013-02-05 18:07:47 +08:00
|
|
|
return LT_ObjCMethodDecl;
|
|
|
|
}
|
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
return LT_Other;
|
|
|
|
}
|
|
|
|
|
Formatter: Correctly format stars in `sizeof(int**)` and similar places.
This redoes how '*' and '&' are classified as pointer / reference markers when
followed by ')', '>', or ','.
Previously, determineStarAmpUsage() marked a single '*' and '&' followed by
')', '>', or ',' as pointer or reference marker. Now, all '*'s and '&'s
preceding ')', '>', or ',' are marked as pointer / reference markers. Fixes
PR14884.
Since only the last '*' in 'int ***' was marked as pointer before (the rest
were unary operators, which don't reach spaceRequiredBetween()),
spaceRequiredBetween() now had to be thought about handing multiple '*'s in
sequence.
Before:
return sizeof(int * *);
Type **A = static_cast<Type * *>(P);
Now:
return sizeof(int**);
Type **A = static_cast<Type **>(P);
While here, also make all methods of AnnotatingParser except parseLine()
private.
Review URL: http://llvm-reviews.chandlerc.com/D384
llvm-svn: 174975
2013-02-13 00:17:07 +08:00
|
|
|
private:
|
2013-01-30 05:01:14 +08:00
|
|
|
void next() {
|
2013-02-04 15:21:18 +08:00
|
|
|
if (CurrentToken != NULL) {
|
|
|
|
determineTokenType(*CurrentToken);
|
2013-02-06 18:05:46 +08:00
|
|
|
CurrentToken->BindingStrength = Contexts.back().BindingStrength;
|
clang-format: Be more conservative about braced list column layout.
Specifically disable it for nested braced lists as it commonly can look
really weird. Eventually, we'll want to become smarter and format some of
the nested lists better.
Before:
SomeStruct my_struct_array = {
{ aaaaaa, aaaaaaaa, aaaaaaaaaa, aaaaaaaaa, aaaaaaaaa,
aaaaaaaaaa, aaaaaaaaaa, aaaaaaa, aaa },
{ aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaa },
{ aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaa, a, aaaaaaaaaa,
aaaaaaaaa, aaa },
};
After:
SomeStruct my_struct_array = {
{ aaaaaa, aaaaaaaa, aaaaaaaaaa, aaaaaaaaa, aaaaaaaaa, aaaaaaaaaa,
aaaaaaaaaaaa, aaaaaaa, aaa },
{ aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaa },
{ aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaa, a, aaaaaaaaaa, aaaaaaaaa, aaa },
};
llvm-svn: 196783
2013-12-09 22:40:19 +08:00
|
|
|
CurrentToken->NestingLevel = Contexts.size() - 1;
|
2013-02-04 15:21:18 +08:00
|
|
|
}
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
if (CurrentToken != NULL)
|
|
|
|
CurrentToken = CurrentToken->Next;
|
2013-02-18 20:44:35 +08:00
|
|
|
|
2013-10-12 05:25:45 +08:00
|
|
|
if (CurrentToken != NULL) {
|
|
|
|
// Reset token type in case we have already looked at it and then
|
|
|
|
// recovered from an error (e.g. failure to find the matching >).
|
|
|
|
if (CurrentToken->Type != TT_LambdaLSquare &&
|
2013-11-21 00:33:05 +08:00
|
|
|
CurrentToken->Type != TT_FunctionLBrace &&
|
2013-10-12 05:25:45 +08:00
|
|
|
CurrentToken->Type != TT_ImplicitStringLiteral)
|
|
|
|
CurrentToken->Type = TT_Unknown;
|
|
|
|
if (CurrentToken->Role)
|
|
|
|
CurrentToken->Role.reset(NULL);
|
|
|
|
CurrentToken->FakeLParens.clear();
|
|
|
|
CurrentToken->FakeRParens = 0;
|
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
2013-02-06 18:05:46 +08:00
|
|
|
/// \brief A struct to hold information valid in a specific context, e.g.
|
|
|
|
/// a pair of parenthesis.
|
|
|
|
struct Context {
|
2013-03-14 21:45:21 +08:00
|
|
|
Context(tok::TokenKind ContextKind, unsigned BindingStrength,
|
|
|
|
bool IsExpression)
|
|
|
|
: ContextKind(ContextKind), BindingStrength(BindingStrength),
|
|
|
|
LongestObjCSelectorName(0), ColonIsForRangeExpr(false),
|
2013-10-24 18:31:50 +08:00
|
|
|
ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
|
2013-05-26 13:39:26 +08:00
|
|
|
FirstObjCSelectorName(NULL), FirstStartOfName(NULL),
|
2013-07-27 00:56:36 +08:00
|
|
|
IsExpression(IsExpression), CanBeExpression(true),
|
|
|
|
InCtorInitializer(false) {}
|
2013-03-14 21:45:21 +08:00
|
|
|
|
|
|
|
tok::TokenKind ContextKind;
|
2013-02-06 18:05:46 +08:00
|
|
|
unsigned BindingStrength;
|
|
|
|
unsigned LongestObjCSelectorName;
|
|
|
|
bool ColonIsForRangeExpr;
|
2013-10-24 18:31:50 +08:00
|
|
|
bool ColonIsDictLiteral;
|
2013-02-06 18:05:46 +08:00
|
|
|
bool ColonIsObjCMethodExpr;
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *FirstObjCSelectorName;
|
|
|
|
FormatToken *FirstStartOfName;
|
2013-02-06 18:05:46 +08:00
|
|
|
bool IsExpression;
|
2013-03-13 15:49:51 +08:00
|
|
|
bool CanBeExpression;
|
2013-07-27 00:56:36 +08:00
|
|
|
bool InCtorInitializer;
|
2013-02-06 18:05:46 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
|
|
|
|
/// of each instance.
|
|
|
|
struct ScopedContextCreator {
|
|
|
|
AnnotatingParser &P;
|
|
|
|
|
2013-03-14 21:45:21 +08:00
|
|
|
ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,
|
|
|
|
unsigned Increase)
|
|
|
|
: P(P) {
|
2013-07-08 22:34:09 +08:00
|
|
|
P.Contexts.push_back(Context(ContextKind,
|
|
|
|
P.Contexts.back().BindingStrength + Increase,
|
|
|
|
P.Contexts.back().IsExpression));
|
2013-02-06 18:05:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
~ScopedContextCreator() { P.Contexts.pop_back(); }
|
|
|
|
};
|
2013-02-04 15:21:18 +08:00
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
void determineTokenType(FormatToken &Current) {
|
|
|
|
if (Current.getPrecedence() == prec::Assignment &&
|
2013-08-12 20:16:34 +08:00
|
|
|
!Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
|
2013-05-29 22:47:47 +08:00
|
|
|
(!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
|
2013-02-06 18:05:46 +08:00
|
|
|
Contexts.back().IsExpression = true;
|
2013-05-29 22:47:47 +08:00
|
|
|
for (FormatToken *Previous = Current.Previous;
|
2013-09-12 04:37:10 +08:00
|
|
|
Previous && !Previous->isOneOf(tok::comma, tok::semi);
|
2013-05-29 22:47:47 +08:00
|
|
|
Previous = Previous->Previous) {
|
2013-02-27 19:43:50 +08:00
|
|
|
if (Previous->is(tok::r_square))
|
|
|
|
Previous = Previous->MatchingParen;
|
2013-02-04 15:21:18 +08:00
|
|
|
if (Previous->Type == TT_BinaryOperator &&
|
2013-03-13 22:41:29 +08:00
|
|
|
Previous->isOneOf(tok::star, tok::amp)) {
|
2013-02-04 15:21:18 +08:00
|
|
|
Previous->Type = TT_PointerOrReference;
|
|
|
|
}
|
|
|
|
}
|
2013-03-13 22:41:29 +08:00
|
|
|
} else if (Current.isOneOf(tok::kw_return, tok::kw_throw) ||
|
Formatter: Correctly format stars in `sizeof(int**)` and similar places.
This redoes how '*' and '&' are classified as pointer / reference markers when
followed by ')', '>', or ','.
Previously, determineStarAmpUsage() marked a single '*' and '&' followed by
')', '>', or ',' as pointer or reference marker. Now, all '*'s and '&'s
preceding ')', '>', or ',' are marked as pointer / reference markers. Fixes
PR14884.
Since only the last '*' in 'int ***' was marked as pointer before (the rest
were unary operators, which don't reach spaceRequiredBetween()),
spaceRequiredBetween() now had to be thought about handing multiple '*'s in
sequence.
Before:
return sizeof(int * *);
Type **A = static_cast<Type * *>(P);
Now:
return sizeof(int**);
Type **A = static_cast<Type **>(P);
While here, also make all methods of AnnotatingParser except parseLine()
private.
Review URL: http://llvm-reviews.chandlerc.com/D384
llvm-svn: 174975
2013-02-13 00:17:07 +08:00
|
|
|
(Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
|
2013-05-13 15:14:40 +08:00
|
|
|
!Line.InPPDirective &&
|
2013-08-12 11:51:17 +08:00
|
|
|
(!Current.Previous ||
|
2013-08-12 20:16:34 +08:00
|
|
|
!Current.Previous->isOneOf(tok::kw_for, tok::kw_catch)))) {
|
2013-02-06 18:05:46 +08:00
|
|
|
Contexts.back().IsExpression = true;
|
2013-03-13 22:41:29 +08:00
|
|
|
} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
|
2013-05-29 22:47:47 +08:00
|
|
|
for (FormatToken *Previous = Current.Previous;
|
2013-03-13 22:41:29 +08:00
|
|
|
Previous && Previous->isOneOf(tok::star, tok::amp);
|
2013-05-29 22:47:47 +08:00
|
|
|
Previous = Previous->Previous)
|
Formatter: Correctly format stars in `sizeof(int**)` and similar places.
This redoes how '*' and '&' are classified as pointer / reference markers when
followed by ')', '>', or ','.
Previously, determineStarAmpUsage() marked a single '*' and '&' followed by
')', '>', or ',' as pointer or reference marker. Now, all '*'s and '&'s
preceding ')', '>', or ',' are marked as pointer / reference markers. Fixes
PR14884.
Since only the last '*' in 'int ***' was marked as pointer before (the rest
were unary operators, which don't reach spaceRequiredBetween()),
spaceRequiredBetween() now had to be thought about handing multiple '*'s in
sequence.
Before:
return sizeof(int * *);
Type **A = static_cast<Type * *>(P);
Now:
return sizeof(int**);
Type **A = static_cast<Type **>(P);
While here, also make all methods of AnnotatingParser except parseLine()
private.
Review URL: http://llvm-reviews.chandlerc.com/D384
llvm-svn: 174975
2013-02-13 00:17:07 +08:00
|
|
|
Previous->Type = TT_PointerOrReference;
|
2013-05-29 22:47:47 +08:00
|
|
|
} else if (Current.Previous &&
|
|
|
|
Current.Previous->Type == TT_CtorInitializerColon) {
|
2013-02-18 20:44:35 +08:00
|
|
|
Contexts.back().IsExpression = true;
|
2013-07-27 00:56:36 +08:00
|
|
|
Contexts.back().InCtorInitializer = true;
|
2013-03-13 15:49:51 +08:00
|
|
|
} else if (Current.is(tok::kw_new)) {
|
|
|
|
Contexts.back().CanBeExpression = false;
|
2013-11-08 03:56:07 +08:00
|
|
|
} else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
|
2013-05-03 22:41:24 +08:00
|
|
|
// This should be the condition or increment in a for-loop.
|
|
|
|
Contexts.back().IsExpression = true;
|
Formatter: Correctly format stars in `sizeof(int**)` and similar places.
This redoes how '*' and '&' are classified as pointer / reference markers when
followed by ')', '>', or ','.
Previously, determineStarAmpUsage() marked a single '*' and '&' followed by
')', '>', or ',' as pointer or reference marker. Now, all '*'s and '&'s
preceding ')', '>', or ',' are marked as pointer / reference markers. Fixes
PR14884.
Since only the last '*' in 'int ***' was marked as pointer before (the rest
were unary operators, which don't reach spaceRequiredBetween()),
spaceRequiredBetween() now had to be thought about handing multiple '*'s in
sequence.
Before:
return sizeof(int * *);
Type **A = static_cast<Type * *>(P);
Now:
return sizeof(int**);
Type **A = static_cast<Type **>(P);
While here, also make all methods of AnnotatingParser except parseLine()
private.
Review URL: http://llvm-reviews.chandlerc.com/D384
llvm-svn: 174975
2013-02-13 00:17:07 +08:00
|
|
|
}
|
2013-02-04 15:21:18 +08:00
|
|
|
|
|
|
|
if (Current.Type == TT_Unknown) {
|
2013-09-27 16:29:16 +08:00
|
|
|
// Line.MightBeFunctionDecl can only be true after the parentheses of a
|
|
|
|
// function declaration have been found. In this case, 'Current' is a
|
|
|
|
// trailing token of this declaration and thus cannot be a name.
|
|
|
|
if (isStartOfName(Current) && !Line.MightBeFunctionDecl) {
|
2013-04-03 21:36:17 +08:00
|
|
|
Contexts.back().FirstStartOfName = &Current;
|
Allow breaking between a type and name in variable declarations.
This fixes llvm.org/PR14967 and is generall necessary to avoid
situations where the column limit is exceeded. The challenge is
restricting such lines splits, otherwise clang-format suddenly starts
breaking at bad places.
Before:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string,
SomeOtherTemplateParameter> &ReallyReallyLongParameterName,
const SomeType<string,
SomeOtherTemplateParameter> &AnotherLongParameterName) {}
After:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string, SomeOtherTemplateParameter> &
ReallyReallyLongParameterName,
const SomeType<string, SomeOtherTemplateParameter> &
AnotherLongParameterName) {}
llvm-svn: 175999
2013-02-25 02:54:32 +08:00
|
|
|
Current.Type = TT_StartOfName;
|
2013-07-09 22:36:48 +08:00
|
|
|
} else if (Current.is(tok::kw_auto)) {
|
|
|
|
AutoFound = true;
|
2013-07-11 22:33:06 +08:00
|
|
|
} else if (Current.is(tok::arrow) && AutoFound &&
|
|
|
|
Line.MustBeDeclaration) {
|
2013-07-09 22:36:48 +08:00
|
|
|
Current.Type = TT_TrailingReturnArrow;
|
2013-03-13 22:41:29 +08:00
|
|
|
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
|
2013-02-06 18:05:46 +08:00
|
|
|
Current.Type =
|
2013-07-05 21:30:40 +08:00
|
|
|
determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
|
|
|
|
Contexts.back().IsExpression);
|
2013-03-13 22:41:29 +08:00
|
|
|
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
|
2013-02-04 15:21:18 +08:00
|
|
|
Current.Type = determinePlusMinusCaretUsage(Current);
|
2013-03-13 22:41:29 +08:00
|
|
|
} else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
|
2013-02-04 15:21:18 +08:00
|
|
|
Current.Type = determineIncrementUsage(Current);
|
|
|
|
} else if (Current.is(tok::exclaim)) {
|
|
|
|
Current.Type = TT_UnaryOperator;
|
2013-09-04 16:20:47 +08:00
|
|
|
} else if (Current.isBinaryOperator() &&
|
|
|
|
(!Current.Previous ||
|
|
|
|
Current.Previous->isNot(tok::l_square))) {
|
2013-02-04 15:21:18 +08:00
|
|
|
Current.Type = TT_BinaryOperator;
|
|
|
|
} else if (Current.is(tok::comment)) {
|
2013-06-05 22:09:10 +08:00
|
|
|
if (Current.TokenText.startswith("//"))
|
2013-02-04 15:21:18 +08:00
|
|
|
Current.Type = TT_LineComment;
|
|
|
|
else
|
|
|
|
Current.Type = TT_BlockComment;
|
2013-02-13 12:13:13 +08:00
|
|
|
} else if (Current.is(tok::r_paren)) {
|
2013-06-01 00:14:28 +08:00
|
|
|
FormatToken *LeftOfParens = NULL;
|
|
|
|
if (Current.MatchingParen)
|
2013-07-04 22:47:51 +08:00
|
|
|
LeftOfParens = Current.MatchingParen->getPreviousNonComment();
|
2013-06-01 00:14:28 +08:00
|
|
|
bool IsCast = false;
|
|
|
|
bool ParensAreEmpty = Current.Previous == Current.MatchingParen;
|
|
|
|
bool ParensAreType = !Current.Previous ||
|
2013-05-29 22:47:47 +08:00
|
|
|
Current.Previous->Type == TT_PointerOrReference ||
|
2013-06-01 00:14:28 +08:00
|
|
|
Current.Previous->Type == TT_TemplateCloser ||
|
|
|
|
isSimpleTypeSpecifier(*Current.Previous);
|
2013-02-13 12:13:13 +08:00
|
|
|
bool ParensCouldEndDecl =
|
2013-05-29 22:47:47 +08:00
|
|
|
Current.Next &&
|
|
|
|
Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
|
2013-03-14 01:13:53 +08:00
|
|
|
bool IsSizeOfOrAlignOf =
|
2013-06-01 00:14:28 +08:00
|
|
|
LeftOfParens &&
|
|
|
|
LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
|
|
|
|
if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
|
2013-07-15 23:04:42 +08:00
|
|
|
(Contexts.back().IsExpression ||
|
|
|
|
(Current.Next && Current.Next->isBinaryOperator())))
|
2013-06-01 00:14:28 +08:00
|
|
|
IsCast = true;
|
2013-07-08 22:34:09 +08:00
|
|
|
if (Current.Next && Current.Next->isNot(tok::string_literal) &&
|
2013-06-01 00:14:28 +08:00
|
|
|
(Current.Next->Tok.isLiteral() ||
|
|
|
|
Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
|
|
|
|
IsCast = true;
|
|
|
|
// If there is an identifier after the (), it is likely a cast, unless
|
|
|
|
// there is also an identifier before the ().
|
2013-06-06 16:20:20 +08:00
|
|
|
if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
|
|
|
|
LeftOfParens->is(tok::kw_return)) &&
|
2013-07-08 22:58:01 +08:00
|
|
|
LeftOfParens->Type != TT_OverloadedOperator &&
|
2013-06-25 08:55:57 +08:00
|
|
|
LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
|
|
|
|
Current.Next->is(tok::identifier))
|
2013-06-01 00:14:28 +08:00
|
|
|
IsCast = true;
|
|
|
|
if (IsCast && !ParensAreEmpty)
|
2013-02-13 12:13:13 +08:00
|
|
|
Current.Type = TT_CastRParen;
|
2013-05-29 22:47:47 +08:00
|
|
|
} else if (Current.is(tok::at) && Current.Next) {
|
|
|
|
switch (Current.Next->Tok.getObjCKeywordID()) {
|
2013-02-04 15:21:18 +08:00
|
|
|
case tok::objc_interface:
|
|
|
|
case tok::objc_implementation:
|
|
|
|
case tok::objc_protocol:
|
|
|
|
Current.Type = TT_ObjCDecl;
|
|
|
|
break;
|
|
|
|
case tok::objc_property:
|
|
|
|
Current.Type = TT_ObjCProperty;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-05-28 19:30:49 +08:00
|
|
|
} else if (Current.is(tok::period)) {
|
2013-07-04 22:47:51 +08:00
|
|
|
FormatToken *PreviousNoComment = Current.getPreviousNonComment();
|
2013-05-28 19:30:49 +08:00
|
|
|
if (PreviousNoComment &&
|
|
|
|
PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
|
|
|
|
Current.Type = TT_DesignatedInitializerPeriod;
|
2013-02-04 15:21:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-02 17:47:29 +08:00
|
|
|
/// \brief Take a guess at whether \p Tok starts a name of a function or
|
|
|
|
/// variable declaration.
|
|
|
|
///
|
|
|
|
/// This is a heuristic based on whether \p Tok is an identifier following
|
|
|
|
/// something that is likely a type.
|
|
|
|
bool isStartOfName(const FormatToken &Tok) {
|
|
|
|
if (Tok.isNot(tok::identifier) || Tok.Previous == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Skip "const" as it does not have an influence on whether this is a name.
|
|
|
|
FormatToken *PreviousNotConst = Tok.Previous;
|
|
|
|
while (PreviousNotConst != NULL && PreviousNotConst->is(tok::kw_const))
|
|
|
|
PreviousNotConst = PreviousNotConst->Previous;
|
|
|
|
|
|
|
|
if (PreviousNotConst == NULL)
|
|
|
|
return false;
|
|
|
|
|
2013-07-08 22:34:09 +08:00
|
|
|
bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
|
|
|
|
PreviousNotConst->Previous &&
|
|
|
|
PreviousNotConst->Previous->is(tok::hash);
|
2013-07-02 17:47:29 +08:00
|
|
|
|
2013-08-19 18:16:18 +08:00
|
|
|
if (PreviousNotConst->Type == TT_TemplateCloser)
|
|
|
|
return PreviousNotConst && PreviousNotConst->MatchingParen &&
|
|
|
|
PreviousNotConst->MatchingParen->Previous &&
|
|
|
|
PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
|
|
|
|
|
2013-07-02 17:47:29 +08:00
|
|
|
return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
|
|
|
|
PreviousNotConst->Type == TT_PointerOrReference ||
|
|
|
|
isSimpleTypeSpecifier(*PreviousNotConst);
|
|
|
|
}
|
|
|
|
|
2013-02-04 15:21:18 +08:00
|
|
|
/// \brief Return the type of the given token assuming it is * or &.
|
2013-05-29 22:47:47 +08:00
|
|
|
TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) {
|
2013-07-04 22:47:51 +08:00
|
|
|
const FormatToken *PrevToken = Tok.getPreviousNonComment();
|
2013-02-04 15:21:18 +08:00
|
|
|
if (PrevToken == NULL)
|
|
|
|
return TT_UnaryOperator;
|
|
|
|
|
2013-07-04 22:47:51 +08:00
|
|
|
const FormatToken *NextToken = Tok.getNextNonComment();
|
2013-02-04 15:21:18 +08:00
|
|
|
if (NextToken == NULL)
|
|
|
|
return TT_Unknown;
|
|
|
|
|
2013-05-28 16:33:00 +08:00
|
|
|
if (PrevToken->is(tok::coloncolon) ||
|
|
|
|
(PrevToken->is(tok::l_paren) && !IsExpression))
|
2013-03-02 01:13:29 +08:00
|
|
|
return TT_PointerOrReference;
|
|
|
|
|
2013-03-13 22:41:29 +08:00
|
|
|
if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace,
|
2013-03-14 18:50:25 +08:00
|
|
|
tok::comma, tok::semi, tok::kw_return, tok::colon,
|
2013-09-22 01:31:51 +08:00
|
|
|
tok::equal, tok::kw_delete, tok::kw_sizeof) ||
|
2013-03-13 22:41:29 +08:00
|
|
|
PrevToken->Type == TT_BinaryOperator ||
|
2013-02-04 15:21:18 +08:00
|
|
|
PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
|
|
|
|
return TT_UnaryOperator;
|
|
|
|
|
2013-02-06 14:20:11 +08:00
|
|
|
if (NextToken->is(tok::l_square))
|
|
|
|
return TT_PointerOrReference;
|
|
|
|
|
2013-09-10 18:26:38 +08:00
|
|
|
if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
|
|
|
|
PrevToken->MatchingParen->Previous &&
|
|
|
|
PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
|
|
|
|
return TT_PointerOrReference;
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
if (PrevToken->Tok.isLiteral() ||
|
2013-03-13 22:41:29 +08:00
|
|
|
PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
|
2013-05-29 22:47:47 +08:00
|
|
|
NextToken->Tok.isLiteral() || NextToken->isUnaryOperator())
|
2013-02-04 15:21:18 +08:00
|
|
|
return TT_BinaryOperator;
|
|
|
|
|
|
|
|
// It is very unlikely that we are going to find a pointer or reference type
|
|
|
|
// definition on the RHS of an assignment.
|
|
|
|
if (IsExpression)
|
|
|
|
return TT_BinaryOperator;
|
|
|
|
|
|
|
|
return TT_PointerOrReference;
|
|
|
|
}
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
|
2013-07-04 22:47:51 +08:00
|
|
|
const FormatToken *PrevToken = Tok.getPreviousNonComment();
|
2013-06-01 00:14:28 +08:00
|
|
|
if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
|
2013-02-04 15:21:18 +08:00
|
|
|
return TT_UnaryOperator;
|
|
|
|
|
|
|
|
// Use heuristics to recognize unary operators.
|
2013-03-13 22:41:29 +08:00
|
|
|
if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square,
|
|
|
|
tok::question, tok::colon, tok::kw_return,
|
|
|
|
tok::kw_case, tok::at, tok::l_brace))
|
2013-02-04 15:21:18 +08:00
|
|
|
return TT_UnaryOperator;
|
|
|
|
|
2013-02-06 00:21:00 +08:00
|
|
|
// There can't be two consecutive binary operators.
|
2013-02-04 15:21:18 +08:00
|
|
|
if (PrevToken->Type == TT_BinaryOperator)
|
|
|
|
return TT_UnaryOperator;
|
|
|
|
|
|
|
|
// Fall back to marking the token as binary operator.
|
|
|
|
return TT_BinaryOperator;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
|
2013-05-29 22:47:47 +08:00
|
|
|
TokenType determineIncrementUsage(const FormatToken &Tok) {
|
2013-07-04 22:47:51 +08:00
|
|
|
const FormatToken *PrevToken = Tok.getPreviousNonComment();
|
2013-06-01 00:14:28 +08:00
|
|
|
if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
|
2013-02-04 15:21:18 +08:00
|
|
|
return TT_UnaryOperator;
|
2013-03-13 22:41:29 +08:00
|
|
|
if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
|
2013-02-04 15:21:18 +08:00
|
|
|
return TT_TrailingUnaryOperator;
|
|
|
|
|
|
|
|
return TT_UnaryOperator;
|
|
|
|
}
|
2013-02-06 18:05:46 +08:00
|
|
|
|
2013-04-03 21:36:17 +08:00
|
|
|
// FIXME: This is copy&pasted from Sema. Put it in a common place and remove
|
|
|
|
// duplication.
|
|
|
|
/// \brief Determine whether the token kind starts a simple-type-specifier.
|
2013-05-29 22:47:47 +08:00
|
|
|
bool isSimpleTypeSpecifier(const FormatToken &Tok) const {
|
|
|
|
switch (Tok.Tok.getKind()) {
|
2013-04-03 21:36:17 +08:00
|
|
|
case tok::kw_short:
|
|
|
|
case tok::kw_long:
|
|
|
|
case tok::kw___int64:
|
|
|
|
case tok::kw___int128:
|
|
|
|
case tok::kw_signed:
|
|
|
|
case tok::kw_unsigned:
|
|
|
|
case tok::kw_void:
|
|
|
|
case tok::kw_char:
|
|
|
|
case tok::kw_int:
|
|
|
|
case tok::kw_half:
|
|
|
|
case tok::kw_float:
|
|
|
|
case tok::kw_double:
|
|
|
|
case tok::kw_wchar_t:
|
|
|
|
case tok::kw_bool:
|
|
|
|
case tok::kw___underlying_type:
|
|
|
|
case tok::annot_typename:
|
|
|
|
case tok::kw_char16_t:
|
|
|
|
case tok::kw_char32_t:
|
|
|
|
case tok::kw_typeof:
|
|
|
|
case tok::kw_decltype:
|
2013-06-05 22:09:10 +08:00
|
|
|
return true;
|
2013-04-03 21:36:17 +08:00
|
|
|
default:
|
2013-06-05 22:09:10 +08:00
|
|
|
return false;
|
2013-04-03 21:36:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 18:05:46 +08:00
|
|
|
SmallVector<Context, 8> Contexts;
|
|
|
|
|
clang-format: Add column layout formatting for braced lists
With this patch, braced lists (with more than 3 elements are formatted in a
column layout if possible). E.g.:
static const uint16_t CallerSavedRegs64Bit[] = {
X86::RAX, X86::RDX, X86::RCX, X86::RSI, X86::RDI,
X86::R8, X86::R9, X86::R10, X86::R11, 0
};
Required other changes:
- FormatTokens can now have a special role that contains extra data and can do
special formattings. A comma separated list is currently the only
implementation.
- Move penalty calculation entirely into ContinuationIndenter (there was a last
piece still in UnwrappedLineFormatter).
Review: http://llvm-reviews.chandlerc.com/D1457
llvm-svn: 189018
2013-08-22 23:00:41 +08:00
|
|
|
const FormatStyle &Style;
|
2013-02-06 18:05:46 +08:00
|
|
|
AnnotatedLine &Line;
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *CurrentToken;
|
2013-02-06 18:05:46 +08:00
|
|
|
bool KeywordVirtualFound;
|
2013-07-09 22:36:48 +08:00
|
|
|
bool AutoFound;
|
2013-02-11 23:32:15 +08:00
|
|
|
IdentifierInfo &Ident_in;
|
2013-01-30 05:01:14 +08:00
|
|
|
};
|
|
|
|
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
static int PrecedenceUnaryOperator = prec::PointerToMember + 1;
|
|
|
|
static int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
|
|
|
|
|
2013-02-08 23:28:42 +08:00
|
|
|
/// \brief Parses binary expressions by inserting fake parenthesis based on
|
|
|
|
/// operator precedence.
|
|
|
|
class ExpressionParser {
|
|
|
|
public:
|
2013-06-06 17:11:58 +08:00
|
|
|
ExpressionParser(AnnotatedLine &Line) : Current(Line.First) {
|
|
|
|
// Skip leading "}", e.g. in "} else if (...) {".
|
|
|
|
if (Current->is(tok::r_brace))
|
|
|
|
next();
|
|
|
|
}
|
2013-02-08 23:28:42 +08:00
|
|
|
|
|
|
|
/// \brief Parse expressions with the given operatore precedence.
|
2013-02-24 05:01:55 +08:00
|
|
|
void parse(int Precedence = 0) {
|
clang-format: Improve ObjC variadic and binary expression parameters.
Before:
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa];
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];
After:
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa];
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];
This addresses llvm.org/PR15349 and llvm.org/PR16185.
llvm-svn: 194214
2013-11-08 03:23:49 +08:00
|
|
|
// Skip 'return' and ObjC selector colons as they are not part of a binary
|
|
|
|
// expression.
|
|
|
|
while (Current &&
|
|
|
|
(Current->is(tok::kw_return) ||
|
|
|
|
(Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr)))
|
2013-09-30 16:29:03 +08:00
|
|
|
next();
|
|
|
|
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
if (Current == NULL || Precedence > PrecedenceArrowAndPeriod)
|
2013-08-23 23:14:03 +08:00
|
|
|
return;
|
|
|
|
|
2013-05-31 22:56:12 +08:00
|
|
|
// Conditional expressions need to be parsed separately for proper nesting.
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
if (Precedence == prec::Conditional) {
|
2013-05-31 22:56:12 +08:00
|
|
|
parseConditionalExpr();
|
|
|
|
return;
|
|
|
|
}
|
2013-08-23 23:14:03 +08:00
|
|
|
|
|
|
|
// Parse unary operators, which all have a higher precedence than binary
|
|
|
|
// operators.
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
if (Precedence == PrecedenceUnaryOperator) {
|
2013-08-23 23:14:03 +08:00
|
|
|
parseUnaryOperator();
|
2013-02-08 23:28:42 +08:00
|
|
|
return;
|
2013-08-23 23:14:03 +08:00
|
|
|
}
|
2013-02-08 23:28:42 +08:00
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Start = Current;
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
FormatToken *LatestOperator = NULL;
|
2013-02-08 23:28:42 +08:00
|
|
|
|
2013-02-24 05:01:55 +08:00
|
|
|
while (Current) {
|
2013-02-08 23:28:42 +08:00
|
|
|
// Consume operators with higher precedence.
|
2013-04-09 04:33:42 +08:00
|
|
|
parse(Precedence + 1);
|
2013-02-08 23:28:42 +08:00
|
|
|
|
2013-08-23 23:14:03 +08:00
|
|
|
int CurrentPrecedence = getCurrentPrecedence();
|
|
|
|
|
|
|
|
if (Current && Current->Type == TT_ObjCSelectorName &&
|
|
|
|
Precedence == CurrentPrecedence)
|
|
|
|
Start = Current;
|
2013-02-24 05:01:55 +08:00
|
|
|
|
2013-02-08 23:28:42 +08:00
|
|
|
// At the end of the line or when an operator with higher precedence is
|
|
|
|
// found, insert fake parenthesis and return.
|
2013-04-10 17:49:49 +08:00
|
|
|
if (Current == NULL || Current->closesScope() ||
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
(CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) {
|
|
|
|
if (LatestOperator) {
|
|
|
|
if (Precedence == PrecedenceArrowAndPeriod) {
|
|
|
|
LatestOperator->LastInChainOfCalls = true;
|
|
|
|
// Call expressions don't have a binary operator precedence.
|
|
|
|
addFakeParenthesis(Start, prec::Unknown);
|
|
|
|
} else {
|
|
|
|
addFakeParenthesis(Start, prec::Level(Precedence));
|
|
|
|
}
|
|
|
|
}
|
2013-02-08 23:28:42 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Consume scopes: (), [], <> and {}
|
2013-04-10 17:49:49 +08:00
|
|
|
if (Current->opensScope()) {
|
|
|
|
while (Current && !Current->closesScope()) {
|
2013-02-08 23:28:42 +08:00
|
|
|
next();
|
|
|
|
parse();
|
|
|
|
}
|
|
|
|
next();
|
|
|
|
} else {
|
|
|
|
// Operator found.
|
2013-02-24 05:01:55 +08:00
|
|
|
if (CurrentPrecedence == Precedence)
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
LatestOperator = Current;
|
2013-02-08 23:28:42 +08:00
|
|
|
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2013-08-23 23:14:03 +08:00
|
|
|
/// \brief Gets the precedence (+1) of the given token for binary operators
|
|
|
|
/// and other tokens that we treat like binary operators.
|
|
|
|
int getCurrentPrecedence() {
|
|
|
|
if (Current) {
|
|
|
|
if (Current->Type == TT_ConditionalExpr)
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
return prec::Conditional;
|
clang-format: Improve ObjC variadic and binary expression parameters.
Before:
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa];
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];
After:
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |
aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa];
[self aaaaaaaaaaaaaaa:aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];
This addresses llvm.org/PR15349 and llvm.org/PR16185.
llvm-svn: 194214
2013-11-08 03:23:49 +08:00
|
|
|
else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon ||
|
|
|
|
Current->Type == TT_ObjCSelectorName)
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
return 0;
|
2013-08-23 23:14:03 +08:00
|
|
|
else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
return Current->getPrecedence();
|
|
|
|
else if (Current->isOneOf(tok::period, tok::arrow))
|
|
|
|
return PrecedenceArrowAndPeriod;
|
2013-08-23 23:14:03 +08:00
|
|
|
}
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
return -1;
|
2013-08-23 23:14:03 +08:00
|
|
|
}
|
|
|
|
|
2013-05-31 22:56:12 +08:00
|
|
|
void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) {
|
|
|
|
Start->FakeLParens.push_back(Precedence);
|
2013-09-06 16:08:14 +08:00
|
|
|
if (Precedence > prec::Unknown)
|
|
|
|
Start->StartsBinaryExpression = true;
|
|
|
|
if (Current) {
|
2013-05-31 22:56:12 +08:00
|
|
|
++Current->Previous->FakeRParens;
|
2013-09-06 16:08:14 +08:00
|
|
|
if (Precedence > prec::Unknown)
|
|
|
|
Current->Previous->EndsBinaryExpression = true;
|
|
|
|
}
|
2013-05-31 22:56:12 +08:00
|
|
|
}
|
|
|
|
|
2013-08-23 23:14:03 +08:00
|
|
|
/// \brief Parse unary operator expressions and surround them with fake
|
|
|
|
/// parentheses if appropriate.
|
|
|
|
void parseUnaryOperator() {
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
if (Current == NULL || Current->Type != TT_UnaryOperator) {
|
|
|
|
parse(PrecedenceArrowAndPeriod);
|
2013-08-23 23:14:03 +08:00
|
|
|
return;
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
}
|
2013-08-23 23:14:03 +08:00
|
|
|
|
|
|
|
FormatToken *Start = Current;
|
|
|
|
next();
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
parseUnaryOperator();
|
2013-08-23 23:14:03 +08:00
|
|
|
|
|
|
|
// The actual precedence doesn't matter.
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
addFakeParenthesis(Start, prec::Unknown);
|
2013-08-23 23:14:03 +08:00
|
|
|
}
|
|
|
|
|
2013-05-31 22:56:12 +08:00
|
|
|
void parseConditionalExpr() {
|
|
|
|
FormatToken *Start = Current;
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
parse(prec::LogicalOr);
|
2013-05-31 22:56:12 +08:00
|
|
|
if (!Current || !Current->is(tok::question))
|
|
|
|
return;
|
|
|
|
next();
|
clang-format: Revamp builder-type call formatting.
Previously builder-type calls were only correctly recognized in
top-level calls.
This fixes llvm.org/PR16981.
Before:
someobj->Add((new util::filetools::Handler(dir))->OnEvent1(
NewPermanentCallback(this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
After:
someobj->Add((new util::filetools::Handler(dir))
->OnEvent1(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBA))
->OnEvent2(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBB))
->OnEvent3(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBC))
->OnEvent5(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBD))
->OnEvent6(NewPermanentCallback(
this, &HandlerHolderClass::EventHandlerCBE)));
llvm-svn: 189337
2013-08-27 19:09:05 +08:00
|
|
|
parse(prec::LogicalOr);
|
2013-05-31 22:56:12 +08:00
|
|
|
if (!Current || Current->Type != TT_ConditionalExpr)
|
|
|
|
return;
|
|
|
|
next();
|
|
|
|
parseConditionalExpr();
|
|
|
|
addFakeParenthesis(Start, prec::Conditional);
|
|
|
|
}
|
|
|
|
|
2013-02-08 23:28:42 +08:00
|
|
|
void next() {
|
2013-06-17 21:19:53 +08:00
|
|
|
if (Current)
|
|
|
|
Current = Current->Next;
|
|
|
|
while (Current && Current->isTrailingComment())
|
2013-05-29 22:47:47 +08:00
|
|
|
Current = Current->Next;
|
2013-02-08 23:28:42 +08:00
|
|
|
}
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Current;
|
2013-02-08 23:28:42 +08:00
|
|
|
};
|
|
|
|
|
2013-07-01 12:03:19 +08:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2013-09-06 15:54:20 +08:00
|
|
|
void
|
|
|
|
TokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {
|
|
|
|
const AnnotatedLine *NextNonCommentLine = NULL;
|
2013-11-06 03:10:03 +08:00
|
|
|
for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
|
|
|
|
E = Lines.rend();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (NextNonCommentLine && (*I)->First->is(tok::comment) &&
|
|
|
|
(*I)->First->Next == NULL)
|
|
|
|
(*I)->Level = NextNonCommentLine->Level;
|
2013-09-06 15:54:20 +08:00
|
|
|
else
|
2013-11-06 03:10:03 +08:00
|
|
|
NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL;
|
|
|
|
|
|
|
|
setCommentLineLevels((*I)->Children);
|
2013-09-06 15:54:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
void TokenAnnotator::annotate(AnnotatedLine &Line) {
|
2013-09-06 15:54:20 +08:00
|
|
|
for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
|
|
|
|
E = Line.Children.end();
|
2013-09-05 17:29:45 +08:00
|
|
|
I != E; ++I) {
|
|
|
|
annotate(**I);
|
|
|
|
}
|
clang-format: Add column layout formatting for braced lists
With this patch, braced lists (with more than 3 elements are formatted in a
column layout if possible). E.g.:
static const uint16_t CallerSavedRegs64Bit[] = {
X86::RAX, X86::RDX, X86::RCX, X86::RSI, X86::RDI,
X86::R8, X86::R9, X86::R10, X86::R11, 0
};
Required other changes:
- FormatTokens can now have a special role that contains extra data and can do
special formattings. A comma separated list is currently the only
implementation.
- Move penalty calculation entirely into ContinuationIndenter (there was a last
piece still in UnwrappedLineFormatter).
Review: http://llvm-reviews.chandlerc.com/D1457
llvm-svn: 189018
2013-08-22 23:00:41 +08:00
|
|
|
AnnotatingParser Parser(Style, Line, Ident_in);
|
2013-01-30 05:01:14 +08:00
|
|
|
Line.Type = Parser.parseLine();
|
|
|
|
if (Line.Type == LT_Invalid)
|
|
|
|
return;
|
|
|
|
|
2013-02-08 23:28:42 +08:00
|
|
|
ExpressionParser ExprParser(Line);
|
|
|
|
ExprParser.parse();
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Line.First->Type == TT_ObjCMethodSpecifier)
|
2013-01-30 05:01:14 +08:00
|
|
|
Line.Type = LT_ObjCMethodDecl;
|
2013-05-29 22:47:47 +08:00
|
|
|
else if (Line.First->Type == TT_ObjCDecl)
|
2013-01-30 05:01:14 +08:00
|
|
|
Line.Type = LT_ObjCDecl;
|
2013-05-29 22:47:47 +08:00
|
|
|
else if (Line.First->Type == TT_ObjCProperty)
|
2013-01-30 05:01:14 +08:00
|
|
|
Line.Type = LT_ObjCProperty;
|
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
Line.First->SpacesRequiredBefore = 1;
|
|
|
|
Line.First->CanBreakBefore = Line.First->MustBreakBefore;
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
|
2013-09-10 17:38:25 +08:00
|
|
|
Line.First->TotalLength =
|
|
|
|
Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (!Line.First->Next)
|
2013-02-06 22:22:40 +08:00
|
|
|
return;
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Current = Line.First->Next;
|
2013-11-08 01:52:51 +08:00
|
|
|
bool InFunctionDecl = Line.MightBeFunctionDecl;
|
2013-02-06 22:22:40 +08:00
|
|
|
while (Current != NULL) {
|
2013-02-11 20:36:37 +08:00
|
|
|
if (Current->Type == TT_LineComment)
|
|
|
|
Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
|
2013-10-12 05:43:05 +08:00
|
|
|
else if (Current->SpacesRequiredBefore == 0 &&
|
|
|
|
spaceRequiredBefore(Line, *Current))
|
|
|
|
Current->SpacesRequiredBefore = 1;
|
2013-02-06 22:22:40 +08:00
|
|
|
|
2013-09-17 17:52:48 +08:00
|
|
|
Current->MustBreakBefore =
|
|
|
|
Current->MustBreakBefore || mustBreakBefore(Line, *Current);
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
Current->CanBreakBefore =
|
|
|
|
Current->MustBreakBefore || canBreakBefore(Line, *Current);
|
2013-09-05 17:29:45 +08:00
|
|
|
if (Current->MustBreakBefore || !Current->Children.empty() ||
|
2013-09-10 17:38:25 +08:00
|
|
|
Current->IsMultiline)
|
2013-05-29 22:47:47 +08:00
|
|
|
Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
|
2013-02-06 22:22:40 +08:00
|
|
|
else
|
2013-07-08 22:34:09 +08:00
|
|
|
Current->TotalLength = Current->Previous->TotalLength +
|
2013-09-10 17:38:25 +08:00
|
|
|
Current->ColumnWidth +
|
2013-07-08 22:34:09 +08:00
|
|
|
Current->SpacesRequiredBefore;
|
2013-11-08 01:52:51 +08:00
|
|
|
|
|
|
|
if (Current->Type == TT_CtorInitializerColon)
|
|
|
|
InFunctionDecl = false;
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
// FIXME: Only calculate this if CanBreakBefore is true once static
|
|
|
|
// initializers etc. are sorted out.
|
|
|
|
// FIXME: Move magic numbers to a better place.
|
2013-11-08 01:52:51 +08:00
|
|
|
Current->SplitPenalty = 20 * Current->BindingStrength +
|
|
|
|
splitPenalty(Line, *Current, InFunctionDecl);
|
2013-02-06 22:22:40 +08:00
|
|
|
|
2013-05-29 22:47:47 +08:00
|
|
|
Current = Current->Next;
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
2013-04-09 04:33:42 +08:00
|
|
|
|
2013-05-22 20:51:29 +08:00
|
|
|
calculateUnbreakableTailLengths(Line);
|
clang-format: Add column layout formatting for braced lists
With this patch, braced lists (with more than 3 elements are formatted in a
column layout if possible). E.g.:
static const uint16_t CallerSavedRegs64Bit[] = {
X86::RAX, X86::RDX, X86::RCX, X86::RSI, X86::RDI,
X86::R8, X86::R9, X86::R10, X86::R11, 0
};
Required other changes:
- FormatTokens can now have a special role that contains extra data and can do
special formattings. A comma separated list is currently the only
implementation.
- Move penalty calculation entirely into ContinuationIndenter (there was a last
piece still in UnwrappedLineFormatter).
Review: http://llvm-reviews.chandlerc.com/D1457
llvm-svn: 189018
2013-08-22 23:00:41 +08:00
|
|
|
for (Current = Line.First; Current != NULL; Current = Current->Next) {
|
|
|
|
if (Current->Role)
|
|
|
|
Current->Role->precomputeFormattingInfos(Current);
|
|
|
|
}
|
|
|
|
|
2013-09-05 17:29:45 +08:00
|
|
|
DEBUG({ printDebugInfo(Line); });
|
|
|
|
|
2013-09-06 15:54:20 +08:00
|
|
|
for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
|
|
|
|
E = Line.Children.end();
|
2013-09-05 17:29:45 +08:00
|
|
|
I != E; ++I) {
|
|
|
|
calculateFormattingInformation(**I);
|
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
2013-05-22 20:51:29 +08:00
|
|
|
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
|
|
|
|
unsigned UnbreakableTailLength = 0;
|
2013-05-29 22:47:47 +08:00
|
|
|
FormatToken *Current = Line.Last;
|
2013-05-22 20:51:29 +08:00
|
|
|
while (Current != NULL) {
|
|
|
|
Current->UnbreakableTailLength = UnbreakableTailLength;
|
|
|
|
if (Current->CanBreakBefore ||
|
|
|
|
Current->isOneOf(tok::comment, tok::string_literal)) {
|
|
|
|
UnbreakableTailLength = 0;
|
|
|
|
} else {
|
|
|
|
UnbreakableTailLength +=
|
2013-09-10 17:38:25 +08:00
|
|
|
Current->ColumnWidth + Current->SpacesRequiredBefore;
|
2013-05-22 20:51:29 +08:00
|
|
|
}
|
2013-05-29 22:47:47 +08:00
|
|
|
Current = Current->Previous;
|
2013-05-22 20:51:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
|
2013-11-08 01:52:51 +08:00
|
|
|
const FormatToken &Tok,
|
|
|
|
bool InFunctionDecl) {
|
2013-05-29 22:47:47 +08:00
|
|
|
const FormatToken &Left = *Tok.Previous;
|
|
|
|
const FormatToken &Right = Tok;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-05-28 19:30:49 +08:00
|
|
|
if (Left.is(tok::semi))
|
|
|
|
return 0;
|
|
|
|
if (Left.is(tok::comma))
|
|
|
|
return 1;
|
2013-07-12 19:19:37 +08:00
|
|
|
if (Right.is(tok::l_square))
|
2013-12-06 23:19:50 +08:00
|
|
|
return 250;
|
2013-05-28 19:30:49 +08:00
|
|
|
|
2013-07-09 15:43:55 +08:00
|
|
|
if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) {
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
|
Allow breaking between a type and name in variable declarations.
This fixes llvm.org/PR14967 and is generall necessary to avoid
situations where the column limit is exceeded. The challenge is
restricting such lines splits, otherwise clang-format suddenly starts
breaking at bad places.
Before:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string,
SomeOtherTemplateParameter> &ReallyReallyLongParameterName,
const SomeType<string,
SomeOtherTemplateParameter> &AnotherLongParameterName) {}
After:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string, SomeOtherTemplateParameter> &
ReallyReallyLongParameterName,
const SomeType<string, SomeOtherTemplateParameter> &
AnotherLongParameterName) {}
llvm-svn: 175999
2013-02-25 02:54:32 +08:00
|
|
|
return 3;
|
2013-07-11 20:34:23 +08:00
|
|
|
if (Left.Type == TT_StartOfName)
|
|
|
|
return 20;
|
clang-format: Be more conservative about braced list column layout.
Specifically disable it for nested braced lists as it commonly can look
really weird. Eventually, we'll want to become smarter and format some of
the nested lists better.
Before:
SomeStruct my_struct_array = {
{ aaaaaa, aaaaaaaa, aaaaaaaaaa, aaaaaaaaa, aaaaaaaaa,
aaaaaaaaaa, aaaaaaaaaa, aaaaaaa, aaa },
{ aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaa },
{ aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaa, a, aaaaaaaaaa,
aaaaaaaaa, aaa },
};
After:
SomeStruct my_struct_array = {
{ aaaaaa, aaaaaaaa, aaaaaaaaaa, aaaaaaaaa, aaaaaaaaa, aaaaaaaaaa,
aaaaaaaaaaaa, aaaaaaa, aaa },
{ aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaa },
{ aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaa, a, aaaaaaaaaa, aaaaaaaaa, aaa },
};
llvm-svn: 196783
2013-12-09 22:40:19 +08:00
|
|
|
if (InFunctionDecl && Right.NestingLevel == 0)
|
Allow breaking between a type and name in variable declarations.
This fixes llvm.org/PR14967 and is generall necessary to avoid
situations where the column limit is exceeded. The challenge is
restricting such lines splits, otherwise clang-format suddenly starts
breaking at bad places.
Before:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string,
SomeOtherTemplateParameter> &ReallyReallyLongParameterName,
const SomeType<string,
SomeOtherTemplateParameter> &AnotherLongParameterName) {}
After:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string, SomeOtherTemplateParameter> &
ReallyReallyLongParameterName,
const SomeType<string, SomeOtherTemplateParameter> &
AnotherLongParameterName) {}
llvm-svn: 175999
2013-02-25 02:54:32 +08:00
|
|
|
return Style.PenaltyReturnTypeOnItsOwnLine;
|
2013-08-19 18:16:18 +08:00
|
|
|
return 200;
|
Allow breaking between a type and name in variable declarations.
This fixes llvm.org/PR14967 and is generall necessary to avoid
situations where the column limit is exceeded. The challenge is
restricting such lines splits, otherwise clang-format suddenly starts
breaking at bad places.
Before:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string,
SomeOtherTemplateParameter> &ReallyReallyLongParameterName,
const SomeType<string,
SomeOtherTemplateParameter> &AnotherLongParameterName) {}
After:
ReallyLongReturnType<TemplateParam1, TemplateParam2>
ReallyReallyLongFunctionName(
const std::string &SomeParameter,
const SomeType<string, SomeOtherTemplateParameter> &
ReallyReallyLongParameterName,
const SomeType<string, SomeOtherTemplateParameter> &
AnotherLongParameterName) {}
llvm-svn: 175999
2013-02-25 02:54:32 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Left.is(tok::equal) && Right.is(tok::l_brace))
|
|
|
|
return 150;
|
2013-07-05 15:58:34 +08:00
|
|
|
if (Left.Type == TT_CastRParen)
|
|
|
|
return 100;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Left.is(tok::coloncolon))
|
|
|
|
return 500;
|
2013-04-06 01:22:09 +08:00
|
|
|
if (Left.isOneOf(tok::kw_class, tok::kw_struct))
|
|
|
|
return 5000;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-02-14 16:42:54 +08:00
|
|
|
if (Left.Type == TT_RangeBasedForLoopColon ||
|
|
|
|
Left.Type == TT_InheritanceColon)
|
2013-02-26 21:18:08 +08:00
|
|
|
return 2;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
clang-format: Format segments of builder-type calls one per line.
This fixes llvm.org/PR14818.
Before:
return llvm::StringSwitch<Reference::Kind>(name)
.StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
.StartsWith(".eh_frame", ORDER_EH_FRAME)
.StartsWith(".init", ORDER_INIT).StartsWith(".fini", ORDER_FINI)
.StartsWith(".hash", ORDER_HASH).Default(ORDER_TEXT);
After:
return llvm::StringSwitch<Reference::Kind>(name)
.StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
.StartsWith(".eh_frame", ORDER_EH_FRAME)
.StartsWith(".init", ORDER_INIT)
.StartsWith(".fini", ORDER_FINI)
.StartsWith(".hash", ORDER_HASH)
.Default(ORDER_TEXT);
llvm-svn: 189353
2013-08-27 22:24:43 +08:00
|
|
|
if (Right.isMemberAccess()) {
|
2013-09-06 16:54:24 +08:00
|
|
|
if (Left.isOneOf(tok::r_paren, tok::r_square) && Left.MatchingParen &&
|
|
|
|
Left.MatchingParen->ParameterCount > 0)
|
2013-02-26 21:59:14 +08:00
|
|
|
return 20; // Should be smaller than breaking at a nested comma.
|
2013-01-30 05:01:14 +08:00
|
|
|
return 150;
|
|
|
|
}
|
|
|
|
|
2013-07-12 05:02:56 +08:00
|
|
|
// Breaking before a trailing 'const' or not-function-like annotation is bad.
|
2013-08-01 21:46:58 +08:00
|
|
|
if (Left.is(tok::r_paren) && Line.Type != LT_ObjCProperty &&
|
2013-07-12 05:02:56 +08:00
|
|
|
(Right.is(tok::kw_const) || (Right.is(tok::identifier) && Right.Next &&
|
|
|
|
Right.Next->isNot(tok::l_paren))))
|
2013-10-19 00:34:40 +08:00
|
|
|
return 100;
|
2013-05-22 16:28:26 +08:00
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
// In for-loops, prefer breaking at ',' and ';'.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Line.First->is(tok::kw_for) && Left.is(tok::equal))
|
Allow breaking between type and name in for loops.
This fixes llvm.org/PR15033.
Also: Always break before a parameter, if the previous parameter was
split over multiple lines. This was necessary to make the right
decisions in for-loops, almost always makes the code more readable and
also fixes llvm.org/PR14873.
Before:
for (llvm::ArrayRef<NamedDecl *>::iterator I = FD->getDeclsInPrototypeScope()
.begin(), E = FD->getDeclsInPrototypeScope().end();
I != E; ++I) {
}
foo(bar(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
ccccccccccccccccccccccccccccc), d, bar(e, f));
After:
for (llvm::ArrayRef<NamedDecl *>::iterator
I = FD->getDeclsInPrototypeScope().begin(),
E = FD->getDeclsInPrototypeScope().end();
I != E; ++I) {
}
foo(bar(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
ccccccccccccccccccccccccccccc),
d, bar(e, f));
llvm-svn: 175741
2013-02-21 23:00:29 +08:00
|
|
|
return 4;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
|
|
|
// In Objective-C method expressions, prefer breaking before "param:" over
|
|
|
|
// breaking after it.
|
2013-02-05 18:07:47 +08:00
|
|
|
if (Right.Type == TT_ObjCSelectorName)
|
2013-01-30 05:01:14 +08:00
|
|
|
return 0;
|
2013-02-05 18:07:47 +08:00
|
|
|
if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
|
2013-11-23 22:27:27 +08:00
|
|
|
return Line.MightBeFunctionDecl ? 50 : 500;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-11-08 01:52:51 +08:00
|
|
|
if (Left.is(tok::l_paren) && InFunctionDecl)
|
2013-04-11 22:29:13 +08:00
|
|
|
return 100;
|
2013-04-10 17:49:49 +08:00
|
|
|
if (Left.opensScope())
|
2013-10-25 22:29:37 +08:00
|
|
|
return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
|
|
|
|
: 19;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-02-07 05:04:05 +08:00
|
|
|
if (Right.is(tok::lessless)) {
|
|
|
|
if (Left.is(tok::string_literal)) {
|
2013-06-05 22:09:10 +08:00
|
|
|
StringRef Content = Left.TokenText;
|
2013-09-29 20:02:57 +08:00
|
|
|
if (Content.startswith("\""))
|
|
|
|
Content = Content.drop_front(1);
|
|
|
|
if (Content.endswith("\""))
|
|
|
|
Content = Content.drop_back(1);
|
|
|
|
Content = Content.trim();
|
2013-03-14 22:00:17 +08:00
|
|
|
if (Content.size() > 1 &&
|
|
|
|
(Content.back() == ':' || Content.back() == '='))
|
2013-07-15 22:33:14 +08:00
|
|
|
return 25;
|
2013-02-07 05:04:05 +08:00
|
|
|
}
|
2013-07-15 23:04:42 +08:00
|
|
|
return 1; // Breaking at a << is really cheap.
|
2013-02-07 05:04:05 +08:00
|
|
|
}
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Left.Type == TT_ConditionalExpr)
|
2013-02-26 21:59:14 +08:00
|
|
|
return prec::Conditional;
|
2013-05-29 22:47:47 +08:00
|
|
|
prec::Level Level = Left.getPrecedence();
|
2013-01-30 05:01:14 +08:00
|
|
|
|
|
|
|
if (Level != prec::Unknown)
|
|
|
|
return Level;
|
2013-03-02 00:48:32 +08:00
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
|
2013-05-29 22:47:47 +08:00
|
|
|
const FormatToken &Left,
|
|
|
|
const FormatToken &Right) {
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Right.is(tok::hashhash))
|
|
|
|
return Left.is(tok::hash);
|
2013-03-13 22:41:29 +08:00
|
|
|
if (Left.isOneOf(tok::hashhash, tok::hash))
|
2013-01-30 05:01:14 +08:00
|
|
|
return Right.is(tok::hash);
|
2013-08-20 20:36:34 +08:00
|
|
|
if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
|
|
|
|
return Style.SpaceInEmptyParentheses;
|
|
|
|
if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
|
2013-08-21 16:39:01 +08:00
|
|
|
return (Right.Type == TT_CastRParen ||
|
|
|
|
(Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen))
|
2013-08-20 20:36:34 +08:00
|
|
|
? Style.SpacesInCStyleCastParentheses
|
|
|
|
: Style.SpacesInParentheses;
|
2013-10-29 22:52:02 +08:00
|
|
|
if (Style.SpacesInAngles &&
|
|
|
|
((Left.Type == TT_TemplateOpener) != (Right.Type == TT_TemplateCloser)))
|
|
|
|
return true;
|
2013-08-20 20:36:34 +08:00
|
|
|
if (Right.isOneOf(tok::semi, tok::comma))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Right.is(tok::less) &&
|
|
|
|
(Left.is(tok::kw_template) ||
|
|
|
|
(Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
|
|
|
|
return true;
|
|
|
|
if (Left.is(tok::arrow) || Right.is(tok::arrow))
|
|
|
|
return false;
|
2013-03-13 22:41:29 +08:00
|
|
|
if (Left.isOneOf(tok::exclaim, tok::tilde))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Left.is(tok::at) &&
|
2013-03-13 22:41:29 +08:00
|
|
|
Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,
|
|
|
|
tok::numeric_constant, tok::l_paren, tok::l_brace,
|
|
|
|
tok::kw_true, tok::kw_false))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Left.is(tok::coloncolon))
|
|
|
|
return false;
|
|
|
|
if (Right.is(tok::coloncolon))
|
2013-10-12 13:16:06 +08:00
|
|
|
return (Left.is(tok::less) && Style.Standard == FormatStyle::LS_Cpp03) ||
|
|
|
|
!Left.isOneOf(tok::identifier, tok::greater, tok::l_paren,
|
|
|
|
tok::r_paren, tok::less);
|
2013-03-13 22:41:29 +08:00
|
|
|
if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-07-01 17:47:25 +08:00
|
|
|
if (Right.is(tok::ellipsis))
|
2013-10-21 00:56:16 +08:00
|
|
|
return Left.Tok.isLiteral();
|
2013-09-04 16:20:47 +08:00
|
|
|
if (Left.is(tok::l_square) && Right.is(tok::amp))
|
|
|
|
return false;
|
2013-03-13 00:28:18 +08:00
|
|
|
if (Right.Type == TT_PointerOrReference)
|
2013-05-29 22:47:47 +08:00
|
|
|
return Left.Tok.isLiteral() ||
|
2013-03-13 00:28:18 +08:00
|
|
|
((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
|
|
|
|
!Style.PointerBindsToType);
|
2013-05-28 23:27:10 +08:00
|
|
|
if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
|
2013-05-08 22:58:20 +08:00
|
|
|
(Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
|
|
|
|
return true;
|
2013-03-13 00:28:18 +08:00
|
|
|
if (Left.Type == TT_PointerOrReference)
|
2013-07-01 17:34:09 +08:00
|
|
|
return Right.Tok.isLiteral() || Right.Type == TT_BlockComment ||
|
2013-03-20 17:53:18 +08:00
|
|
|
((Right.Type != TT_PointerOrReference) &&
|
2013-04-02 01:13:26 +08:00
|
|
|
Right.isNot(tok::l_paren) && Style.PointerBindsToType &&
|
2013-05-29 22:47:47 +08:00
|
|
|
Left.Previous &&
|
|
|
|
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Right.is(tok::star) && Left.is(tok::l_paren))
|
|
|
|
return false;
|
2013-02-10 10:08:05 +08:00
|
|
|
if (Left.is(tok::l_square))
|
2013-10-22 23:30:28 +08:00
|
|
|
return Left.Type == TT_ArrayInitializerLSquare &&
|
|
|
|
Right.isNot(tok::r_square);
|
2013-02-10 10:08:05 +08:00
|
|
|
if (Right.is(tok::r_square))
|
2013-10-22 23:30:28 +08:00
|
|
|
return Right.MatchingParen &&
|
|
|
|
Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
|
2013-08-30 18:36:58 +08:00
|
|
|
if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
|
2013-09-05 17:29:45 +08:00
|
|
|
Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Left.is(tok::colon))
|
|
|
|
return Left.Type != TT_ObjCMethodExpr;
|
|
|
|
if (Right.is(tok::colon))
|
2013-08-02 06:05:00 +08:00
|
|
|
return Right.Type != TT_ObjCMethodExpr && !Left.is(tok::question);
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Right.is(tok::l_paren)) {
|
2013-07-18 04:25:02 +08:00
|
|
|
if (Left.is(tok::r_paren) && Left.MatchingParen &&
|
|
|
|
Left.MatchingParen->Previous &&
|
|
|
|
Left.MatchingParen->Previous->is(tok::kw___attribute))
|
|
|
|
return true;
|
2013-03-13 22:41:29 +08:00
|
|
|
return Line.Type == LT_ObjCDecl ||
|
2013-08-21 16:39:01 +08:00
|
|
|
Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete,
|
|
|
|
tok::semi) ||
|
|
|
|
(Style.SpaceAfterControlStatementKeyword &&
|
|
|
|
Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
|
|
|
|
tok::kw_catch));
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
|
2013-09-05 17:29:45 +08:00
|
|
|
return !Left.Children.empty(); // No spaces in "{}".
|
2013-05-23 18:15:45 +08:00
|
|
|
if (Left.is(tok::l_brace) || Right.is(tok::r_brace))
|
2013-07-17 02:22:10 +08:00
|
|
|
return !Style.Cpp11BracedListStyle;
|
2013-11-23 22:51:47 +08:00
|
|
|
if (Left.Type == TT_BlockComment && Left.TokenText.endswith("=*/"))
|
|
|
|
return false;
|
2013-05-24 02:05:18 +08:00
|
|
|
if (Right.Type == TT_UnaryOperator)
|
|
|
|
return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
|
|
|
|
(Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
|
2013-05-24 05:35:49 +08:00
|
|
|
if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) &&
|
2013-09-04 16:20:47 +08:00
|
|
|
Right.is(tok::l_brace) && Right.getNextNonComment() &&
|
|
|
|
Right.BlockKind != BK_Block)
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-05-28 19:30:49 +08:00
|
|
|
if (Left.is(tok::period) || Right.is(tok::period))
|
|
|
|
return false;
|
2013-09-10 21:41:43 +08:00
|
|
|
if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L")
|
|
|
|
return false;
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
2013-05-29 22:47:47 +08:00
|
|
|
const FormatToken &Tok) {
|
|
|
|
if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo())
|
2013-02-11 16:01:18 +08:00
|
|
|
return true; // Never ever merge two identifiers.
|
2013-10-12 03:45:02 +08:00
|
|
|
if (Tok.Previous->Type == TT_ImplicitStringLiteral)
|
|
|
|
return Tok.WhitespaceRange.getBegin() != Tok.WhitespaceRange.getEnd();
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Line.Type == LT_ObjCMethodDecl) {
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->Type == TT_ObjCMethodSpecifier)
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->is(tok::r_paren) && Tok.is(tok::identifier))
|
2013-01-30 05:01:14 +08:00
|
|
|
// Don't space between ')' and <id>
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (Line.Type == LT_ObjCProperty &&
|
2013-05-29 22:47:47 +08:00
|
|
|
(Tok.is(tok::equal) || Tok.Previous->is(tok::equal)))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
|
2013-07-09 22:36:48 +08:00
|
|
|
if (Tok.Type == TT_TrailingReturnArrow ||
|
|
|
|
Tok.Previous->Type == TT_TrailingReturnArrow)
|
|
|
|
return true;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->is(tok::comma))
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
2013-02-28 21:40:17 +08:00
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
return false;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
|
|
|
|
return true;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->Tok.is(tok::kw_operator))
|
2013-10-29 20:24:23 +08:00
|
|
|
return Tok.is(tok::coloncolon);
|
2013-02-11 16:01:18 +08:00
|
|
|
if (Tok.Type == TT_OverloadedOperatorLParen)
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Tok.is(tok::colon))
|
2013-05-29 22:47:47 +08:00
|
|
|
return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
|
2013-08-02 06:05:00 +08:00
|
|
|
Tok.getNextNonComment() != NULL && Tok.Type != TT_ObjCMethodExpr &&
|
|
|
|
!Tok.Previous->is(tok::question);
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->Type == TT_UnaryOperator ||
|
|
|
|
Tok.Previous->Type == TT_CastRParen)
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) {
|
2013-02-08 23:28:42 +08:00
|
|
|
return Tok.Type == TT_TemplateCloser &&
|
2013-05-29 22:47:47 +08:00
|
|
|
Tok.Previous->Type == TT_TemplateCloser &&
|
2013-10-29 22:52:02 +08:00
|
|
|
(Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
2013-03-21 00:41:56 +08:00
|
|
|
if (Tok.isOneOf(tok::arrowstar, tok::periodstar) ||
|
2013-05-29 22:47:47 +08:00
|
|
|
Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar))
|
2013-02-28 21:40:17 +08:00
|
|
|
return false;
|
2013-09-25 23:15:02 +08:00
|
|
|
if (!Style.SpaceBeforeAssignmentOperators &&
|
|
|
|
Tok.getPrecedence() == prec::Assignment)
|
|
|
|
return false;
|
2013-08-08 00:29:23 +08:00
|
|
|
if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) ||
|
|
|
|
Tok.Previous->Type == TT_BinaryOperator)
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-08-28 16:24:04 +08:00
|
|
|
if (Tok.is(tok::less) && Tok.Previous->isNot(tok::l_paren) &&
|
|
|
|
Line.First->is(tok::hash))
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
|
|
|
if (Tok.Type == TT_TrailingUnaryOperator)
|
|
|
|
return false;
|
2013-05-29 22:47:47 +08:00
|
|
|
return spaceRequiredBetween(Line, *Tok.Previous, Tok);
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
2013-09-17 17:52:48 +08:00
|
|
|
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
|
|
|
const FormatToken &Right) {
|
|
|
|
if (Right.is(tok::comment)) {
|
|
|
|
return Right.NewlinesBefore > 0;
|
|
|
|
} else if (Right.Previous->isTrailingComment() ||
|
|
|
|
(Right.is(tok::string_literal) &&
|
|
|
|
Right.Previous->is(tok::string_literal))) {
|
|
|
|
return true;
|
|
|
|
} else if (Right.Previous->IsUnterminatedLiteral) {
|
|
|
|
return true;
|
|
|
|
} else if (Right.is(tok::lessless) && Right.Next &&
|
|
|
|
Right.Previous->is(tok::string_literal) &&
|
|
|
|
Right.Next->is(tok::string_literal)) {
|
|
|
|
return true;
|
|
|
|
} else if (Right.Previous->ClosesTemplateDeclaration &&
|
|
|
|
Right.Previous->MatchingParen &&
|
clang-format: Be more conservative about braced list column layout.
Specifically disable it for nested braced lists as it commonly can look
really weird. Eventually, we'll want to become smarter and format some of
the nested lists better.
Before:
SomeStruct my_struct_array = {
{ aaaaaa, aaaaaaaa, aaaaaaaaaa, aaaaaaaaa, aaaaaaaaa,
aaaaaaaaaa, aaaaaaaaaa, aaaaaaa, aaa },
{ aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaa },
{ aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaa, a, aaaaaaaaaa,
aaaaaaaaa, aaa },
};
After:
SomeStruct my_struct_array = {
{ aaaaaa, aaaaaaaa, aaaaaaaaaa, aaaaaaaaa, aaaaaaaaa, aaaaaaaaaa,
aaaaaaaaaaaa, aaaaaaa, aaa },
{ aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaaa, aaa },
{ aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaa, a, aaaaaaaaaa, aaaaaaaaa, aaa },
};
llvm-svn: 196783
2013-12-09 22:40:19 +08:00
|
|
|
Right.Previous->MatchingParen->NestingLevel == 0 &&
|
2013-09-17 17:52:48 +08:00
|
|
|
Style.AlwaysBreakTemplateDeclarations) {
|
|
|
|
return true;
|
|
|
|
} else if (Right.Type == TT_CtorInitializerComma &&
|
2013-10-08 13:11:18 +08:00
|
|
|
Style.BreakConstructorInitializersBeforeComma &&
|
|
|
|
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
|
2013-09-17 17:52:48 +08:00
|
|
|
return true;
|
|
|
|
} else if (Right.Previous->BlockKind == BK_Block &&
|
2013-10-10 21:36:20 +08:00
|
|
|
Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) {
|
2013-09-17 17:52:48 +08:00
|
|
|
return true;
|
|
|
|
} else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
|
|
|
|
return Style.BreakBeforeBraces == FormatStyle::BS_Allman;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-02-06 22:22:40 +08:00
|
|
|
bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
2013-05-29 22:47:47 +08:00
|
|
|
const FormatToken &Right) {
|
|
|
|
const FormatToken &Left = *Right.Previous;
|
2013-11-23 22:27:27 +08:00
|
|
|
if (Left.is(tok::at))
|
|
|
|
return false;
|
2013-07-09 15:43:55 +08:00
|
|
|
if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
2013-11-08 08:57:11 +08:00
|
|
|
if (Right.isTrailingComment())
|
|
|
|
// We rely on MustBreakBefore being set correctly here as we should not
|
|
|
|
// change the "binding" behavior of a comment.
|
|
|
|
return false;
|
|
|
|
if (Left.is(tok::question) && Right.is(tok::colon))
|
|
|
|
return false;
|
|
|
|
if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
|
|
|
|
return Style.BreakBeforeTernaryOperators;
|
|
|
|
if (Left.Type == TT_ConditionalExpr || Left.is(tok::question))
|
|
|
|
return !Style.BreakBeforeTernaryOperators;
|
2013-05-26 13:39:26 +08:00
|
|
|
if (Right.is(tok::colon) &&
|
2013-10-24 18:31:50 +08:00
|
|
|
(Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
2013-05-26 13:39:26 +08:00
|
|
|
if (Left.is(tok::colon) &&
|
2013-10-24 18:31:50 +08:00
|
|
|
(Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr))
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
2013-02-05 18:07:47 +08:00
|
|
|
if (Right.Type == TT_ObjCSelectorName)
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
2013-08-01 21:46:58 +08:00
|
|
|
if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
|
|
|
|
return true;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Left.ClosesTemplateDeclaration)
|
|
|
|
return true;
|
2013-02-14 16:42:54 +08:00
|
|
|
if (Right.Type == TT_RangeBasedForLoopColon ||
|
2013-08-28 15:27:35 +08:00
|
|
|
Right.Type == TT_OverloadedOperatorLParen ||
|
|
|
|
Right.Type == TT_OverloadedOperator)
|
2013-02-14 16:42:54 +08:00
|
|
|
return false;
|
2013-05-06 14:45:09 +08:00
|
|
|
if (Left.Type == TT_RangeBasedForLoopColon)
|
2013-01-30 05:01:14 +08:00
|
|
|
return true;
|
Allow breaking between type and name in for loops.
This fixes llvm.org/PR15033.
Also: Always break before a parameter, if the previous parameter was
split over multiple lines. This was necessary to make the right
decisions in for-loops, almost always makes the code more readable and
also fixes llvm.org/PR14873.
Before:
for (llvm::ArrayRef<NamedDecl *>::iterator I = FD->getDeclsInPrototypeScope()
.begin(), E = FD->getDeclsInPrototypeScope().end();
I != E; ++I) {
}
foo(bar(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
ccccccccccccccccccccccccccccc), d, bar(e, f));
After:
for (llvm::ArrayRef<NamedDecl *>::iterator
I = FD->getDeclsInPrototypeScope().begin(),
E = FD->getDeclsInPrototypeScope().end();
I != E; ++I) {
}
foo(bar(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
ccccccccccccccccccccccccccccc),
d, bar(e, f));
llvm-svn: 175741
2013-02-21 23:00:29 +08:00
|
|
|
if (Right.Type == TT_RangeBasedForLoopColon)
|
|
|
|
return false;
|
2013-01-30 05:01:14 +08:00
|
|
|
if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
|
2013-11-08 08:57:11 +08:00
|
|
|
Left.Type == TT_UnaryOperator || Left.is(tok::kw_operator))
|
2013-01-30 05:01:14 +08:00
|
|
|
return false;
|
|
|
|
if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
|
|
|
|
return false;
|
2013-07-05 15:58:34 +08:00
|
|
|
if (Left.Previous) {
|
|
|
|
if (Left.is(tok::l_paren) && Right.is(tok::l_paren) &&
|
|
|
|
Left.Previous->is(tok::kw___attribute))
|
|
|
|
return false;
|
2013-07-09 22:36:48 +08:00
|
|
|
if (Left.is(tok::l_paren) && (Left.Previous->Type == TT_BinaryOperator ||
|
2013-07-18 22:46:07 +08:00
|
|
|
Left.Previous->Type == TT_CastRParen))
|
2013-07-05 15:58:34 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-10-30 21:54:53 +08:00
|
|
|
if (Right.Type == TT_ImplicitStringLiteral)
|
|
|
|
return false;
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-09-05 17:29:45 +08:00
|
|
|
if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)
|
|
|
|
return false;
|
|
|
|
|
2013-05-22 16:28:26 +08:00
|
|
|
// We only break before r_brace if there was a corresponding break before
|
|
|
|
// the l_brace, which is tracked by BreakBeforeClosingBrace.
|
2013-09-05 17:29:45 +08:00
|
|
|
if (Right.is(tok::r_brace))
|
|
|
|
return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
|
2013-05-22 16:28:26 +08:00
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
// Allow breaking after a trailing 'const', e.g. after a method declaration,
|
|
|
|
// unless it is follow by ';', '{' or '='.
|
2013-05-29 22:47:47 +08:00
|
|
|
if (Left.is(tok::kw_const) && Left.Previous != NULL &&
|
|
|
|
Left.Previous->is(tok::r_paren))
|
2013-03-13 22:41:29 +08:00
|
|
|
return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal);
|
2013-01-30 05:01:14 +08:00
|
|
|
|
2013-03-14 17:50:46 +08:00
|
|
|
if (Right.is(tok::kw___attribute))
|
|
|
|
return true;
|
|
|
|
|
2013-02-23 15:46:38 +08:00
|
|
|
if (Left.is(tok::identifier) && Right.is(tok::string_literal))
|
|
|
|
return true;
|
2013-07-27 00:56:36 +08:00
|
|
|
|
|
|
|
if (Left.Type == TT_CtorInitializerComma &&
|
|
|
|
Style.BreakConstructorInitializersBeforeComma)
|
|
|
|
return false;
|
2013-10-08 13:11:18 +08:00
|
|
|
if (Right.Type == TT_CtorInitializerComma &&
|
|
|
|
Style.BreakConstructorInitializersBeforeComma)
|
|
|
|
return true;
|
2013-11-23 22:45:49 +08:00
|
|
|
if (Right.Type == TT_BinaryOperator && Style.BreakBeforeBinaryOperators)
|
2013-07-27 00:56:36 +08:00
|
|
|
return true;
|
2013-09-17 16:15:46 +08:00
|
|
|
if (Left.is(tok::greater) && Right.is(tok::greater) &&
|
|
|
|
Left.Type != TT_TemplateCloser)
|
|
|
|
return false;
|
2013-10-22 23:30:28 +08:00
|
|
|
if (Left.Type == TT_ArrayInitializerLSquare)
|
|
|
|
return true;
|
2013-07-27 00:56:36 +08:00
|
|
|
return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
|
|
|
|
!Style.BreakBeforeBinaryOperators) ||
|
2013-04-06 01:22:09 +08:00
|
|
|
Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
|
|
|
|
tok::kw_class, tok::kw_struct) ||
|
2013-10-22 23:30:28 +08:00
|
|
|
Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon,
|
|
|
|
tok::l_square, tok::at) ||
|
2013-07-05 15:58:34 +08:00
|
|
|
(Left.is(tok::r_paren) &&
|
2013-05-21 17:16:31 +08:00
|
|
|
Right.isOneOf(tok::identifier, tok::kw_const, tok::kw___attribute)) ||
|
2013-10-22 23:30:28 +08:00
|
|
|
(Left.is(tok::l_paren) && !Right.is(tok::r_paren));
|
2013-01-30 05:01:14 +08:00
|
|
|
}
|
|
|
|
|
2013-04-09 04:33:42 +08:00
|
|
|
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
|
|
|
|
llvm::errs() << "AnnotatedTokens:\n";
|
2013-05-29 22:47:47 +08:00
|
|
|
const FormatToken *Tok = Line.First;
|
2013-04-09 04:33:42 +08:00
|
|
|
while (Tok) {
|
2013-05-29 22:47:47 +08:00
|
|
|
llvm::errs() << " M=" << Tok->MustBreakBefore
|
2013-07-10 22:02:49 +08:00
|
|
|
<< " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
|
|
|
|
<< " S=" << Tok->SpacesRequiredBefore
|
|
|
|
<< " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
|
2013-10-12 05:25:45 +08:00
|
|
|
<< " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
|
|
|
|
<< " FakeLParens=";
|
2013-04-09 04:33:42 +08:00
|
|
|
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
|
|
|
|
llvm::errs() << Tok->FakeLParens[i] << "/";
|
|
|
|
llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
|
2013-10-12 05:25:45 +08:00
|
|
|
if (Tok->Next == NULL)
|
|
|
|
assert(Tok == Line.Last);
|
2013-05-29 22:47:47 +08:00
|
|
|
Tok = Tok->Next;
|
2013-04-09 04:33:42 +08:00
|
|
|
}
|
|
|
|
llvm::errs() << "----\n";
|
|
|
|
}
|
|
|
|
|
2013-01-30 05:01:14 +08:00
|
|
|
} // namespace format
|
|
|
|
} // namespace clang
|