summaryrefslogtreecommitdiff
path: root/lib/Format/TokenAnnotator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Format/TokenAnnotator.cpp')
-rw-r--r--lib/Format/TokenAnnotator.cpp132
1 files changed, 103 insertions, 29 deletions
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 490c4f46135e2..1ed35597d075d 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -15,6 +15,7 @@
#include "TokenAnnotator.h"
#include "FormatToken.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
@@ -40,6 +41,21 @@ static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
return Tok.Tok.getIdentifierInfo() != nullptr;
}
+/// With `Left` being '(', check if we're at either `[...](` or
+/// `[...]<...>(`, where the [ opens a lambda capture list.
+static bool isLambdaParameterList(const FormatToken *Left) {
+ // Skip <...> if present.
+ if (Left->Previous && Left->Previous->is(tok::greater) &&
+ Left->Previous->MatchingParen &&
+ Left->Previous->MatchingParen->is(TT_TemplateOpener))
+ Left = Left->Previous->MatchingParen;
+
+ // Check for `[...]`.
+ return Left->Previous && Left->Previous->is(tok::r_square) &&
+ Left->Previous->MatchingParen &&
+ Left->Previous->MatchingParen->is(TT_LambdaLSquare);
+}
+
/// A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
@@ -175,9 +191,9 @@ private:
Contexts.back().IsExpression = false;
} else if (Left->Previous &&
(Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
- tok::kw_if, tok::kw_while, tok::l_paren,
+ tok::kw_while, tok::l_paren,
tok::comma) ||
- Left->Previous->endsSequence(tok::kw_constexpr, tok::kw_if) ||
+ Left->Previous->isIf() ||
Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
@@ -191,9 +207,7 @@ private:
Left->Previous->is(TT_JsTypeColon)) {
// let x: (SomeType);
Contexts.back().IsExpression = false;
- } else if (Left->Previous && Left->Previous->is(tok::r_square) &&
- Left->Previous->MatchingParen &&
- Left->Previous->MatchingParen->is(TT_LambdaLSquare)) {
+ } else if (isLambdaParameterList(Left)) {
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
} else if (Line.InPPDirective &&
@@ -382,6 +396,12 @@ private:
Keywords.kw_internal)) {
return true;
}
+
+ // incase its a [XXX] retval func(....
+ if (AttrTok->Next &&
+ AttrTok->Next->startsSequence(tok::identifier, tok::l_paren))
+ return true;
+
return false;
}
@@ -476,6 +496,8 @@ private:
} else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->Type = TT_DesignatedInitializerLSquare;
+ } else if (IsCSharp11AttributeSpecifier) {
+ Left->Type = TT_AttributeSquare;
} else if (CurrentToken->is(tok::r_square) && Parent &&
Parent->is(TT_TemplateCloser)) {
Left->Type = TT_ArraySubscriptLSquare;
@@ -523,8 +545,6 @@ private:
// Should only be relevant to JavaScript:
tok::kw_default)) {
Left->Type = TT_ArrayInitializerLSquare;
- } else if (IsCSharp11AttributeSpecifier) {
- Left->Type = TT_AttributeSquare;
} else {
BindingIncrease = 10;
Left->Type = TT_ArraySubscriptLSquare;
@@ -826,7 +846,7 @@ private:
case tok::kw_if:
case tok::kw_while:
if (Tok->is(tok::kw_if) && CurrentToken &&
- CurrentToken->is(tok::kw_constexpr))
+ CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier))
next();
if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
@@ -918,6 +938,8 @@ private:
case tok::greater:
if (Style.Language != FormatStyle::LK_TextProto)
Tok->Type = TT_BinaryOperator;
+ if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))
+ Tok->SpacesRequiredBefore = 1;
break;
case tok::kw_operator:
if (Style.Language == FormatStyle::LK_TextProto ||
@@ -1078,6 +1100,7 @@ private:
case tok::pp_if:
case tok::pp_elif:
Contexts.back().IsExpression = true;
+ next();
parseLine();
break;
default:
@@ -1097,6 +1120,8 @@ private:
public:
LineType parseLine() {
+ if (!CurrentToken)
+ return LT_Invalid;
NonTemplateLess.clear();
if (CurrentToken->is(tok::hash))
return parsePreprocessorDirective();
@@ -1368,7 +1393,9 @@ private:
Style.Language == FormatStyle::LK_Java) {
Current.Type = TT_LambdaArrow;
} else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration &&
- Current.NestingLevel == 0) {
+ Current.NestingLevel == 0 &&
+ !Current.Previous->is(tok::kw_operator)) {
+ // not auto operator->() -> xxx;
Current.Type = TT_TrailingReturnArrow;
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
Current.Type = determineStarAmpUsage(Current,
@@ -1467,7 +1494,8 @@ private:
// colon after this, this is the only place which annotates the identifier
// as a selector.)
Current.Type = TT_SelectorName;
- } else if (Current.isOneOf(tok::identifier, tok::kw_const) &&
+ } else if (Current.isOneOf(tok::identifier, tok::kw_const,
+ tok::kw_noexcept) &&
Current.Previous &&
!Current.Previous->isOneOf(tok::equal, tok::at) &&
Line.MightBeFunctionDecl && Contexts.size() == 1) {
@@ -1576,6 +1604,14 @@ private:
if (Tok.Next->is(tok::question))
return false;
+ // Functions which end with decorations like volatile, noexcept are unlikely
+ // to be casts.
+ if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
+ tok::kw_throw, tok::arrow, Keywords.kw_override,
+ Keywords.kw_final) ||
+ isCpp11AttributeSpecifier(*Tok.Next))
+ return false;
+
// As Java has no function types, a "(" after the ")" likely means that this
// is a cast.
if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
@@ -1647,7 +1683,8 @@ private:
const FormatToken *NextToken = Tok.getNextNonComment();
if (!NextToken ||
- NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_const) ||
+ NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_const,
+ tok::kw_noexcept) ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
return TT_PointerOrReference;
@@ -1720,7 +1757,7 @@ private:
// Use heuristics to recognize unary operators.
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))
+ tok::kw_case, tok::at, tok::l_brace, tok::kw_throw))
return TT_UnaryOperator;
// There can't be two consecutive binary operators.
@@ -2160,7 +2197,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
if (Current->is(TT_LineComment)) {
if (Current->Previous->BlockKind == BK_BracedInit &&
Current->Previous->opensScope())
- Current->SpacesRequiredBefore = Style.Cpp11BracedListStyle ? 0 : 1;
+ Current->SpacesRequiredBefore =
+ (Style.Cpp11BracedListStyle && !Style.SpacesInParentheses) ? 0 : 1;
else
Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
@@ -2409,8 +2447,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
return 100;
if (Left.is(tok::l_paren) && Left.Previous &&
- (Left.Previous->isOneOf(tok::kw_if, tok::kw_for) ||
- Left.Previous->endsSequence(tok::kw_constexpr, tok::kw_if)))
+ (Left.Previous->is(tok::kw_for) || Left.Previous->isIf()))
return 1000;
if (Left.is(tok::equal) && InFunctionDecl)
return 110;
@@ -2429,6 +2466,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(TT_JavaAnnotation))
return 50;
+ if (Left.is(TT_UnaryOperator))
+ return 60;
if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&
Left.Previous->isLabelString() &&
(Left.NextOperator || Left.OperatorIndex != 0))
@@ -2483,7 +2522,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Left.is(tok::hash);
if (Left.isOneOf(tok::hashhash, tok::hash))
return Right.is(tok::hash);
- if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
+ if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
+ (Left.is(tok::l_brace) && Left.BlockKind != BK_Block &&
+ Right.is(tok::r_brace) && Right.BlockKind != BK_Block))
return Style.SpaceInEmptyParentheses;
if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
return (Right.is(TT_CastRParen) ||
@@ -2560,7 +2601,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Style.PointerAlignment != FormatStyle::PAS_Right &&
!Line.IsMultiVariableDeclStmt) &&
Left.Previous &&
- !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
+ !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon,
+ tok::l_square));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
const auto SpaceRequiredForArrayInitializerLSquare =
@@ -2575,8 +2617,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::l_square))
return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
- (Left.isOneOf(TT_ArraySubscriptLSquare,
- TT_StructuredBindingLSquare) &&
+ (Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare,
+ TT_LambdaLSquare) &&
Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
if (Right.is(tok::r_square))
return Right.MatchingParen &&
@@ -2585,7 +2627,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Style)) ||
(Style.SpacesInSquareBrackets &&
Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
- TT_StructuredBindingLSquare)) ||
+ TT_StructuredBindingLSquare,
+ TT_LambdaLSquare)) ||
Right.MatchingParen->is(TT_AttributeParen));
if (Right.is(tok::l_square) &&
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
@@ -2598,7 +2641,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
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;
+ return Style.Cpp11BracedListStyle ? Style.SpacesInParentheses : true;
if (Left.is(TT_BlockComment))
// No whitespace in x(/*foo=*/1), except for JavaScript.
return Style.Language == FormatStyle::LK_JavaScript ||
@@ -2609,10 +2652,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return true;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
- (Left.isOneOf(tok::kw_if, tok::pp_elif, tok::kw_for, tok::kw_while,
+ (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,
tok::kw_switch, tok::kw_case, TT_ForEachMacro,
TT_ObjCForIn) ||
- Left.endsSequence(tok::kw_constexpr, tok::kw_if) ||
+ Left.isIf(Line.Type != LT_PreprocessorDirective) ||
(Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
tok::kw_new, tok::kw_delete) &&
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
@@ -2655,6 +2698,14 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at))
// Objective-C dictionary literal -> no space before closing brace.
return false;
+ if (Right.Type == TT_TrailingAnnotation &&
+ Right.isOneOf(tok::amp, tok::ampamp) &&
+ Left.isOneOf(tok::kw_const, tok::kw_volatile) &&
+ (!Right.Next || Right.Next->is(tok::semi)))
+ // Match const and volatile ref-qualifiers without any additional
+ // qualifiers such as
+ // void Fn() const &;
+ return Style.PointerAlignment != FormatStyle::PAS_Left;
return true;
}
@@ -2694,7 +2745,15 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// and "%d %d"
if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
return Right.WhitespaceRange.getEnd() != Right.WhitespaceRange.getBegin();
- } else if (Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) {
+ } else if (Style.isCSharp()) {
+ // space between type and variable e.g. Dictionary<string,string> foo;
+ if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))
+ return true;
+ // space between keywords and paren e.g. "using ("
+ if (Right.is(tok::l_paren))
+ if (Left.is(tok::kw_using))
+ return spaceRequiredBeforeParens(Left);
+ } else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
// for await ( ...
@@ -2739,6 +2798,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
tok::kw_void))
return true;
}
+ // `foo as const;` casts into a const type.
+ if (Left.endsSequence(tok::kw_const, Keywords.kw_as)) {
+ return false;
+ }
if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
tok::kw_const) ||
// "of" is only a keyword if it appears after another identifier
@@ -2842,9 +2905,19 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
return true;
}
- if (Left.is(TT_UnaryOperator))
+ if (Left.is(TT_UnaryOperator)) {
+ // The alternative operators for ~ and ! are "compl" and "not".
+ // If they are used instead, we do not want to combine them with
+ // the token to the right, unless that is a left paren.
+ if (!Right.is(tok::l_paren)) {
+ if (Left.is(tok::exclaim) && Left.TokenText == "not")
+ return true;
+ if (Left.is(tok::tilde) && Left.TokenText == "compl")
+ return true;
+ }
return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
Right.is(TT_BinaryOperator);
+ }
// If the next token is a binary operator or a selector name, we have
// incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
@@ -2857,13 +2930,13 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
(Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
return !Style.Cpp11BracedListStyle;
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
- (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
+ (Style.Standard < FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
}
if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
(Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
return false;
- if (!Style.SpaceBeforeAssignmentOperators &&
+ if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&
Right.getPrecedence() == prec::Assignment)
return false;
if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) &&
@@ -2876,7 +2949,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment))
return (Left.is(TT_TemplateOpener) &&
- Style.Standard == FormatStyle::LS_Cpp03) ||
+ Style.Standard < FormatStyle::LS_Cpp11) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
tok::kw___super, TT_TemplateCloser,
TT_TemplateOpener)) ||
@@ -3039,7 +3112,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Style.BraceWrapping.AfterEnum) ||
(Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
(Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
- if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine)
+ if (Left.is(TT_ObjCBlockLBrace) &&
+ Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
return true;
if (Left.is(TT_LambdaLBrace)) {