aboutsummaryrefslogtreecommitdiff
path: root/lib/Format/TokenAnnotator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Format/TokenAnnotator.cpp')
-rw-r--r--lib/Format/TokenAnnotator.cpp1041
1 files changed, 640 insertions, 401 deletions
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 017afe1a370b..4ba3f9196977 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -32,9 +32,9 @@ namespace {
class AnnotatingParser {
public:
AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
- IdentifierInfo &Ident_in)
- : Style(Style), Line(Line), CurrentToken(Line.First),
- KeywordVirtualFound(false), AutoFound(false), Ident_in(Ident_in) {
+ const AdditionalKeywords &Keywords)
+ : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
+ Keywords(Keywords) {
Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
resetTokenMetadata(CurrentToken);
}
@@ -51,6 +51,10 @@ private:
Contexts.back().InTemplateArgument =
Left->Previous && Left->Previous->Tok.isNot(tok::kw_template);
+ if (Style.Language == FormatStyle::LK_Java &&
+ CurrentToken->is(tok::question))
+ next();
+
while (CurrentToken) {
if (CurrentToken->is(tok::greater)) {
Left->MatchingParen = CurrentToken;
@@ -59,8 +63,13 @@ private:
next();
return true;
}
+ if (CurrentToken->is(tok::question) &&
+ Style.Language == FormatStyle::LK_Java) {
+ next();
+ continue;
+ }
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
- tok::question, tok::colon))
+ tok::colon, tok::question))
return false;
// If a && or || is found and interpreted as a binary operator, this set
// of angles is likely part of something like "a < b && c > d". If the
@@ -69,12 +78,8 @@ private:
// parameters.
// FIXME: This is getting out of hand, write a decent parser.
if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
- ((CurrentToken->Previous->Type == TT_BinaryOperator &&
- // Toplevel bool expressions do not make lots of sense;
- // If we're on the top level, it contains only the base context and
- // the context for the current opening angle bracket.
- Contexts.size() > 2) ||
- Contexts[Contexts.size() - 2].IsExpression) &&
+ CurrentToken->Previous->is(TT_BinaryOperator) &&
+ Contexts[Contexts.size() - 2].IsExpression &&
Line.First->isNot(tok::kw_template))
return false;
updateParameterCount(Left, CurrentToken);
@@ -109,17 +114,17 @@ private:
if (Left->Previous &&
(Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_if,
tok::kw_while, tok::l_paren, tok::comma) ||
- Left->Previous->Type == TT_BinaryOperator)) {
+ Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
} else if (Line.InPPDirective &&
(!Left->Previous ||
- (Left->Previous->isNot(tok::identifier) &&
- Left->Previous->Type != TT_OverloadedOperator))) {
+ !Left->Previous->isOneOf(tok::identifier,
+ TT_OverloadedOperator))) {
Contexts.back().IsExpression = true;
} else if (Left->Previous && Left->Previous->is(tok::r_square) &&
Left->Previous->MatchingParen &&
- Left->Previous->MatchingParen->Type == TT_LambdaLSquare) {
+ Left->Previous->MatchingParen->is(TT_LambdaLSquare)) {
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
} else if (Contexts[Contexts.size() - 2].CaretFound) {
@@ -131,6 +136,9 @@ private:
// The first argument to a foreach macro is a declaration.
Contexts.back().IsForEachMacro = true;
Contexts.back().IsExpression = false;
+ } else if (Left->Previous && Left->Previous->MatchingParen &&
+ Left->Previous->MatchingParen->is(TT_ObjCBlockLParen)) {
+ Contexts.back().IsExpression = false;
}
if (StartsObjCMethodExpr) {
@@ -160,11 +168,11 @@ private:
}
}
- if (CurrentToken->Previous->Type == TT_PointerOrReference &&
+ if (CurrentToken->Previous->is(TT_PointerOrReference) &&
CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
tok::coloncolon))
MightBeFunctionType = true;
- if (CurrentToken->Previous->Type == TT_BinaryOperator)
+ if (CurrentToken->Previous->is(TT_BinaryOperator))
Contexts.back().IsExpression = true;
if (CurrentToken->is(tok::r_paren)) {
if (MightBeFunctionType && CurrentToken->Next &&
@@ -183,8 +191,12 @@ private:
}
}
- if (Left->Type == TT_AttributeParen)
+ if (Left->is(TT_AttributeParen))
CurrentToken->Type = TT_AttributeParen;
+ if (Left->Previous && Left->Previous->is(TT_JavaAnnotation))
+ CurrentToken->Type = TT_JavaAnnotation;
+ if (Left->Previous && Left->Previous->is(TT_LeadingJavaAnnotation))
+ CurrentToken->Type = TT_LeadingJavaAnnotation;
if (!HasMultipleLines)
Left->PackingKind = PPK_Inconclusive;
@@ -227,12 +239,13 @@ private:
FormatToken *Left = CurrentToken->Previous;
FormatToken *Parent = Left->getPreviousNonComment();
bool StartsObjCMethodExpr =
- Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&
+ Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
CurrentToken->isNot(tok::l_brace) &&
- (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
- tok::kw_return, tok::kw_throw) ||
- Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
- Parent->Type == TT_CastRParen ||
+ (!Parent ||
+ Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
+ tok::kw_return, tok::kw_throw) ||
+ Parent->isUnaryOperator() ||
+ Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
Contexts.back().IsExpression = true;
@@ -243,14 +256,14 @@ private:
Left->Type = TT_ObjCMethodExpr;
} else if (Parent && Parent->is(tok::at)) {
Left->Type = TT_ArrayInitializerLSquare;
- } else if (Left->Type == TT_Unknown) {
+ } else if (Left->is(TT_Unknown)) {
Left->Type = TT_ArraySubscriptLSquare;
}
while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
- Left->Type == TT_ObjCMethodExpr) {
+ Left->is(TT_ObjCMethodExpr)) {
// An ObjC method call is rarely followed by an open parenthesis.
// FIXME: Do we incorrectly label ":" with this?
StartsObjCMethodExpr = false;
@@ -261,7 +274,7 @@ private:
// determineStarAmpUsage() thinks that '*' '[' is allocating an
// array of pointers, but if '[' starts a selector then '*' is a
// binary operator.
- if (Parent && Parent->Type == TT_PointerOrReference)
+ if (Parent && Parent->is(TT_PointerOrReference))
Parent->Type = TT_BinaryOperator;
}
Left->MatchingParen = CurrentToken;
@@ -277,14 +290,22 @@ private:
}
if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
return false;
- if (CurrentToken->is(tok::colon))
+ if (CurrentToken->is(tok::colon)) {
+ if (Left->is(TT_ArraySubscriptLSquare)) {
+ Left->Type = TT_ObjCMethodExpr;
+ StartsObjCMethodExpr = true;
+ Contexts.back().ColonIsObjCMethodExpr = true;
+ if (Parent && Parent->is(tok::r_paren))
+ Parent->Type = TT_CastRParen;
+ }
ColonFound = true;
+ }
if (CurrentToken->is(tok::comma) &&
Style.Language != FormatStyle::LK_Proto &&
- (Left->Type == TT_ArraySubscriptLSquare ||
- (Left->Type == TT_ObjCMethodExpr && !ColonFound)))
+ (Left->is(TT_ArraySubscriptLSquare) ||
+ (Left->is(TT_ObjCMethodExpr) && !ColonFound)))
Left->Type = TT_ArrayInitializerLSquare;
- FormatToken* Tok = CurrentToken;
+ FormatToken *Tok = CurrentToken;
if (!consumeToken())
return false;
updateParameterCount(Left, Tok);
@@ -315,11 +336,14 @@ private:
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
return false;
updateParameterCount(Left, CurrentToken);
- if (CurrentToken->is(tok::colon) &&
- Style.Language != FormatStyle::LK_Proto) {
- if (CurrentToken->getPreviousNonComment()->is(tok::identifier))
- CurrentToken->getPreviousNonComment()->Type = TT_SelectorName;
- Left->Type = TT_DictLiteral;
+ if (CurrentToken->isOneOf(tok::colon, tok::l_brace)) {
+ FormatToken *Previous = CurrentToken->getPreviousNonComment();
+ if ((CurrentToken->is(tok::colon) ||
+ Style.Language == FormatStyle::LK_Proto) &&
+ Previous->is(tok::identifier))
+ Previous->Type = TT_SelectorName;
+ if (CurrentToken->is(tok::colon))
+ Left->Type = TT_DictLiteral;
}
if (!consumeToken())
return false;
@@ -329,10 +353,10 @@ private:
}
void updateParameterCount(FormatToken *Left, FormatToken *Current) {
- if (Current->Type == TT_LambdaLSquare ||
- (Current->is(tok::caret) && Current->Type == TT_UnaryOperator) ||
+ if (Current->is(TT_LambdaLSquare) ||
+ (Current->is(tok::caret) && Current->is(TT_UnaryOperator)) ||
(Style.Language == FormatStyle::LK_JavaScript &&
- Current->TokenText == "function")) {
+ Current->is(Keywords.kw_function))) {
++Left->BlockParameterCount;
}
if (Current->is(tok::comma)) {
@@ -390,7 +414,7 @@ private:
} else if (Contexts.back().ColonIsDictLiteral) {
Tok->Type = TT_DictLiteral;
} else if (Contexts.back().ColonIsObjCMethodExpr ||
- Line.First->Type == TT_ObjCMethodSpecifier) {
+ Line.First->is(TT_ObjCMethodSpecifier)) {
Tok->Type = TT_ObjCMethodExpr;
Tok->Previous->Type = TT_SelectorName;
if (Tok->Previous->ColumnWidth >
@@ -406,6 +430,11 @@ private:
} else if (Contexts.size() == 1 &&
!Line.First->isOneOf(tok::kw_enum, tok::kw_case)) {
Tok->Type = TT_InheritanceColon;
+ } else if (Tok->Previous->is(tok::identifier) && Tok->Next &&
+ Tok->Next->isOneOf(tok::r_paren, tok::comma)) {
+ // This handles a special macro in ObjC code where selectors including
+ // the colon are passed as macro arguments.
+ Tok->Type = TT_ObjCMethodExpr;
} else if (Contexts.back().ContextKind == tok::l_paren) {
Tok->Type = TT_InlineASMColon;
}
@@ -428,9 +457,9 @@ private:
if (!parseParens())
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
- !Contexts.back().IsExpression &&
- Line.First->Type != TT_ObjCProperty &&
- (!Tok->Previous || Tok->Previous->isNot(tok::kw_decltype)))
+ !Contexts.back().IsExpression && Line.First->isNot(TT_ObjCProperty) &&
+ (!Tok->Previous ||
+ !Tok->Previous->isOneOf(tok::kw_decltype, TT_LeadingJavaAnnotation)))
Line.MightBeFunctionDecl = true;
break;
case tok::l_square:
@@ -442,9 +471,12 @@ private:
return false;
break;
case tok::less:
- if (Tok->Previous && !Tok->Previous->Tok.isLiteral() && parseAngle())
+ if ((!Tok->Previous ||
+ (!Tok->Previous->Tok.isLiteral() &&
+ !(Tok->Previous->is(tok::r_paren) && Contexts.size() > 1))) &&
+ parseAngle()) {
Tok->Type = TT_TemplateOpener;
- else {
+ } else {
Tok->Type = TT_BinaryOperator;
CurrentToken = Tok;
next();
@@ -467,12 +499,12 @@ private:
if (CurrentToken->isOneOf(tok::star, tok::amp))
CurrentToken->Type = TT_PointerOrReference;
consumeToken();
- if (CurrentToken && CurrentToken->Previous->Type == TT_BinaryOperator)
+ if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))
CurrentToken->Previous->Type = TT_OverloadedOperator;
}
if (CurrentToken) {
CurrentToken->Type = TT_OverloadedOperatorLParen;
- if (CurrentToken->Previous->Type == TT_BinaryOperator)
+ if (CurrentToken->Previous->is(TT_BinaryOperator))
CurrentToken->Previous->Type = TT_OverloadedOperator;
}
break;
@@ -483,8 +515,8 @@ private:
parseTemplateDeclaration();
break;
case tok::identifier:
- if (Line.First->is(tok::kw_for) &&
- Tok->Tok.getIdentifierInfo() == &Ident_in)
+ if (Line.First->is(tok::kw_for) && Tok->is(Keywords.kw_in) &&
+ Tok->Previous->isNot(tok::colon))
Tok->Type = TT_ObjCForIn;
break;
case tok::comma:
@@ -502,7 +534,6 @@ private:
}
void parseIncludeDirective() {
- next();
if (CurrentToken && CurrentToken->is(tok::less)) {
next();
while (CurrentToken) {
@@ -510,14 +541,6 @@ private:
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
- } else {
- while (CurrentToken) {
- 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;
- next();
- }
}
}
@@ -544,22 +567,25 @@ private:
}
}
- void parsePreprocessorDirective() {
+ LineType parsePreprocessorDirective() {
+ LineType Type = LT_PreprocessorDirective;
next();
if (!CurrentToken)
- return;
+ return Type;
if (CurrentToken->Tok.is(tok::numeric_constant)) {
CurrentToken->SpacesRequiredBefore = 1;
- return;
+ return Type;
}
// Hashes in the middle of a line can lead to any strange token
// sequence.
if (!CurrentToken->Tok.getIdentifierInfo())
- return;
+ return Type;
switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
case tok::pp_import:
+ next();
parseIncludeDirective();
+ Type = LT_ImportStatement;
break;
case tok::pp_error:
case tok::pp_warning:
@@ -578,33 +604,53 @@ private:
}
while (CurrentToken)
next();
+ return Type;
}
public:
LineType parseLine() {
if (CurrentToken->is(tok::hash)) {
- parsePreprocessorDirective();
- return LT_PreprocessorDirective;
+ return parsePreprocessorDirective();
}
// Directly allow to 'import <string-literal>' to support protocol buffer
// definitions (code.google.com/p/protobuf) or missing "#" (either way we
// should not break the line).
IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();
- if (Info && Info->getPPKeywordID() == tok::pp_import &&
- CurrentToken->Next && CurrentToken->Next->is(tok::string_literal))
+ if ((Style.Language == FormatStyle::LK_Java &&
+ CurrentToken->is(Keywords.kw_package)) ||
+ (Info && Info->getPPKeywordID() == tok::pp_import &&
+ CurrentToken->Next &&
+ CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier,
+ tok::kw_static))) {
+ next();
parseIncludeDirective();
+ return LT_ImportStatement;
+ }
+ // If this line starts and ends in '<' and '>', respectively, it is likely
+ // part of "#define <a/b.h>".
+ if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) {
+ parseIncludeDirective();
+ return LT_ImportStatement;
+ }
+
+ bool KeywordVirtualFound = false;
+ bool ImportStatement = false;
while (CurrentToken) {
if (CurrentToken->is(tok::kw_virtual))
KeywordVirtualFound = true;
+ if (IsImportStatement(*CurrentToken))
+ ImportStatement = true;
if (!consumeToken())
return LT_Invalid;
}
if (KeywordVirtualFound)
return LT_VirtualFunctionDecl;
+ if (ImportStatement)
+ return LT_ImportStatement;
- if (Line.First->Type == TT_ObjCMethodSpecifier) {
+ if (Line.First->is(TT_ObjCMethodSpecifier)) {
if (Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
@@ -615,17 +661,26 @@ public:
}
private:
+ bool IsImportStatement(const FormatToken &Tok) {
+ // FIXME: Closure-library specific stuff should not be hard-coded but be
+ // configurable.
+ return Style.Language == FormatStyle::LK_JavaScript &&
+ Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&
+ Tok.Next->Next && (Tok.Next->Next->TokenText == "module" ||
+ Tok.Next->Next->TokenText == "require" ||
+ Tok.Next->Next->TokenText == "provide") &&
+ Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
+ }
+
void resetTokenMetadata(FormatToken *Token) {
if (!Token)
return;
// 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 &&
- CurrentToken->Type != TT_FunctionLBrace &&
- CurrentToken->Type != TT_ImplicitStringLiteral &&
- CurrentToken->Type != TT_RegexLiteral &&
- CurrentToken->Type != TT_TrailingReturnArrow)
+ if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_FunctionLBrace,
+ TT_ImplicitStringLiteral, TT_RegexLiteral,
+ TT_TrailingReturnArrow))
CurrentToken->Type = TT_Unknown;
CurrentToken->Role.reset();
CurrentToken->FakeLParens.clear();
@@ -634,9 +689,10 @@ private:
void next() {
if (CurrentToken) {
- determineTokenType(*CurrentToken);
- CurrentToken->BindingStrength = Contexts.back().BindingStrength;
CurrentToken->NestingLevel = Contexts.size() - 1;
+ CurrentToken->BindingStrength = Contexts.back().BindingStrength;
+ modifyContext(*CurrentToken);
+ determineTokenType(*CurrentToken);
CurrentToken = CurrentToken->Next;
}
@@ -688,23 +744,29 @@ private:
~ScopedContextCreator() { P.Contexts.pop_back(); }
};
- void determineTokenType(FormatToken &Current) {
+ void modifyContext(const FormatToken &Current) {
if (Current.getPrecedence() == prec::Assignment &&
- !Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
+ !Line.First->isOneOf(tok::kw_template, tok::kw_using,
+ TT_UnaryOperator) &&
(!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
Contexts.back().IsExpression = true;
for (FormatToken *Previous = Current.Previous;
Previous && !Previous->isOneOf(tok::comma, tok::semi);
Previous = Previous->Previous) {
- if (Previous->isOneOf(tok::r_square, tok::r_paren))
+ if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
Previous = Previous->MatchingParen;
- if (Previous->Type == TT_BinaryOperator &&
- Previous->isOneOf(tok::star, tok::amp)) {
- Previous->Type = TT_PointerOrReference;
+ if (!Previous)
+ break;
}
+ if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
+ Previous->isOneOf(tok::star, tok::amp) && Previous->Previous &&
+ Previous->Previous->isNot(tok::equal))
+ Previous->Type = TT_PointerOrReference;
}
} else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {
Contexts.back().IsExpression = true;
+ } else if (Current.is(TT_TrailingReturnArrow)) {
+ Contexts.back().IsExpression = false;
} else if (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
!Line.InPPDirective &&
(!Current.Previous ||
@@ -712,7 +774,7 @@ private:
bool ParametersOfFunctionType =
Current.Previous && Current.Previous->is(tok::r_paren) &&
Current.Previous->MatchingParen &&
- Current.Previous->MatchingParen->Type == TT_FunctionTypeLParen;
+ Current.Previous->MatchingParen->is(TT_FunctionTypeLParen);
bool IsForOrCatch = Current.Previous &&
Current.Previous->isOneOf(tok::kw_for, tok::kw_catch);
Contexts.back().IsExpression = !ParametersOfFunctionType && !IsForOrCatch;
@@ -721,8 +783,10 @@ private:
Previous && Previous->isOneOf(tok::star, tok::amp);
Previous = Previous->Previous)
Previous->Type = TT_PointerOrReference;
+ if (Line.MustBeDeclaration)
+ Contexts.back().IsExpression = Contexts.front().InCtorInitializer;
} else if (Current.Previous &&
- Current.Previous->Type == TT_CtorInitializerColon) {
+ Current.Previous->is(TT_CtorInitializerColon)) {
Contexts.back().IsExpression = true;
Contexts.back().InCtorInitializer = true;
} else if (Current.is(tok::kw_new)) {
@@ -731,70 +795,99 @@ private:
// This should be the condition or increment in a for-loop.
Contexts.back().IsExpression = true;
}
+ }
+
+ void determineTokenType(FormatToken &Current) {
+ if (!Current.is(TT_Unknown))
+ // The token type is already known.
+ return;
- if (Current.Type == TT_Unknown) {
+ // 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 (Current.is(Keywords.kw_instanceof)) {
+ Current.Type = TT_BinaryOperator;
+ } else if (isStartOfName(Current) &&
+ (!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
+ Contexts.back().FirstStartOfName = &Current;
+ Current.Type = TT_StartOfName;
+ } else if (Current.is(tok::kw_auto)) {
+ AutoFound = true;
+ } else if (Current.is(tok::arrow) &&
+ Style.Language == FormatStyle::LK_Java) {
+ Current.Type = TT_LambdaArrow;
+ } else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration &&
+ Current.NestingLevel == 0) {
+ Current.Type = TT_TrailingReturnArrow;
+ } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
+ Current.Type =
+ determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
+ Contexts.back().IsExpression,
+ Contexts.back().InTemplateArgument);
+ } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
+ Current.Type = determinePlusMinusCaretUsage(Current);
+ if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))
+ Contexts.back().CaretFound = true;
+ } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
+ Current.Type = determineIncrementUsage(Current);
+ } else if (Current.isOneOf(tok::exclaim, tok::tilde)) {
+ Current.Type = TT_UnaryOperator;
+ } else if (Current.is(tok::question)) {
+ Current.Type = TT_ConditionalExpr;
+ } else if (Current.isBinaryOperator() &&
+ (!Current.Previous || Current.Previous->isNot(tok::l_square))) {
+ Current.Type = TT_BinaryOperator;
+ } else if (Current.is(tok::comment)) {
+ if (Current.TokenText.startswith("//"))
+ Current.Type = TT_LineComment;
+ else
+ Current.Type = TT_BlockComment;
+ } else if (Current.is(tok::r_paren)) {
+ if (rParenEndsCast(Current))
+ Current.Type = TT_CastRParen;
+ } else if (Current.is(tok::at) && Current.Next) {
+ switch (Current.Next->Tok.getObjCKeywordID()) {
+ 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;
+ }
+ } else if (Current.is(tok::period)) {
+ FormatToken *PreviousNoComment = Current.getPreviousNonComment();
+ if (PreviousNoComment &&
+ PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
+ Current.Type = TT_DesignatedInitializerPeriod;
+ else if (Style.Language == FormatStyle::LK_Java && Current.Previous &&
+ Current.Previous->isOneOf(TT_JavaAnnotation,
+ TT_LeadingJavaAnnotation)) {
+ Current.Type = Current.Previous->Type;
+ }
+ } else if (Current.isOneOf(tok::identifier, tok::kw_const) &&
+ Current.Previous &&
+ !Current.Previous->isOneOf(tok::equal, tok::at) &&
+ Line.MightBeFunctionDecl && Contexts.size() == 1) {
// 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) {
- Contexts.back().FirstStartOfName = &Current;
- Current.Type = TT_StartOfName;
- } else if (Current.is(tok::kw_auto)) {
- AutoFound = true;
- } else if (Current.is(tok::arrow) && AutoFound &&
- Line.MustBeDeclaration) {
- Current.Type = TT_TrailingReturnArrow;
- } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
- Current.Type =
- determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
- Contexts.back().IsExpression,
- Contexts.back().InTemplateArgument);
- } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
- Current.Type = determinePlusMinusCaretUsage(Current);
- if (Current.Type == TT_UnaryOperator && Current.is(tok::caret))
- Contexts.back().CaretFound = true;
- } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
- Current.Type = determineIncrementUsage(Current);
- } else if (Current.is(tok::exclaim)) {
- Current.Type = TT_UnaryOperator;
- } else if (Current.is(tok::question)) {
- Current.Type = TT_ConditionalExpr;
- } else if (Current.isBinaryOperator() &&
- (!Current.Previous ||
- Current.Previous->isNot(tok::l_square))) {
- Current.Type = TT_BinaryOperator;
- } else if (Current.is(tok::comment)) {
- if (Current.TokenText.startswith("//"))
- Current.Type = TT_LineComment;
+ // function declaration have been found.
+ Current.Type = TT_TrailingAnnotation;
+ } else if (Style.Language == FormatStyle::LK_Java && Current.Previous) {
+ if (Current.Previous->is(tok::at) &&
+ Current.isNot(Keywords.kw_interface)) {
+ const FormatToken &AtToken = *Current.Previous;
+ const FormatToken *Previous = AtToken.getPreviousNonComment();
+ if (!Previous || Previous->is(TT_LeadingJavaAnnotation))
+ Current.Type = TT_LeadingJavaAnnotation;
else
- Current.Type = TT_BlockComment;
- } else if (Current.is(tok::r_paren)) {
- if (rParenEndsCast(Current))
- Current.Type = TT_CastRParen;
- } else if (Current.is(tok::at) && Current.Next) {
- switch (Current.Next->Tok.getObjCKeywordID()) {
- 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;
- }
- } else if (Current.is(tok::period)) {
- FormatToken *PreviousNoComment = Current.getPreviousNonComment();
- if (PreviousNoComment &&
- PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
- Current.Type = TT_DesignatedInitializerPeriod;
- } else if (Current.isOneOf(tok::identifier, tok::kw_const) &&
- Current.Previous && Current.Previous->isNot(tok::equal) &&
- Line.MightBeFunctionDecl && Contexts.size() == 1) {
- // Line.MightBeFunctionDecl can only be true after the parentheses of a
- // function declaration have been found.
- Current.Type = TT_TrailingAnnotation;
+ Current.Type = TT_JavaAnnotation;
+ } else if (Current.Previous->is(tok::period) &&
+ Current.Previous->isOneOf(TT_JavaAnnotation,
+ TT_LeadingJavaAnnotation)) {
+ Current.Type = Current.Previous->Type;
}
}
}
@@ -808,6 +901,9 @@ private:
if (Tok.isNot(tok::identifier) || !Tok.Previous)
return false;
+ if (Tok.Previous->is(TT_LeadingJavaAnnotation))
+ return false;
+
// Skip "const" as it does not have an influence on whether this is a name.
FormatToken *PreviousNotConst = Tok.Previous;
while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))
@@ -820,9 +916,10 @@ private:
PreviousNotConst->Previous &&
PreviousNotConst->Previous->is(tok::hash);
- if (PreviousNotConst->Type == TT_TemplateCloser)
+ if (PreviousNotConst->is(TT_TemplateCloser))
return PreviousNotConst && PreviousNotConst->MatchingParen &&
PreviousNotConst->MatchingParen->Previous &&
+ PreviousNotConst->MatchingParen->Previous->isNot(tok::period) &&
PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
if (PreviousNotConst->is(tok::r_paren) && PreviousNotConst->MatchingParen &&
@@ -831,7 +928,7 @@ private:
return true;
return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
- PreviousNotConst->Type == TT_PointerOrReference ||
+ PreviousNotConst->is(TT_PointerOrReference) ||
PreviousNotConst->isSimpleTypeSpecifier();
}
@@ -840,14 +937,28 @@ private:
FormatToken *LeftOfParens = nullptr;
if (Tok.MatchingParen)
LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
- if (LeftOfParens && LeftOfParens->is(tok::r_paren))
+ if (LeftOfParens && LeftOfParens->is(tok::r_paren) &&
+ LeftOfParens->MatchingParen)
+ LeftOfParens = LeftOfParens->MatchingParen->Previous;
+ if (LeftOfParens && LeftOfParens->is(tok::r_square) &&
+ LeftOfParens->MatchingParen &&
+ LeftOfParens->MatchingParen->is(TT_LambdaLSquare))
return false;
+ if (Tok.Next) {
+ if (Tok.Next->is(tok::question))
+ return false;
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ Tok.Next->is(Keywords.kw_in))
+ return false;
+ if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
+ return true;
+ }
bool IsCast = false;
bool ParensAreEmpty = Tok.Previous == Tok.MatchingParen;
- bool ParensAreType = !Tok.Previous ||
- Tok.Previous->Type == TT_PointerOrReference ||
- Tok.Previous->Type == TT_TemplateCloser ||
- Tok.Previous->isSimpleTypeSpecifier();
+ bool ParensAreType =
+ !Tok.Previous ||
+ Tok.Previous->isOneOf(TT_PointerOrReference, TT_TemplateCloser) ||
+ Tok.Previous->isSimpleTypeSpecifier();
bool ParensCouldEndDecl =
Tok.Next && Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
bool IsSizeOfOrAlignOf =
@@ -862,12 +973,11 @@ private:
IsCast = true;
// If there is an identifier after the (), it is likely a cast, unless
// there is also an identifier before the ().
- else if (LeftOfParens &&
+ else if (LeftOfParens && Tok.Next &&
(LeftOfParens->Tok.getIdentifierInfo() == nullptr ||
LeftOfParens->is(tok::kw_return)) &&
- LeftOfParens->Type != TT_OverloadedOperator &&
- LeftOfParens->isNot(tok::at) &&
- LeftOfParens->Type != TT_TemplateCloser && Tok.Next) {
+ !LeftOfParens->isOneOf(TT_OverloadedOperator, tok::at,
+ TT_TemplateCloser)) {
if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) {
IsCast = true;
} else {
@@ -879,8 +989,9 @@ private:
if (Prev && Tok.Next && Tok.Next->Next) {
bool NextIsUnary = Tok.Next->isUnaryOperator() ||
Tok.Next->isOneOf(tok::amp, tok::star);
- IsCast = NextIsUnary && Tok.Next->Next->isOneOf(
- tok::identifier, tok::numeric_constant);
+ IsCast =
+ NextIsUnary && !Tok.Next->is(tok::plus) &&
+ Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant);
}
for (; Prev != Tok.MatchingParen; Prev = Prev->Previous) {
@@ -897,29 +1008,31 @@ private:
/// \brief Return the type of the given token assuming it is * or &.
TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
bool InTemplateArgument) {
+ if (Style.Language == FormatStyle::LK_JavaScript)
+ return TT_BinaryOperator;
+
const FormatToken *PrevToken = Tok.getPreviousNonComment();
if (!PrevToken)
return TT_UnaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment();
- if (!NextToken || NextToken->is(tok::l_brace))
+ if (!NextToken ||
+ (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
return TT_Unknown;
- if (PrevToken->is(tok::coloncolon) ||
- (PrevToken->is(tok::l_paren) && !IsExpression))
+ if (PrevToken->is(tok::coloncolon))
return TT_PointerOrReference;
if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace,
tok::comma, tok::semi, tok::kw_return, tok::colon,
tok::equal, tok::kw_delete, tok::kw_sizeof) ||
- PrevToken->Type == TT_BinaryOperator ||
- PrevToken->Type == TT_ConditionalExpr ||
- PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
+ PrevToken->isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
+ TT_UnaryOperator, TT_CastRParen))
return TT_UnaryOperator;
- if (NextToken->is(tok::l_square) && NextToken->Type != TT_LambdaLSquare)
+ if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))
return TT_PointerOrReference;
- if (NextToken->is(tok::kw_operator))
+ if (NextToken->isOneOf(tok::kw_operator, tok::comma))
return TT_PointerOrReference;
if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
@@ -930,7 +1043,7 @@ private:
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
- tok::kw_false) ||
+ tok::kw_false, tok::r_brace) ||
NextToken->Tok.isLiteral() ||
NextToken->isOneOf(tok::kw_true, tok::kw_false) ||
NextToken->isUnaryOperator() ||
@@ -940,6 +1053,10 @@ private:
(InTemplateArgument && NextToken->Tok.isAnyIdentifier()))
return TT_BinaryOperator;
+ // "&&(" is quite unlikely to be two successive unary "&".
+ if (Tok.is(tok::ampamp) && NextToken && NextToken->is(tok::l_paren))
+ return TT_BinaryOperator;
+
// This catches some cases where evaluation order is used as control flow:
// aaa && aaa->f();
const FormatToken *NextNextToken = NextToken->getNextNonComment();
@@ -948,7 +1065,7 @@ private:
// It is very unlikely that we are going to find a pointer or reference type
// definition on the RHS of an assignment.
- if (IsExpression)
+ if (IsExpression && !Contexts.back().CaretFound)
return TT_BinaryOperator;
return TT_PointerOrReference;
@@ -956,7 +1073,7 @@ private:
TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
- if (!PrevToken || PrevToken->Type == TT_CastRParen)
+ if (!PrevToken || PrevToken->is(TT_CastRParen))
return TT_UnaryOperator;
// Use heuristics to recognize unary operators.
@@ -966,7 +1083,7 @@ private:
return TT_UnaryOperator;
// There can't be two consecutive binary operators.
- if (PrevToken->Type == TT_BinaryOperator)
+ if (PrevToken->is(TT_BinaryOperator))
return TT_UnaryOperator;
// Fall back to marking the token as binary operator.
@@ -976,7 +1093,7 @@ private:
/// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
TokenType determineIncrementUsage(const FormatToken &Tok) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
- if (!PrevToken || PrevToken->Type == TT_CastRParen)
+ if (!PrevToken || PrevToken->is(TT_CastRParen))
return TT_UnaryOperator;
if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
return TT_TrailingUnaryOperator;
@@ -989,9 +1106,8 @@ private:
const FormatStyle &Style;
AnnotatedLine &Line;
FormatToken *CurrentToken;
- bool KeywordVirtualFound;
bool AutoFound;
- IdentifierInfo &Ident_in;
+ const AdditionalKeywords &Keywords;
};
static int PrecedenceUnaryOperator = prec::PointerToMember + 1;
@@ -1001,20 +1117,17 @@ static int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
/// operator precedence.
class ExpressionParser {
public:
- ExpressionParser(AnnotatedLine &Line) : Current(Line.First) {
- // Skip leading "}", e.g. in "} else if (...) {".
- if (Current->is(tok::r_brace))
- next();
- }
+ ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords,
+ AnnotatedLine &Line)
+ : Style(Style), Keywords(Keywords), Current(Line.First) {}
/// \brief Parse expressions with the given operatore precedence.
void parse(int Precedence = 0) {
// 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 ||
- Current->Type == TT_DictLiteral))))
+ while (Current && (Current->is(tok::kw_return) ||
+ (Current->is(tok::colon) &&
+ Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral))))
next();
if (!Current || Precedence > PrecedenceArrowAndPeriod)
@@ -1043,7 +1156,7 @@ public:
int CurrentPrecedence = getCurrentPrecedence();
- if (Current && Current->Type == TT_SelectorName &&
+ if (Current && Current->is(TT_SelectorName) &&
Precedence == CurrentPrecedence) {
if (LatestOperator)
addFakeParenthesis(Start, prec::Level(Precedence));
@@ -1052,18 +1165,11 @@ public:
// At the end of the line or when an operator with higher precedence is
// found, insert fake parenthesis and return.
- if (!Current || Current->closesScope() ||
- (CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) {
- if (LatestOperator) {
- LatestOperator->LastOperator = true;
- if (Precedence == PrecedenceArrowAndPeriod) {
- // Call expressions don't have a binary operator precedence.
- addFakeParenthesis(Start, prec::Unknown);
- } else {
- addFakeParenthesis(Start, prec::Level(Precedence));
- }
- }
- return;
+ if (!Current || (Current->closesScope() && Current->MatchingParen) ||
+ (CurrentPrecedence != -1 && CurrentPrecedence < Precedence) ||
+ (CurrentPrecedence == prec::Conditional &&
+ Precedence == prec::Assignment && Current->is(tok::colon))) {
+ break;
}
// Consume scopes: (), [], <> and {}
@@ -1080,8 +1186,17 @@ public:
Current->OperatorIndex = OperatorIndex;
++OperatorIndex;
}
+ next(/*SkipPastLeadingComments=*/Precedence > 0);
+ }
+ }
- next();
+ if (LatestOperator && (Current || Precedence > 0)) {
+ LatestOperator->LastOperator = true;
+ if (Precedence == PrecedenceArrowAndPeriod) {
+ // Call expressions don't have a binary operator precedence.
+ addFakeParenthesis(Start, prec::Unknown);
+ } else {
+ addFakeParenthesis(Start, prec::Level(Precedence));
}
}
}
@@ -1091,17 +1206,29 @@ private:
/// and other tokens that we treat like binary operators.
int getCurrentPrecedence() {
if (Current) {
- if (Current->Type == TT_ConditionalExpr)
+ const FormatToken *NextNonComment = Current->getNextNonComment();
+ if (Current->is(TT_ConditionalExpr))
return prec::Conditional;
- else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon ||
- Current->Type == TT_SelectorName)
+ else if (NextNonComment && NextNonComment->is(tok::colon) &&
+ NextNonComment->is(TT_DictLiteral))
+ return prec::Comma;
+ else if (Current->is(TT_LambdaArrow))
+ return prec::Comma;
+ else if (Current->isOneOf(tok::semi, TT_InlineASMColon,
+ TT_SelectorName) ||
+ (Current->is(tok::comment) && NextNonComment &&
+ NextNonComment->is(TT_SelectorName)))
return 0;
- else if (Current->Type == TT_RangeBasedForLoopColon)
+ else if (Current->is(TT_RangeBasedForLoopColon))
return prec::Comma;
- else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
+ else if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
return Current->getPrecedence();
else if (Current->isOneOf(tok::period, tok::arrow))
return PrecedenceArrowAndPeriod;
+ else if (Style.Language == FormatStyle::LK_Java &&
+ Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
+ Keywords.kw_throws))
+ return 0;
}
return -1;
}
@@ -1111,16 +1238,19 @@ private:
if (Precedence > prec::Unknown)
Start->StartsBinaryExpression = true;
if (Current) {
- ++Current->Previous->FakeRParens;
+ FormatToken *Previous = Current->Previous;
+ while (Previous->is(tok::comment) && Previous->Previous)
+ Previous = Previous->Previous;
+ ++Previous->FakeRParens;
if (Precedence > prec::Unknown)
- Current->Previous->EndsBinaryExpression = true;
+ Previous->EndsBinaryExpression = true;
}
}
/// \brief Parse unary operator expressions and surround them with fake
/// parentheses if appropriate.
void parseUnaryOperator() {
- if (!Current || Current->Type != TT_UnaryOperator) {
+ if (!Current || Current->isNot(TT_UnaryOperator)) {
parse(PrecedenceArrowAndPeriod);
return;
}
@@ -1134,33 +1264,40 @@ private:
}
void parseConditionalExpr() {
+ while (Current && Current->isTrailingComment()) {
+ next();
+ }
FormatToken *Start = Current;
parse(prec::LogicalOr);
if (!Current || !Current->is(tok::question))
return;
next();
- parseConditionalExpr();
- if (!Current || Current->Type != TT_ConditionalExpr)
+ parse(prec::Assignment);
+ if (!Current || Current->isNot(TT_ConditionalExpr))
return;
next();
- parseConditionalExpr();
+ parse(prec::Assignment);
addFakeParenthesis(Start, prec::Conditional);
}
- void next() {
+ void next(bool SkipPastLeadingComments = true) {
if (Current)
Current = Current->Next;
- while (Current && Current->isTrailingComment())
+ while (Current &&
+ (Current->NewlinesBefore == 0 || SkipPastLeadingComments) &&
+ Current->isTrailingComment())
Current = Current->Next;
}
+ const FormatStyle &Style;
+ const AdditionalKeywords &Keywords;
FormatToken *Current;
};
} // end anonymous namespace
-void
-TokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {
+void TokenAnnotator::setCommentLineLevels(
+ SmallVectorImpl<AnnotatedLine *> &Lines) {
const AnnotatedLine *NextNonCommentLine = nullptr;
for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
E = Lines.rend();
@@ -1181,19 +1318,19 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
I != E; ++I) {
annotate(**I);
}
- AnnotatingParser Parser(Style, Line, Ident_in);
+ AnnotatingParser Parser(Style, Line, Keywords);
Line.Type = Parser.parseLine();
if (Line.Type == LT_Invalid)
return;
- ExpressionParser ExprParser(Line);
+ ExpressionParser ExprParser(Style, Keywords, Line);
ExprParser.parse();
- if (Line.First->Type == TT_ObjCMethodSpecifier)
+ if (Line.First->is(TT_ObjCMethodSpecifier))
Line.Type = LT_ObjCMethodDecl;
- else if (Line.First->Type == TT_ObjCDecl)
+ else if (Line.First->is(TT_ObjCDecl))
Line.Type = LT_ObjCDecl;
- else if (Line.First->Type == TT_ObjCProperty)
+ else if (Line.First->is(TT_ObjCProperty))
Line.Type = LT_ObjCProperty;
Line.First->SpacesRequiredBefore = 1;
@@ -1203,13 +1340,11 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
// This function heuristically determines whether 'Current' starts the name of a
// function declaration.
static bool isFunctionDeclarationName(const FormatToken &Current) {
- if (Current.Type != TT_StartOfName ||
- Current.NestingLevel != 0 ||
- Current.Previous->Type == TT_StartOfName)
+ if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0)
return false;
const FormatToken *Next = Current.Next;
for (; Next; Next = Next->Next) {
- if (Next->Type == TT_TemplateOpener) {
+ if (Next->is(TT_TemplateOpener)) {
Next = Next->MatchingParen;
} else if (Next->is(tok::coloncolon)) {
Next = Next->Next;
@@ -1229,7 +1364,7 @@ static bool isFunctionDeclarationName(const FormatToken &Current) {
for (const FormatToken *Tok = Next->Next; Tok != Next->MatchingParen;
Tok = Tok->Next) {
if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
- Tok->Type == TT_PointerOrReference || Tok->Type == TT_StartOfName)
+ Tok->isOneOf(TT_PointerOrReference, TT_StartOfName))
return true;
if (Tok->isOneOf(tok::l_brace, tok::string_literal) || Tok->Tok.isLiteral())
return false;
@@ -1253,7 +1388,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
while (Current) {
if (isFunctionDeclarationName(*Current))
Current->Type = TT_FunctionDeclarationName;
- if (Current->Type == TT_LineComment) {
+ if (Current->is(TT_LineComment)) {
if (Current->Previous->BlockKind == BK_BracedInit &&
Current->Previous->opensScope())
Current->SpacesRequiredBefore = Style.Cpp11BracedListStyle ? 0 : 1;
@@ -1273,7 +1408,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
if (Parameter->isOneOf(tok::comment, tok::r_brace))
break;
if (Parameter->Previous && Parameter->Previous->is(tok::comma)) {
- if (Parameter->Previous->Type != TT_CtorInitializerComma &&
+ if (!Parameter->Previous->is(TT_CtorInitializerComma) &&
Parameter->HasUnescapedNewline)
Parameter->MustBreakBefore = true;
break;
@@ -1288,6 +1423,13 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
Current->MustBreakBefore =
Current->MustBreakBefore || mustBreakBefore(Line, *Current);
+ if (Style.AlwaysBreakAfterDefinitionReturnType && InFunctionDecl &&
+ Current->is(TT_FunctionDeclarationName) &&
+ !Line.Last->isOneOf(tok::semi, tok::comment)) // Only for definitions.
+ // FIXME: Line.Last points to other characters than tok::semi
+ // and tok::lbrace.
+ Current->MustBreakBefore = true;
+
Current->CanBreakBefore =
Current->MustBreakBefore || canBreakBefore(Line, *Current);
unsigned ChildSize = 0;
@@ -1296,15 +1438,17 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit
: LastOfChild.TotalLength + 1;
}
- if (Current->MustBreakBefore || Current->Previous->Children.size() > 1 ||
+ const FormatToken *Prev = Current->Previous;
+ if (Current->MustBreakBefore || Prev->Children.size() > 1 ||
+ (Prev->Children.size() == 1 &&
+ Prev->Children[0]->First->MustBreakBefore) ||
Current->IsMultiline)
- Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
+ Current->TotalLength = Prev->TotalLength + Style.ColumnLimit;
else
- Current->TotalLength = Current->Previous->TotalLength +
- Current->ColumnWidth + ChildSize +
- Current->SpacesRequiredBefore;
+ Current->TotalLength = Prev->TotalLength + Current->ColumnWidth +
+ ChildSize + Current->SpacesRequiredBefore;
- if (Current->Type == TT_CtorInitializerColon)
+ if (Current->is(TT_CtorInitializerColon))
InFunctionDecl = false;
// FIXME: Only calculate this if CanBreakBefore is true once static
@@ -1349,20 +1493,34 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::semi))
return 0;
+
+ if (Style.Language == FormatStyle::LK_Java) {
+ if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws))
+ return 1;
+ if (Right.is(Keywords.kw_implements))
+ return 2;
+ if (Left.is(tok::comma) && Left.NestingLevel == 0)
+ return 3;
+ } else if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Right.is(Keywords.kw_function))
+ return 100;
+ }
+
if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
- Right.Next->Type == TT_DictLiteral))
+ Right.Next->is(TT_DictLiteral)))
return 1;
if (Right.is(tok::l_square)) {
if (Style.Language == FormatStyle::LK_Proto)
return 1;
- if (Right.Type != TT_ObjCMethodExpr && Right.Type != TT_LambdaLSquare)
+ if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare))
return 500;
}
- if (Right.Type == TT_StartOfName ||
- Right.Type == TT_FunctionDeclarationName || Right.is(tok::kw_operator)) {
+
+ if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
+ Right.is(tok::kw_operator)) {
if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
- if (Left.Type == TT_StartOfName)
+ if (Left.is(TT_StartOfName))
return 20;
if (InFunctionDecl && Right.NestingLevel == 0)
return Style.PenaltyReturnTypeOnItsOwnLine;
@@ -1370,7 +1528,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
}
if (Left.is(tok::equal) && Right.is(tok::l_brace))
return 150;
- if (Left.Type == TT_CastRParen)
+ if (Left.is(TT_CastRParen))
return 100;
if (Left.is(tok::coloncolon) ||
(Right.is(tok::period) && Style.Language == FormatStyle::LK_Proto))
@@ -1378,8 +1536,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.isOneOf(tok::kw_class, tok::kw_struct))
return 5000;
- if (Left.Type == TT_RangeBasedForLoopColon ||
- Left.Type == TT_InheritanceColon)
+ if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon))
return 2;
if (Right.isMemberAccess()) {
@@ -1389,8 +1546,13 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 150;
}
- if (Right.Type == TT_TrailingAnnotation &&
+ if (Right.is(TT_TrailingAnnotation) &&
(!Right.Next || Right.Next->isNot(tok::l_paren))) {
+ // Moving trailing annotations to the next line is fine for ObjC method
+ // declarations.
+ if (Line.First->is(TT_ObjCMethodSpecifier))
+
+ return 10;
// Generally, breaking before a trailing annotation is bad unless it is
// function-like. It seems to be especially preferable to keep standard
// annotations (i.e. "const", "final" and "override") on the same line.
@@ -1406,18 +1568,27 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
// In Objective-C method expressions, prefer breaking before "param:" over
// breaking after it.
- if (Right.Type == TT_SelectorName)
+ if (Right.is(TT_SelectorName))
return 0;
- if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
+ if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr))
return Line.MightBeFunctionDecl ? 50 : 500;
- if (Left.is(tok::l_paren) && InFunctionDecl)
+ if (Left.is(tok::l_paren) && InFunctionDecl && Style.AlignAfterOpenBracket)
return 100;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
- if (Left.opensScope())
+ if (Right.is(tok::r_brace))
+ return 1;
+ if (Left.is(TT_TemplateOpener))
+ return 100;
+ if (Left.opensScope()) {
+ if (!Style.AlignAfterOpenBracket)
+ return 0;
return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
: 19;
+ }
+ if (Left.is(TT_JavaAnnotation))
+ return 50;
if (Right.is(tok::lessless)) {
if (Left.is(tok::string_literal)) {
@@ -1433,7 +1604,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
}
return 1; // Breaking at a << is really cheap.
}
- if (Left.Type == TT_ConditionalExpr)
+ if (Left.is(TT_ConditionalExpr))
return prec::Conditional;
prec::Level Level = Left.getPrecedence();
@@ -1446,18 +1617,6 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
const FormatToken &Left,
const FormatToken &Right) {
- if (Style.Language == FormatStyle::LK_Proto) {
- if (Right.is(tok::period) &&
- (Left.TokenText == "optional" || Left.TokenText == "required" ||
- Left.TokenText == "repeated"))
- return true;
- if (Right.is(tok::l_paren) &&
- (Left.TokenText == "returns" || Left.TokenText == "option"))
- return true;
- } else if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Left.TokenText == "var")
- return true;
- }
if (Left.is(tok::kw_return) && Right.isNot(tok::semi))
return true;
if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&
@@ -1470,21 +1629,16 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
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))
- return (Right.Type == TT_CastRParen ||
- (Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen))
+ return (Right.is(TT_CastRParen) ||
+ (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
? Style.SpacesInCStyleCastParentheses
: Style.SpacesInParentheses;
- if (Style.SpacesInAngles &&
- ((Left.Type == TT_TemplateOpener) != (Right.Type == TT_TemplateCloser)))
- return true;
if (Right.isOneOf(tok::semi, tok::comma))
return false;
if (Right.is(tok::less) &&
- (Left.is(tok::kw_template) ||
+ (Left.isOneOf(tok::kw_template, tok::r_paren) ||
(Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
return true;
- if (Left.is(tok::arrow) || Right.is(tok::arrow))
- return false;
if (Left.isOneOf(tok::exclaim, tok::tilde))
return false;
if (Left.is(tok::at) &&
@@ -1494,69 +1648,72 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
if (Left.is(tok::coloncolon))
return false;
- if (Right.is(tok::coloncolon) && Left.isNot(tok::l_brace))
- return (Left.is(tok::less) && Style.Standard == FormatStyle::LS_Cpp03) ||
- !Left.isOneOf(tok::identifier, tok::greater, tok::l_paren,
- tok::r_paren, tok::less);
if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
return false;
if (Right.is(tok::ellipsis))
return Left.Tok.isLiteral();
if (Left.is(tok::l_square) && Right.is(tok::amp))
return false;
- if (Right.Type == TT_PointerOrReference)
+ if (Right.is(TT_PointerOrReference))
return Left.Tok.isLiteral() ||
- ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
+ (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
Style.PointerAlignment != FormatStyle::PAS_Left);
- if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
- (Left.Type != TT_PointerOrReference || Style.PointerAlignment != FormatStyle::PAS_Right))
+ if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
+ (!Left.is(TT_PointerOrReference) ||
+ Style.PointerAlignment != FormatStyle::PAS_Right))
return true;
- if (Left.Type == TT_PointerOrReference)
- return Right.Tok.isLiteral() || Right.Type == TT_BlockComment ||
- ((Right.Type != TT_PointerOrReference) &&
- Right.isNot(tok::l_paren) && Style.PointerAlignment != FormatStyle::PAS_Right &&
- Left.Previous &&
+ if (Left.is(TT_PointerOrReference))
+ return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
+ (!Right.isOneOf(TT_PointerOrReference, tok::l_paren) &&
+ Style.PointerAlignment != FormatStyle::PAS_Right && Left.Previous &&
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
if (Left.is(tok::l_square))
- return Left.Type == TT_ArrayInitializerLSquare &&
- Style.SpacesInContainerLiterals && Right.isNot(tok::r_square);
+ return (Left.is(TT_ArrayInitializerLSquare) &&
+ Style.SpacesInContainerLiterals && Right.isNot(tok::r_square)) ||
+ (Left.is(TT_ArraySubscriptLSquare) && Style.SpacesInSquareBrackets &&
+ Right.isNot(tok::r_square));
if (Right.is(tok::r_square))
- return Right.MatchingParen && Style.SpacesInContainerLiterals &&
- Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
- if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
- Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant) &&
- Left.Type != TT_DictLiteral)
+ return Right.MatchingParen &&
+ ((Style.SpacesInContainerLiterals &&
+ Right.MatchingParen->is(TT_ArrayInitializerLSquare)) ||
+ (Style.SpacesInSquareBrackets &&
+ Right.MatchingParen->is(TT_ArraySubscriptLSquare)));
+ if (Right.is(tok::l_square) &&
+ !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare) &&
+ !Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
return false;
if (Left.is(tok::colon))
- return Left.Type != TT_ObjCMethodExpr;
- if (Left.Type == TT_BlockComment)
+ return !Left.is(TT_ObjCMethodExpr);
+ if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
+ return !Left.Children.empty(); // No spaces in "{}".
+ if ((Left.is(tok::l_brace) && Left.BlockKind != BK_Block) ||
+ (Right.is(tok::r_brace) && Right.MatchingParen &&
+ Right.MatchingParen->BlockKind != BK_Block))
+ return !Style.Cpp11BracedListStyle;
+ if (Left.is(TT_BlockComment))
return !Left.TokenText.endswith("=*/");
if (Right.is(tok::l_paren)) {
- if (Left.is(tok::r_paren) && Left.Type == TT_AttributeParen)
+ if (Left.is(tok::r_paren) && Left.is(TT_AttributeParen))
return true;
- return Line.Type == LT_ObjCDecl ||
- Left.isOneOf(tok::kw_new, tok::kw_delete, tok::semi) ||
+ return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
(Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while,
- tok::kw_switch, tok::kw_catch, tok::kw_case) ||
+ tok::kw_switch, tok::kw_case) ||
+ (Left.isOneOf(tok::kw_try, tok::kw_catch, tok::kw_new,
+ tok::kw_delete) &&
+ (!Left.Previous || Left.Previous->isNot(tok::period))) ||
Left.IsForEachMacro)) ||
(Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
- Left.isOneOf(tok::identifier, tok::kw___attribute) &&
+ (Left.is(tok::identifier) || Left.isFunctionLikeKeyword()) &&
Line.Type != LT_PreprocessorDirective);
}
if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
return false;
- if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
- return !Left.Children.empty(); // No spaces in "{}".
- if ((Left.is(tok::l_brace) && Left.BlockKind != BK_Block) ||
- (Right.is(tok::r_brace) && Right.MatchingParen &&
- Right.MatchingParen->BlockKind != BK_Block))
- return !Style.Cpp11BracedListStyle;
- if (Right.Type == TT_UnaryOperator)
+ if (Right.is(TT_UnaryOperator))
return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
- (Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
+ (Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr));
if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
tok::r_paren) ||
Left.isSimpleTypeSpecifier()) &&
@@ -1567,78 +1724,120 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L")
return false;
+ if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&
+ Left.MatchingParen->Previous &&
+ Left.MatchingParen->Previous->is(tok::period))
+ // A.<B>DoSomething();
+ return false;
+ if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
+ return false;
return true;
}
bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
- const FormatToken &Tok) {
- if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo())
+ const FormatToken &Right) {
+ const FormatToken &Left = *Right.Previous;
+ if (Style.Language == FormatStyle::LK_Proto) {
+ if (Right.is(tok::period) &&
+ Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
+ Keywords.kw_repeated))
+ return true;
+ if (Right.is(tok::l_paren) &&
+ Left.isOneOf(Keywords.kw_returns, Keywords.kw_option))
+ return true;
+ } else if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Left.is(Keywords.kw_var))
+ return true;
+ } else if (Style.Language == FormatStyle::LK_Java) {
+ if (Left.is(tok::r_square) && Right.is(tok::l_brace))
+ return true;
+ if (Left.is(TT_LambdaArrow) || Right.is(TT_LambdaArrow))
+ return true;
+ if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren))
+ return Style.SpaceBeforeParens != FormatStyle::SBPO_Never;
+ if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
+ tok::kw_protected) ||
+ Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
+ Keywords.kw_native)) &&
+ Right.is(TT_TemplateOpener))
+ return true;
+ }
+ if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
return true; // Never ever merge two identifiers.
- if (Tok.Previous->Type == TT_ImplicitStringLiteral)
- return Tok.WhitespaceRange.getBegin() != Tok.WhitespaceRange.getEnd();
+ if (Left.is(TT_ImplicitStringLiteral))
+ return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
if (Line.Type == LT_ObjCMethodDecl) {
- if (Tok.Previous->Type == TT_ObjCMethodSpecifier)
+ if (Left.is(TT_ObjCMethodSpecifier))
return true;
- if (Tok.Previous->is(tok::r_paren) && Tok.is(tok::identifier))
+ if (Left.is(tok::r_paren) && Right.is(tok::identifier))
// Don't space between ')' and <id>
return false;
}
if (Line.Type == LT_ObjCProperty &&
- (Tok.is(tok::equal) || Tok.Previous->is(tok::equal)))
+ (Right.is(tok::equal) || Left.is(tok::equal)))
return false;
- if (Tok.Type == TT_TrailingReturnArrow ||
- Tok.Previous->Type == TT_TrailingReturnArrow)
+ if (Right.is(TT_TrailingReturnArrow) || Left.is(TT_TrailingReturnArrow))
return true;
- if (Tok.Previous->is(tok::comma))
+ if (Left.is(tok::comma))
return true;
- if (Tok.is(tok::comma))
+ if (Right.is(tok::comma))
return false;
- if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
+ if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen))
return true;
- if (Tok.Previous->Tok.is(tok::kw_operator))
- return Tok.is(tok::coloncolon);
- if (Tok.Type == TT_OverloadedOperatorLParen)
+ if (Left.is(tok::kw_operator))
+ return Right.is(tok::coloncolon);
+ if (Right.is(TT_OverloadedOperatorLParen))
return false;
- if (Tok.is(tok::colon))
+ if (Right.is(tok::colon))
return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
- Tok.getNextNonComment() && Tok.Type != TT_ObjCMethodExpr &&
- !Tok.Previous->is(tok::question) &&
- (Tok.Type != TT_DictLiteral || Style.SpacesInContainerLiterals);
- if (Tok.Previous->Type == TT_UnaryOperator ||
- Tok.Previous->Type == TT_CastRParen)
- return Tok.Type == TT_BinaryOperator;
- if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) {
- return Tok.Type == TT_TemplateCloser &&
- Tok.Previous->Type == TT_TemplateCloser &&
+ Right.getNextNonComment() && Right.isNot(TT_ObjCMethodExpr) &&
+ !Left.is(tok::question) &&
+ !(Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon)) &&
+ (Right.isNot(TT_DictLiteral) || Style.SpacesInContainerLiterals);
+ if (Left.is(TT_UnaryOperator))
+ return Right.is(TT_BinaryOperator);
+ if (Left.is(TT_CastRParen))
+ return Style.SpaceAfterCStyleCast || Right.is(TT_BinaryOperator);
+ if (Left.is(tok::greater) && Right.is(tok::greater)) {
+ return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
(Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
}
- if (Tok.isOneOf(tok::arrowstar, tok::periodstar) ||
- Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar))
+ if (Right.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
+ Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar))
return false;
if (!Style.SpaceBeforeAssignmentOperators &&
- Tok.getPrecedence() == prec::Assignment)
+ Right.getPrecedence() == prec::Assignment)
return false;
- if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) ||
- Tok.Previous->Type == TT_BinaryOperator ||
- Tok.Previous->Type == TT_ConditionalExpr)
+ if (Right.is(tok::coloncolon) && Left.isNot(tok::l_brace))
+ return (Left.is(TT_TemplateOpener) &&
+ Style.Standard == FormatStyle::LS_Cpp03) ||
+ !(Left.isOneOf(tok::identifier, tok::l_paren, tok::r_paren) ||
+ Left.isOneOf(TT_TemplateCloser, TT_TemplateOpener));
+ if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
+ return Style.SpacesInAngles;
+ if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
+ Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr))
return true;
- if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
+ if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren))
+ return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
+ if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
+ Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
return false;
- if (Tok.is(tok::less) && Tok.Previous->isNot(tok::l_paren) &&
+ if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
Line.First->is(tok::hash))
return true;
- if (Tok.Type == TT_TrailingUnaryOperator)
+ if (Right.is(TT_TrailingUnaryOperator))
return false;
- if (Tok.Previous->Type == TT_RegexLiteral)
+ if (Left.is(TT_RegexLiteral))
return false;
- return spaceRequiredBetween(Line, *Tok.Previous, Tok);
+ return spaceRequiredBetween(Line, Left, Right);
}
// Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.
static bool isAllmanBrace(const FormatToken &Tok) {
return Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block &&
- Tok.Type != TT_ObjCBlockLBrace && Tok.Type != TT_DictLiteral;
+ !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral);
}
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
@@ -1646,54 +1845,66 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
const FormatToken &Left = *Right.Previous;
if (Right.NewlinesBefore > 1)
return true;
- if (Right.is(tok::comment)) {
- return Right.Previous->BlockKind != BK_BracedInit &&
- Right.Previous->Type != TT_CtorInitializerColon &&
+
+ // If the last token before a '}' is a comma or a trailing comment, the
+ // intention is to insert a line break after it in order to make shuffling
+ // around entries easier.
+ const FormatToken *BeforeClosingBrace = nullptr;
+ if (Left.is(tok::l_brace) && Left.BlockKind != BK_Block && Left.MatchingParen)
+ BeforeClosingBrace = Left.MatchingParen->Previous;
+ else if (Right.is(tok::r_brace) && Right.BlockKind != BK_Block)
+ BeforeClosingBrace = &Left;
+ if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
+ BeforeClosingBrace->isTrailingComment()))
+ return true;
+
+ if (Right.is(tok::comment))
+ return Left.BlockKind != BK_BracedInit &&
+ Left.isNot(TT_CtorInitializerColon) &&
(Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
- } else if (Right.Previous->isTrailingComment() ||
- (Right.isStringLiteral() && Right.Previous->isStringLiteral())) {
+ if (Right.Previous->isTrailingComment() ||
+ (Right.isStringLiteral() && Right.Previous->isStringLiteral()))
return true;
- } else if (Right.Previous->IsUnterminatedLiteral) {
+ 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)) {
+ 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 &&
- Right.Previous->MatchingParen->NestingLevel == 0 &&
- Style.AlwaysBreakTemplateDeclarations) {
+ if (Right.Previous->ClosesTemplateDeclaration &&
+ Right.Previous->MatchingParen &&
+ Right.Previous->MatchingParen->NestingLevel == 0 &&
+ Style.AlwaysBreakTemplateDeclarations)
return true;
- } else if ((Right.Type == TT_CtorInitializerComma ||
- Right.Type == TT_CtorInitializerColon) &&
- Style.BreakConstructorInitializersBeforeComma &&
- !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
+ if ((Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) &&
+ Style.BreakConstructorInitializersBeforeComma &&
+ !Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
return true;
- } else if (Right.is(tok::string_literal) &&
- Right.TokenText.startswith("R\"")) {
+ if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\""))
// Raw string literals are special wrt. line breaks. The author has made a
// deliberate choice and might have aligned the contents of the string
// literal accordingly. Thus, we try keep existing line breaks.
return Right.NewlinesBefore > 0;
- } else if (Right.Previous->is(tok::l_brace) && Right.NestingLevel == 1 &&
- Style.Language == FormatStyle::LK_Proto) {
- // Don't enums onto single lines in protocol buffers.
+ if (Right.Previous->is(tok::l_brace) && Right.NestingLevel == 1 &&
+ Style.Language == FormatStyle::LK_Proto)
+ // Don't put enums onto single lines in protocol buffers.
return true;
- } else if (isAllmanBrace(Left) || isAllmanBrace(Right)) {
+ if (Style.Language == FormatStyle::LK_JavaScript && Right.is(tok::r_brace) &&
+ Left.is(tok::l_brace) && !Left.Children.empty())
+ // Support AllowShortFunctionsOnASingleLine for JavaScript.
+ return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
+ (Left.NestingLevel == 0 && Line.Level == 0 &&
+ Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline);
+ if (isAllmanBrace(Left) || isAllmanBrace(Right))
return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU;
- }
-
- // If the last token before a '}' is a comma or a comment, the intention is to
- // insert a line break after it in order to make shuffling around entries
- // easier.
- const FormatToken *BeforeClosingBrace = nullptr;
- if (Left.is(tok::l_brace) && Left.MatchingParen)
- BeforeClosingBrace = Left.MatchingParen->Previous;
- else if (Right.is(tok::r_brace))
- BeforeClosingBrace = Right.Previous;
- if (BeforeClosingBrace &&
- BeforeClosingBrace->isOneOf(tok::comma, tok::comment))
+ if (Style.Language == FormatStyle::LK_Proto && Left.isNot(tok::l_brace) &&
+ Right.is(TT_SelectorName))
+ return true;
+ if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine)
+ return true;
+ if (Right.is(tok::lessless) && Left.is(tok::identifier) &&
+ Left.TokenText == "endl")
return true;
if (Style.Language == FormatStyle::LK_JavaScript) {
@@ -1701,6 +1912,17 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous &&
Left.Previous->is(tok::char_constant))
return true;
+ if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) &&
+ Left.NestingLevel == 0)
+ return true;
+ } else if (Style.Language == FormatStyle::LK_Java) {
+ if (Left.is(TT_LeadingJavaAnnotation) &&
+ Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
+ Line.Last->is(tok::l_brace))
+ return true;
+ if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
+ Right.Next->is(tok::string_literal))
+ return true;
}
return false;
@@ -1709,12 +1931,24 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
+
+ if (Style.Language == FormatStyle::LK_Java) {
+ if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
+ Keywords.kw_implements))
+ return false;
+ if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
+ Keywords.kw_implements))
+ return true;
+ }
+
if (Left.is(tok::at))
return false;
if (Left.Tok.getObjCKeywordID() == tok::objc_interface)
return false;
- if (Right.Type == TT_StartOfName ||
- Right.Type == TT_FunctionDeclarationName || Right.is(tok::kw_operator))
+ if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation))
+ return !Right.is(tok::l_paren);
+ if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
+ Right.is(tok::kw_operator))
return true;
if (Right.isTrailingComment())
// We rely on MustBreakBefore being set correctly here as we should not
@@ -1725,47 +1959,46 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return Left.BlockKind == BK_BracedInit;
if (Left.is(tok::question) && Right.is(tok::colon))
return false;
- if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
+ if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))
return Style.BreakBeforeTernaryOperators;
- if (Left.Type == TT_ConditionalExpr || Left.is(tok::question))
+ if (Left.is(TT_ConditionalExpr) || Left.is(tok::question))
return !Style.BreakBeforeTernaryOperators;
- if (Right.Type == TT_InheritanceColon)
+ if (Right.is(TT_InheritanceColon))
return true;
- if (Right.is(tok::colon) && (Right.Type != TT_CtorInitializerColon &&
- Right.Type != TT_InlineASMColon))
+ if (Right.is(tok::colon) &&
+ !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon))
return false;
- if (Left.is(tok::colon) &&
- (Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr))
+ if (Left.is(tok::colon) && (Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))
return true;
- if (Right.Type == TT_SelectorName)
+ if (Right.is(TT_SelectorName))
return true;
if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
return true;
if (Left.ClosesTemplateDeclaration)
return true;
- if (Right.Type == TT_RangeBasedForLoopColon ||
- Right.Type == TT_OverloadedOperatorLParen ||
- Right.Type == TT_OverloadedOperator)
+ if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen,
+ TT_OverloadedOperator))
return false;
- if (Left.Type == TT_RangeBasedForLoopColon)
+ if (Left.is(TT_RangeBasedForLoopColon))
return true;
- if (Right.Type == TT_RangeBasedForLoopColon)
+ if (Right.is(TT_RangeBasedForLoopColon))
return false;
- if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
- Left.Type == TT_UnaryOperator || Left.is(tok::kw_operator))
+ if (Left.isOneOf(TT_PointerOrReference, TT_TemplateCloser,
+ TT_UnaryOperator) ||
+ Left.is(tok::kw_operator))
return false;
if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
return false;
- if (Left.is(tok::l_paren) && Left.Type == TT_AttributeParen)
+ if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen))
return false;
if (Left.is(tok::l_paren) && Left.Previous &&
- (Left.Previous->Type == TT_BinaryOperator ||
- Left.Previous->Type == TT_CastRParen || Left.Previous->is(tok::kw_if)))
+ (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen) ||
+ Left.Previous->is(tok::kw_if)))
return false;
- if (Right.Type == TT_ImplicitStringLiteral)
+ if (Right.is(TT_ImplicitStringLiteral))
return false;
- if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)
+ if (Right.is(tok::r_paren) || Right.is(TT_TemplateCloser))
return false;
// We only break before r_brace if there was a corresponding break before
@@ -1775,7 +2008,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// Allow breaking after a trailing annotation, e.g. after a method
// declaration.
- if (Left.Type == TT_TrailingAnnotation)
+ if (Left.is(TT_TrailingAnnotation))
return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,
tok::less, tok::coloncolon);
@@ -1785,29 +2018,35 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Left.is(tok::identifier) && Right.is(tok::string_literal))
return true;
- if (Right.is(tok::identifier) && Right.Next &&
- Right.Next->Type == TT_DictLiteral)
+ if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
return true;
- if (Left.Type == TT_CtorInitializerComma &&
+ if (Left.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
return false;
- if (Right.Type == TT_CtorInitializerComma &&
+ if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
return true;
if (Left.is(tok::greater) && Right.is(tok::greater) &&
- Left.Type != TT_TemplateCloser)
+ Left.isNot(TT_TemplateCloser))
return false;
- if (Right.Type == TT_BinaryOperator && Style.BreakBeforeBinaryOperators)
+ if (Right.is(TT_BinaryOperator) &&
+ Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None &&
+ (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All ||
+ Right.getPrecedence() != prec::Assignment))
+ return true;
+ if (Left.is(TT_ArrayInitializerLSquare))
+ return true;
+ if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const))
return true;
- if (Left.Type == TT_ArrayInitializerLSquare)
+ if (Left.isBinaryOperator() && !Left.isOneOf(tok::arrowstar, tok::lessless) &&
+ Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All &&
+ (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||
+ Left.getPrecedence() == prec::Assignment))
return true;
- return (Left.isBinaryOperator() &&
- !Left.isOneOf(tok::arrowstar, tok::lessless) &&
- !Style.BreakBeforeBinaryOperators) ||
- Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
+ return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct) ||
- Right.isMemberAccess() ||
+ Right.isMemberAccess() || Right.is(TT_TrailingReturnArrow) ||
Right.isOneOf(tok::lessless, tok::colon, tok::l_square, tok::at) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const)) ||