Path: blob/main/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
35233 views
//===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file implements a token annotator, i.e. creates10/// \c AnnotatedTokens out of \c FormatTokens with required extra information.11///12//===----------------------------------------------------------------------===//1314#include "TokenAnnotator.h"15#include "FormatToken.h"16#include "clang/Basic/SourceManager.h"17#include "clang/Basic/TokenKinds.h"18#include "llvm/ADT/SmallPtrSet.h"19#include "llvm/Support/Debug.h"2021#define DEBUG_TYPE "format-token-annotator"2223namespace clang {24namespace format {2526static bool mustBreakAfterAttributes(const FormatToken &Tok,27const FormatStyle &Style) {28switch (Style.BreakAfterAttributes) {29case FormatStyle::ABS_Always:30return true;31case FormatStyle::ABS_Leave:32return Tok.NewlinesBefore > 0;33default:34return false;35}36}3738namespace {3940/// Returns \c true if the line starts with a token that can start a statement41/// with an initializer.42static bool startsWithInitStatement(const AnnotatedLine &Line) {43return Line.startsWith(tok::kw_for) || Line.startsWith(tok::kw_if) ||44Line.startsWith(tok::kw_switch);45}4647/// Returns \c true if the token can be used as an identifier in48/// an Objective-C \c \@selector, \c false otherwise.49///50/// Because getFormattingLangOpts() always lexes source code as51/// Objective-C++, C++ keywords like \c new and \c delete are52/// lexed as tok::kw_*, not tok::identifier, even for Objective-C.53///54/// For Objective-C and Objective-C++, both identifiers and keywords55/// are valid inside @selector(...) (or a macro which56/// invokes @selector(...)). So, we allow treat any identifier or57/// keyword as a potential Objective-C selector component.58static bool canBeObjCSelectorComponent(const FormatToken &Tok) {59return Tok.Tok.getIdentifierInfo();60}6162/// With `Left` being '(', check if we're at either `[...](` or63/// `[...]<...>(`, where the [ opens a lambda capture list.64static bool isLambdaParameterList(const FormatToken *Left) {65// Skip <...> if present.66if (Left->Previous && Left->Previous->is(tok::greater) &&67Left->Previous->MatchingParen &&68Left->Previous->MatchingParen->is(TT_TemplateOpener)) {69Left = Left->Previous->MatchingParen;70}7172// Check for `[...]`.73return Left->Previous && Left->Previous->is(tok::r_square) &&74Left->Previous->MatchingParen &&75Left->Previous->MatchingParen->is(TT_LambdaLSquare);76}7778/// Returns \c true if the token is followed by a boolean condition, \c false79/// otherwise.80static bool isKeywordWithCondition(const FormatToken &Tok) {81return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,82tok::kw_constexpr, tok::kw_catch);83}8485/// Returns \c true if the token starts a C++ attribute, \c false otherwise.86static bool isCppAttribute(bool IsCpp, const FormatToken &Tok) {87if (!IsCpp || !Tok.startsSequence(tok::l_square, tok::l_square))88return false;89// The first square bracket is part of an ObjC array literal90if (Tok.Previous && Tok.Previous->is(tok::at))91return false;92const FormatToken *AttrTok = Tok.Next->Next;93if (!AttrTok)94return false;95// C++17 '[[using ns: foo, bar(baz, blech)]]'96// We assume nobody will name an ObjC variable 'using'.97if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))98return true;99if (AttrTok->isNot(tok::identifier))100return false;101while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {102// ObjC message send. We assume nobody will use : in a C++11 attribute103// specifier parameter, although this is technically valid:104// [[foo(:)]].105if (AttrTok->is(tok::colon) ||106AttrTok->startsSequence(tok::identifier, tok::identifier) ||107AttrTok->startsSequence(tok::r_paren, tok::identifier)) {108return false;109}110if (AttrTok->is(tok::ellipsis))111return true;112AttrTok = AttrTok->Next;113}114return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);115}116117/// A parser that gathers additional information about tokens.118///119/// The \c TokenAnnotator tries to match parenthesis and square brakets and120/// store a parenthesis levels. It also tries to resolve matching "<" and ">"121/// into template parameter lists.122class AnnotatingParser {123public:124AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,125const AdditionalKeywords &Keywords,126SmallVector<ScopeType> &Scopes)127: Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),128IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),129Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) {130assert(IsCpp == LangOpts.CXXOperatorNames);131Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));132resetTokenMetadata();133}134135private:136ScopeType getScopeType(const FormatToken &Token) const {137switch (Token.getType()) {138case TT_FunctionLBrace:139case TT_LambdaLBrace:140return ST_Function;141case TT_ClassLBrace:142case TT_StructLBrace:143case TT_UnionLBrace:144return ST_Class;145default:146return ST_Other;147}148}149150bool parseAngle() {151if (!CurrentToken || !CurrentToken->Previous)152return false;153if (NonTemplateLess.count(CurrentToken->Previous) > 0)154return false;155156if (const auto &Previous = *CurrentToken->Previous; // The '<'.157Previous.Previous) {158if (Previous.Previous->Tok.isLiteral())159return false;160if (Previous.Previous->is(tok::r_brace))161return false;162if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 &&163(!Previous.Previous->MatchingParen ||164Previous.Previous->MatchingParen->isNot(165TT_OverloadedOperatorLParen))) {166return false;167}168if (Previous.Previous->is(tok::kw_operator) &&169CurrentToken->is(tok::l_paren)) {170return false;171}172}173174FormatToken *Left = CurrentToken->Previous;175Left->ParentBracket = Contexts.back().ContextKind;176ScopedContextCreator ContextCreator(*this, tok::less, 12);177Contexts.back().IsExpression = false;178179const auto *BeforeLess = Left->Previous;180181// If there's a template keyword before the opening angle bracket, this is a182// template parameter, not an argument.183if (BeforeLess && BeforeLess->isNot(tok::kw_template))184Contexts.back().ContextType = Context::TemplateArgument;185186if (Style.Language == FormatStyle::LK_Java &&187CurrentToken->is(tok::question)) {188next();189}190191for (bool SeenTernaryOperator = false, MaybeAngles = true; CurrentToken;) {192const bool InExpr = Contexts[Contexts.size() - 2].IsExpression;193if (CurrentToken->is(tok::greater)) {194const auto *Next = CurrentToken->Next;195if (CurrentToken->isNot(TT_TemplateCloser)) {196// Try to do a better job at looking for ">>" within the condition of197// a statement. Conservatively insert spaces between consecutive ">"198// tokens to prevent splitting right shift operators and potentially199// altering program semantics. This check is overly conservative and200// will prevent spaces from being inserted in select nested template201// parameter cases, but should not alter program semantics.202if (Next && Next->is(tok::greater) &&203Left->ParentBracket != tok::less &&204CurrentToken->getStartOfNonWhitespace() ==205Next->getStartOfNonWhitespace().getLocWithOffset(-1)) {206return false;207}208if (InExpr && SeenTernaryOperator &&209(!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) {210return false;211}212if (!MaybeAngles)213return false;214}215Left->MatchingParen = CurrentToken;216CurrentToken->MatchingParen = Left;217// In TT_Proto, we must distignuish between:218// map<key, value>219// msg < item: data >220// msg: < item: data >221// In TT_TextProto, map<key, value> does not occur.222if (Style.Language == FormatStyle::LK_TextProto ||223(Style.Language == FormatStyle::LK_Proto && BeforeLess &&224BeforeLess->isOneOf(TT_SelectorName, TT_DictLiteral))) {225CurrentToken->setType(TT_DictLiteral);226} else {227CurrentToken->setType(TT_TemplateCloser);228CurrentToken->Tok.setLength(1);229}230if (Next && Next->Tok.isLiteral())231return false;232next();233return true;234}235if (CurrentToken->is(tok::question) &&236Style.Language == FormatStyle::LK_Java) {237next();238continue;239}240if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace))241return false;242const auto &Prev = *CurrentToken->Previous;243// If a && or || is found and interpreted as a binary operator, this set244// of angles is likely part of something like "a < b && c > d". If the245// angles are inside an expression, the ||/&& might also be a binary246// operator that was misinterpreted because we are parsing template247// parameters.248// FIXME: This is getting out of hand, write a decent parser.249if (MaybeAngles && InExpr && !Line.startsWith(tok::kw_template) &&250Prev.is(TT_BinaryOperator)) {251const auto Precedence = Prev.getPrecedence();252if (Precedence > prec::Conditional && Precedence < prec::Relational)253MaybeAngles = false;254}255if (Prev.isOneOf(tok::question, tok::colon) && !Style.isProto())256SeenTernaryOperator = true;257updateParameterCount(Left, CurrentToken);258if (Style.Language == FormatStyle::LK_Proto) {259if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) {260if (CurrentToken->is(tok::colon) ||261(CurrentToken->isOneOf(tok::l_brace, tok::less) &&262Previous->isNot(tok::colon))) {263Previous->setType(TT_SelectorName);264}265}266}267if (Style.isTableGen()) {268if (CurrentToken->isOneOf(tok::comma, tok::equal)) {269// They appear as separators. Unless they are not in class definition.270next();271continue;272}273// In angle, there must be Value like tokens. Types are also able to be274// parsed in the same way with Values.275if (!parseTableGenValue())276return false;277continue;278}279if (!consumeToken())280return false;281}282return false;283}284285bool parseUntouchableParens() {286while (CurrentToken) {287CurrentToken->Finalized = true;288switch (CurrentToken->Tok.getKind()) {289case tok::l_paren:290next();291if (!parseUntouchableParens())292return false;293continue;294case tok::r_paren:295next();296return true;297default:298// no-op299break;300}301next();302}303return false;304}305306bool parseParens(bool LookForDecls = false) {307if (!CurrentToken)308return false;309assert(CurrentToken->Previous && "Unknown previous token");310FormatToken &OpeningParen = *CurrentToken->Previous;311assert(OpeningParen.is(tok::l_paren));312FormatToken *PrevNonComment = OpeningParen.getPreviousNonComment();313OpeningParen.ParentBracket = Contexts.back().ContextKind;314ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);315316// FIXME: This is a bit of a hack. Do better.317Contexts.back().ColonIsForRangeExpr =318Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;319320if (OpeningParen.Previous &&321OpeningParen.Previous->is(TT_UntouchableMacroFunc)) {322OpeningParen.Finalized = true;323return parseUntouchableParens();324}325326bool StartsObjCMethodExpr = false;327if (!Style.isVerilog()) {328if (FormatToken *MaybeSel = OpeningParen.Previous) {329// @selector( starts a selector.330if (MaybeSel->isObjCAtKeyword(tok::objc_selector) &&331MaybeSel->Previous && MaybeSel->Previous->is(tok::at)) {332StartsObjCMethodExpr = true;333}334}335}336337if (OpeningParen.is(TT_OverloadedOperatorLParen)) {338// Find the previous kw_operator token.339FormatToken *Prev = &OpeningParen;340while (Prev->isNot(tok::kw_operator)) {341Prev = Prev->Previous;342assert(Prev && "Expect a kw_operator prior to the OperatorLParen!");343}344345// If faced with "a.operator*(argument)" or "a->operator*(argument)",346// i.e. the operator is called as a member function,347// then the argument must be an expression.348bool OperatorCalledAsMemberFunction =349Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow);350Contexts.back().IsExpression = OperatorCalledAsMemberFunction;351} else if (OpeningParen.is(TT_VerilogInstancePortLParen)) {352Contexts.back().IsExpression = true;353Contexts.back().ContextType = Context::VerilogInstancePortList;354} else if (Style.isJavaScript() &&355(Line.startsWith(Keywords.kw_type, tok::identifier) ||356Line.startsWith(tok::kw_export, Keywords.kw_type,357tok::identifier))) {358// type X = (...);359// export type X = (...);360Contexts.back().IsExpression = false;361} else if (OpeningParen.Previous &&362(OpeningParen.Previous->isOneOf(363tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,364tok::kw_while, tok::l_paren, tok::comma,365TT_BinaryOperator) ||366OpeningParen.Previous->isIf())) {367// static_assert, if and while usually contain expressions.368Contexts.back().IsExpression = true;369} else if (Style.isJavaScript() && OpeningParen.Previous &&370(OpeningParen.Previous->is(Keywords.kw_function) ||371(OpeningParen.Previous->endsSequence(tok::identifier,372Keywords.kw_function)))) {373// function(...) or function f(...)374Contexts.back().IsExpression = false;375} else if (Style.isJavaScript() && OpeningParen.Previous &&376OpeningParen.Previous->is(TT_JsTypeColon)) {377// let x: (SomeType);378Contexts.back().IsExpression = false;379} else if (isLambdaParameterList(&OpeningParen)) {380// This is a parameter list of a lambda expression.381Contexts.back().IsExpression = false;382} else if (OpeningParen.is(TT_RequiresExpressionLParen)) {383Contexts.back().IsExpression = false;384} else if (OpeningParen.Previous &&385OpeningParen.Previous->is(tok::kw__Generic)) {386Contexts.back().ContextType = Context::C11GenericSelection;387Contexts.back().IsExpression = true;388} else if (Line.InPPDirective &&389(!OpeningParen.Previous ||390OpeningParen.Previous->isNot(tok::identifier))) {391Contexts.back().IsExpression = true;392} else if (Contexts[Contexts.size() - 2].CaretFound) {393// This is the parameter list of an ObjC block.394Contexts.back().IsExpression = false;395} else if (OpeningParen.Previous &&396OpeningParen.Previous->is(TT_ForEachMacro)) {397// The first argument to a foreach macro is a declaration.398Contexts.back().ContextType = Context::ForEachMacro;399Contexts.back().IsExpression = false;400} else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen &&401OpeningParen.Previous->MatchingParen->isOneOf(402TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {403Contexts.back().IsExpression = false;404} else if (!Line.MustBeDeclaration && !Line.InPPDirective) {405bool IsForOrCatch =406OpeningParen.Previous &&407OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch);408Contexts.back().IsExpression = !IsForOrCatch;409}410411if (Style.isTableGen()) {412if (FormatToken *Prev = OpeningParen.Previous) {413if (Prev->is(TT_TableGenCondOperator)) {414Contexts.back().IsTableGenCondOpe = true;415Contexts.back().IsExpression = true;416} else if (Contexts.size() > 1 &&417Contexts[Contexts.size() - 2].IsTableGenBangOpe) {418// Hack to handle bang operators. The parent context's flag419// was set by parseTableGenSimpleValue().420// We have to specify the context outside because the prev of "(" may421// be ">", not the bang operator in this case.422Contexts.back().IsTableGenBangOpe = true;423Contexts.back().IsExpression = true;424} else {425// Otherwise, this paren seems DAGArg.426if (!parseTableGenDAGArg())427return false;428return parseTableGenDAGArgAndList(&OpeningParen);429}430}431}432433// Infer the role of the l_paren based on the previous token if we haven't434// detected one yet.435if (PrevNonComment && OpeningParen.is(TT_Unknown)) {436if (PrevNonComment->isAttribute()) {437OpeningParen.setType(TT_AttributeLParen);438} else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,439tok::kw_typeof,440#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,441#include "clang/Basic/TransformTypeTraits.def"442tok::kw__Atomic)) {443OpeningParen.setType(TT_TypeDeclarationParen);444// decltype() and typeof() usually contain expressions.445if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))446Contexts.back().IsExpression = true;447}448}449450if (StartsObjCMethodExpr) {451Contexts.back().ColonIsObjCMethodExpr = true;452OpeningParen.setType(TT_ObjCMethodExpr);453}454455// MightBeFunctionType and ProbablyFunctionType are used for456// function pointer and reference types as well as Objective-C457// block types:458//459// void (*FunctionPointer)(void);460// void (&FunctionReference)(void);461// void (&&FunctionReference)(void);462// void (^ObjCBlock)(void);463bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;464bool ProbablyFunctionType =465CurrentToken->isPointerOrReference() || CurrentToken->is(tok::caret);466bool HasMultipleLines = false;467bool HasMultipleParametersOnALine = false;468bool MightBeObjCForRangeLoop =469OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for);470FormatToken *PossibleObjCForInToken = nullptr;471while (CurrentToken) {472// LookForDecls is set when "if (" has been seen. Check for473// 'identifier' '*' 'identifier' followed by not '=' -- this474// '*' has to be a binary operator but determineStarAmpUsage() will475// categorize it as an unary operator, so set the right type here.476if (LookForDecls && CurrentToken->Next) {477FormatToken *Prev = CurrentToken->getPreviousNonComment();478if (Prev) {479FormatToken *PrevPrev = Prev->getPreviousNonComment();480FormatToken *Next = CurrentToken->Next;481if (PrevPrev && PrevPrev->is(tok::identifier) &&482PrevPrev->isNot(TT_TypeName) && Prev->isPointerOrReference() &&483CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {484Prev->setType(TT_BinaryOperator);485LookForDecls = false;486}487}488}489490if (CurrentToken->Previous->is(TT_PointerOrReference) &&491CurrentToken->Previous->Previous->isOneOf(tok::l_paren,492tok::coloncolon)) {493ProbablyFunctionType = true;494}495if (CurrentToken->is(tok::comma))496MightBeFunctionType = false;497if (CurrentToken->Previous->is(TT_BinaryOperator))498Contexts.back().IsExpression = true;499if (CurrentToken->is(tok::r_paren)) {500if (OpeningParen.isNot(TT_CppCastLParen) && MightBeFunctionType &&501ProbablyFunctionType && CurrentToken->Next &&502(CurrentToken->Next->is(tok::l_paren) ||503(CurrentToken->Next->is(tok::l_square) &&504Line.MustBeDeclaration))) {505OpeningParen.setType(OpeningParen.Next->is(tok::caret)506? TT_ObjCBlockLParen507: TT_FunctionTypeLParen);508}509OpeningParen.MatchingParen = CurrentToken;510CurrentToken->MatchingParen = &OpeningParen;511512if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&513OpeningParen.Previous && OpeningParen.Previous->is(tok::l_paren)) {514// Detect the case where macros are used to generate lambdas or515// function bodies, e.g.:516// auto my_lambda = MACRO((Type *type, int i) { .. body .. });517for (FormatToken *Tok = &OpeningParen; Tok != CurrentToken;518Tok = Tok->Next) {519if (Tok->is(TT_BinaryOperator) && Tok->isPointerOrReference())520Tok->setType(TT_PointerOrReference);521}522}523524if (StartsObjCMethodExpr) {525CurrentToken->setType(TT_ObjCMethodExpr);526if (Contexts.back().FirstObjCSelectorName) {527Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =528Contexts.back().LongestObjCSelectorName;529}530}531532if (OpeningParen.is(TT_AttributeLParen))533CurrentToken->setType(TT_AttributeRParen);534if (OpeningParen.is(TT_TypeDeclarationParen))535CurrentToken->setType(TT_TypeDeclarationParen);536if (OpeningParen.Previous &&537OpeningParen.Previous->is(TT_JavaAnnotation)) {538CurrentToken->setType(TT_JavaAnnotation);539}540if (OpeningParen.Previous &&541OpeningParen.Previous->is(TT_LeadingJavaAnnotation)) {542CurrentToken->setType(TT_LeadingJavaAnnotation);543}544if (OpeningParen.Previous &&545OpeningParen.Previous->is(TT_AttributeSquare)) {546CurrentToken->setType(TT_AttributeSquare);547}548549if (!HasMultipleLines)550OpeningParen.setPackingKind(PPK_Inconclusive);551else if (HasMultipleParametersOnALine)552OpeningParen.setPackingKind(PPK_BinPacked);553else554OpeningParen.setPackingKind(PPK_OnePerLine);555556next();557return true;558}559if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))560return false;561562if (CurrentToken->is(tok::l_brace) && OpeningParen.is(TT_ObjCBlockLParen))563OpeningParen.setType(TT_Unknown);564if (CurrentToken->is(tok::comma) && CurrentToken->Next &&565!CurrentToken->Next->HasUnescapedNewline &&566!CurrentToken->Next->isTrailingComment()) {567HasMultipleParametersOnALine = true;568}569bool ProbablyFunctionTypeLParen =570(CurrentToken->is(tok::l_paren) && CurrentToken->Next &&571CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));572if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||573CurrentToken->Previous->isTypeName(LangOpts)) &&574!(CurrentToken->is(tok::l_brace) ||575(CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {576Contexts.back().IsExpression = false;577}578if (CurrentToken->isOneOf(tok::semi, tok::colon)) {579MightBeObjCForRangeLoop = false;580if (PossibleObjCForInToken) {581PossibleObjCForInToken->setType(TT_Unknown);582PossibleObjCForInToken = nullptr;583}584}585if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) {586PossibleObjCForInToken = CurrentToken;587PossibleObjCForInToken->setType(TT_ObjCForIn);588}589// When we discover a 'new', we set CanBeExpression to 'false' in order to590// parse the type correctly. Reset that after a comma.591if (CurrentToken->is(tok::comma))592Contexts.back().CanBeExpression = true;593594if (Style.isTableGen()) {595if (CurrentToken->is(tok::comma)) {596if (Contexts.back().IsTableGenCondOpe)597CurrentToken->setType(TT_TableGenCondOperatorComma);598next();599} else if (CurrentToken->is(tok::colon)) {600if (Contexts.back().IsTableGenCondOpe)601CurrentToken->setType(TT_TableGenCondOperatorColon);602next();603}604// In TableGen there must be Values in parens.605if (!parseTableGenValue())606return false;607continue;608}609610FormatToken *Tok = CurrentToken;611if (!consumeToken())612return false;613updateParameterCount(&OpeningParen, Tok);614if (CurrentToken && CurrentToken->HasUnescapedNewline)615HasMultipleLines = true;616}617return false;618}619620bool isCSharpAttributeSpecifier(const FormatToken &Tok) {621if (!Style.isCSharp())622return false;623624// `identifier[i]` is not an attribute.625if (Tok.Previous && Tok.Previous->is(tok::identifier))626return false;627628// Chains of [] in `identifier[i][j][k]` are not attributes.629if (Tok.Previous && Tok.Previous->is(tok::r_square)) {630auto *MatchingParen = Tok.Previous->MatchingParen;631if (!MatchingParen || MatchingParen->is(TT_ArraySubscriptLSquare))632return false;633}634635const FormatToken *AttrTok = Tok.Next;636if (!AttrTok)637return false;638639// Just an empty declaration e.g. string [].640if (AttrTok->is(tok::r_square))641return false;642643// Move along the tokens inbetween the '[' and ']' e.g. [STAThread].644while (AttrTok && AttrTok->isNot(tok::r_square))645AttrTok = AttrTok->Next;646647if (!AttrTok)648return false;649650// Allow an attribute to be the only content of a file.651AttrTok = AttrTok->Next;652if (!AttrTok)653return true;654655// Limit this to being an access modifier that follows.656if (AttrTok->isAccessSpecifierKeyword() ||657AttrTok->isOneOf(tok::comment, tok::kw_class, tok::kw_static,658tok::l_square, Keywords.kw_internal)) {659return true;660}661662// incase its a [XXX] retval func(....663if (AttrTok->Next &&664AttrTok->Next->startsSequence(tok::identifier, tok::l_paren)) {665return true;666}667668return false;669}670671bool parseSquare() {672if (!CurrentToken)673return false;674675// A '[' could be an index subscript (after an identifier or after676// ')' or ']'), it could be the start of an Objective-C method677// expression, it could the start of an Objective-C array literal,678// or it could be a C++ attribute specifier [[foo::bar]].679FormatToken *Left = CurrentToken->Previous;680Left->ParentBracket = Contexts.back().ContextKind;681FormatToken *Parent = Left->getPreviousNonComment();682683// Cases where '>' is followed by '['.684// In C++, this can happen either in array of templates (foo<int>[10])685// or when array is a nested template type (unique_ptr<type1<type2>[]>).686bool CppArrayTemplates =687IsCpp && Parent && Parent->is(TT_TemplateCloser) &&688(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||689Contexts.back().ContextType == Context::TemplateArgument);690691const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;692const bool IsCpp11AttributeSpecifier =693isCppAttribute(IsCpp, *Left) || IsInnerSquare;694695// Treat C# Attributes [STAThread] much like C++ attributes [[...]].696bool IsCSharpAttributeSpecifier =697isCSharpAttributeSpecifier(*Left) ||698Contexts.back().InCSharpAttributeSpecifier;699700bool InsideInlineASM = Line.startsWith(tok::kw_asm);701bool IsCppStructuredBinding = Left->isCppStructuredBinding(IsCpp);702bool StartsObjCMethodExpr =703!IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&704IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&705Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&706!CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&707(!Parent ||708Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,709tok::kw_return, tok::kw_throw) ||710Parent->isUnaryOperator() ||711// FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.712Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||713(getBinOpPrecedence(Parent->Tok.getKind(), true, true) >714prec::Unknown));715bool ColonFound = false;716717unsigned BindingIncrease = 1;718if (IsCppStructuredBinding) {719Left->setType(TT_StructuredBindingLSquare);720} else if (Left->is(TT_Unknown)) {721if (StartsObjCMethodExpr) {722Left->setType(TT_ObjCMethodExpr);723} else if (InsideInlineASM) {724Left->setType(TT_InlineASMSymbolicNameLSquare);725} else if (IsCpp11AttributeSpecifier) {726Left->setType(TT_AttributeSquare);727if (!IsInnerSquare && Left->Previous)728Left->Previous->EndsCppAttributeGroup = false;729} else if (Style.isJavaScript() && Parent &&730Contexts.back().ContextKind == tok::l_brace &&731Parent->isOneOf(tok::l_brace, tok::comma)) {732Left->setType(TT_JsComputedPropertyName);733} else if (IsCpp && Contexts.back().ContextKind == tok::l_brace &&734Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {735Left->setType(TT_DesignatedInitializerLSquare);736} else if (IsCSharpAttributeSpecifier) {737Left->setType(TT_AttributeSquare);738} else if (CurrentToken->is(tok::r_square) && Parent &&739Parent->is(TT_TemplateCloser)) {740Left->setType(TT_ArraySubscriptLSquare);741} else if (Style.isProto()) {742// Square braces in LK_Proto can either be message field attributes:743//744// optional Aaa aaa = 1 [745// (aaa) = aaa746// ];747//748// extensions 123 [749// (aaa) = aaa750// ];751//752// or text proto extensions (in options):753//754// option (Aaa.options) = {755// [type.type/type] {756// key: value757// }758// }759//760// or repeated fields (in options):761//762// option (Aaa.options) = {763// keys: [ 1, 2, 3 ]764// }765//766// In the first and the third case we want to spread the contents inside767// the square braces; in the second we want to keep them inline.768Left->setType(TT_ArrayInitializerLSquare);769if (!Left->endsSequence(tok::l_square, tok::numeric_constant,770tok::equal) &&771!Left->endsSequence(tok::l_square, tok::numeric_constant,772tok::identifier) &&773!Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) {774Left->setType(TT_ProtoExtensionLSquare);775BindingIncrease = 10;776}777} else if (!CppArrayTemplates && Parent &&778Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,779tok::comma, tok::l_paren, tok::l_square,780tok::question, tok::colon, tok::kw_return,781// Should only be relevant to JavaScript:782tok::kw_default)) {783Left->setType(TT_ArrayInitializerLSquare);784} else {785BindingIncrease = 10;786Left->setType(TT_ArraySubscriptLSquare);787}788}789790ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);791Contexts.back().IsExpression = true;792if (Style.isJavaScript() && Parent && Parent->is(TT_JsTypeColon))793Contexts.back().IsExpression = false;794795Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;796Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;797Contexts.back().InCSharpAttributeSpecifier = IsCSharpAttributeSpecifier;798799while (CurrentToken) {800if (CurrentToken->is(tok::r_square)) {801if (IsCpp11AttributeSpecifier) {802CurrentToken->setType(TT_AttributeSquare);803if (!IsInnerSquare)804CurrentToken->EndsCppAttributeGroup = true;805}806if (IsCSharpAttributeSpecifier) {807CurrentToken->setType(TT_AttributeSquare);808} else if (((CurrentToken->Next &&809CurrentToken->Next->is(tok::l_paren)) ||810(CurrentToken->Previous &&811CurrentToken->Previous->Previous == Left)) &&812Left->is(TT_ObjCMethodExpr)) {813// An ObjC method call is rarely followed by an open parenthesis. It814// also can't be composed of just one token, unless it's a macro that815// will be expanded to more tokens.816// FIXME: Do we incorrectly label ":" with this?817StartsObjCMethodExpr = false;818Left->setType(TT_Unknown);819}820if (StartsObjCMethodExpr && CurrentToken->Previous != Left) {821CurrentToken->setType(TT_ObjCMethodExpr);822// If we haven't seen a colon yet, make sure the last identifier823// before the r_square is tagged as a selector name component.824if (!ColonFound && CurrentToken->Previous &&825CurrentToken->Previous->is(TT_Unknown) &&826canBeObjCSelectorComponent(*CurrentToken->Previous)) {827CurrentToken->Previous->setType(TT_SelectorName);828}829// determineStarAmpUsage() thinks that '*' '[' is allocating an830// array of pointers, but if '[' starts a selector then '*' is a831// binary operator.832if (Parent && Parent->is(TT_PointerOrReference))833Parent->overwriteFixedType(TT_BinaryOperator);834}835// An arrow after an ObjC method expression is not a lambda arrow.836if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&837CurrentToken->Next->is(TT_LambdaArrow)) {838CurrentToken->Next->overwriteFixedType(TT_Unknown);839}840Left->MatchingParen = CurrentToken;841CurrentToken->MatchingParen = Left;842// FirstObjCSelectorName is set when a colon is found. This does843// not work, however, when the method has no parameters.844// Here, we set FirstObjCSelectorName when the end of the method call is845// reached, in case it was not set already.846if (!Contexts.back().FirstObjCSelectorName) {847FormatToken *Previous = CurrentToken->getPreviousNonComment();848if (Previous && Previous->is(TT_SelectorName)) {849Previous->ObjCSelectorNameParts = 1;850Contexts.back().FirstObjCSelectorName = Previous;851}852} else {853Left->ParameterCount =854Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;855}856if (Contexts.back().FirstObjCSelectorName) {857Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =858Contexts.back().LongestObjCSelectorName;859if (Left->BlockParameterCount > 1)860Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0;861}862if (Style.isTableGen() && Left->is(TT_TableGenListOpener))863CurrentToken->setType(TT_TableGenListCloser);864next();865return true;866}867if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))868return false;869if (CurrentToken->is(tok::colon)) {870if (IsCpp11AttributeSpecifier &&871CurrentToken->endsSequence(tok::colon, tok::identifier,872tok::kw_using)) {873// Remember that this is a [[using ns: foo]] C++ attribute, so we874// don't add a space before the colon (unlike other colons).875CurrentToken->setType(TT_AttributeColon);876} else if (!Style.isVerilog() && !Line.InPragmaDirective &&877Left->isOneOf(TT_ArraySubscriptLSquare,878TT_DesignatedInitializerLSquare)) {879Left->setType(TT_ObjCMethodExpr);880StartsObjCMethodExpr = true;881Contexts.back().ColonIsObjCMethodExpr = true;882if (Parent && Parent->is(tok::r_paren)) {883// FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.884Parent->setType(TT_CastRParen);885}886}887ColonFound = true;888}889if (CurrentToken->is(tok::comma) && Left->is(TT_ObjCMethodExpr) &&890!ColonFound) {891Left->setType(TT_ArrayInitializerLSquare);892}893FormatToken *Tok = CurrentToken;894if (Style.isTableGen()) {895if (CurrentToken->isOneOf(tok::comma, tok::minus, tok::ellipsis)) {896// '-' and '...' appears as a separator in slice.897next();898} else {899// In TableGen there must be a list of Values in square brackets.900// It must be ValueList or SliceElements.901if (!parseTableGenValue())902return false;903}904updateParameterCount(Left, Tok);905continue;906}907if (!consumeToken())908return false;909updateParameterCount(Left, Tok);910}911return false;912}913914void skipToNextNonComment() {915next();916while (CurrentToken && CurrentToken->is(tok::comment))917next();918}919920// Simplified parser for TableGen Value. Returns true on success.921// It consists of SimpleValues, SimpleValues with Suffixes, and Value followed922// by '#', paste operator.923// There also exists the case the Value is parsed as NameValue.924// In this case, the Value ends if '{' is found.925bool parseTableGenValue(bool ParseNameMode = false) {926if (!CurrentToken)927return false;928while (CurrentToken->is(tok::comment))929next();930if (!parseTableGenSimpleValue())931return false;932if (!CurrentToken)933return true;934// Value "#" [Value]935if (CurrentToken->is(tok::hash)) {936if (CurrentToken->Next &&937CurrentToken->Next->isOneOf(tok::colon, tok::semi, tok::l_brace)) {938// Trailing paste operator.939// These are only the allowed cases in TGParser::ParseValue().940CurrentToken->setType(TT_TableGenTrailingPasteOperator);941next();942return true;943}944FormatToken *HashTok = CurrentToken;945skipToNextNonComment();946HashTok->setType(TT_Unknown);947if (!parseTableGenValue(ParseNameMode))948return false;949}950// In name mode, '{' is regarded as the end of the value.951// See TGParser::ParseValue in TGParser.cpp952if (ParseNameMode && CurrentToken->is(tok::l_brace))953return true;954// These tokens indicates this is a value with suffixes.955if (CurrentToken->isOneOf(tok::l_brace, tok::l_square, tok::period)) {956CurrentToken->setType(TT_TableGenValueSuffix);957FormatToken *Suffix = CurrentToken;958skipToNextNonComment();959if (Suffix->is(tok::l_square))960return parseSquare();961if (Suffix->is(tok::l_brace)) {962Scopes.push_back(getScopeType(*Suffix));963return parseBrace();964}965}966return true;967}968969// TokVarName ::= "$" ualpha (ualpha | "0"..."9")*970// Appears as a part of DagArg.971// This does not change the current token on fail.972bool tryToParseTableGenTokVar() {973if (!CurrentToken)974return false;975if (CurrentToken->is(tok::identifier) &&976CurrentToken->TokenText.front() == '$') {977skipToNextNonComment();978return true;979}980return false;981}982983// DagArg ::= Value [":" TokVarName] | TokVarName984// Appears as a part of SimpleValue6.985bool parseTableGenDAGArg(bool AlignColon = false) {986if (tryToParseTableGenTokVar())987return true;988if (parseTableGenValue()) {989if (CurrentToken && CurrentToken->is(tok::colon)) {990if (AlignColon)991CurrentToken->setType(TT_TableGenDAGArgListColonToAlign);992else993CurrentToken->setType(TT_TableGenDAGArgListColon);994skipToNextNonComment();995return tryToParseTableGenTokVar();996}997return true;998}999return false;1000}10011002// Judge if the token is a operator ID to insert line break in DAGArg.1003// That is, TableGenBreakingDAGArgOperators is empty (by the definition of the1004// option) or the token is in the list.1005bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) {1006auto &Opes = Style.TableGenBreakingDAGArgOperators;1007// If the list is empty, all operators are breaking operators.1008if (Opes.empty())1009return true;1010// Otherwise, the operator is limited to normal identifiers.1011if (Tok.isNot(tok::identifier) ||1012Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {1013return false;1014}1015// The case next is colon, it is not a operator of identifier.1016if (!Tok.Next || Tok.Next->is(tok::colon))1017return false;1018return std::find(Opes.begin(), Opes.end(), Tok.TokenText.str()) !=1019Opes.end();1020}10211022// SimpleValue6 ::= "(" DagArg [DagArgList] ")"1023// This parses SimpleValue 6's inside part of "(" ")"1024bool parseTableGenDAGArgAndList(FormatToken *Opener) {1025FormatToken *FirstTok = CurrentToken;1026if (!parseTableGenDAGArg())1027return false;1028bool BreakInside = false;1029if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) {1030// Specialized detection for DAGArgOperator, that determines the way of1031// line break for this DAGArg elements.1032if (isTableGenDAGArgBreakingOperator(*FirstTok)) {1033// Special case for identifier DAGArg operator.1034BreakInside = true;1035Opener->setType(TT_TableGenDAGArgOpenerToBreak);1036if (FirstTok->isOneOf(TT_TableGenBangOperator,1037TT_TableGenCondOperator)) {1038// Special case for bang/cond operators. Set the whole operator as1039// the DAGArg operator. Always break after it.1040CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak);1041} else if (FirstTok->is(tok::identifier)) {1042if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll)1043FirstTok->setType(TT_TableGenDAGArgOperatorToBreak);1044else1045FirstTok->setType(TT_TableGenDAGArgOperatorID);1046}1047}1048}1049// Parse the [DagArgList] part1050bool FirstDAGArgListElm = true;1051while (CurrentToken) {1052if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) {1053CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak1054: TT_TableGenDAGArgListComma);1055skipToNextNonComment();1056}1057if (CurrentToken && CurrentToken->is(tok::r_paren)) {1058CurrentToken->setType(TT_TableGenDAGArgCloser);1059Opener->MatchingParen = CurrentToken;1060CurrentToken->MatchingParen = Opener;1061skipToNextNonComment();1062return true;1063}1064if (!parseTableGenDAGArg(1065BreakInside &&1066Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) {1067return false;1068}1069FirstDAGArgListElm = false;1070}1071return false;1072}10731074bool parseTableGenSimpleValue() {1075assert(Style.isTableGen());1076if (!CurrentToken)1077return false;1078FormatToken *Tok = CurrentToken;1079skipToNextNonComment();1080// SimpleValue 1, 2, 3: Literals1081if (Tok->isOneOf(tok::numeric_constant, tok::string_literal,1082TT_TableGenMultiLineString, tok::kw_true, tok::kw_false,1083tok::question, tok::kw_int)) {1084return true;1085}1086// SimpleValue 4: ValueList, Type1087if (Tok->is(tok::l_brace)) {1088Scopes.push_back(getScopeType(*Tok));1089return parseBrace();1090}1091// SimpleValue 5: List initializer1092if (Tok->is(tok::l_square)) {1093Tok->setType(TT_TableGenListOpener);1094if (!parseSquare())1095return false;1096if (Tok->is(tok::less)) {1097CurrentToken->setType(TT_TemplateOpener);1098return parseAngle();1099}1100return true;1101}1102// SimpleValue 6: DAGArg [DAGArgList]1103// SimpleValue6 ::= "(" DagArg [DagArgList] ")"1104if (Tok->is(tok::l_paren)) {1105Tok->setType(TT_TableGenDAGArgOpener);1106return parseTableGenDAGArgAndList(Tok);1107}1108// SimpleValue 9: Bang operator1109if (Tok->is(TT_TableGenBangOperator)) {1110if (CurrentToken && CurrentToken->is(tok::less)) {1111CurrentToken->setType(TT_TemplateOpener);1112skipToNextNonComment();1113if (!parseAngle())1114return false;1115}1116if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1117return false;1118skipToNextNonComment();1119// FIXME: Hack using inheritance to child context1120Contexts.back().IsTableGenBangOpe = true;1121bool Result = parseParens();1122Contexts.back().IsTableGenBangOpe = false;1123return Result;1124}1125// SimpleValue 9: Cond operator1126if (Tok->is(TT_TableGenCondOperator)) {1127Tok = CurrentToken;1128skipToNextNonComment();1129if (!Tok || Tok->isNot(tok::l_paren))1130return false;1131bool Result = parseParens();1132return Result;1133}1134// We have to check identifier at the last because the kind of bang/cond1135// operators are also identifier.1136// SimpleValue 7: Identifiers1137if (Tok->is(tok::identifier)) {1138// SimpleValue 8: Anonymous record1139if (CurrentToken && CurrentToken->is(tok::less)) {1140CurrentToken->setType(TT_TemplateOpener);1141skipToNextNonComment();1142return parseAngle();1143}1144return true;1145}11461147return false;1148}11491150bool couldBeInStructArrayInitializer() const {1151if (Contexts.size() < 2)1152return false;1153// We want to back up no more then 2 context levels i.e.1154// . { { <-1155const auto End = std::next(Contexts.rbegin(), 2);1156auto Last = Contexts.rbegin();1157unsigned Depth = 0;1158for (; Last != End; ++Last)1159if (Last->ContextKind == tok::l_brace)1160++Depth;1161return Depth == 2 && Last->ContextKind != tok::l_brace;1162}11631164bool parseBrace() {1165if (!CurrentToken)1166return true;11671168assert(CurrentToken->Previous);1169FormatToken &OpeningBrace = *CurrentToken->Previous;1170assert(OpeningBrace.is(tok::l_brace));1171OpeningBrace.ParentBracket = Contexts.back().ContextKind;11721173if (Contexts.back().CaretFound)1174OpeningBrace.overwriteFixedType(TT_ObjCBlockLBrace);1175Contexts.back().CaretFound = false;11761177ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);1178Contexts.back().ColonIsDictLiteral = true;1179if (OpeningBrace.is(BK_BracedInit))1180Contexts.back().IsExpression = true;1181if (Style.isJavaScript() && OpeningBrace.Previous &&1182OpeningBrace.Previous->is(TT_JsTypeColon)) {1183Contexts.back().IsExpression = false;1184}1185if (Style.isVerilog() &&1186(!OpeningBrace.getPreviousNonComment() ||1187OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) {1188Contexts.back().VerilogMayBeConcatenation = true;1189}1190if (Style.isTableGen())1191Contexts.back().ColonIsDictLiteral = false;11921193unsigned CommaCount = 0;1194while (CurrentToken) {1195if (CurrentToken->is(tok::r_brace)) {1196assert(!Scopes.empty());1197assert(Scopes.back() == getScopeType(OpeningBrace));1198Scopes.pop_back();1199assert(OpeningBrace.Optional == CurrentToken->Optional);1200OpeningBrace.MatchingParen = CurrentToken;1201CurrentToken->MatchingParen = &OpeningBrace;1202if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {1203if (OpeningBrace.ParentBracket == tok::l_brace &&1204couldBeInStructArrayInitializer() && CommaCount > 0) {1205Contexts.back().ContextType = Context::StructArrayInitializer;1206}1207}1208next();1209return true;1210}1211if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))1212return false;1213updateParameterCount(&OpeningBrace, CurrentToken);1214if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {1215FormatToken *Previous = CurrentToken->getPreviousNonComment();1216if (Previous->is(TT_JsTypeOptionalQuestion))1217Previous = Previous->getPreviousNonComment();1218if ((CurrentToken->is(tok::colon) && !Style.isTableGen() &&1219(!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||1220Style.isProto()) {1221OpeningBrace.setType(TT_DictLiteral);1222if (Previous->Tok.getIdentifierInfo() ||1223Previous->is(tok::string_literal)) {1224Previous->setType(TT_SelectorName);1225}1226}1227if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) &&1228!Style.isTableGen()) {1229OpeningBrace.setType(TT_DictLiteral);1230} else if (Style.isJavaScript()) {1231OpeningBrace.overwriteFixedType(TT_DictLiteral);1232}1233}1234if (CurrentToken->is(tok::comma)) {1235if (Style.isJavaScript())1236OpeningBrace.overwriteFixedType(TT_DictLiteral);1237++CommaCount;1238}1239if (!consumeToken())1240return false;1241}1242return true;1243}12441245void updateParameterCount(FormatToken *Left, FormatToken *Current) {1246// For ObjC methods, the number of parameters is calculated differently as1247// method declarations have a different structure (the parameters are not1248// inside a bracket scope).1249if (Current->is(tok::l_brace) && Current->is(BK_Block))1250++Left->BlockParameterCount;1251if (Current->is(tok::comma)) {1252++Left->ParameterCount;1253if (!Left->Role)1254Left->Role.reset(new CommaSeparatedList(Style));1255Left->Role->CommaFound(Current);1256} else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {1257Left->ParameterCount = 1;1258}1259}12601261bool parseConditional() {1262while (CurrentToken) {1263if (CurrentToken->is(tok::colon)) {1264CurrentToken->setType(TT_ConditionalExpr);1265next();1266return true;1267}1268if (!consumeToken())1269return false;1270}1271return false;1272}12731274bool parseTemplateDeclaration() {1275if (!CurrentToken || CurrentToken->isNot(tok::less))1276return false;12771278CurrentToken->setType(TT_TemplateOpener);1279next();12801281TemplateDeclarationDepth++;1282const bool WellFormed = parseAngle();1283TemplateDeclarationDepth--;1284if (!WellFormed)1285return false;12861287if (CurrentToken && TemplateDeclarationDepth == 0)1288CurrentToken->Previous->ClosesTemplateDeclaration = true;12891290return true;1291}12921293bool consumeToken() {1294if (IsCpp) {1295const auto *Prev = CurrentToken->getPreviousNonComment();1296if (Prev && Prev->is(tok::r_square) && Prev->is(TT_AttributeSquare) &&1297CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case,1298tok::kw_default, tok::kw_for, tok::kw_while) &&1299mustBreakAfterAttributes(*CurrentToken, Style)) {1300CurrentToken->MustBreakBefore = true;1301}1302}1303FormatToken *Tok = CurrentToken;1304next();1305// In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal1306// operators.1307if (Tok->is(TT_VerilogTableItem))1308return true;1309// Multi-line string itself is a single annotated token.1310if (Tok->is(TT_TableGenMultiLineString))1311return true;1312switch (Tok->Tok.getKind()) {1313case tok::plus:1314case tok::minus:1315if (!Tok->Previous && Line.MustBeDeclaration)1316Tok->setType(TT_ObjCMethodSpecifier);1317break;1318case tok::colon:1319if (!Tok->Previous)1320return false;1321// Goto labels and case labels are already identified in1322// UnwrappedLineParser.1323if (Tok->isTypeFinalized())1324break;1325// Colons from ?: are handled in parseConditional().1326if (Style.isJavaScript()) {1327if (Contexts.back().ColonIsForRangeExpr || // colon in for loop1328(Contexts.size() == 1 && // switch/case labels1329!Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||1330Contexts.back().ContextKind == tok::l_paren || // function params1331Contexts.back().ContextKind == tok::l_square || // array type1332(!Contexts.back().IsExpression &&1333Contexts.back().ContextKind == tok::l_brace) || // object type1334(Contexts.size() == 1 &&1335Line.MustBeDeclaration)) { // method/property declaration1336Contexts.back().IsExpression = false;1337Tok->setType(TT_JsTypeColon);1338break;1339}1340} else if (Style.isCSharp()) {1341if (Contexts.back().InCSharpAttributeSpecifier) {1342Tok->setType(TT_AttributeColon);1343break;1344}1345if (Contexts.back().ContextKind == tok::l_paren) {1346Tok->setType(TT_CSharpNamedArgumentColon);1347break;1348}1349} else if (Style.isVerilog() && Tok->isNot(TT_BinaryOperator)) {1350// The distribution weight operators are labeled1351// TT_BinaryOperator by the lexer.1352if (Keywords.isVerilogEnd(*Tok->Previous) ||1353Keywords.isVerilogBegin(*Tok->Previous)) {1354Tok->setType(TT_VerilogBlockLabelColon);1355} else if (Contexts.back().ContextKind == tok::l_square) {1356Tok->setType(TT_BitFieldColon);1357} else if (Contexts.back().ColonIsDictLiteral) {1358Tok->setType(TT_DictLiteral);1359} else if (Contexts.size() == 1) {1360// In Verilog a case label doesn't have the case keyword. We1361// assume a colon following an expression is a case label.1362// Colons from ?: are annotated in parseConditional().1363Tok->setType(TT_CaseLabelColon);1364if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))1365--Line.Level;1366}1367break;1368}1369if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||1370Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||1371Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {1372Tok->setType(TT_ModulePartitionColon);1373} else if (Line.First->is(tok::kw_asm)) {1374Tok->setType(TT_InlineASMColon);1375} else if (Contexts.back().ColonIsDictLiteral || Style.isProto()) {1376Tok->setType(TT_DictLiteral);1377if (Style.Language == FormatStyle::LK_TextProto) {1378if (FormatToken *Previous = Tok->getPreviousNonComment())1379Previous->setType(TT_SelectorName);1380}1381} else if (Contexts.back().ColonIsObjCMethodExpr ||1382Line.startsWith(TT_ObjCMethodSpecifier)) {1383Tok->setType(TT_ObjCMethodExpr);1384const FormatToken *BeforePrevious = Tok->Previous->Previous;1385// Ensure we tag all identifiers in method declarations as1386// TT_SelectorName.1387bool UnknownIdentifierInMethodDeclaration =1388Line.startsWith(TT_ObjCMethodSpecifier) &&1389Tok->Previous->is(tok::identifier) && Tok->Previous->is(TT_Unknown);1390if (!BeforePrevious ||1391// FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.1392!(BeforePrevious->is(TT_CastRParen) ||1393(BeforePrevious->is(TT_ObjCMethodExpr) &&1394BeforePrevious->is(tok::colon))) ||1395BeforePrevious->is(tok::r_square) ||1396Contexts.back().LongestObjCSelectorName == 0 ||1397UnknownIdentifierInMethodDeclaration) {1398Tok->Previous->setType(TT_SelectorName);1399if (!Contexts.back().FirstObjCSelectorName) {1400Contexts.back().FirstObjCSelectorName = Tok->Previous;1401} else if (Tok->Previous->ColumnWidth >1402Contexts.back().LongestObjCSelectorName) {1403Contexts.back().LongestObjCSelectorName =1404Tok->Previous->ColumnWidth;1405}1406Tok->Previous->ParameterIndex =1407Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;1408++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;1409}1410} else if (Contexts.back().ColonIsForRangeExpr) {1411Tok->setType(TT_RangeBasedForLoopColon);1412} else if (Contexts.back().ContextType == Context::C11GenericSelection) {1413Tok->setType(TT_GenericSelectionColon);1414} else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {1415Tok->setType(TT_BitFieldColon);1416} else if (Contexts.size() == 1 &&1417!Line.First->isOneOf(tok::kw_enum, tok::kw_case,1418tok::kw_default)) {1419FormatToken *Prev = Tok->getPreviousNonComment();1420if (!Prev)1421break;1422if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept) ||1423Prev->ClosesRequiresClause) {1424Tok->setType(TT_CtorInitializerColon);1425} else if (Prev->is(tok::kw_try)) {1426// Member initializer list within function try block.1427FormatToken *PrevPrev = Prev->getPreviousNonComment();1428if (!PrevPrev)1429break;1430if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))1431Tok->setType(TT_CtorInitializerColon);1432} else {1433Tok->setType(TT_InheritanceColon);1434if (Prev->isAccessSpecifierKeyword())1435Line.Type = LT_AccessModifier;1436}1437} else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&1438(Tok->Next->isOneOf(tok::r_paren, tok::comma) ||1439(canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next &&1440Tok->Next->Next->is(tok::colon)))) {1441// This handles a special macro in ObjC code where selectors including1442// the colon are passed as macro arguments.1443Tok->setType(TT_ObjCMethodExpr);1444}1445break;1446case tok::pipe:1447case tok::amp:1448// | and & in declarations/type expressions represent union and1449// intersection types, respectively.1450if (Style.isJavaScript() && !Contexts.back().IsExpression)1451Tok->setType(TT_JsTypeOperator);1452break;1453case tok::kw_if:1454if (Style.isTableGen()) {1455// In TableGen it has the form 'if' <value> 'then'.1456if (!parseTableGenValue())1457return false;1458if (CurrentToken && CurrentToken->is(Keywords.kw_then))1459next(); // skip then1460break;1461}1462if (CurrentToken &&1463CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {1464next();1465}1466[[fallthrough]];1467case tok::kw_while:1468if (CurrentToken && CurrentToken->is(tok::l_paren)) {1469next();1470if (!parseParens(/*LookForDecls=*/true))1471return false;1472}1473break;1474case tok::kw_for:1475if (Style.isJavaScript()) {1476// x.for and {for: ...}1477if ((Tok->Previous && Tok->Previous->is(tok::period)) ||1478(Tok->Next && Tok->Next->is(tok::colon))) {1479break;1480}1481// JS' for await ( ...1482if (CurrentToken && CurrentToken->is(Keywords.kw_await))1483next();1484}1485if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await))1486next();1487Contexts.back().ColonIsForRangeExpr = true;1488if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1489return false;1490next();1491if (!parseParens())1492return false;1493break;1494case tok::l_paren:1495// When faced with 'operator()()', the kw_operator handler incorrectly1496// marks the first l_paren as a OverloadedOperatorLParen. Here, we make1497// the first two parens OverloadedOperators and the second l_paren an1498// OverloadedOperatorLParen.1499if (Tok->Previous && Tok->Previous->is(tok::r_paren) &&1500Tok->Previous->MatchingParen &&1501Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) {1502Tok->Previous->setType(TT_OverloadedOperator);1503Tok->Previous->MatchingParen->setType(TT_OverloadedOperator);1504Tok->setType(TT_OverloadedOperatorLParen);1505}15061507if (Style.isVerilog()) {1508// Identify the parameter list and port list in a module instantiation.1509// This is still needed when we already have1510// UnwrappedLineParser::parseVerilogHierarchyHeader because that1511// function is only responsible for the definition, not the1512// instantiation.1513auto IsInstancePort = [&]() {1514const FormatToken *Prev = Tok->getPreviousNonComment();1515const FormatToken *PrevPrev;1516// In the following example all 4 left parentheses will be treated as1517// 'TT_VerilogInstancePortLParen'.1518//1519// module_x instance_1(port_1); // Case A.1520// module_x #(parameter_1) // Case B.1521// instance_2(port_1), // Case C.1522// instance_3(port_1); // Case D.1523if (!Prev || !(PrevPrev = Prev->getPreviousNonComment()))1524return false;1525// Case A.1526if (Keywords.isVerilogIdentifier(*Prev) &&1527Keywords.isVerilogIdentifier(*PrevPrev)) {1528return true;1529}1530// Case B.1531if (Prev->is(Keywords.kw_verilogHash) &&1532Keywords.isVerilogIdentifier(*PrevPrev)) {1533return true;1534}1535// Case C.1536if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::r_paren))1537return true;1538// Case D.1539if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::comma)) {1540const FormatToken *PrevParen = PrevPrev->getPreviousNonComment();1541if (PrevParen->is(tok::r_paren) && PrevParen->MatchingParen &&1542PrevParen->MatchingParen->is(TT_VerilogInstancePortLParen)) {1543return true;1544}1545}1546return false;1547};15481549if (IsInstancePort())1550Tok->setFinalizedType(TT_VerilogInstancePortLParen);1551}15521553if (!parseParens())1554return false;1555if (Line.MustBeDeclaration && Contexts.size() == 1 &&1556!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&1557!Line.startsWith(tok::l_paren) &&1558!Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {1559if (const auto *Previous = Tok->Previous;1560!Previous ||1561(!Previous->isAttribute() &&1562!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {1563Line.MightBeFunctionDecl = true;1564Tok->MightBeFunctionDeclParen = true;1565}1566}1567break;1568case tok::l_square:1569if (Style.isTableGen())1570Tok->setType(TT_TableGenListOpener);1571if (!parseSquare())1572return false;1573break;1574case tok::l_brace:1575if (Style.Language == FormatStyle::LK_TextProto) {1576FormatToken *Previous = Tok->getPreviousNonComment();1577if (Previous && Previous->isNot(TT_DictLiteral))1578Previous->setType(TT_SelectorName);1579}1580Scopes.push_back(getScopeType(*Tok));1581if (!parseBrace())1582return false;1583break;1584case tok::less:1585if (parseAngle()) {1586Tok->setType(TT_TemplateOpener);1587// In TT_Proto, we must distignuish between:1588// map<key, value>1589// msg < item: data >1590// msg: < item: data >1591// In TT_TextProto, map<key, value> does not occur.1592if (Style.Language == FormatStyle::LK_TextProto ||1593(Style.Language == FormatStyle::LK_Proto && Tok->Previous &&1594Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {1595Tok->setType(TT_DictLiteral);1596FormatToken *Previous = Tok->getPreviousNonComment();1597if (Previous && Previous->isNot(TT_DictLiteral))1598Previous->setType(TT_SelectorName);1599}1600if (Style.isTableGen())1601Tok->setType(TT_TemplateOpener);1602} else {1603Tok->setType(TT_BinaryOperator);1604NonTemplateLess.insert(Tok);1605CurrentToken = Tok;1606next();1607}1608break;1609case tok::r_paren:1610case tok::r_square:1611return false;1612case tok::r_brace:1613// Don't pop scope when encountering unbalanced r_brace.1614if (!Scopes.empty())1615Scopes.pop_back();1616// Lines can start with '}'.1617if (Tok->Previous)1618return false;1619break;1620case tok::greater:1621if (Style.Language != FormatStyle::LK_TextProto && Tok->is(TT_Unknown))1622Tok->setType(TT_BinaryOperator);1623if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))1624Tok->SpacesRequiredBefore = 1;1625break;1626case tok::kw_operator:1627if (Style.isProto())1628break;1629while (CurrentToken &&1630!CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {1631if (CurrentToken->isOneOf(tok::star, tok::amp))1632CurrentToken->setType(TT_PointerOrReference);1633auto Next = CurrentToken->getNextNonComment();1634if (!Next)1635break;1636if (Next->is(tok::less))1637next();1638else1639consumeToken();1640if (!CurrentToken)1641break;1642auto Previous = CurrentToken->getPreviousNonComment();1643assert(Previous);1644if (CurrentToken->is(tok::comma) && Previous->isNot(tok::kw_operator))1645break;1646if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator, tok::comma,1647tok::star, tok::arrow, tok::amp, tok::ampamp) ||1648// User defined literal.1649Previous->TokenText.starts_with("\"\"")) {1650Previous->setType(TT_OverloadedOperator);1651if (CurrentToken->isOneOf(tok::less, tok::greater))1652break;1653}1654}1655if (CurrentToken && CurrentToken->is(tok::l_paren))1656CurrentToken->setType(TT_OverloadedOperatorLParen);1657if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))1658CurrentToken->Previous->setType(TT_OverloadedOperator);1659break;1660case tok::question:1661if (Style.isJavaScript() && Tok->Next &&1662Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,1663tok::r_brace, tok::r_square)) {1664// Question marks before semicolons, colons, etc. indicate optional1665// types (fields, parameters), e.g.1666// function(x?: string, y?) {...}1667// class X { y?; }1668Tok->setType(TT_JsTypeOptionalQuestion);1669break;1670}1671// Declarations cannot be conditional expressions, this can only be part1672// of a type declaration.1673if (Line.MustBeDeclaration && !Contexts.back().IsExpression &&1674Style.isJavaScript()) {1675break;1676}1677if (Style.isCSharp()) {1678// `Type?)`, `Type?>`, `Type? name;` and `Type? name =` can only be1679// nullable types.16801681// `Type?)`, `Type?>`, `Type? name;`1682if (Tok->Next &&1683(Tok->Next->startsSequence(tok::question, tok::r_paren) ||1684Tok->Next->startsSequence(tok::question, tok::greater) ||1685Tok->Next->startsSequence(tok::question, tok::identifier,1686tok::semi))) {1687Tok->setType(TT_CSharpNullable);1688break;1689}16901691// `Type? name =`1692if (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next &&1693Tok->Next->Next->is(tok::equal)) {1694Tok->setType(TT_CSharpNullable);1695break;1696}16971698// Line.MustBeDeclaration will be true for `Type? name;`.1699// But not1700// cond ? "A" : "B";1701// cond ? id : "B";1702// cond ? cond2 ? "A" : "B" : "C";1703if (!Contexts.back().IsExpression && Line.MustBeDeclaration &&1704(!Tok->Next ||1705!Tok->Next->isOneOf(tok::identifier, tok::string_literal) ||1706!Tok->Next->Next ||1707!Tok->Next->Next->isOneOf(tok::colon, tok::question))) {1708Tok->setType(TT_CSharpNullable);1709break;1710}1711}1712parseConditional();1713break;1714case tok::kw_template:1715parseTemplateDeclaration();1716break;1717case tok::comma:1718switch (Contexts.back().ContextType) {1719case Context::CtorInitializer:1720Tok->setType(TT_CtorInitializerComma);1721break;1722case Context::InheritanceList:1723Tok->setType(TT_InheritanceComma);1724break;1725case Context::VerilogInstancePortList:1726Tok->setFinalizedType(TT_VerilogInstancePortComma);1727break;1728default:1729if (Style.isVerilog() && Contexts.size() == 1 &&1730Line.startsWith(Keywords.kw_assign)) {1731Tok->setFinalizedType(TT_VerilogAssignComma);1732} else if (Contexts.back().FirstStartOfName &&1733(Contexts.size() == 1 || startsWithInitStatement(Line))) {1734Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;1735Line.IsMultiVariableDeclStmt = true;1736}1737break;1738}1739if (Contexts.back().ContextType == Context::ForEachMacro)1740Contexts.back().IsExpression = true;1741break;1742case tok::kw_default:1743// Unindent case labels.1744if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) &&1745(Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) {1746--Line.Level;1747}1748break;1749case tok::identifier:1750if (Tok->isOneOf(Keywords.kw___has_include,1751Keywords.kw___has_include_next)) {1752parseHasInclude();1753}1754if (Style.isCSharp() && Tok->is(Keywords.kw_where) && Tok->Next &&1755Tok->Next->isNot(tok::l_paren)) {1756Tok->setType(TT_CSharpGenericTypeConstraint);1757parseCSharpGenericTypeConstraint();1758if (!Tok->getPreviousNonComment())1759Line.IsContinuation = true;1760}1761if (Style.isTableGen()) {1762if (Tok->is(Keywords.kw_assert)) {1763if (!parseTableGenValue())1764return false;1765} else if (Tok->isOneOf(Keywords.kw_def, Keywords.kw_defm) &&1766(!Tok->Next ||1767!Tok->Next->isOneOf(tok::colon, tok::l_brace))) {1768// The case NameValue appears.1769if (!parseTableGenValue(true))1770return false;1771}1772}1773break;1774case tok::arrow:1775if (Tok->isNot(TT_LambdaArrow) && Tok->Previous &&1776Tok->Previous->is(tok::kw_noexcept)) {1777Tok->setType(TT_TrailingReturnArrow);1778}1779break;1780case tok::equal:1781// In TableGen, there must be a value after "=";1782if (Style.isTableGen() && !parseTableGenValue())1783return false;1784break;1785default:1786break;1787}1788return true;1789}17901791void parseCSharpGenericTypeConstraint() {1792int OpenAngleBracketsCount = 0;1793while (CurrentToken) {1794if (CurrentToken->is(tok::less)) {1795// parseAngle is too greedy and will consume the whole line.1796CurrentToken->setType(TT_TemplateOpener);1797++OpenAngleBracketsCount;1798next();1799} else if (CurrentToken->is(tok::greater)) {1800CurrentToken->setType(TT_TemplateCloser);1801--OpenAngleBracketsCount;1802next();1803} else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) {1804// We allow line breaks after GenericTypeConstraintComma's1805// so do not flag commas in Generics as GenericTypeConstraintComma's.1806CurrentToken->setType(TT_CSharpGenericTypeConstraintComma);1807next();1808} else if (CurrentToken->is(Keywords.kw_where)) {1809CurrentToken->setType(TT_CSharpGenericTypeConstraint);1810next();1811} else if (CurrentToken->is(tok::colon)) {1812CurrentToken->setType(TT_CSharpGenericTypeConstraintColon);1813next();1814} else {1815next();1816}1817}1818}18191820void parseIncludeDirective() {1821if (CurrentToken && CurrentToken->is(tok::less)) {1822next();1823while (CurrentToken) {1824// Mark tokens up to the trailing line comments as implicit string1825// literals.1826if (CurrentToken->isNot(tok::comment) &&1827!CurrentToken->TokenText.starts_with("//")) {1828CurrentToken->setType(TT_ImplicitStringLiteral);1829}1830next();1831}1832}1833}18341835void parseWarningOrError() {1836next();1837// We still want to format the whitespace left of the first token of the1838// warning or error.1839next();1840while (CurrentToken) {1841CurrentToken->setType(TT_ImplicitStringLiteral);1842next();1843}1844}18451846void parsePragma() {1847next(); // Consume "pragma".1848if (CurrentToken &&1849CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option,1850Keywords.kw_region)) {1851bool IsMarkOrRegion =1852CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_region);1853next();1854next(); // Consume first token (so we fix leading whitespace).1855while (CurrentToken) {1856if (IsMarkOrRegion || CurrentToken->Previous->is(TT_BinaryOperator))1857CurrentToken->setType(TT_ImplicitStringLiteral);1858next();1859}1860}1861}18621863void parseHasInclude() {1864if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1865return;1866next(); // '('1867parseIncludeDirective();1868next(); // ')'1869}18701871LineType parsePreprocessorDirective() {1872bool IsFirstToken = CurrentToken->IsFirst;1873LineType Type = LT_PreprocessorDirective;1874next();1875if (!CurrentToken)1876return Type;18771878if (Style.isJavaScript() && IsFirstToken) {1879// JavaScript files can contain shebang lines of the form:1880// #!/usr/bin/env node1881// Treat these like C++ #include directives.1882while (CurrentToken) {1883// Tokens cannot be comments here.1884CurrentToken->setType(TT_ImplicitStringLiteral);1885next();1886}1887return LT_ImportStatement;1888}18891890if (CurrentToken->is(tok::numeric_constant)) {1891CurrentToken->SpacesRequiredBefore = 1;1892return Type;1893}1894// Hashes in the middle of a line can lead to any strange token1895// sequence.1896if (!CurrentToken->Tok.getIdentifierInfo())1897return Type;1898// In Verilog macro expansions start with a backtick just like preprocessor1899// directives. Thus we stop if the word is not a preprocessor directive.1900if (Style.isVerilog() && !Keywords.isVerilogPPDirective(*CurrentToken))1901return LT_Invalid;1902switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {1903case tok::pp_include:1904case tok::pp_include_next:1905case tok::pp_import:1906next();1907parseIncludeDirective();1908Type = LT_ImportStatement;1909break;1910case tok::pp_error:1911case tok::pp_warning:1912parseWarningOrError();1913break;1914case tok::pp_pragma:1915parsePragma();1916break;1917case tok::pp_if:1918case tok::pp_elif:1919Contexts.back().IsExpression = true;1920next();1921if (CurrentToken)1922CurrentToken->SpacesRequiredBefore = true;1923parseLine();1924break;1925default:1926break;1927}1928while (CurrentToken) {1929FormatToken *Tok = CurrentToken;1930next();1931if (Tok->is(tok::l_paren)) {1932parseParens();1933} else if (Tok->isOneOf(Keywords.kw___has_include,1934Keywords.kw___has_include_next)) {1935parseHasInclude();1936}1937}1938return Type;1939}19401941public:1942LineType parseLine() {1943if (!CurrentToken)1944return LT_Invalid;1945NonTemplateLess.clear();1946if (!Line.InMacroBody && CurrentToken->is(tok::hash)) {1947// We were not yet allowed to use C++17 optional when this was being1948// written. So we used LT_Invalid to mark that the line is not a1949// preprocessor directive.1950auto Type = parsePreprocessorDirective();1951if (Type != LT_Invalid)1952return Type;1953}19541955// Directly allow to 'import <string-literal>' to support protocol buffer1956// definitions (github.com/google/protobuf) or missing "#" (either way we1957// should not break the line).1958IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();1959if ((Style.Language == FormatStyle::LK_Java &&1960CurrentToken->is(Keywords.kw_package)) ||1961(!Style.isVerilog() && Info &&1962Info->getPPKeywordID() == tok::pp_import && CurrentToken->Next &&1963CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier,1964tok::kw_static))) {1965next();1966parseIncludeDirective();1967return LT_ImportStatement;1968}19691970// If this line starts and ends in '<' and '>', respectively, it is likely1971// part of "#define <a/b.h>".1972if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) {1973parseIncludeDirective();1974return LT_ImportStatement;1975}19761977// In .proto files, top-level options and package statements are very1978// similar to import statements and should not be line-wrapped.1979if (Style.Language == FormatStyle::LK_Proto && Line.Level == 0 &&1980CurrentToken->isOneOf(Keywords.kw_option, Keywords.kw_package)) {1981next();1982if (CurrentToken && CurrentToken->is(tok::identifier)) {1983while (CurrentToken)1984next();1985return LT_ImportStatement;1986}1987}19881989bool KeywordVirtualFound = false;1990bool ImportStatement = false;19911992// import {...} from '...';1993if (Style.isJavaScript() && CurrentToken->is(Keywords.kw_import))1994ImportStatement = true;19951996while (CurrentToken) {1997if (CurrentToken->is(tok::kw_virtual))1998KeywordVirtualFound = true;1999if (Style.isJavaScript()) {2000// export {...} from '...';2001// An export followed by "from 'some string';" is a re-export from2002// another module identified by a URI and is treated as a2003// LT_ImportStatement (i.e. prevent wraps on it for long URIs).2004// Just "export {...};" or "export class ..." should not be treated as2005// an import in this sense.2006if (Line.First->is(tok::kw_export) &&2007CurrentToken->is(Keywords.kw_from) && CurrentToken->Next &&2008CurrentToken->Next->isStringLiteral()) {2009ImportStatement = true;2010}2011if (isClosureImportStatement(*CurrentToken))2012ImportStatement = true;2013}2014if (!consumeToken())2015return LT_Invalid;2016}2017if (Line.Type == LT_AccessModifier)2018return LT_AccessModifier;2019if (KeywordVirtualFound)2020return LT_VirtualFunctionDecl;2021if (ImportStatement)2022return LT_ImportStatement;20232024if (Line.startsWith(TT_ObjCMethodSpecifier)) {2025if (Contexts.back().FirstObjCSelectorName) {2026Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =2027Contexts.back().LongestObjCSelectorName;2028}2029return LT_ObjCMethodDecl;2030}20312032for (const auto &ctx : Contexts)2033if (ctx.ContextType == Context::StructArrayInitializer)2034return LT_ArrayOfStructInitializer;20352036return LT_Other;2037}20382039private:2040bool isClosureImportStatement(const FormatToken &Tok) {2041// FIXME: Closure-library specific stuff should not be hard-coded but be2042// configurable.2043return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&2044Tok.Next->Next &&2045(Tok.Next->Next->TokenText == "module" ||2046Tok.Next->Next->TokenText == "provide" ||2047Tok.Next->Next->TokenText == "require" ||2048Tok.Next->Next->TokenText == "requireType" ||2049Tok.Next->Next->TokenText == "forwardDeclare") &&2050Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);2051}20522053void resetTokenMetadata() {2054if (!CurrentToken)2055return;20562057// Reset token type in case we have already looked at it and then2058// recovered from an error (e.g. failure to find the matching >).2059if (!CurrentToken->isTypeFinalized() &&2060!CurrentToken->isOneOf(2061TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro,2062TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,2063TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,2064TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,2065TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,2066TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro,2067TT_FunctionLikeOrFreestandingMacro, TT_ClassLBrace, TT_EnumLBrace,2068TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,2069TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,2070TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,2071TT_BracedListLBrace)) {2072CurrentToken->setType(TT_Unknown);2073}2074CurrentToken->Role.reset();2075CurrentToken->MatchingParen = nullptr;2076CurrentToken->FakeLParens.clear();2077CurrentToken->FakeRParens = 0;2078}20792080void next() {2081if (!CurrentToken)2082return;20832084CurrentToken->NestingLevel = Contexts.size() - 1;2085CurrentToken->BindingStrength = Contexts.back().BindingStrength;2086modifyContext(*CurrentToken);2087determineTokenType(*CurrentToken);2088CurrentToken = CurrentToken->Next;20892090resetTokenMetadata();2091}20922093/// A struct to hold information valid in a specific context, e.g.2094/// a pair of parenthesis.2095struct Context {2096Context(tok::TokenKind ContextKind, unsigned BindingStrength,2097bool IsExpression)2098: ContextKind(ContextKind), BindingStrength(BindingStrength),2099IsExpression(IsExpression) {}21002101tok::TokenKind ContextKind;2102unsigned BindingStrength;2103bool IsExpression;2104unsigned LongestObjCSelectorName = 0;2105bool ColonIsForRangeExpr = false;2106bool ColonIsDictLiteral = false;2107bool ColonIsObjCMethodExpr = false;2108FormatToken *FirstObjCSelectorName = nullptr;2109FormatToken *FirstStartOfName = nullptr;2110bool CanBeExpression = true;2111bool CaretFound = false;2112bool InCpp11AttributeSpecifier = false;2113bool InCSharpAttributeSpecifier = false;2114bool VerilogAssignmentFound = false;2115// Whether the braces may mean concatenation instead of structure or array2116// literal.2117bool VerilogMayBeConcatenation = false;2118bool IsTableGenDAGArg = false;2119bool IsTableGenBangOpe = false;2120bool IsTableGenCondOpe = false;2121enum {2122Unknown,2123// Like the part after `:` in a constructor.2124// Context(...) : IsExpression(IsExpression)2125CtorInitializer,2126// Like in the parentheses in a foreach.2127ForEachMacro,2128// Like the inheritance list in a class declaration.2129// class Input : public IO2130InheritanceList,2131// Like in the braced list.2132// int x[] = {};2133StructArrayInitializer,2134// Like in `static_cast<int>`.2135TemplateArgument,2136// C11 _Generic selection.2137C11GenericSelection,2138// Like in the outer parentheses in `ffnand ff1(.q());`.2139VerilogInstancePortList,2140} ContextType = Unknown;2141};21422143/// Puts a new \c Context onto the stack \c Contexts for the lifetime2144/// of each instance.2145struct ScopedContextCreator {2146AnnotatingParser &P;21472148ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,2149unsigned Increase)2150: P(P) {2151P.Contexts.push_back(Context(ContextKind,2152P.Contexts.back().BindingStrength + Increase,2153P.Contexts.back().IsExpression));2154}21552156~ScopedContextCreator() {2157if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {2158if (P.Contexts.back().ContextType == Context::StructArrayInitializer) {2159P.Contexts.pop_back();2160P.Contexts.back().ContextType = Context::StructArrayInitializer;2161return;2162}2163}2164P.Contexts.pop_back();2165}2166};21672168void modifyContext(const FormatToken &Current) {2169auto AssignmentStartsExpression = [&]() {2170if (Current.getPrecedence() != prec::Assignment)2171return false;21722173if (Line.First->isOneOf(tok::kw_using, tok::kw_return))2174return false;2175if (Line.First->is(tok::kw_template)) {2176assert(Current.Previous);2177if (Current.Previous->is(tok::kw_operator)) {2178// `template ... operator=` cannot be an expression.2179return false;2180}21812182// `template` keyword can start a variable template.2183const FormatToken *Tok = Line.First->getNextNonComment();2184assert(Tok); // Current token is on the same line.2185if (Tok->isNot(TT_TemplateOpener)) {2186// Explicit template instantiations do not have `<>`.2187return false;2188}21892190// This is the default value of a template parameter, determine if it's2191// type or non-type.2192if (Contexts.back().ContextKind == tok::less) {2193assert(Current.Previous->Previous);2194return !Current.Previous->Previous->isOneOf(tok::kw_typename,2195tok::kw_class);2196}21972198Tok = Tok->MatchingParen;2199if (!Tok)2200return false;2201Tok = Tok->getNextNonComment();2202if (!Tok)2203return false;22042205if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct,2206tok::kw_using)) {2207return false;2208}22092210return true;2211}22122213// Type aliases use `type X = ...;` in TypeScript and can be exported2214// using `export type ...`.2215if (Style.isJavaScript() &&2216(Line.startsWith(Keywords.kw_type, tok::identifier) ||2217Line.startsWith(tok::kw_export, Keywords.kw_type,2218tok::identifier))) {2219return false;2220}22212222return !Current.Previous || Current.Previous->isNot(tok::kw_operator);2223};22242225if (AssignmentStartsExpression()) {2226Contexts.back().IsExpression = true;2227if (!Line.startsWith(TT_UnaryOperator)) {2228for (FormatToken *Previous = Current.Previous;2229Previous && Previous->Previous &&2230!Previous->Previous->isOneOf(tok::comma, tok::semi);2231Previous = Previous->Previous) {2232if (Previous->isOneOf(tok::r_square, tok::r_paren, tok::greater)) {2233Previous = Previous->MatchingParen;2234if (!Previous)2235break;2236}2237if (Previous->opensScope())2238break;2239if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&2240Previous->isPointerOrReference() && Previous->Previous &&2241Previous->Previous->isNot(tok::equal)) {2242Previous->setType(TT_PointerOrReference);2243}2244}2245}2246} else if (Current.is(tok::lessless) &&2247(!Current.Previous ||2248Current.Previous->isNot(tok::kw_operator))) {2249Contexts.back().IsExpression = true;2250} else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {2251Contexts.back().IsExpression = true;2252} else if (Current.is(TT_TrailingReturnArrow)) {2253Contexts.back().IsExpression = false;2254} else if (Current.isOneOf(TT_LambdaArrow, Keywords.kw_assert)) {2255Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java;2256} else if (Current.Previous &&2257Current.Previous->is(TT_CtorInitializerColon)) {2258Contexts.back().IsExpression = true;2259Contexts.back().ContextType = Context::CtorInitializer;2260} else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) {2261Contexts.back().ContextType = Context::InheritanceList;2262} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {2263for (FormatToken *Previous = Current.Previous;2264Previous && Previous->isOneOf(tok::star, tok::amp);2265Previous = Previous->Previous) {2266Previous->setType(TT_PointerOrReference);2267}2268if (Line.MustBeDeclaration &&2269Contexts.front().ContextType != Context::CtorInitializer) {2270Contexts.back().IsExpression = false;2271}2272} else if (Current.is(tok::kw_new)) {2273Contexts.back().CanBeExpression = false;2274} else if (Current.is(tok::semi) ||2275(Current.is(tok::exclaim) && Current.Previous &&2276Current.Previous->isNot(tok::kw_operator))) {2277// This should be the condition or increment in a for-loop.2278// But not operator !() (can't use TT_OverloadedOperator here as its not2279// been annotated yet).2280Contexts.back().IsExpression = true;2281}2282}22832284static FormatToken *untilMatchingParen(FormatToken *Current) {2285// Used when `MatchingParen` is not yet established.2286int ParenLevel = 0;2287while (Current) {2288if (Current->is(tok::l_paren))2289++ParenLevel;2290if (Current->is(tok::r_paren))2291--ParenLevel;2292if (ParenLevel < 1)2293break;2294Current = Current->Next;2295}2296return Current;2297}22982299static bool isDeductionGuide(FormatToken &Current) {2300// Look for a deduction guide template<T> A(...) -> A<...>;2301if (Current.Previous && Current.Previous->is(tok::r_paren) &&2302Current.startsSequence(tok::arrow, tok::identifier, tok::less)) {2303// Find the TemplateCloser.2304FormatToken *TemplateCloser = Current.Next->Next;2305int NestingLevel = 0;2306while (TemplateCloser) {2307// Skip over an expressions in parens A<(3 < 2)>;2308if (TemplateCloser->is(tok::l_paren)) {2309// No Matching Paren yet so skip to matching paren2310TemplateCloser = untilMatchingParen(TemplateCloser);2311if (!TemplateCloser)2312break;2313}2314if (TemplateCloser->is(tok::less))2315++NestingLevel;2316if (TemplateCloser->is(tok::greater))2317--NestingLevel;2318if (NestingLevel < 1)2319break;2320TemplateCloser = TemplateCloser->Next;2321}2322// Assuming we have found the end of the template ensure its followed2323// with a semi-colon.2324if (TemplateCloser && TemplateCloser->Next &&2325TemplateCloser->Next->is(tok::semi) &&2326Current.Previous->MatchingParen) {2327// Determine if the identifier `A` prior to the A<..>; is the same as2328// prior to the A(..)2329FormatToken *LeadingIdentifier =2330Current.Previous->MatchingParen->Previous;23312332return LeadingIdentifier &&2333LeadingIdentifier->TokenText == Current.Next->TokenText;2334}2335}2336return false;2337}23382339void determineTokenType(FormatToken &Current) {2340if (Current.isNot(TT_Unknown)) {2341// The token type is already known.2342return;2343}23442345if ((Style.isJavaScript() || Style.isCSharp()) &&2346Current.is(tok::exclaim)) {2347if (Current.Previous) {2348bool IsIdentifier =2349Style.isJavaScript()2350? Keywords.isJavaScriptIdentifier(2351*Current.Previous, /* AcceptIdentifierName= */ true)2352: Current.Previous->is(tok::identifier);2353if (IsIdentifier ||2354Current.Previous->isOneOf(2355tok::kw_default, tok::kw_namespace, tok::r_paren, tok::r_square,2356tok::r_brace, tok::kw_false, tok::kw_true, Keywords.kw_type,2357Keywords.kw_get, Keywords.kw_init, Keywords.kw_set) ||2358Current.Previous->Tok.isLiteral()) {2359Current.setType(TT_NonNullAssertion);2360return;2361}2362}2363if (Current.Next &&2364Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {2365Current.setType(TT_NonNullAssertion);2366return;2367}2368}23692370// Line.MightBeFunctionDecl can only be true after the parentheses of a2371// function declaration have been found. In this case, 'Current' is a2372// trailing token of this declaration and thus cannot be a name.2373if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&2374Current.is(Keywords.kw_instanceof)) {2375Current.setType(TT_BinaryOperator);2376} else if (isStartOfName(Current) &&2377(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {2378Contexts.back().FirstStartOfName = &Current;2379Current.setType(TT_StartOfName);2380} else if (Current.is(tok::semi)) {2381// Reset FirstStartOfName after finding a semicolon so that a for loop2382// with multiple increment statements is not confused with a for loop2383// having multiple variable declarations.2384Contexts.back().FirstStartOfName = nullptr;2385} else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {2386AutoFound = true;2387} else if (Current.is(tok::arrow) &&2388Style.Language == FormatStyle::LK_Java) {2389Current.setType(TT_LambdaArrow);2390} else if (Current.is(tok::arrow) && Style.isVerilog()) {2391// The implication operator.2392Current.setType(TT_BinaryOperator);2393} else if (Current.is(tok::arrow) && AutoFound &&2394Line.MightBeFunctionDecl && Current.NestingLevel == 0 &&2395!Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {2396// not auto operator->() -> xxx;2397Current.setType(TT_TrailingReturnArrow);2398} else if (Current.is(tok::arrow) && Current.Previous &&2399Current.Previous->is(tok::r_brace)) {2400// Concept implicit conversion constraint needs to be treated like2401// a trailing return type ... } -> <type>.2402Current.setType(TT_TrailingReturnArrow);2403} else if (isDeductionGuide(Current)) {2404// Deduction guides trailing arrow " A(...) -> A<T>;".2405Current.setType(TT_TrailingReturnArrow);2406} else if (Current.isPointerOrReference()) {2407Current.setType(determineStarAmpUsage(2408Current,2409Contexts.back().CanBeExpression && Contexts.back().IsExpression,2410Contexts.back().ContextType == Context::TemplateArgument));2411} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||2412(Style.isVerilog() && Current.is(tok::pipe))) {2413Current.setType(determinePlusMinusCaretUsage(Current));2414if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))2415Contexts.back().CaretFound = true;2416} else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {2417Current.setType(determineIncrementUsage(Current));2418} else if (Current.isOneOf(tok::exclaim, tok::tilde)) {2419Current.setType(TT_UnaryOperator);2420} else if (Current.is(tok::question)) {2421if (Style.isJavaScript() && Line.MustBeDeclaration &&2422!Contexts.back().IsExpression) {2423// In JavaScript, `interface X { foo?(): bar; }` is an optional method2424// on the interface, not a ternary expression.2425Current.setType(TT_JsTypeOptionalQuestion);2426} else if (Style.isTableGen()) {2427// In TableGen, '?' is just an identifier like token.2428Current.setType(TT_Unknown);2429} else {2430Current.setType(TT_ConditionalExpr);2431}2432} else if (Current.isBinaryOperator() &&2433(!Current.Previous || Current.Previous->isNot(tok::l_square)) &&2434(Current.isNot(tok::greater) &&2435Style.Language != FormatStyle::LK_TextProto)) {2436if (Style.isVerilog()) {2437if (Current.is(tok::lessequal) && Contexts.size() == 1 &&2438!Contexts.back().VerilogAssignmentFound) {2439// In Verilog `<=` is assignment if in its own statement. It is a2440// statement instead of an expression, that is it can not be chained.2441Current.ForcedPrecedence = prec::Assignment;2442Current.setFinalizedType(TT_BinaryOperator);2443}2444if (Current.getPrecedence() == prec::Assignment)2445Contexts.back().VerilogAssignmentFound = true;2446}2447Current.setType(TT_BinaryOperator);2448} else if (Current.is(tok::comment)) {2449if (Current.TokenText.starts_with("/*")) {2450if (Current.TokenText.ends_with("*/")) {2451Current.setType(TT_BlockComment);2452} else {2453// The lexer has for some reason determined a comment here. But we2454// cannot really handle it, if it isn't properly terminated.2455Current.Tok.setKind(tok::unknown);2456}2457} else {2458Current.setType(TT_LineComment);2459}2460} else if (Current.is(tok::string_literal)) {2461if (Style.isVerilog() && Contexts.back().VerilogMayBeConcatenation &&2462Current.getPreviousNonComment() &&2463Current.getPreviousNonComment()->isOneOf(tok::comma, tok::l_brace) &&2464Current.getNextNonComment() &&2465Current.getNextNonComment()->isOneOf(tok::comma, tok::r_brace)) {2466Current.setType(TT_StringInConcatenation);2467}2468} else if (Current.is(tok::l_paren)) {2469if (lParenStartsCppCast(Current))2470Current.setType(TT_CppCastLParen);2471} else if (Current.is(tok::r_paren)) {2472if (rParenEndsCast(Current))2473Current.setType(TT_CastRParen);2474if (Current.MatchingParen && Current.Next &&2475!Current.Next->isBinaryOperator() &&2476!Current.Next->isOneOf(2477tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma,2478tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) {2479if (FormatToken *AfterParen = Current.MatchingParen->Next;2480AfterParen && AfterParen->isNot(tok::caret)) {2481// Make sure this isn't the return type of an Obj-C block declaration.2482if (FormatToken *BeforeParen = Current.MatchingParen->Previous;2483BeforeParen && BeforeParen->is(tok::identifier) &&2484BeforeParen->isNot(TT_TypenameMacro) &&2485BeforeParen->TokenText == BeforeParen->TokenText.upper() &&2486(!BeforeParen->Previous ||2487BeforeParen->Previous->ClosesTemplateDeclaration ||2488BeforeParen->Previous->ClosesRequiresClause)) {2489Current.setType(TT_FunctionAnnotationRParen);2490}2491}2492}2493} else if (Current.is(tok::at) && Current.Next && !Style.isJavaScript() &&2494Style.Language != FormatStyle::LK_Java) {2495// In Java & JavaScript, "@..." is a decorator or annotation. In ObjC, it2496// marks declarations and properties that need special formatting.2497switch (Current.Next->Tok.getObjCKeywordID()) {2498case tok::objc_interface:2499case tok::objc_implementation:2500case tok::objc_protocol:2501Current.setType(TT_ObjCDecl);2502break;2503case tok::objc_property:2504Current.setType(TT_ObjCProperty);2505break;2506default:2507break;2508}2509} else if (Current.is(tok::period)) {2510FormatToken *PreviousNoComment = Current.getPreviousNonComment();2511if (PreviousNoComment &&2512PreviousNoComment->isOneOf(tok::comma, tok::l_brace)) {2513Current.setType(TT_DesignatedInitializerPeriod);2514} else if (Style.Language == FormatStyle::LK_Java && Current.Previous &&2515Current.Previous->isOneOf(TT_JavaAnnotation,2516TT_LeadingJavaAnnotation)) {2517Current.setType(Current.Previous->getType());2518}2519} else if (canBeObjCSelectorComponent(Current) &&2520// FIXME(bug 36976): ObjC return types shouldn't use2521// TT_CastRParen.2522Current.Previous && Current.Previous->is(TT_CastRParen) &&2523Current.Previous->MatchingParen &&2524Current.Previous->MatchingParen->Previous &&2525Current.Previous->MatchingParen->Previous->is(2526TT_ObjCMethodSpecifier)) {2527// This is the first part of an Objective-C selector name. (If there's no2528// colon after this, this is the only place which annotates the identifier2529// as a selector.)2530Current.setType(TT_SelectorName);2531} else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept,2532tok::kw_requires) &&2533Current.Previous &&2534!Current.Previous->isOneOf(tok::equal, tok::at,2535TT_CtorInitializerComma,2536TT_CtorInitializerColon) &&2537Line.MightBeFunctionDecl && Contexts.size() == 1) {2538// Line.MightBeFunctionDecl can only be true after the parentheses of a2539// function declaration have been found.2540Current.setType(TT_TrailingAnnotation);2541} else if ((Style.Language == FormatStyle::LK_Java ||2542Style.isJavaScript()) &&2543Current.Previous) {2544if (Current.Previous->is(tok::at) &&2545Current.isNot(Keywords.kw_interface)) {2546const FormatToken &AtToken = *Current.Previous;2547const FormatToken *Previous = AtToken.getPreviousNonComment();2548if (!Previous || Previous->is(TT_LeadingJavaAnnotation))2549Current.setType(TT_LeadingJavaAnnotation);2550else2551Current.setType(TT_JavaAnnotation);2552} else if (Current.Previous->is(tok::period) &&2553Current.Previous->isOneOf(TT_JavaAnnotation,2554TT_LeadingJavaAnnotation)) {2555Current.setType(Current.Previous->getType());2556}2557}2558}25592560/// Take a guess at whether \p Tok starts a name of a function or2561/// variable declaration.2562///2563/// This is a heuristic based on whether \p Tok is an identifier following2564/// something that is likely a type.2565bool isStartOfName(const FormatToken &Tok) {2566// Handled in ExpressionParser for Verilog.2567if (Style.isVerilog())2568return false;25692570if (Tok.isNot(tok::identifier) || !Tok.Previous)2571return false;25722573if (const auto *NextNonComment = Tok.getNextNonComment();2574(!NextNonComment && !Line.InMacroBody) ||2575(NextNonComment &&2576(NextNonComment->isPointerOrReference() ||2577NextNonComment->is(tok::string_literal) ||2578(Line.InPragmaDirective && NextNonComment->is(tok::identifier))))) {2579return false;2580}25812582if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,2583Keywords.kw_as)) {2584return false;2585}2586if (Style.isJavaScript() && Tok.Previous->is(Keywords.kw_in))2587return false;25882589// Skip "const" as it does not have an influence on whether this is a name.2590FormatToken *PreviousNotConst = Tok.getPreviousNonComment();25912592// For javascript const can be like "let" or "var"2593if (!Style.isJavaScript())2594while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))2595PreviousNotConst = PreviousNotConst->getPreviousNonComment();25962597if (!PreviousNotConst)2598return false;25992600if (PreviousNotConst->ClosesRequiresClause)2601return false;26022603if (Style.isTableGen()) {2604// keywords such as let and def* defines names.2605if (Keywords.isTableGenDefinition(*PreviousNotConst))2606return true;2607// Otherwise C++ style declarations is available only inside the brace.2608if (Contexts.back().ContextKind != tok::l_brace)2609return false;2610}26112612bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&2613PreviousNotConst->Previous &&2614PreviousNotConst->Previous->is(tok::hash);26152616if (PreviousNotConst->is(TT_TemplateCloser)) {2617return PreviousNotConst && PreviousNotConst->MatchingParen &&2618PreviousNotConst->MatchingParen->Previous &&2619PreviousNotConst->MatchingParen->Previous->isNot(tok::period) &&2620PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);2621}26222623if ((PreviousNotConst->is(tok::r_paren) &&2624PreviousNotConst->is(TT_TypeDeclarationParen)) ||2625PreviousNotConst->is(TT_AttributeRParen)) {2626return true;2627}26282629// If is a preprocess keyword like #define.2630if (IsPPKeyword)2631return false;26322633// int a or auto a.2634if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) &&2635PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) {2636return true;2637}26382639// *a or &a or &&a.2640if (PreviousNotConst->is(TT_PointerOrReference))2641return true;26422643// MyClass a;2644if (PreviousNotConst->isTypeName(LangOpts))2645return true;26462647// type[] a in Java2648if (Style.Language == FormatStyle::LK_Java &&2649PreviousNotConst->is(tok::r_square)) {2650return true;2651}26522653// const a = in JavaScript.2654return Style.isJavaScript() && PreviousNotConst->is(tok::kw_const);2655}26562657/// Determine whether '(' is starting a C++ cast.2658bool lParenStartsCppCast(const FormatToken &Tok) {2659// C-style casts are only used in C++.2660if (!IsCpp)2661return false;26622663FormatToken *LeftOfParens = Tok.getPreviousNonComment();2664if (LeftOfParens && LeftOfParens->is(TT_TemplateCloser) &&2665LeftOfParens->MatchingParen) {2666auto *Prev = LeftOfParens->MatchingParen->getPreviousNonComment();2667if (Prev &&2668Prev->isOneOf(tok::kw_const_cast, tok::kw_dynamic_cast,2669tok::kw_reinterpret_cast, tok::kw_static_cast)) {2670// FIXME: Maybe we should handle identifiers ending with "_cast",2671// e.g. any_cast?2672return true;2673}2674}2675return false;2676}26772678/// Determine whether ')' is ending a cast.2679bool rParenEndsCast(const FormatToken &Tok) {2680assert(Tok.is(tok::r_paren));26812682if (!Tok.MatchingParen || !Tok.Previous)2683return false;26842685// C-style casts are only used in C++, C# and Java.2686if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java)2687return false;26882689const auto *LParen = Tok.MatchingParen;2690const auto *BeforeRParen = Tok.Previous;2691const auto *AfterRParen = Tok.Next;26922693// Empty parens aren't casts and there are no casts at the end of the line.2694if (BeforeRParen == LParen || !AfterRParen)2695return false;26962697if (LParen->is(TT_OverloadedOperatorLParen))2698return false;26992700auto *LeftOfParens = LParen->getPreviousNonComment();2701if (LeftOfParens) {2702// If there is a closing parenthesis left of the current2703// parentheses, look past it as these might be chained casts.2704if (LeftOfParens->is(tok::r_paren) &&2705LeftOfParens->isNot(TT_CastRParen)) {2706if (!LeftOfParens->MatchingParen ||2707!LeftOfParens->MatchingParen->Previous) {2708return false;2709}2710LeftOfParens = LeftOfParens->MatchingParen->Previous;2711}27122713if (LeftOfParens->is(tok::r_square)) {2714// delete[] (void *)ptr;2715auto MayBeArrayDelete = [](FormatToken *Tok) -> FormatToken * {2716if (Tok->isNot(tok::r_square))2717return nullptr;27182719Tok = Tok->getPreviousNonComment();2720if (!Tok || Tok->isNot(tok::l_square))2721return nullptr;27222723Tok = Tok->getPreviousNonComment();2724if (!Tok || Tok->isNot(tok::kw_delete))2725return nullptr;2726return Tok;2727};2728if (FormatToken *MaybeDelete = MayBeArrayDelete(LeftOfParens))2729LeftOfParens = MaybeDelete;2730}27312732// The Condition directly below this one will see the operator arguments2733// as a (void *foo) cast.2734// void operator delete(void *foo) ATTRIB;2735if (LeftOfParens->Tok.getIdentifierInfo() && LeftOfParens->Previous &&2736LeftOfParens->Previous->is(tok::kw_operator)) {2737return false;2738}27392740// If there is an identifier (or with a few exceptions a keyword) right2741// before the parentheses, this is unlikely to be a cast.2742if (LeftOfParens->Tok.getIdentifierInfo() &&2743!LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case,2744tok::kw_delete, tok::kw_throw)) {2745return false;2746}27472748// Certain other tokens right before the parentheses are also signals that2749// this cannot be a cast.2750if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator,2751TT_TemplateCloser, tok::ellipsis)) {2752return false;2753}2754}27552756if (AfterRParen->is(tok::question) ||2757(AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) {2758return false;2759}27602761// `foreach((A a, B b) in someList)` should not be seen as a cast.2762if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp())2763return false;27642765// Functions which end with decorations like volatile, noexcept are unlikely2766// to be casts.2767if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,2768tok::kw_requires, tok::kw_throw, tok::arrow,2769Keywords.kw_override, Keywords.kw_final) ||2770isCppAttribute(IsCpp, *AfterRParen)) {2771return false;2772}27732774// As Java has no function types, a "(" after the ")" likely means that this2775// is a cast.2776if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren))2777return true;27782779// If a (non-string) literal follows, this is likely a cast.2780if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||2781(AfterRParen->Tok.isLiteral() &&2782AfterRParen->isNot(tok::string_literal))) {2783return true;2784}27852786// Heuristically try to determine whether the parentheses contain a type.2787auto IsQualifiedPointerOrReference = [](const FormatToken *T,2788const LangOptions &LangOpts) {2789// This is used to handle cases such as x = (foo *const)&y;2790assert(!T->isTypeName(LangOpts) && "Should have already been checked");2791// Strip trailing qualifiers such as const or volatile when checking2792// whether the parens could be a cast to a pointer/reference type.2793while (T) {2794if (T->is(TT_AttributeRParen)) {2795// Handle `x = (foo *__attribute__((foo)))&v;`:2796assert(T->is(tok::r_paren));2797assert(T->MatchingParen);2798assert(T->MatchingParen->is(tok::l_paren));2799assert(T->MatchingParen->is(TT_AttributeLParen));2800if (const auto *Tok = T->MatchingParen->Previous;2801Tok && Tok->isAttribute()) {2802T = Tok->Previous;2803continue;2804}2805} else if (T->is(TT_AttributeSquare)) {2806// Handle `x = (foo *[[clang::foo]])&v;`:2807if (T->MatchingParen && T->MatchingParen->Previous) {2808T = T->MatchingParen->Previous;2809continue;2810}2811} else if (T->canBePointerOrReferenceQualifier()) {2812T = T->Previous;2813continue;2814}2815break;2816}2817return T && T->is(TT_PointerOrReference);2818};2819bool ParensAreType =2820BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||2821BeforeRParen->isTypeName(LangOpts) ||2822IsQualifiedPointerOrReference(BeforeRParen, LangOpts);2823bool ParensCouldEndDecl =2824AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);2825if (ParensAreType && !ParensCouldEndDecl)2826return true;28272828// At this point, we heuristically assume that there are no casts at the2829// start of the line. We assume that we have found most cases where there2830// are by the logic above, e.g. "(void)x;".2831if (!LeftOfParens)2832return false;28332834// Certain token types inside the parentheses mean that this can't be a2835// cast.2836for (const auto *Token = LParen->Next; Token != &Tok; Token = Token->Next)2837if (Token->is(TT_BinaryOperator))2838return false;28392840// If the following token is an identifier or 'this', this is a cast. All2841// cases where this can be something else are handled above.2842if (AfterRParen->isOneOf(tok::identifier, tok::kw_this))2843return true;28442845// Look for a cast `( x ) (`.2846if (AfterRParen->is(tok::l_paren) && BeforeRParen->Previous) {2847if (BeforeRParen->is(tok::identifier) &&2848BeforeRParen->Previous->is(tok::l_paren)) {2849return true;2850}2851}28522853if (!AfterRParen->Next)2854return false;28552856if (AfterRParen->is(tok::l_brace) &&2857AfterRParen->getBlockKind() == BK_BracedInit) {2858return true;2859}28602861// If the next token after the parenthesis is a unary operator, assume2862// that this is cast, unless there are unexpected tokens inside the2863// parenthesis.2864const bool NextIsAmpOrStar = AfterRParen->isOneOf(tok::amp, tok::star);2865if (!(AfterRParen->isUnaryOperator() || NextIsAmpOrStar) ||2866AfterRParen->is(tok::plus) ||2867!AfterRParen->Next->isOneOf(tok::identifier, tok::numeric_constant)) {2868return false;2869}28702871if (NextIsAmpOrStar &&2872(AfterRParen->Next->is(tok::numeric_constant) || Line.InPPDirective)) {2873return false;2874}28752876if (Line.InPPDirective && AfterRParen->is(tok::minus))2877return false;28782879// Search for unexpected tokens.2880for (auto *Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous) {2881if (Prev->is(tok::r_paren)) {2882if (Prev->is(TT_CastRParen))2883return false;2884Prev = Prev->MatchingParen;2885if (!Prev)2886return false;2887if (Prev->is(TT_FunctionTypeLParen))2888break;2889continue;2890}2891if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))2892return false;2893}28942895return true;2896}28972898/// Returns true if the token is used as a unary operator.2899bool determineUnaryOperatorByUsage(const FormatToken &Tok) {2900const FormatToken *PrevToken = Tok.getPreviousNonComment();2901if (!PrevToken)2902return true;29032904// These keywords are deliberately not included here because they may2905// precede only one of unary star/amp and plus/minus but not both. They are2906// either included in determineStarAmpUsage or determinePlusMinusCaretUsage.2907//2908// @ - It may be followed by a unary `-` in Objective-C literals. We don't2909// know how they can be followed by a star or amp.2910if (PrevToken->isOneOf(2911TT_ConditionalExpr, tok::l_paren, tok::comma, tok::colon, tok::semi,2912tok::equal, tok::question, tok::l_square, tok::l_brace,2913tok::kw_case, tok::kw_co_await, tok::kw_co_return, tok::kw_co_yield,2914tok::kw_delete, tok::kw_return, tok::kw_throw)) {2915return true;2916}29172918// We put sizeof here instead of only in determineStarAmpUsage. In the cases2919// where the unary `+` operator is overloaded, it is reasonable to write2920// things like `sizeof +x`. Like commit 446d6ec996c6c3.2921if (PrevToken->is(tok::kw_sizeof))2922return true;29232924// A sequence of leading unary operators.2925if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator))2926return true;29272928// There can't be two consecutive binary operators.2929if (PrevToken->is(TT_BinaryOperator))2930return true;29312932return false;2933}29342935/// Return the type of the given token assuming it is * or &.2936TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,2937bool InTemplateArgument) {2938if (Style.isJavaScript())2939return TT_BinaryOperator;29402941// && in C# must be a binary operator.2942if (Style.isCSharp() && Tok.is(tok::ampamp))2943return TT_BinaryOperator;29442945if (Style.isVerilog()) {2946// In Verilog, `*` can only be a binary operator. `&` can be either unary2947// or binary. `*` also includes `*>` in module path declarations in2948// specify blocks because merged tokens take the type of the first one by2949// default.2950if (Tok.is(tok::star))2951return TT_BinaryOperator;2952return determineUnaryOperatorByUsage(Tok) ? TT_UnaryOperator2953: TT_BinaryOperator;2954}29552956const FormatToken *PrevToken = Tok.getPreviousNonComment();2957if (!PrevToken)2958return TT_UnaryOperator;2959if (PrevToken->is(TT_TypeName))2960return TT_PointerOrReference;2961if (PrevToken->isOneOf(tok::kw_new, tok::kw_delete) && Tok.is(tok::ampamp))2962return TT_BinaryOperator;29632964const FormatToken *NextToken = Tok.getNextNonComment();29652966if (InTemplateArgument && NextToken && NextToken->is(tok::kw_noexcept))2967return TT_BinaryOperator;29682969if (!NextToken ||2970NextToken->isOneOf(tok::arrow, tok::equal, tok::comma, tok::r_paren,2971TT_RequiresClause) ||2972(NextToken->is(tok::kw_noexcept) && !IsExpression) ||2973NextToken->canBePointerOrReferenceQualifier() ||2974(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) {2975return TT_PointerOrReference;2976}29772978if (PrevToken->is(tok::coloncolon))2979return TT_PointerOrReference;29802981if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen))2982return TT_PointerOrReference;29832984if (determineUnaryOperatorByUsage(Tok))2985return TT_UnaryOperator;29862987if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))2988return TT_PointerOrReference;2989if (NextToken->is(tok::kw_operator) && !IsExpression)2990return TT_PointerOrReference;2991if (NextToken->isOneOf(tok::comma, tok::semi))2992return TT_PointerOrReference;29932994// After right braces, star tokens are likely to be pointers to struct,2995// union, or class.2996// struct {} *ptr;2997// This by itself is not sufficient to distinguish from multiplication2998// following a brace-initialized expression, as in:2999// int i = int{42} * 2;3000// In the struct case, the part of the struct declaration until the `{` and3001// the `}` are put on separate unwrapped lines; in the brace-initialized3002// case, the matching `{` is on the same unwrapped line, so check for the3003// presence of the matching brace to distinguish between those.3004if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) &&3005!PrevToken->MatchingParen) {3006return TT_PointerOrReference;3007}30083009if (PrevToken->endsSequence(tok::r_square, tok::l_square, tok::kw_delete))3010return TT_UnaryOperator;30113012if (PrevToken->Tok.isLiteral() ||3013PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,3014tok::kw_false, tok::r_brace)) {3015return TT_BinaryOperator;3016}30173018const FormatToken *NextNonParen = NextToken;3019while (NextNonParen && NextNonParen->is(tok::l_paren))3020NextNonParen = NextNonParen->getNextNonComment();3021if (NextNonParen && (NextNonParen->Tok.isLiteral() ||3022NextNonParen->isOneOf(tok::kw_true, tok::kw_false) ||3023NextNonParen->isUnaryOperator())) {3024return TT_BinaryOperator;3025}30263027// If we know we're in a template argument, there are no named declarations.3028// Thus, having an identifier on the right-hand side indicates a binary3029// operator.3030if (InTemplateArgument && NextToken->Tok.isAnyIdentifier())3031return TT_BinaryOperator;30323033// "&&" followed by "(", "*", or "&" is quite unlikely to be two successive3034// unary "&".3035if (Tok.is(tok::ampamp) &&3036NextToken->isOneOf(tok::l_paren, tok::star, tok::amp)) {3037return TT_BinaryOperator;3038}30393040// This catches some cases where evaluation order is used as control flow:3041// aaa && aaa->f();3042if (NextToken->Tok.isAnyIdentifier()) {3043const FormatToken *NextNextToken = NextToken->getNextNonComment();3044if (NextNextToken && NextNextToken->is(tok::arrow))3045return TT_BinaryOperator;3046}30473048// It is very unlikely that we are going to find a pointer or reference type3049// definition on the RHS of an assignment.3050if (IsExpression && !Contexts.back().CaretFound)3051return TT_BinaryOperator;30523053// Opeartors at class scope are likely pointer or reference members.3054if (!Scopes.empty() && Scopes.back() == ST_Class)3055return TT_PointerOrReference;30563057// Tokens that indicate member access or chained operator& use.3058auto IsChainedOperatorAmpOrMember = [](const FormatToken *token) {3059return !token || token->isOneOf(tok::amp, tok::period, tok::arrow,3060tok::arrowstar, tok::periodstar);3061};30623063// It's more likely that & represents operator& than an uninitialized3064// reference.3065if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() &&3066IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&3067NextToken && NextToken->Tok.isAnyIdentifier()) {3068if (auto NextNext = NextToken->getNextNonComment();3069NextNext &&3070(IsChainedOperatorAmpOrMember(NextNext) || NextNext->is(tok::semi))) {3071return TT_BinaryOperator;3072}3073}30743075return TT_PointerOrReference;3076}30773078TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {3079if (determineUnaryOperatorByUsage(Tok))3080return TT_UnaryOperator;30813082const FormatToken *PrevToken = Tok.getPreviousNonComment();3083if (!PrevToken)3084return TT_UnaryOperator;30853086if (PrevToken->is(tok::at))3087return TT_UnaryOperator;30883089// Fall back to marking the token as binary operator.3090return TT_BinaryOperator;3091}30923093/// Determine whether ++/-- are pre- or post-increments/-decrements.3094TokenType determineIncrementUsage(const FormatToken &Tok) {3095const FormatToken *PrevToken = Tok.getPreviousNonComment();3096if (!PrevToken || PrevToken->is(TT_CastRParen))3097return TT_UnaryOperator;3098if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))3099return TT_TrailingUnaryOperator;31003101return TT_UnaryOperator;3102}31033104SmallVector<Context, 8> Contexts;31053106const FormatStyle &Style;3107AnnotatedLine &Line;3108FormatToken *CurrentToken;3109bool AutoFound;3110bool IsCpp;3111LangOptions LangOpts;3112const AdditionalKeywords &Keywords;31133114SmallVector<ScopeType> &Scopes;31153116// Set of "<" tokens that do not open a template parameter list. If parseAngle3117// determines that a specific token can't be a template opener, it will make3118// same decision irrespective of the decisions for tokens leading up to it.3119// Store this information to prevent this from causing exponential runtime.3120llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;31213122int TemplateDeclarationDepth;3123};31243125static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;3126static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;31273128/// Parses binary expressions by inserting fake parenthesis based on3129/// operator precedence.3130class ExpressionParser {3131public:3132ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords,3133AnnotatedLine &Line)3134: Style(Style), Keywords(Keywords), Line(Line), Current(Line.First) {}31353136/// Parse expressions with the given operator precedence.3137void parse(int Precedence = 0) {3138// Skip 'return' and ObjC selector colons as they are not part of a binary3139// expression.3140while (Current && (Current->is(tok::kw_return) ||3141(Current->is(tok::colon) &&3142Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)))) {3143next();3144}31453146if (!Current || Precedence > PrecedenceArrowAndPeriod)3147return;31483149// Conditional expressions need to be parsed separately for proper nesting.3150if (Precedence == prec::Conditional) {3151parseConditionalExpr();3152return;3153}31543155// Parse unary operators, which all have a higher precedence than binary3156// operators.3157if (Precedence == PrecedenceUnaryOperator) {3158parseUnaryOperator();3159return;3160}31613162FormatToken *Start = Current;3163FormatToken *LatestOperator = nullptr;3164unsigned OperatorIndex = 0;3165// The first name of the current type in a port list.3166FormatToken *VerilogFirstOfType = nullptr;31673168while (Current) {3169// In Verilog ports in a module header that don't have a type take the3170// type of the previous one. For example,3171// module a(output b,3172// c,3173// output d);3174// In this case there need to be fake parentheses around b and c.3175if (Style.isVerilog() && Precedence == prec::Comma) {3176VerilogFirstOfType =3177verilogGroupDecl(VerilogFirstOfType, LatestOperator);3178}31793180// Consume operators with higher precedence.3181parse(Precedence + 1);31823183int CurrentPrecedence = getCurrentPrecedence();31843185if (Precedence == CurrentPrecedence && Current &&3186Current->is(TT_SelectorName)) {3187if (LatestOperator)3188addFakeParenthesis(Start, prec::Level(Precedence));3189Start = Current;3190}31913192if ((Style.isCSharp() || Style.isJavaScript() ||3193Style.Language == FormatStyle::LK_Java) &&3194Precedence == prec::Additive && Current) {3195// A string can be broken without parentheses around it when it is3196// already in a sequence of strings joined by `+` signs.3197FormatToken *Prev = Current->getPreviousNonComment();3198if (Prev && Prev->is(tok::string_literal) &&3199(Prev == Start || Prev->endsSequence(tok::string_literal, tok::plus,3200TT_StringInConcatenation))) {3201Prev->setType(TT_StringInConcatenation);3202}3203}32043205// At the end of the line or when an operator with lower precedence is3206// found, insert fake parenthesis and return.3207if (!Current ||3208(Current->closesScope() &&3209(Current->MatchingParen || Current->is(TT_TemplateString))) ||3210(CurrentPrecedence != -1 && CurrentPrecedence < Precedence) ||3211(CurrentPrecedence == prec::Conditional &&3212Precedence == prec::Assignment && Current->is(tok::colon))) {3213break;3214}32153216// Consume scopes: (), [], <> and {}3217// In addition to that we handle require clauses as scope, so that the3218// constraints in that are correctly indented.3219if (Current->opensScope() ||3220Current->isOneOf(TT_RequiresClause,3221TT_RequiresClauseInARequiresExpression)) {3222// In fragment of a JavaScript template string can look like '}..${' and3223// thus close a scope and open a new one at the same time.3224while (Current && (!Current->closesScope() || Current->opensScope())) {3225next();3226parse();3227}3228next();3229} else {3230// Operator found.3231if (CurrentPrecedence == Precedence) {3232if (LatestOperator)3233LatestOperator->NextOperator = Current;3234LatestOperator = Current;3235Current->OperatorIndex = OperatorIndex;3236++OperatorIndex;3237}3238next(/*SkipPastLeadingComments=*/Precedence > 0);3239}3240}32413242// Group variables of the same type.3243if (Style.isVerilog() && Precedence == prec::Comma && VerilogFirstOfType)3244addFakeParenthesis(VerilogFirstOfType, prec::Comma);32453246if (LatestOperator && (Current || Precedence > 0)) {3247// The requires clauses do not neccessarily end in a semicolon or a brace,3248// but just go over to struct/class or a function declaration, we need to3249// intervene so that the fake right paren is inserted correctly.3250auto End =3251(Start->Previous &&3252Start->Previous->isOneOf(TT_RequiresClause,3253TT_RequiresClauseInARequiresExpression))3254? [this]() {3255auto Ret = Current ? Current : Line.Last;3256while (!Ret->ClosesRequiresClause && Ret->Previous)3257Ret = Ret->Previous;3258return Ret;3259}()3260: nullptr;32613262if (Precedence == PrecedenceArrowAndPeriod) {3263// Call expressions don't have a binary operator precedence.3264addFakeParenthesis(Start, prec::Unknown, End);3265} else {3266addFakeParenthesis(Start, prec::Level(Precedence), End);3267}3268}3269}32703271private:3272/// Gets the precedence (+1) of the given token for binary operators3273/// and other tokens that we treat like binary operators.3274int getCurrentPrecedence() {3275if (Current) {3276const FormatToken *NextNonComment = Current->getNextNonComment();3277if (Current->is(TT_ConditionalExpr))3278return prec::Conditional;3279if (NextNonComment && Current->is(TT_SelectorName) &&3280(NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) ||3281(Style.isProto() && NextNonComment->is(tok::less)))) {3282return prec::Assignment;3283}3284if (Current->is(TT_JsComputedPropertyName))3285return prec::Assignment;3286if (Current->is(TT_LambdaArrow))3287return prec::Comma;3288if (Current->is(TT_FatArrow))3289return prec::Assignment;3290if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName) ||3291(Current->is(tok::comment) && NextNonComment &&3292NextNonComment->is(TT_SelectorName))) {3293return 0;3294}3295if (Current->is(TT_RangeBasedForLoopColon))3296return prec::Comma;3297if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&3298Current->is(Keywords.kw_instanceof)) {3299return prec::Relational;3300}3301if (Style.isJavaScript() &&3302Current->isOneOf(Keywords.kw_in, Keywords.kw_as)) {3303return prec::Relational;3304}3305if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))3306return Current->getPrecedence();3307if (Current->isOneOf(tok::period, tok::arrow) &&3308Current->isNot(TT_TrailingReturnArrow)) {3309return PrecedenceArrowAndPeriod;3310}3311if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&3312Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,3313Keywords.kw_throws)) {3314return 0;3315}3316// In Verilog case labels are not on separate lines straight out of3317// UnwrappedLineParser. The colon is not part of an expression.3318if (Style.isVerilog() && Current->is(tok::colon))3319return 0;3320}3321return -1;3322}33233324void addFakeParenthesis(FormatToken *Start, prec::Level Precedence,3325FormatToken *End = nullptr) {3326// Do not assign fake parenthesis to tokens that are part of an3327// unexpanded macro call. The line within the macro call contains3328// the parenthesis and commas, and we will not find operators within3329// that structure.3330if (Start->MacroParent)3331return;33323333Start->FakeLParens.push_back(Precedence);3334if (Precedence > prec::Unknown)3335Start->StartsBinaryExpression = true;3336if (!End && Current)3337End = Current->getPreviousNonComment();3338if (End) {3339++End->FakeRParens;3340if (Precedence > prec::Unknown)3341End->EndsBinaryExpression = true;3342}3343}33443345/// Parse unary operator expressions and surround them with fake3346/// parentheses if appropriate.3347void parseUnaryOperator() {3348llvm::SmallVector<FormatToken *, 2> Tokens;3349while (Current && Current->is(TT_UnaryOperator)) {3350Tokens.push_back(Current);3351next();3352}3353parse(PrecedenceArrowAndPeriod);3354for (FormatToken *Token : llvm::reverse(Tokens)) {3355// The actual precedence doesn't matter.3356addFakeParenthesis(Token, prec::Unknown);3357}3358}33593360void parseConditionalExpr() {3361while (Current && Current->isTrailingComment())3362next();3363FormatToken *Start = Current;3364parse(prec::LogicalOr);3365if (!Current || Current->isNot(tok::question))3366return;3367next();3368parse(prec::Assignment);3369if (!Current || Current->isNot(TT_ConditionalExpr))3370return;3371next();3372parse(prec::Assignment);3373addFakeParenthesis(Start, prec::Conditional);3374}33753376void next(bool SkipPastLeadingComments = true) {3377if (Current)3378Current = Current->Next;3379while (Current &&3380(Current->NewlinesBefore == 0 || SkipPastLeadingComments) &&3381Current->isTrailingComment()) {3382Current = Current->Next;3383}3384}33853386// Add fake parenthesis around declarations of the same type for example in a3387// module prototype. Return the first port / variable of the current type.3388FormatToken *verilogGroupDecl(FormatToken *FirstOfType,3389FormatToken *PreviousComma) {3390if (!Current)3391return nullptr;33923393FormatToken *Start = Current;33943395// Skip attributes.3396while (Start->startsSequence(tok::l_paren, tok::star)) {3397if (!(Start = Start->MatchingParen) ||3398!(Start = Start->getNextNonComment())) {3399return nullptr;3400}3401}34023403FormatToken *Tok = Start;34043405if (Tok->is(Keywords.kw_assign))3406Tok = Tok->getNextNonComment();34073408// Skip any type qualifiers to find the first identifier. It may be either a3409// new type name or a variable name. There can be several type qualifiers3410// preceding a variable name, and we can not tell them apart by looking at3411// the word alone since a macro can be defined as either a type qualifier or3412// a variable name. Thus we use the last word before the dimensions instead3413// of the first word as the candidate for the variable or type name.3414FormatToken *First = nullptr;3415while (Tok) {3416FormatToken *Next = Tok->getNextNonComment();34173418if (Tok->is(tok::hash)) {3419// Start of a macro expansion.3420First = Tok;3421Tok = Next;3422if (Tok)3423Tok = Tok->getNextNonComment();3424} else if (Tok->is(tok::hashhash)) {3425// Concatenation. Skip.3426Tok = Next;3427if (Tok)3428Tok = Tok->getNextNonComment();3429} else if (Keywords.isVerilogQualifier(*Tok) ||3430Keywords.isVerilogIdentifier(*Tok)) {3431First = Tok;3432Tok = Next;3433// The name may have dots like `interface_foo.modport_foo`.3434while (Tok && Tok->isOneOf(tok::period, tok::coloncolon) &&3435(Tok = Tok->getNextNonComment())) {3436if (Keywords.isVerilogIdentifier(*Tok))3437Tok = Tok->getNextNonComment();3438}3439} else if (!Next) {3440Tok = nullptr;3441} else if (Tok->is(tok::l_paren)) {3442// Make sure the parenthesized list is a drive strength. Otherwise the3443// statement may be a module instantiation in which case we have already3444// found the instance name.3445if (Next->isOneOf(3446Keywords.kw_highz0, Keywords.kw_highz1, Keywords.kw_large,3447Keywords.kw_medium, Keywords.kw_pull0, Keywords.kw_pull1,3448Keywords.kw_small, Keywords.kw_strong0, Keywords.kw_strong1,3449Keywords.kw_supply0, Keywords.kw_supply1, Keywords.kw_weak0,3450Keywords.kw_weak1)) {3451Tok->setType(TT_VerilogStrength);3452Tok = Tok->MatchingParen;3453if (Tok) {3454Tok->setType(TT_VerilogStrength);3455Tok = Tok->getNextNonComment();3456}3457} else {3458break;3459}3460} else if (Tok->is(Keywords.kw_verilogHash)) {3461// Delay control.3462if (Next->is(tok::l_paren))3463Next = Next->MatchingParen;3464if (Next)3465Tok = Next->getNextNonComment();3466} else {3467break;3468}3469}34703471// Find the second identifier. If it exists it will be the name.3472FormatToken *Second = nullptr;3473// Dimensions.3474while (Tok && Tok->is(tok::l_square) && (Tok = Tok->MatchingParen))3475Tok = Tok->getNextNonComment();3476if (Tok && (Tok->is(tok::hash) || Keywords.isVerilogIdentifier(*Tok)))3477Second = Tok;34783479// If the second identifier doesn't exist and there are qualifiers, the type3480// is implied.3481FormatToken *TypedName = nullptr;3482if (Second) {3483TypedName = Second;3484if (First && First->is(TT_Unknown))3485First->setType(TT_VerilogDimensionedTypeName);3486} else if (First != Start) {3487// If 'First' is null, then this isn't a declaration, 'TypedName' gets set3488// to null as intended.3489TypedName = First;3490}34913492if (TypedName) {3493// This is a declaration with a new type.3494if (TypedName->is(TT_Unknown))3495TypedName->setType(TT_StartOfName);3496// Group variables of the previous type.3497if (FirstOfType && PreviousComma) {3498PreviousComma->setType(TT_VerilogTypeComma);3499addFakeParenthesis(FirstOfType, prec::Comma, PreviousComma->Previous);3500}35013502FirstOfType = TypedName;35033504// Don't let higher precedence handle the qualifiers. For example if we3505// have:3506// parameter x = 03507// We skip `parameter` here. This way the fake parentheses for the3508// assignment will be around `x = 0`.3509while (Current && Current != FirstOfType) {3510if (Current->opensScope()) {3511next();3512parse();3513}3514next();3515}3516}35173518return FirstOfType;3519}35203521const FormatStyle &Style;3522const AdditionalKeywords &Keywords;3523const AnnotatedLine &Line;3524FormatToken *Current;3525};35263527} // end anonymous namespace35283529void TokenAnnotator::setCommentLineLevels(3530SmallVectorImpl<AnnotatedLine *> &Lines) const {3531const AnnotatedLine *NextNonCommentLine = nullptr;3532for (AnnotatedLine *Line : llvm::reverse(Lines)) {3533assert(Line->First);35343535// If the comment is currently aligned with the line immediately following3536// it, that's probably intentional and we should keep it.3537if (NextNonCommentLine && NextNonCommentLine->First->NewlinesBefore < 2 &&3538Line->isComment() && !isClangFormatOff(Line->First->TokenText) &&3539NextNonCommentLine->First->OriginalColumn ==3540Line->First->OriginalColumn) {3541const bool PPDirectiveOrImportStmt =3542NextNonCommentLine->Type == LT_PreprocessorDirective ||3543NextNonCommentLine->Type == LT_ImportStatement;3544if (PPDirectiveOrImportStmt)3545Line->Type = LT_CommentAbovePPDirective;3546// Align comments for preprocessor lines with the # in column 0 if3547// preprocessor lines are not indented. Otherwise, align with the next3548// line.3549Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&3550PPDirectiveOrImportStmt3551? 03552: NextNonCommentLine->Level;3553} else {3554NextNonCommentLine = Line->First->isNot(tok::r_brace) ? Line : nullptr;3555}35563557setCommentLineLevels(Line->Children);3558}3559}35603561static unsigned maxNestingDepth(const AnnotatedLine &Line) {3562unsigned Result = 0;3563for (const auto *Tok = Line.First; Tok; Tok = Tok->Next)3564Result = std::max(Result, Tok->NestingLevel);3565return Result;3566}35673568// Returns the name of a function with no return type, e.g. a constructor or3569// destructor.3570static FormatToken *getFunctionName(const AnnotatedLine &Line,3571FormatToken *&OpeningParen) {3572for (FormatToken *Tok = Line.getFirstNonComment(), *Name = nullptr; Tok;3573Tok = Tok->getNextNonComment()) {3574// Skip C++11 attributes both before and after the function name.3575if (Tok->is(tok::l_square) && Tok->is(TT_AttributeSquare)) {3576Tok = Tok->MatchingParen;3577if (!Tok)3578break;3579continue;3580}35813582// Make sure the name is followed by a pair of parentheses.3583if (Name) {3584if (Tok->is(tok::l_paren) && Tok->isNot(TT_FunctionTypeLParen) &&3585Tok->MatchingParen) {3586OpeningParen = Tok;3587return Name;3588}3589return nullptr;3590}35913592// Skip keywords that may precede the constructor/destructor name.3593if (Tok->isOneOf(tok::kw_friend, tok::kw_inline, tok::kw_virtual,3594tok::kw_constexpr, tok::kw_consteval, tok::kw_explicit)) {3595continue;3596}35973598// A qualified name may start from the global namespace.3599if (Tok->is(tok::coloncolon)) {3600Tok = Tok->Next;3601if (!Tok)3602break;3603}36043605// Skip to the unqualified part of the name.3606while (Tok->startsSequence(tok::identifier, tok::coloncolon)) {3607assert(Tok->Next);3608Tok = Tok->Next->Next;3609if (!Tok)3610return nullptr;3611}36123613// Skip the `~` if a destructor name.3614if (Tok->is(tok::tilde)) {3615Tok = Tok->Next;3616if (!Tok)3617break;3618}36193620// Make sure the name is not already annotated, e.g. as NamespaceMacro.3621if (Tok->isNot(tok::identifier) || Tok->isNot(TT_Unknown))3622break;36233624Name = Tok;3625}36263627return nullptr;3628}36293630// Checks if Tok is a constructor/destructor name qualified by its class name.3631static bool isCtorOrDtorName(const FormatToken *Tok) {3632assert(Tok && Tok->is(tok::identifier));3633const auto *Prev = Tok->Previous;36343635if (Prev && Prev->is(tok::tilde))3636Prev = Prev->Previous;36373638if (!Prev || !Prev->endsSequence(tok::coloncolon, tok::identifier))3639return false;36403641assert(Prev->Previous);3642return Prev->Previous->TokenText == Tok->TokenText;3643}36443645void TokenAnnotator::annotate(AnnotatedLine &Line) {3646AnnotatingParser Parser(Style, Line, Keywords, Scopes);3647Line.Type = Parser.parseLine();36483649for (auto &Child : Line.Children)3650annotate(*Child);36513652// With very deep nesting, ExpressionParser uses lots of stack and the3653// formatting algorithm is very slow. We're not going to do a good job here3654// anyway - it's probably generated code being formatted by mistake.3655// Just skip the whole line.3656if (maxNestingDepth(Line) > 50)3657Line.Type = LT_Invalid;36583659if (Line.Type == LT_Invalid)3660return;36613662ExpressionParser ExprParser(Style, Keywords, Line);3663ExprParser.parse();36643665if (IsCpp) {3666FormatToken *OpeningParen = nullptr;3667auto *Tok = getFunctionName(Line, OpeningParen);3668if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) ||3669Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) {3670Tok->setFinalizedType(TT_CtorDtorDeclName);3671assert(OpeningParen);3672OpeningParen->setFinalizedType(TT_FunctionDeclarationLParen);3673}3674}36753676if (Line.startsWith(TT_ObjCMethodSpecifier))3677Line.Type = LT_ObjCMethodDecl;3678else if (Line.startsWith(TT_ObjCDecl))3679Line.Type = LT_ObjCDecl;3680else if (Line.startsWith(TT_ObjCProperty))3681Line.Type = LT_ObjCProperty;36823683auto *First = Line.First;3684First->SpacesRequiredBefore = 1;3685First->CanBreakBefore = First->MustBreakBefore;3686}36873688// This function heuristically determines whether 'Current' starts the name of a3689// function declaration.3690static bool isFunctionDeclarationName(const LangOptions &LangOpts,3691const FormatToken &Current,3692const AnnotatedLine &Line,3693FormatToken *&ClosingParen) {3694assert(Current.Previous);36953696if (Current.is(TT_FunctionDeclarationName))3697return true;36983699if (!Current.Tok.getIdentifierInfo())3700return false;37013702const auto &Previous = *Current.Previous;37033704if (const auto *PrevPrev = Previous.Previous;3705PrevPrev && PrevPrev->is(TT_ObjCDecl)) {3706return false;3707}37083709auto skipOperatorName =3710[&LangOpts](const FormatToken *Next) -> const FormatToken * {3711for (; Next; Next = Next->Next) {3712if (Next->is(TT_OverloadedOperatorLParen))3713return Next;3714if (Next->is(TT_OverloadedOperator))3715continue;3716if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {3717// For 'new[]' and 'delete[]'.3718if (Next->Next &&3719Next->Next->startsSequence(tok::l_square, tok::r_square)) {3720Next = Next->Next->Next;3721}3722continue;3723}3724if (Next->startsSequence(tok::l_square, tok::r_square)) {3725// For operator[]().3726Next = Next->Next;3727continue;3728}3729if ((Next->isTypeName(LangOpts) || Next->is(tok::identifier)) &&3730Next->Next && Next->Next->isPointerOrReference()) {3731// For operator void*(), operator char*(), operator Foo*().3732Next = Next->Next;3733continue;3734}3735if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {3736Next = Next->MatchingParen;3737continue;3738}37393740break;3741}3742return nullptr;3743};37443745const auto *Next = Current.Next;3746const bool IsCpp = LangOpts.CXXOperatorNames;37473748// Find parentheses of parameter list.3749if (Current.is(tok::kw_operator)) {3750if (Previous.Tok.getIdentifierInfo() &&3751!Previous.isOneOf(tok::kw_return, tok::kw_co_return)) {3752return true;3753}3754if (Previous.is(tok::r_paren) && Previous.is(TT_TypeDeclarationParen)) {3755assert(Previous.MatchingParen);3756assert(Previous.MatchingParen->is(tok::l_paren));3757assert(Previous.MatchingParen->is(TT_TypeDeclarationParen));3758return true;3759}3760if (!Previous.isPointerOrReference() && Previous.isNot(TT_TemplateCloser))3761return false;3762Next = skipOperatorName(Next);3763} else {3764if (Current.isNot(TT_StartOfName) || Current.NestingLevel != 0)3765return false;3766for (; Next; Next = Next->Next) {3767if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {3768Next = Next->MatchingParen;3769} else if (Next->is(tok::coloncolon)) {3770Next = Next->Next;3771if (!Next)3772return false;3773if (Next->is(tok::kw_operator)) {3774Next = skipOperatorName(Next->Next);3775break;3776}3777if (Next->isNot(tok::identifier))3778return false;3779} else if (isCppAttribute(IsCpp, *Next)) {3780Next = Next->MatchingParen;3781if (!Next)3782return false;3783} else if (Next->is(tok::l_paren)) {3784break;3785} else {3786return false;3787}3788}3789}37903791// Check whether parameter list can belong to a function declaration.3792if (!Next || Next->isNot(tok::l_paren) || !Next->MatchingParen)3793return false;3794ClosingParen = Next->MatchingParen;3795assert(ClosingParen->is(tok::r_paren));3796// If the lines ends with "{", this is likely a function definition.3797if (Line.Last->is(tok::l_brace))3798return true;3799if (Next->Next == ClosingParen)3800return true; // Empty parentheses.3801// If there is an &/&& after the r_paren, this is likely a function.3802if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference))3803return true;38043805// Check for K&R C function definitions (and C++ function definitions with3806// unnamed parameters), e.g.:3807// int f(i)3808// {3809// return i + 1;3810// }3811// bool g(size_t = 0, bool b = false)3812// {3813// return !b;3814// }3815if (IsCpp && Next->Next && Next->Next->is(tok::identifier) &&3816!Line.endsWith(tok::semi)) {3817return true;3818}38193820for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen;3821Tok = Tok->Next) {3822if (Tok->is(TT_TypeDeclarationParen))3823return true;3824if (Tok->isOneOf(tok::l_paren, TT_TemplateOpener) && Tok->MatchingParen) {3825Tok = Tok->MatchingParen;3826continue;3827}3828if (Tok->is(tok::kw_const) || Tok->isTypeName(LangOpts) ||3829Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) {3830return true;3831}3832if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral())3833return false;3834}3835return false;3836}38373838bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {3839assert(Line.MightBeFunctionDecl);38403841if ((Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevel ||3842Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevelDefinitions) &&3843Line.Level > 0) {3844return false;3845}38463847switch (Style.BreakAfterReturnType) {3848case FormatStyle::RTBS_None:3849case FormatStyle::RTBS_Automatic:3850case FormatStyle::RTBS_ExceptShortType:3851return false;3852case FormatStyle::RTBS_All:3853case FormatStyle::RTBS_TopLevel:3854return true;3855case FormatStyle::RTBS_AllDefinitions:3856case FormatStyle::RTBS_TopLevelDefinitions:3857return Line.mightBeFunctionDefinition();3858}38593860return false;3861}38623863void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {3864for (AnnotatedLine *ChildLine : Line.Children)3865calculateFormattingInformation(*ChildLine);38663867auto *First = Line.First;3868First->TotalLength = First->IsMultiline3869? Style.ColumnLimit3870: Line.FirstStartColumn + First->ColumnWidth;3871FormatToken *Current = First->Next;3872bool InFunctionDecl = Line.MightBeFunctionDecl;3873bool AlignArrayOfStructures =3874(Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&3875Line.Type == LT_ArrayOfStructInitializer);3876if (AlignArrayOfStructures)3877calculateArrayInitializerColumnList(Line);38783879bool SeenName = false;3880bool LineIsFunctionDeclaration = false;3881FormatToken *ClosingParen = nullptr;3882FormatToken *AfterLastAttribute = nullptr;38833884for (auto *Tok = Current; Tok; Tok = Tok->Next) {3885if (Tok->is(TT_StartOfName))3886SeenName = true;3887if (Tok->Previous->EndsCppAttributeGroup)3888AfterLastAttribute = Tok;3889if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);3890IsCtorOrDtor ||3891isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) {3892if (!IsCtorOrDtor)3893Tok->setFinalizedType(TT_FunctionDeclarationName);3894LineIsFunctionDeclaration = true;3895SeenName = true;3896if (ClosingParen) {3897auto *OpeningParen = ClosingParen->MatchingParen;3898assert(OpeningParen);3899if (OpeningParen->is(TT_Unknown))3900OpeningParen->setType(TT_FunctionDeclarationLParen);3901}3902break;3903}3904}39053906if (IsCpp && (LineIsFunctionDeclaration || First->is(TT_CtorDtorDeclName)) &&3907Line.endsWith(tok::semi, tok::r_brace)) {3908auto *Tok = Line.Last->Previous;3909while (Tok->isNot(tok::r_brace))3910Tok = Tok->Previous;3911if (auto *LBrace = Tok->MatchingParen; LBrace) {3912assert(LBrace->is(tok::l_brace));3913Tok->setBlockKind(BK_Block);3914LBrace->setBlockKind(BK_Block);3915LBrace->setFinalizedType(TT_FunctionLBrace);3916}3917}39183919if (IsCpp && SeenName && AfterLastAttribute &&3920mustBreakAfterAttributes(*AfterLastAttribute, Style)) {3921AfterLastAttribute->MustBreakBefore = true;3922if (LineIsFunctionDeclaration)3923Line.ReturnTypeWrapped = true;3924}39253926if (IsCpp) {3927if (!LineIsFunctionDeclaration) {3928// Annotate */&/&& in `operator` function calls as binary operators.3929for (const auto *Tok = First; Tok; Tok = Tok->Next) {3930if (Tok->isNot(tok::kw_operator))3931continue;3932do {3933Tok = Tok->Next;3934} while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));3935if (!Tok || !Tok->MatchingParen)3936break;3937const auto *LeftParen = Tok;3938for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;3939Tok = Tok->Next) {3940if (Tok->isNot(tok::identifier))3941continue;3942auto *Next = Tok->Next;3943const bool NextIsBinaryOperator =3944Next && Next->isPointerOrReference() && Next->Next &&3945Next->Next->is(tok::identifier);3946if (!NextIsBinaryOperator)3947continue;3948Next->setType(TT_BinaryOperator);3949Tok = Next;3950}3951}3952} else if (ClosingParen) {3953for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {3954if (Tok->is(TT_CtorInitializerColon))3955break;3956if (Tok->is(tok::arrow)) {3957Tok->setType(TT_TrailingReturnArrow);3958break;3959}3960if (Tok->isNot(TT_TrailingAnnotation))3961continue;3962const auto *Next = Tok->Next;3963if (!Next || Next->isNot(tok::l_paren))3964continue;3965Tok = Next->MatchingParen;3966if (!Tok)3967break;3968}3969}3970}39713972while (Current) {3973const FormatToken *Prev = Current->Previous;3974if (Current->is(TT_LineComment)) {3975if (Prev->is(BK_BracedInit) && Prev->opensScope()) {3976Current->SpacesRequiredBefore =3977(Style.Cpp11BracedListStyle && !Style.SpacesInParensOptions.Other)3978? 03979: 1;3980} else if (Prev->is(TT_VerilogMultiLineListLParen)) {3981Current->SpacesRequiredBefore = 0;3982} else {3983Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;3984}39853986// If we find a trailing comment, iterate backwards to determine whether3987// it seems to relate to a specific parameter. If so, break before that3988// parameter to avoid changing the comment's meaning. E.g. don't move 'b'3989// to the previous line in:3990// SomeFunction(a,3991// b, // comment3992// c);3993if (!Current->HasUnescapedNewline) {3994for (FormatToken *Parameter = Current->Previous; Parameter;3995Parameter = Parameter->Previous) {3996if (Parameter->isOneOf(tok::comment, tok::r_brace))3997break;3998if (Parameter->Previous && Parameter->Previous->is(tok::comma)) {3999if (Parameter->Previous->isNot(TT_CtorInitializerComma) &&4000Parameter->HasUnescapedNewline) {4001Parameter->MustBreakBefore = true;4002}4003break;4004}4005}4006}4007} else if (!Current->Finalized && Current->SpacesRequiredBefore == 0 &&4008spaceRequiredBefore(Line, *Current)) {4009Current->SpacesRequiredBefore = 1;4010}40114012const auto &Children = Prev->Children;4013if (!Children.empty() && Children.back()->Last->is(TT_LineComment)) {4014Current->MustBreakBefore = true;4015} else {4016Current->MustBreakBefore =4017Current->MustBreakBefore || mustBreakBefore(Line, *Current);4018if (!Current->MustBreakBefore && InFunctionDecl &&4019Current->is(TT_FunctionDeclarationName)) {4020Current->MustBreakBefore = mustBreakForReturnType(Line);4021}4022}40234024Current->CanBreakBefore =4025Current->MustBreakBefore || canBreakBefore(Line, *Current);4026unsigned ChildSize = 0;4027if (Prev->Children.size() == 1) {4028FormatToken &LastOfChild = *Prev->Children[0]->Last;4029ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit4030: LastOfChild.TotalLength + 1;4031}4032if (Current->MustBreakBefore || Prev->Children.size() > 1 ||4033(Prev->Children.size() == 1 &&4034Prev->Children[0]->First->MustBreakBefore) ||4035Current->IsMultiline) {4036Current->TotalLength = Prev->TotalLength + Style.ColumnLimit;4037} else {4038Current->TotalLength = Prev->TotalLength + Current->ColumnWidth +4039ChildSize + Current->SpacesRequiredBefore;4040}40414042if (Current->is(TT_CtorInitializerColon))4043InFunctionDecl = false;40444045// FIXME: Only calculate this if CanBreakBefore is true once static4046// initializers etc. are sorted out.4047// FIXME: Move magic numbers to a better place.40484049// Reduce penalty for aligning ObjC method arguments using the colon4050// alignment as this is the canonical way (still prefer fitting everything4051// into one line if possible). Trying to fit a whole expression into one4052// line should not force other line breaks (e.g. when ObjC method4053// expression is a part of other expression).4054Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl);4055if (Style.Language == FormatStyle::LK_ObjC &&4056Current->is(TT_SelectorName) && Current->ParameterIndex > 0) {4057if (Current->ParameterIndex == 1)4058Current->SplitPenalty += 5 * Current->BindingStrength;4059} else {4060Current->SplitPenalty += 20 * Current->BindingStrength;4061}40624063Current = Current->Next;4064}40654066calculateUnbreakableTailLengths(Line);4067unsigned IndentLevel = Line.Level;4068for (Current = First; Current; Current = Current->Next) {4069if (Current->Role)4070Current->Role->precomputeFormattingInfos(Current);4071if (Current->MatchingParen &&4072Current->MatchingParen->opensBlockOrBlockTypeList(Style) &&4073IndentLevel > 0) {4074--IndentLevel;4075}4076Current->IndentLevel = IndentLevel;4077if (Current->opensBlockOrBlockTypeList(Style))4078++IndentLevel;4079}40804081LLVM_DEBUG({ printDebugInfo(Line); });4082}40834084void TokenAnnotator::calculateUnbreakableTailLengths(4085AnnotatedLine &Line) const {4086unsigned UnbreakableTailLength = 0;4087FormatToken *Current = Line.Last;4088while (Current) {4089Current->UnbreakableTailLength = UnbreakableTailLength;4090if (Current->CanBreakBefore ||4091Current->isOneOf(tok::comment, tok::string_literal)) {4092UnbreakableTailLength = 0;4093} else {4094UnbreakableTailLength +=4095Current->ColumnWidth + Current->SpacesRequiredBefore;4096}4097Current = Current->Previous;4098}4099}41004101void TokenAnnotator::calculateArrayInitializerColumnList(4102AnnotatedLine &Line) const {4103if (Line.First == Line.Last)4104return;4105auto *CurrentToken = Line.First;4106CurrentToken->ArrayInitializerLineStart = true;4107unsigned Depth = 0;4108while (CurrentToken && CurrentToken != Line.Last) {4109if (CurrentToken->is(tok::l_brace)) {4110CurrentToken->IsArrayInitializer = true;4111if (CurrentToken->Next)4112CurrentToken->Next->MustBreakBefore = true;4113CurrentToken =4114calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1);4115} else {4116CurrentToken = CurrentToken->Next;4117}4118}4119}41204121FormatToken *TokenAnnotator::calculateInitializerColumnList(4122AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) const {4123while (CurrentToken && CurrentToken != Line.Last) {4124if (CurrentToken->is(tok::l_brace))4125++Depth;4126else if (CurrentToken->is(tok::r_brace))4127--Depth;4128if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) {4129CurrentToken = CurrentToken->Next;4130if (!CurrentToken)4131break;4132CurrentToken->StartsColumn = true;4133CurrentToken = CurrentToken->Previous;4134}4135CurrentToken = CurrentToken->Next;4136}4137return CurrentToken;4138}41394140unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,4141const FormatToken &Tok,4142bool InFunctionDecl) const {4143const FormatToken &Left = *Tok.Previous;4144const FormatToken &Right = Tok;41454146if (Left.is(tok::semi))4147return 0;41484149// Language specific handling.4150if (Style.Language == FormatStyle::LK_Java) {4151if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws))4152return 1;4153if (Right.is(Keywords.kw_implements))4154return 2;4155if (Left.is(tok::comma) && Left.NestingLevel == 0)4156return 3;4157} else if (Style.isJavaScript()) {4158if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))4159return 100;4160if (Left.is(TT_JsTypeColon))4161return 35;4162if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) ||4163(Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) {4164return 100;4165}4166// Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".4167if (Left.opensScope() && Right.closesScope())4168return 200;4169} else if (Style.Language == FormatStyle::LK_Proto) {4170if (Right.is(tok::l_square))4171return 1;4172if (Right.is(tok::period))4173return 500;4174}41754176if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))4177return 1;4178if (Right.is(tok::l_square)) {4179if (Left.is(tok::r_square))4180return 200;4181// Slightly prefer formatting local lambda definitions like functions.4182if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))4183return 35;4184if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,4185TT_ArrayInitializerLSquare,4186TT_DesignatedInitializerLSquare, TT_AttributeSquare)) {4187return 500;4188}4189}41904191if (Left.is(tok::coloncolon))4192return Style.PenaltyBreakScopeResolution;4193if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||4194Right.is(tok::kw_operator)) {4195if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)4196return 3;4197if (Left.is(TT_StartOfName))4198return 110;4199if (InFunctionDecl && Right.NestingLevel == 0)4200return Style.PenaltyReturnTypeOnItsOwnLine;4201return 200;4202}4203if (Right.is(TT_PointerOrReference))4204return 190;4205if (Right.is(TT_LambdaArrow))4206return 110;4207if (Left.is(tok::equal) && Right.is(tok::l_brace))4208return 160;4209if (Left.is(TT_CastRParen))4210return 100;4211if (Left.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union))4212return 5000;4213if (Left.is(tok::comment))4214return 1000;42154216if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon,4217TT_CtorInitializerColon)) {4218return 2;4219}42204221if (Right.isMemberAccess()) {4222// Breaking before the "./->" of a chained call/member access is reasonably4223// cheap, as formatting those with one call per line is generally4224// desirable. In particular, it should be cheaper to break before the call4225// than it is to break inside a call's parameters, which could lead to weird4226// "hanging" indents. The exception is the very last "./->" to support this4227// frequent pattern:4228//4229// aaaaaaaa.aaaaaaaa.bbbbbbb().ccccccccccccccccccccc(4230// dddddddd);4231//4232// which might otherwise be blown up onto many lines. Here, clang-format4233// won't produce "hanging" indents anyway as there is no other trailing4234// call.4235//4236// Also apply higher penalty is not a call as that might lead to a wrapping4237// like:4238//4239// aaaaaaa4240// .aaaaaaaaa.bbbbbbbb(cccccccc);4241return !Right.NextOperator || !Right.NextOperator->Previous->closesScope()4242? 1504243: 35;4244}42454246if (Right.is(TT_TrailingAnnotation) &&4247(!Right.Next || Right.Next->isNot(tok::l_paren))) {4248// Moving trailing annotations to the next line is fine for ObjC method4249// declarations.4250if (Line.startsWith(TT_ObjCMethodSpecifier))4251return 10;4252// Generally, breaking before a trailing annotation is bad unless it is4253// function-like. It seems to be especially preferable to keep standard4254// annotations (i.e. "const", "final" and "override") on the same line.4255// Use a slightly higher penalty after ")" so that annotations like4256// "const override" are kept together.4257bool is_short_annotation = Right.TokenText.size() < 10;4258return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0);4259}42604261// In for-loops, prefer breaking at ',' and ';'.4262if (Line.startsWith(tok::kw_for) && Left.is(tok::equal))4263return 4;42644265// In Objective-C method expressions, prefer breaking before "param:" over4266// breaking after it.4267if (Right.is(TT_SelectorName))4268return 0;4269if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr))4270return Line.MightBeFunctionDecl ? 50 : 500;42714272// In Objective-C type declarations, avoid breaking after the category's4273// open paren (we'll prefer breaking after the protocol list's opening4274// angle bracket, if present).4275if (Line.Type == LT_ObjCDecl && Left.is(tok::l_paren) && Left.Previous &&4276Left.Previous->isOneOf(tok::identifier, tok::greater)) {4277return 500;4278}42794280if (Left.is(tok::l_paren) && Style.PenaltyBreakOpenParenthesis != 0)4281return Style.PenaltyBreakOpenParenthesis;4282if (Left.is(tok::l_paren) && InFunctionDecl &&4283Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign) {4284return 100;4285}4286if (Left.is(tok::l_paren) && Left.Previous &&4287(Left.Previous->isOneOf(tok::kw_for, tok::kw__Generic) ||4288Left.Previous->isIf())) {4289return 1000;4290}4291if (Left.is(tok::equal) && InFunctionDecl)4292return 110;4293if (Right.is(tok::r_brace))4294return 1;4295if (Left.is(TT_TemplateOpener))4296return 100;4297if (Left.opensScope()) {4298// If we aren't aligning after opening parens/braces we can always break4299// here unless the style does not want us to place all arguments on the4300// next line.4301if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign &&4302(Left.ParameterCount <= 1 || Style.AllowAllArgumentsOnNextLine)) {4303return 0;4304}4305if (Left.is(tok::l_brace) && !Style.Cpp11BracedListStyle)4306return 19;4307return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter4308: 19;4309}4310if (Left.is(TT_JavaAnnotation))4311return 50;43124313if (Left.is(TT_UnaryOperator))4314return 60;4315if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&4316Left.Previous->isLabelString() &&4317(Left.NextOperator || Left.OperatorIndex != 0)) {4318return 50;4319}4320if (Right.is(tok::plus) && Left.isLabelString() &&4321(Right.NextOperator || Right.OperatorIndex != 0)) {4322return 25;4323}4324if (Left.is(tok::comma))4325return 1;4326if (Right.is(tok::lessless) && Left.isLabelString() &&4327(Right.NextOperator || Right.OperatorIndex != 1)) {4328return 25;4329}4330if (Right.is(tok::lessless)) {4331// Breaking at a << is really cheap.4332if (Left.isNot(tok::r_paren) || Right.OperatorIndex > 0) {4333// Slightly prefer to break before the first one in log-like statements.4334return 2;4335}4336return 1;4337}4338if (Left.ClosesTemplateDeclaration)4339return Style.PenaltyBreakTemplateDeclaration;4340if (Left.ClosesRequiresClause)4341return 0;4342if (Left.is(TT_ConditionalExpr))4343return prec::Conditional;4344prec::Level Level = Left.getPrecedence();4345if (Level == prec::Unknown)4346Level = Right.getPrecedence();4347if (Level == prec::Assignment)4348return Style.PenaltyBreakAssignment;4349if (Level != prec::Unknown)4350return Level;43514352return 3;4353}43544355bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {4356if (Style.SpaceBeforeParens == FormatStyle::SBPO_Always)4357return true;4358if (Right.is(TT_OverloadedOperatorLParen) &&4359Style.SpaceBeforeParensOptions.AfterOverloadedOperator) {4360return true;4361}4362if (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses &&4363Right.ParameterCount > 0) {4364return true;4365}4366return false;4367}43684369bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,4370const FormatToken &Left,4371const FormatToken &Right) const {4372if (Left.is(tok::kw_return) &&4373!Right.isOneOf(tok::semi, tok::r_paren, tok::hashhash)) {4374return true;4375}4376if (Left.is(tok::kw_throw) && Right.is(tok::l_paren) && Right.MatchingParen &&4377Right.MatchingParen->is(TT_CastRParen)) {4378return true;4379}4380if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java)4381return true;4382if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&4383Left.Tok.getObjCKeywordID() == tok::objc_property) {4384return true;4385}4386if (Right.is(tok::hashhash))4387return Left.is(tok::hash);4388if (Left.isOneOf(tok::hashhash, tok::hash))4389return Right.is(tok::hash);4390if (Left.is(BK_Block) && Right.is(tok::r_brace) &&4391Right.MatchingParen == &Left && Line.Children.empty()) {4392return Style.SpaceInEmptyBlock;4393}4394if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||4395(Left.is(tok::l_brace) && Left.isNot(BK_Block) &&4396Right.is(tok::r_brace) && Right.isNot(BK_Block))) {4397return Style.SpacesInParensOptions.InEmptyParentheses;4398}4399if (Style.SpacesInParens == FormatStyle::SIPO_Custom &&4400Style.SpacesInParensOptions.ExceptDoubleParentheses &&4401Left.is(tok::r_paren) && Right.is(tok::r_paren)) {4402auto *InnerLParen = Left.MatchingParen;4403if (InnerLParen && InnerLParen->Previous == Right.MatchingParen) {4404InnerLParen->SpacesRequiredBefore = 0;4405return false;4406}4407}4408if (Style.SpacesInParensOptions.InConditionalStatements) {4409const FormatToken *LeftParen = nullptr;4410if (Left.is(tok::l_paren))4411LeftParen = &Left;4412else if (Right.is(tok::r_paren) && Right.MatchingParen)4413LeftParen = Right.MatchingParen;4414if (LeftParen) {4415if (LeftParen->is(TT_ConditionLParen))4416return true;4417if (LeftParen->Previous && isKeywordWithCondition(*LeftParen->Previous))4418return true;4419}4420}44214422// trailing return type 'auto': []() -> auto {}, auto foo() -> auto {}4423if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace,4424// function return type 'auto'4425TT_FunctionTypeLParen)) {4426return true;4427}44284429// auto{x} auto(x)4430if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))4431return false;44324433const auto *BeforeLeft = Left.Previous;44344435// operator co_await(x)4436if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft &&4437BeforeLeft->is(tok::kw_operator)) {4438return false;4439}4440// co_await (x), co_yield (x), co_return (x)4441if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) &&4442!Right.isOneOf(tok::semi, tok::r_paren)) {4443return true;4444}44454446if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) {4447return (Right.is(TT_CastRParen) ||4448(Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))4449? Style.SpacesInParensOptions.InCStyleCasts4450: Style.SpacesInParensOptions.Other;4451}4452if (Right.isOneOf(tok::semi, tok::comma))4453return false;4454if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) {4455bool IsLightweightGeneric = Right.MatchingParen &&4456Right.MatchingParen->Next &&4457Right.MatchingParen->Next->is(tok::colon);4458return !IsLightweightGeneric && Style.ObjCSpaceBeforeProtocolList;4459}4460if (Right.is(tok::less) && Left.is(tok::kw_template))4461return Style.SpaceAfterTemplateKeyword;4462if (Left.isOneOf(tok::exclaim, tok::tilde))4463return false;4464if (Left.is(tok::at) &&4465Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,4466tok::numeric_constant, tok::l_paren, tok::l_brace,4467tok::kw_true, tok::kw_false)) {4468return false;4469}4470if (Left.is(tok::colon))4471return Left.isNot(TT_ObjCMethodExpr);4472if (Left.is(tok::coloncolon))4473return false;4474if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {4475if (Style.Language == FormatStyle::LK_TextProto ||4476(Style.Language == FormatStyle::LK_Proto &&4477(Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) {4478// Format empty list as `<>`.4479if (Left.is(tok::less) && Right.is(tok::greater))4480return false;4481return !Style.Cpp11BracedListStyle;4482}4483// Don't attempt to format operator<(), as it is handled later.4484if (Right.isNot(TT_OverloadedOperatorLParen))4485return false;4486}4487if (Right.is(tok::ellipsis)) {4488return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft &&4489BeforeLeft->is(tok::kw_case));4490}4491if (Left.is(tok::l_square) && Right.is(tok::amp))4492return Style.SpacesInSquareBrackets;4493if (Right.is(TT_PointerOrReference)) {4494if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) {4495if (!Left.MatchingParen)4496return true;4497FormatToken *TokenBeforeMatchingParen =4498Left.MatchingParen->getPreviousNonComment();4499if (!TokenBeforeMatchingParen || Left.isNot(TT_TypeDeclarationParen))4500return true;4501}4502// Add a space if the previous token is a pointer qualifier or the closing4503// parenthesis of __attribute__(()) expression and the style requires spaces4504// after pointer qualifiers.4505if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After ||4506Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&4507(Left.is(TT_AttributeRParen) ||4508Left.canBePointerOrReferenceQualifier())) {4509return true;4510}4511if (Left.Tok.isLiteral())4512return true;4513// for (auto a = 0, b = 0; const auto & c : {1, 2, 3})4514if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next &&4515Right.Next->Next->is(TT_RangeBasedForLoopColon)) {4516return getTokenPointerOrReferenceAlignment(Right) !=4517FormatStyle::PAS_Left;4518}4519return !Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&4520(getTokenPointerOrReferenceAlignment(Right) !=4521FormatStyle::PAS_Left ||4522(Line.IsMultiVariableDeclStmt &&4523(Left.NestingLevel == 0 ||4524(Left.NestingLevel == 1 && startsWithInitStatement(Line)))));4525}4526if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&4527(Left.isNot(TT_PointerOrReference) ||4528(getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right &&4529!Line.IsMultiVariableDeclStmt))) {4530return true;4531}4532if (Left.is(TT_PointerOrReference)) {4533// Add a space if the next token is a pointer qualifier and the style4534// requires spaces before pointer qualifiers.4535if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||4536Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&4537Right.canBePointerOrReferenceQualifier()) {4538return true;4539}4540// & 14541if (Right.Tok.isLiteral())4542return true;4543// & /* comment4544if (Right.is(TT_BlockComment))4545return true;4546// foo() -> const Bar * override/final4547// S::foo() & noexcept/requires4548if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, tok::kw_noexcept,4549TT_RequiresClause) &&4550Right.isNot(TT_StartOfName)) {4551return true;4552}4553// & {4554if (Right.is(tok::l_brace) && Right.is(BK_Block))4555return true;4556// for (auto a = 0, b = 0; const auto& c : {1, 2, 3})4557if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next &&4558Right.Next->is(TT_RangeBasedForLoopColon)) {4559return getTokenPointerOrReferenceAlignment(Left) !=4560FormatStyle::PAS_Right;4561}4562if (Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,4563tok::l_paren)) {4564return false;4565}4566if (getTokenPointerOrReferenceAlignment(Left) == FormatStyle::PAS_Right)4567return false;4568// FIXME: Setting IsMultiVariableDeclStmt for the whole line is error-prone,4569// because it does not take into account nested scopes like lambdas.4570// In multi-variable declaration statements, attach */& to the variable4571// independently of the style. However, avoid doing it if we are in a nested4572// scope, e.g. lambda. We still need to special-case statements with4573// initializers.4574if (Line.IsMultiVariableDeclStmt &&4575(Left.NestingLevel == Line.First->NestingLevel ||4576((Left.NestingLevel == Line.First->NestingLevel + 1) &&4577startsWithInitStatement(Line)))) {4578return false;4579}4580if (!BeforeLeft)4581return false;4582if (BeforeLeft->is(tok::coloncolon)) {4583if (Left.isNot(tok::star))4584return false;4585assert(Style.PointerAlignment != FormatStyle::PAS_Right);4586if (!Right.startsSequence(tok::identifier, tok::r_paren))4587return true;4588assert(Right.Next);4589const auto *LParen = Right.Next->MatchingParen;4590return !LParen || LParen->isNot(TT_FunctionTypeLParen);4591}4592return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square);4593}4594// Ensure right pointer alignment with ellipsis e.g. int *...P4595if (Left.is(tok::ellipsis) && BeforeLeft &&4596BeforeLeft->isPointerOrReference()) {4597return Style.PointerAlignment != FormatStyle::PAS_Right;4598}45994600if (Right.is(tok::star) && Left.is(tok::l_paren))4601return false;4602if (Left.is(tok::star) && Right.isPointerOrReference())4603return false;4604if (Right.isPointerOrReference()) {4605const FormatToken *Previous = &Left;4606while (Previous && Previous->isNot(tok::kw_operator)) {4607if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) {4608Previous = Previous->getPreviousNonComment();4609continue;4610}4611if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) {4612Previous = Previous->MatchingParen->getPreviousNonComment();4613continue;4614}4615if (Previous->is(tok::coloncolon)) {4616Previous = Previous->getPreviousNonComment();4617continue;4618}4619break;4620}4621// Space between the type and the * in:4622// operator void*()4623// operator char*()4624// operator void const*()4625// operator void volatile*()4626// operator /*comment*/ const char*()4627// operator volatile /*comment*/ char*()4628// operator Foo*()4629// operator C<T>*()4630// operator std::Foo*()4631// operator C<T>::D<U>*()4632// dependent on PointerAlignment style.4633if (Previous) {4634if (Previous->endsSequence(tok::kw_operator))4635return Style.PointerAlignment != FormatStyle::PAS_Left;4636if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) {4637return (Style.PointerAlignment != FormatStyle::PAS_Left) ||4638(Style.SpaceAroundPointerQualifiers ==4639FormatStyle::SAPQ_After) ||4640(Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);4641}4642}4643}4644if (Style.isCSharp() && Left.is(Keywords.kw_is) && Right.is(tok::l_square))4645return true;4646const auto SpaceRequiredForArrayInitializerLSquare =4647[](const FormatToken &LSquareTok, const FormatStyle &Style) {4648return Style.SpacesInContainerLiterals ||4649(Style.isProto() && !Style.Cpp11BracedListStyle &&4650LSquareTok.endsSequence(tok::l_square, tok::colon,4651TT_SelectorName));4652};4653if (Left.is(tok::l_square)) {4654return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&4655SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||4656(Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare,4657TT_LambdaLSquare) &&4658Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));4659}4660if (Right.is(tok::r_square)) {4661return Right.MatchingParen &&4662((Right.MatchingParen->is(TT_ArrayInitializerLSquare) &&4663SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen,4664Style)) ||4665(Style.SpacesInSquareBrackets &&4666Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,4667TT_StructuredBindingLSquare,4668TT_LambdaLSquare)));4669}4670if (Right.is(tok::l_square) &&4671!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,4672TT_DesignatedInitializerLSquare,4673TT_StructuredBindingLSquare, TT_AttributeSquare) &&4674!Left.isOneOf(tok::numeric_constant, TT_DictLiteral) &&4675!(Left.isNot(tok::r_square) && Style.SpaceBeforeSquareBrackets &&4676Right.is(TT_ArraySubscriptLSquare))) {4677return false;4678}4679if (Left.is(tok::l_brace) && Right.is(tok::r_brace))4680return !Left.Children.empty(); // No spaces in "{}".4681if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||4682(Right.is(tok::r_brace) && Right.MatchingParen &&4683Right.MatchingParen->isNot(BK_Block))) {4684return !Style.Cpp11BracedListStyle || Style.SpacesInParensOptions.Other;4685}4686if (Left.is(TT_BlockComment)) {4687// No whitespace in x(/*foo=*/1), except for JavaScript.4688return Style.isJavaScript() || !Left.TokenText.ends_with("=*/");4689}46904691// Space between template and attribute.4692// e.g. template <typename T> [[nodiscard]] ...4693if (Left.is(TT_TemplateCloser) && Right.is(TT_AttributeSquare))4694return true;4695// Space before parentheses common for all languages4696if (Right.is(tok::l_paren)) {4697if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))4698return spaceRequiredBeforeParens(Right);4699if (Left.isOneOf(TT_RequiresClause,4700TT_RequiresClauseInARequiresExpression)) {4701return Style.SpaceBeforeParensOptions.AfterRequiresInClause ||4702spaceRequiredBeforeParens(Right);4703}4704if (Left.is(TT_RequiresExpression)) {4705return Style.SpaceBeforeParensOptions.AfterRequiresInExpression ||4706spaceRequiredBeforeParens(Right);4707}4708if (Left.is(TT_AttributeRParen) ||4709(Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) {4710return true;4711}4712if (Left.is(TT_ForEachMacro)) {4713return Style.SpaceBeforeParensOptions.AfterForeachMacros ||4714spaceRequiredBeforeParens(Right);4715}4716if (Left.is(TT_IfMacro)) {4717return Style.SpaceBeforeParensOptions.AfterIfMacros ||4718spaceRequiredBeforeParens(Right);4719}4720if (Style.SpaceBeforeParens == FormatStyle::SBPO_Custom &&4721Left.isOneOf(tok::kw_new, tok::kw_delete) &&4722Right.isNot(TT_OverloadedOperatorLParen) &&4723!(Line.MightBeFunctionDecl && Left.is(TT_FunctionDeclarationName))) {4724return Style.SpaceBeforeParensOptions.AfterPlacementOperator;4725}4726if (Line.Type == LT_ObjCDecl)4727return true;4728if (Left.is(tok::semi))4729return true;4730if (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while, tok::kw_switch,4731tok::kw_case, TT_ForEachMacro, TT_ObjCForIn) ||4732Left.isIf(Line.Type != LT_PreprocessorDirective) ||4733Right.is(TT_ConditionLParen)) {4734return Style.SpaceBeforeParensOptions.AfterControlStatements ||4735spaceRequiredBeforeParens(Right);4736}47374738// TODO add Operator overloading specific Options to4739// SpaceBeforeParensOptions4740if (Right.is(TT_OverloadedOperatorLParen))4741return spaceRequiredBeforeParens(Right);4742// Function declaration or definition4743if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) {4744if (spaceRequiredBeforeParens(Right))4745return true;4746const auto &Options = Style.SpaceBeforeParensOptions;4747return Line.mightBeFunctionDefinition()4748? Options.AfterFunctionDefinitionName4749: Options.AfterFunctionDeclarationName;4750}4751// Lambda4752if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) &&4753Left.MatchingParen && Left.MatchingParen->is(TT_LambdaLSquare)) {4754return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||4755spaceRequiredBeforeParens(Right);4756}4757if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) {4758if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) {4759return Style.SpaceBeforeParensOptions.AfterControlStatements ||4760spaceRequiredBeforeParens(Right);4761}4762if (Left.isOneOf(tok::kw_new, tok::kw_delete)) {4763return ((!Line.MightBeFunctionDecl || !BeforeLeft) &&4764Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||4765spaceRequiredBeforeParens(Right);4766}47674768if (Left.is(tok::r_square) && Left.MatchingParen &&4769Left.MatchingParen->Previous &&4770Left.MatchingParen->Previous->is(tok::kw_delete)) {4771return (Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||4772spaceRequiredBeforeParens(Right);4773}4774}4775// Handle builtins like identifiers.4776if (Line.Type != LT_PreprocessorDirective &&4777(Left.Tok.getIdentifierInfo() || Left.is(tok::r_paren))) {4778return spaceRequiredBeforeParens(Right);4779}4780return false;4781}4782if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)4783return false;4784if (Right.is(TT_UnaryOperator)) {4785return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&4786(Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr));4787}4788// No space between the variable name and the initializer list.4789// A a1{1};4790// Verilog doesn't have such syntax, but it has word operators that are C++4791// identifiers like `a inside {b, c}`. So the rule is not applicable.4792if (!Style.isVerilog() &&4793(Left.isOneOf(tok::identifier, tok::greater, tok::r_square,4794tok::r_paren) ||4795Left.isTypeName(LangOpts)) &&4796Right.is(tok::l_brace) && Right.getNextNonComment() &&4797Right.isNot(BK_Block)) {4798return false;4799}4800if (Left.is(tok::period) || Right.is(tok::period))4801return false;4802// u#str, U#str, L#str, u8#str4803// uR#str, UR#str, LR#str, u8R#str4804if (Right.is(tok::hash) && Left.is(tok::identifier) &&4805(Left.TokenText == "L" || Left.TokenText == "u" ||4806Left.TokenText == "U" || Left.TokenText == "u8" ||4807Left.TokenText == "LR" || Left.TokenText == "uR" ||4808Left.TokenText == "UR" || Left.TokenText == "u8R")) {4809return false;4810}4811if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&4812Left.MatchingParen->Previous &&4813(Left.MatchingParen->Previous->is(tok::period) ||4814Left.MatchingParen->Previous->is(tok::coloncolon))) {4815// Java call to generic function with explicit type:4816// A.<B<C<...>>>DoSomething();4817// A::<B<C<...>>>DoSomething(); // With a Java 8 method reference.4818return false;4819}4820if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))4821return false;4822if (Left.is(tok::l_brace) && Left.endsSequence(TT_DictLiteral, tok::at)) {4823// Objective-C dictionary literal -> no space after opening brace.4824return false;4825}4826if (Right.is(tok::r_brace) && Right.MatchingParen &&4827Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at)) {4828// Objective-C dictionary literal -> no space before closing brace.4829return false;4830}4831if (Right.is(TT_TrailingAnnotation) && Right.isOneOf(tok::amp, tok::ampamp) &&4832Left.isOneOf(tok::kw_const, tok::kw_volatile) &&4833(!Right.Next || Right.Next->is(tok::semi))) {4834// Match const and volatile ref-qualifiers without any additional4835// qualifiers such as4836// void Fn() const &;4837return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;4838}48394840return true;4841}48424843bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,4844const FormatToken &Right) const {4845const FormatToken &Left = *Right.Previous;48464847// If the token is finalized don't touch it (as it could be in a4848// clang-format-off section).4849if (Left.Finalized)4850return Right.hasWhitespaceBefore();48514852const bool IsVerilog = Style.isVerilog();4853assert(!IsVerilog || !IsCpp);48544855// Never ever merge two words.4856if (Keywords.isWordLike(Right, IsVerilog) &&4857Keywords.isWordLike(Left, IsVerilog)) {4858return true;4859}48604861// Leave a space between * and /* to avoid C4138 `comment end` found outside4862// of comment.4863if (Left.is(tok::star) && Right.is(tok::comment))4864return true;48654866if (IsCpp) {4867if (Left.is(TT_OverloadedOperator) &&4868Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {4869return true;4870}4871// Space between UDL and dot: auto b = 4s .count();4872if (Right.is(tok::period) && Left.is(tok::numeric_constant))4873return true;4874// Space between import <iostream>.4875// or import .....;4876if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))4877return true;4878// Space between `module :` and `import :`.4879if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&4880Right.is(TT_ModulePartitionColon)) {4881return true;4882}4883// No space between import foo:bar but keep a space between import :bar;4884if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))4885return false;4886// No space between :bar;4887if (Left.is(TT_ModulePartitionColon) &&4888Right.isOneOf(tok::identifier, tok::kw_private)) {4889return false;4890}4891if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&4892Line.First->is(Keywords.kw_import)) {4893return false;4894}4895// Space in __attribute__((attr)) ::type.4896if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) &&4897Right.is(tok::coloncolon)) {4898return true;4899}49004901if (Left.is(tok::kw_operator))4902return Right.is(tok::coloncolon);4903if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&4904!Left.opensScope() && Style.SpaceBeforeCpp11BracedList) {4905return true;4906}4907if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) &&4908Right.is(TT_TemplateOpener)) {4909return true;4910}4911// C++ Core Guidelines suppression tag, e.g. `[[suppress(type.5)]]`.4912if (Left.is(tok::identifier) && Right.is(tok::numeric_constant))4913return Right.TokenText[0] != '.';4914// `Left` is a keyword (including C++ alternative operator) or identifier.4915if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral())4916return true;4917} else if (Style.isProto()) {4918if (Right.is(tok::period) &&4919Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,4920Keywords.kw_repeated, Keywords.kw_extend)) {4921return true;4922}4923if (Right.is(tok::l_paren) &&4924Left.isOneOf(Keywords.kw_returns, Keywords.kw_option)) {4925return true;4926}4927if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))4928return true;4929// Slashes occur in text protocol extension syntax: [type/type] { ... }.4930if (Left.is(tok::slash) || Right.is(tok::slash))4931return false;4932if (Left.MatchingParen &&4933Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&4934Right.isOneOf(tok::l_brace, tok::less)) {4935return !Style.Cpp11BracedListStyle;4936}4937// A percent is probably part of a formatting specification, such as %lld.4938if (Left.is(tok::percent))4939return false;4940// Preserve the existence of a space before a percent for cases like 0x%04x4941// and "%d %d"4942if (Left.is(tok::numeric_constant) && Right.is(tok::percent))4943return Right.hasWhitespaceBefore();4944} else if (Style.isJson()) {4945if (Right.is(tok::colon) && Left.is(tok::string_literal))4946return Style.SpaceBeforeJsonColon;4947} else if (Style.isCSharp()) {4948// Require spaces around '{' and before '}' unless they appear in4949// interpolated strings. Interpolated strings are merged into a single token4950// so cannot have spaces inserted by this function.49514952// No space between 'this' and '['4953if (Left.is(tok::kw_this) && Right.is(tok::l_square))4954return false;49554956// No space between 'new' and '('4957if (Left.is(tok::kw_new) && Right.is(tok::l_paren))4958return false;49594960// Space before { (including space within '{ {').4961if (Right.is(tok::l_brace))4962return true;49634964// Spaces inside braces.4965if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))4966return true;49674968if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))4969return true;49704971// Spaces around '=>'.4972if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow))4973return true;49744975// No spaces around attribute target colons4976if (Left.is(TT_AttributeColon) || Right.is(TT_AttributeColon))4977return false;49784979// space between type and variable e.g. Dictionary<string,string> foo;4980if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))4981return true;49824983// spaces inside square brackets.4984if (Left.is(tok::l_square) || Right.is(tok::r_square))4985return Style.SpacesInSquareBrackets;49864987// No space before ? in nullable types.4988if (Right.is(TT_CSharpNullable))4989return false;49904991// No space before null forgiving '!'.4992if (Right.is(TT_NonNullAssertion))4993return false;49944995// No space between consecutive commas '[,,]'.4996if (Left.is(tok::comma) && Right.is(tok::comma))4997return false;49984999// space after var in `var (key, value)`5000if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))5001return true;50025003// space between keywords and paren e.g. "using ("5004if (Right.is(tok::l_paren)) {5005if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when,5006Keywords.kw_lock)) {5007return Style.SpaceBeforeParensOptions.AfterControlStatements ||5008spaceRequiredBeforeParens(Right);5009}5010}50115012// space between method modifier and opening parenthesis of a tuple return5013// type5014if ((Left.isAccessSpecifierKeyword() ||5015Left.isOneOf(tok::kw_virtual, tok::kw_extern, tok::kw_static,5016Keywords.kw_internal, Keywords.kw_abstract,5017Keywords.kw_sealed, Keywords.kw_override,5018Keywords.kw_async, Keywords.kw_unsafe)) &&5019Right.is(tok::l_paren)) {5020return true;5021}5022} else if (Style.isJavaScript()) {5023if (Left.is(TT_FatArrow))5024return true;5025// for await ( ...5026if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&5027Left.Previous->is(tok::kw_for)) {5028return true;5029}5030if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&5031Right.MatchingParen) {5032const FormatToken *Next = Right.MatchingParen->getNextNonComment();5033// An async arrow function, for example: `x = async () => foo();`,5034// as opposed to calling a function called async: `x = async();`5035if (Next && Next->is(TT_FatArrow))5036return true;5037}5038if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) ||5039(Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) {5040return false;5041}5042// In tagged template literals ("html`bar baz`"), there is no space between5043// the tag identifier and the template string.5044if (Keywords.isJavaScriptIdentifier(Left,5045/* AcceptIdentifierName= */ false) &&5046Right.is(TT_TemplateString)) {5047return false;5048}5049if (Right.is(tok::star) &&5050Left.isOneOf(Keywords.kw_function, Keywords.kw_yield)) {5051return false;5052}5053if (Right.isOneOf(tok::l_brace, tok::l_square) &&5054Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,5055Keywords.kw_extends, Keywords.kw_implements)) {5056return true;5057}5058if (Right.is(tok::l_paren)) {5059// JS methods can use some keywords as names (e.g. `delete()`).5060if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())5061return false;5062// Valid JS method names can include keywords, e.g. `foo.delete()` or5063// `bar.instanceof()`. Recognize call positions by preceding period.5064if (Left.Previous && Left.Previous->is(tok::period) &&5065Left.Tok.getIdentifierInfo()) {5066return false;5067}5068// Additional unary JavaScript operators that need a space after.5069if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,5070tok::kw_void)) {5071return true;5072}5073}5074// `foo as const;` casts into a const type.5075if (Left.endsSequence(tok::kw_const, Keywords.kw_as))5076return false;5077if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,5078tok::kw_const) ||5079// "of" is only a keyword if it appears after another identifier5080// (e.g. as "const x of y" in a for loop), or after a destructuring5081// operation (const [x, y] of z, const {a, b} of c).5082(Left.is(Keywords.kw_of) && Left.Previous &&5083(Left.Previous->is(tok::identifier) ||5084Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&5085(!Left.Previous || Left.Previous->isNot(tok::period))) {5086return true;5087}5088if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&5089Left.Previous->is(tok::period) && Right.is(tok::l_paren)) {5090return false;5091}5092if (Left.is(Keywords.kw_as) &&5093Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) {5094return true;5095}5096if (Left.is(tok::kw_default) && Left.Previous &&5097Left.Previous->is(tok::kw_export)) {5098return true;5099}5100if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))5101return true;5102if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))5103return false;5104if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))5105return false;5106if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) &&5107Line.First->isOneOf(Keywords.kw_import, tok::kw_export)) {5108return false;5109}5110if (Left.is(tok::ellipsis))5111return false;5112if (Left.is(TT_TemplateCloser) &&5113!Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,5114Keywords.kw_implements, Keywords.kw_extends)) {5115// Type assertions ('<type>expr') are not followed by whitespace. Other5116// locations that should have whitespace following are identified by the5117// above set of follower tokens.5118return false;5119}5120if (Right.is(TT_NonNullAssertion))5121return false;5122if (Left.is(TT_NonNullAssertion) &&5123Right.isOneOf(Keywords.kw_as, Keywords.kw_in)) {5124return true; // "x! as string", "x! in y"5125}5126} else if (Style.Language == FormatStyle::LK_Java) {5127if (Left.is(TT_CaseLabelArrow) || Right.is(TT_CaseLabelArrow))5128return true;5129if (Left.is(tok::r_square) && Right.is(tok::l_brace))5130return true;5131// spaces inside square brackets.5132if (Left.is(tok::l_square) || Right.is(tok::r_square))5133return Style.SpacesInSquareBrackets;51345135if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) {5136return Style.SpaceBeforeParensOptions.AfterControlStatements ||5137spaceRequiredBeforeParens(Right);5138}5139if ((Left.isAccessSpecifierKeyword() ||5140Left.isOneOf(tok::kw_static, Keywords.kw_final, Keywords.kw_abstract,5141Keywords.kw_native)) &&5142Right.is(TT_TemplateOpener)) {5143return true;5144}5145} else if (IsVerilog) {5146// An escaped identifier ends with whitespace.5147if (Left.is(tok::identifier) && Left.TokenText[0] == '\\')5148return true;5149// Add space between things in a primitive's state table unless in a5150// transition like `(0?)`.5151if ((Left.is(TT_VerilogTableItem) &&5152!Right.isOneOf(tok::r_paren, tok::semi)) ||5153(Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) {5154const FormatToken *Next = Right.getNextNonComment();5155return !(Next && Next->is(tok::r_paren));5156}5157// Don't add space within a delay like `#0`.5158if (Left.isNot(TT_BinaryOperator) &&5159Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) {5160return false;5161}5162// Add space after a delay.5163if (Right.isNot(tok::semi) &&5164(Left.endsSequence(tok::numeric_constant, Keywords.kw_verilogHash) ||5165Left.endsSequence(tok::numeric_constant,5166Keywords.kw_verilogHashHash) ||5167(Left.is(tok::r_paren) && Left.MatchingParen &&5168Left.MatchingParen->endsSequence(tok::l_paren, tok::at)))) {5169return true;5170}5171// Don't add embedded spaces in a number literal like `16'h1?ax` or an array5172// literal like `'{}`.5173if (Left.is(Keywords.kw_apostrophe) ||5174(Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) {5175return false;5176}5177// Add spaces around the implication operator `->`.5178if (Left.is(tok::arrow) || Right.is(tok::arrow))5179return true;5180// Don't add spaces between two at signs. Like in a coverage event.5181// Don't add spaces between at and a sensitivity list like5182// `@(posedge clk)`.5183if (Left.is(tok::at) && Right.isOneOf(tok::l_paren, tok::star, tok::at))5184return false;5185// Add space between the type name and dimension like `logic [1:0]`.5186if (Right.is(tok::l_square) &&5187Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) {5188return true;5189}5190// In a tagged union expression, there should be a space after the tag.5191if (Right.isOneOf(tok::period, Keywords.kw_apostrophe) &&5192Keywords.isVerilogIdentifier(Left) && Left.getPreviousNonComment() &&5193Left.getPreviousNonComment()->is(Keywords.kw_tagged)) {5194return true;5195}5196// Don't add spaces between a casting type and the quote or repetition count5197// and the brace. The case of tagged union expressions is handled by the5198// previous rule.5199if ((Right.is(Keywords.kw_apostrophe) ||5200(Right.is(BK_BracedInit) && Right.is(tok::l_brace))) &&5201!(Left.isOneOf(Keywords.kw_assign, Keywords.kw_unique) ||5202Keywords.isVerilogWordOperator(Left)) &&5203(Left.isOneOf(tok::r_square, tok::r_paren, tok::r_brace,5204tok::numeric_constant) ||5205Keywords.isWordLike(Left))) {5206return false;5207}5208// Don't add spaces in imports like `import foo::*;`.5209if ((Right.is(tok::star) && Left.is(tok::coloncolon)) ||5210(Left.is(tok::star) && Right.is(tok::semi))) {5211return false;5212}5213// Add space in attribute like `(* ASYNC_REG = "TRUE" *)`.5214if (Left.endsSequence(tok::star, tok::l_paren) && Right.is(tok::identifier))5215return true;5216// Add space before drive strength like in `wire (strong1, pull0)`.5217if (Right.is(tok::l_paren) && Right.is(TT_VerilogStrength))5218return true;5219// Don't add space in a streaming concatenation like `{>>{j}}`.5220if ((Left.is(tok::l_brace) &&5221Right.isOneOf(tok::lessless, tok::greatergreater)) ||5222(Left.endsSequence(tok::lessless, tok::l_brace) ||5223Left.endsSequence(tok::greatergreater, tok::l_brace))) {5224return false;5225}5226} else if (Style.isTableGen()) {5227// Avoid to connect [ and {. [{ is start token of multiline string.5228if (Left.is(tok::l_square) && Right.is(tok::l_brace))5229return true;5230if (Left.is(tok::r_brace) && Right.is(tok::r_square))5231return true;5232// Do not insert around colon in DAGArg and cond operator.5233if (Right.isOneOf(TT_TableGenDAGArgListColon,5234TT_TableGenDAGArgListColonToAlign) ||5235Left.isOneOf(TT_TableGenDAGArgListColon,5236TT_TableGenDAGArgListColonToAlign)) {5237return false;5238}5239if (Right.is(TT_TableGenCondOperatorColon))5240return false;5241if (Left.isOneOf(TT_TableGenDAGArgOperatorID,5242TT_TableGenDAGArgOperatorToBreak) &&5243Right.isNot(TT_TableGenDAGArgCloser)) {5244return true;5245}5246// Do not insert bang operators and consequent openers.5247if (Right.isOneOf(tok::l_paren, tok::less) &&5248Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {5249return false;5250}5251// Trailing paste requires space before '{' or ':', the case in name values.5252// Not before ';', the case in normal values.5253if (Left.is(TT_TableGenTrailingPasteOperator) &&5254Right.isOneOf(tok::l_brace, tok::colon)) {5255return true;5256}5257// Otherwise paste operator does not prefer space around.5258if (Left.is(tok::hash) || Right.is(tok::hash))5259return false;5260// Sure not to connect after defining keywords.5261if (Keywords.isTableGenDefinition(Left))5262return true;5263}52645265if (Left.is(TT_ImplicitStringLiteral))5266return Right.hasWhitespaceBefore();5267if (Line.Type == LT_ObjCMethodDecl) {5268if (Left.is(TT_ObjCMethodSpecifier))5269return true;5270if (Left.is(tok::r_paren) && Left.isNot(TT_AttributeRParen) &&5271canBeObjCSelectorComponent(Right)) {5272// Don't space between ')' and <id> or ')' and 'new'. 'new' is not a5273// keyword in Objective-C, and '+ (instancetype)new;' is a standard class5274// method declaration.5275return false;5276}5277}5278if (Line.Type == LT_ObjCProperty &&5279(Right.is(tok::equal) || Left.is(tok::equal))) {5280return false;5281}52825283if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||5284Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) {5285return true;5286}5287if (Left.is(tok::comma) && Right.isNot(TT_OverloadedOperatorLParen) &&5288// In an unexpanded macro call we only find the parentheses and commas5289// in a line; the commas and closing parenthesis do not require a space.5290(Left.Children.empty() || !Left.MacroParent)) {5291return true;5292}5293if (Right.is(tok::comma))5294return false;5295if (Right.is(TT_ObjCBlockLParen))5296return true;5297if (Right.is(TT_CtorInitializerColon))5298return Style.SpaceBeforeCtorInitializerColon;5299if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)5300return false;5301if (Right.is(TT_RangeBasedForLoopColon) &&5302!Style.SpaceBeforeRangeBasedForLoopColon) {5303return false;5304}5305if (Left.is(TT_BitFieldColon)) {5306return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||5307Style.BitFieldColonSpacing == FormatStyle::BFCS_After;5308}5309if (Right.is(tok::colon)) {5310if (Right.is(TT_CaseLabelColon))5311return Style.SpaceBeforeCaseColon;5312if (Right.is(TT_GotoLabelColon))5313return false;5314// `private:` and `public:`.5315if (!Right.getNextNonComment())5316return false;5317if (Right.is(TT_ObjCMethodExpr))5318return false;5319if (Left.is(tok::question))5320return false;5321if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))5322return false;5323if (Right.is(TT_DictLiteral))5324return Style.SpacesInContainerLiterals;5325if (Right.is(TT_AttributeColon))5326return false;5327if (Right.is(TT_CSharpNamedArgumentColon))5328return false;5329if (Right.is(TT_GenericSelectionColon))5330return false;5331if (Right.is(TT_BitFieldColon)) {5332return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||5333Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;5334}5335return true;5336}5337// Do not merge "- -" into "--".5338if ((Left.isOneOf(tok::minus, tok::minusminus) &&5339Right.isOneOf(tok::minus, tok::minusminus)) ||5340(Left.isOneOf(tok::plus, tok::plusplus) &&5341Right.isOneOf(tok::plus, tok::plusplus))) {5342return true;5343}5344if (Left.is(TT_UnaryOperator)) {5345// Lambda captures allow for a lone &, so "&]" needs to be properly5346// handled.5347if (Left.is(tok::amp) && Right.is(tok::r_square))5348return Style.SpacesInSquareBrackets;5349return Style.SpaceAfterLogicalNot && Left.is(tok::exclaim);5350}53515352// If the next token is a binary operator or a selector name, we have5353// incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.5354if (Left.is(TT_CastRParen)) {5355return Style.SpaceAfterCStyleCast ||5356Right.isOneOf(TT_BinaryOperator, TT_SelectorName);5357}53585359auto ShouldAddSpacesInAngles = [this, &Right]() {5360if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)5361return true;5362if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)5363return Right.hasWhitespaceBefore();5364return false;5365};53665367if (Left.is(tok::greater) && Right.is(tok::greater)) {5368if (Style.Language == FormatStyle::LK_TextProto ||5369(Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral))) {5370return !Style.Cpp11BracedListStyle;5371}5372return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&5373((Style.Standard < FormatStyle::LS_Cpp11) ||5374ShouldAddSpacesInAngles());5375}5376if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||5377Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||5378(Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod))) {5379return false;5380}5381if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&5382Right.getPrecedence() == prec::Assignment) {5383return false;5384}5385if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) &&5386(Left.is(tok::identifier) || Left.is(tok::kw_this))) {5387return false;5388}5389if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) {5390// Generally don't remove existing spaces between an identifier and "::".5391// The identifier might actually be a macro name such as ALWAYS_INLINE. If5392// this turns out to be too lenient, add analysis of the identifier itself.5393return Right.hasWhitespaceBefore();5394}5395if (Right.is(tok::coloncolon) &&5396!Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren)) {5397// Put a space between < and :: in vector< ::std::string >5398return (Left.is(TT_TemplateOpener) &&5399((Style.Standard < FormatStyle::LS_Cpp11) ||5400ShouldAddSpacesInAngles())) ||5401!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,5402tok::kw___super, TT_TemplateOpener,5403TT_TemplateCloser)) ||5404(Left.is(tok::l_paren) && Style.SpacesInParensOptions.Other);5405}5406if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))5407return ShouldAddSpacesInAngles();5408// Space before TT_StructuredBindingLSquare.5409if (Right.is(TT_StructuredBindingLSquare)) {5410return !Left.isOneOf(tok::amp, tok::ampamp) ||5411getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right;5412}5413// Space before & or && following a TT_StructuredBindingLSquare.5414if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&5415Right.isOneOf(tok::amp, tok::ampamp)) {5416return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;5417}5418if ((Right.is(TT_BinaryOperator) && Left.isNot(tok::l_paren)) ||5419(Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&5420Right.isNot(tok::r_paren))) {5421return true;5422}5423if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&5424Left.MatchingParen &&5425Left.MatchingParen->is(TT_OverloadedOperatorLParen)) {5426return false;5427}5428if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&5429Line.Type == LT_ImportStatement) {5430return true;5431}5432if (Right.is(TT_TrailingUnaryOperator))5433return false;5434if (Left.is(TT_RegexLiteral))5435return false;5436return spaceRequiredBetween(Line, Left, Right);5437}54385439// Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.5440static bool isAllmanBrace(const FormatToken &Tok) {5441return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&5442!Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);5443}54445445// Returns 'true' if 'Tok' is a function argument.5446static bool IsFunctionArgument(const FormatToken &Tok) {5447return Tok.MatchingParen && Tok.MatchingParen->Next &&5448Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren);5449}54505451static bool5452isItAnEmptyLambdaAllowed(const FormatToken &Tok,5453FormatStyle::ShortLambdaStyle ShortLambdaOption) {5454return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;5455}54565457static bool isAllmanLambdaBrace(const FormatToken &Tok) {5458return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&5459!Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral);5460}54615462bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,5463const FormatToken &Right) const {5464const FormatToken &Left = *Right.Previous;5465if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)5466return true;54675468if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&5469Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&5470Left.ParameterCount > 0) {5471return true;5472}54735474const auto *BeforeLeft = Left.Previous;5475const auto *AfterRight = Right.Next;54765477if (Style.isCSharp()) {5478if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&5479Style.BraceWrapping.AfterFunction) {5480return true;5481}5482if (Right.is(TT_CSharpNamedArgumentColon) ||5483Left.is(TT_CSharpNamedArgumentColon)) {5484return false;5485}5486if (Right.is(TT_CSharpGenericTypeConstraint))5487return true;5488if (AfterRight && AfterRight->is(TT_FatArrow) &&5489(Right.is(tok::numeric_constant) ||5490(Right.is(tok::identifier) && Right.TokenText == "_"))) {5491return true;5492}54935494// Break after C# [...] and before public/protected/private/internal.5495if (Left.is(TT_AttributeSquare) && Left.is(tok::r_square) &&5496(Right.isAccessSpecifier(/*ColonRequired=*/false) ||5497Right.is(Keywords.kw_internal))) {5498return true;5499}5500// Break between ] and [ but only when there are really 2 attributes.5501if (Left.is(TT_AttributeSquare) && Right.is(TT_AttributeSquare) &&5502Left.is(tok::r_square) && Right.is(tok::l_square)) {5503return true;5504}5505} else if (Style.isJavaScript()) {5506// FIXME: This might apply to other languages and token kinds.5507if (Right.is(tok::string_literal) && Left.is(tok::plus) && BeforeLeft &&5508BeforeLeft->is(tok::string_literal)) {5509return true;5510}5511if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&5512BeforeLeft && BeforeLeft->is(tok::equal) &&5513Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,5514tok::kw_const) &&5515// kw_var/kw_let are pseudo-tokens that are tok::identifier, so match5516// above.5517!Line.First->isOneOf(Keywords.kw_var, Keywords.kw_let)) {5518// Object literals on the top level of a file are treated as "enum-style".5519// Each key/value pair is put on a separate line, instead of bin-packing.5520return true;5521}5522if (Left.is(tok::l_brace) && Line.Level == 0 &&5523(Line.startsWith(tok::kw_enum) ||5524Line.startsWith(tok::kw_const, tok::kw_enum) ||5525Line.startsWith(tok::kw_export, tok::kw_enum) ||5526Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum))) {5527// JavaScript top-level enum key/value pairs are put on separate lines5528// instead of bin-packing.5529return true;5530}5531if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && BeforeLeft &&5532BeforeLeft->is(TT_FatArrow)) {5533// JS arrow function (=> {...}).5534switch (Style.AllowShortLambdasOnASingleLine) {5535case FormatStyle::SLS_All:5536return false;5537case FormatStyle::SLS_None:5538return true;5539case FormatStyle::SLS_Empty:5540return !Left.Children.empty();5541case FormatStyle::SLS_Inline:5542// allow one-lining inline (e.g. in function call args) and empty arrow5543// functions.5544return (Left.NestingLevel == 0 && Line.Level == 0) &&5545!Left.Children.empty();5546}5547llvm_unreachable("Unknown FormatStyle::ShortLambdaStyle enum");5548}55495550if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&5551!Left.Children.empty()) {5552// Support AllowShortFunctionsOnASingleLine for JavaScript.5553return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||5554Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||5555(Left.NestingLevel == 0 && Line.Level == 0 &&5556Style.AllowShortFunctionsOnASingleLine &5557FormatStyle::SFS_InlineOnly);5558}5559} else if (Style.Language == FormatStyle::LK_Java) {5560if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight &&5561AfterRight->is(tok::string_literal)) {5562return true;5563}5564} else if (Style.isVerilog()) {5565// Break between assignments.5566if (Left.is(TT_VerilogAssignComma))5567return true;5568// Break between ports of different types.5569if (Left.is(TT_VerilogTypeComma))5570return true;5571// Break between ports in a module instantiation and after the parameter5572// list.5573if (Style.VerilogBreakBetweenInstancePorts &&5574(Left.is(TT_VerilogInstancePortComma) ||5575(Left.is(tok::r_paren) && Keywords.isVerilogIdentifier(Right) &&5576Left.MatchingParen &&5577Left.MatchingParen->is(TT_VerilogInstancePortLParen)))) {5578return true;5579}5580// Break after labels. In Verilog labels don't have the 'case' keyword, so5581// it is hard to identify them in UnwrappedLineParser.5582if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))5583return true;5584} else if (Style.BreakAdjacentStringLiterals &&5585(IsCpp || Style.isProto() ||5586Style.Language == FormatStyle::LK_TableGen)) {5587if (Left.isStringLiteral() && Right.isStringLiteral())5588return true;5589}55905591// Basic JSON newline processing.5592if (Style.isJson()) {5593// Always break after a JSON record opener.5594// {5595// }5596if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace))5597return true;5598// Always break after a JSON array opener based on BreakArrays.5599if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&5600Right.isNot(tok::r_square)) ||5601Left.is(tok::comma)) {5602if (Right.is(tok::l_brace))5603return true;5604// scan to the right if an we see an object or an array inside5605// then break.5606for (const auto *Tok = &Right; Tok; Tok = Tok->Next) {5607if (Tok->isOneOf(tok::l_brace, tok::l_square))5608return true;5609if (Tok->isOneOf(tok::r_brace, tok::r_square))5610break;5611}5612return Style.BreakArrays;5613}5614} else if (Style.isTableGen()) {5615// Break the comma in side cond operators.5616// !cond(case1:1,5617// case2:0);5618if (Left.is(TT_TableGenCondOperatorComma))5619return true;5620if (Left.is(TT_TableGenDAGArgOperatorToBreak) &&5621Right.isNot(TT_TableGenDAGArgCloser)) {5622return true;5623}5624if (Left.is(TT_TableGenDAGArgListCommaToBreak))5625return true;5626if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen &&5627Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) &&5628&Left != Right.MatchingParen->Next) {5629// Check to avoid empty DAGArg such as (ins).5630return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll;5631}5632}56335634if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&5635Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always) {5636return true;5637}56385639// If the last token before a '}', ']', or ')' is a comma or a trailing5640// comment, the intention is to insert a line break after it in order to make5641// shuffling around entries easier. Import statements, especially in5642// JavaScript, can be an exception to this rule.5643if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) {5644const FormatToken *BeforeClosingBrace = nullptr;5645if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||5646(Style.isJavaScript() && Left.is(tok::l_paren))) &&5647Left.isNot(BK_Block) && Left.MatchingParen) {5648BeforeClosingBrace = Left.MatchingParen->Previous;5649} else if (Right.MatchingParen &&5650(Right.MatchingParen->isOneOf(tok::l_brace,5651TT_ArrayInitializerLSquare) ||5652(Style.isJavaScript() &&5653Right.MatchingParen->is(tok::l_paren)))) {5654BeforeClosingBrace = &Left;5655}5656if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||5657BeforeClosingBrace->isTrailingComment())) {5658return true;5659}5660}56615662if (Right.is(tok::comment)) {5663return Left.isNot(BK_BracedInit) && Left.isNot(TT_CtorInitializerColon) &&5664(Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);5665}5666if (Left.isTrailingComment())5667return true;5668if (Left.IsUnterminatedLiteral)5669return true;56705671if (BeforeLeft && BeforeLeft->is(tok::lessless) &&5672Left.is(tok::string_literal) && Right.is(tok::lessless) && AfterRight &&5673AfterRight->is(tok::string_literal)) {5674return Right.NewlinesBefore > 0;5675}56765677if (Right.is(TT_RequiresClause)) {5678switch (Style.RequiresClausePosition) {5679case FormatStyle::RCPS_OwnLine:5680case FormatStyle::RCPS_WithFollowing:5681return true;5682default:5683break;5684}5685}5686// Can break after template<> declaration5687if (Left.ClosesTemplateDeclaration && Left.MatchingParen &&5688Left.MatchingParen->NestingLevel == 0) {5689// Put concepts on the next line e.g.5690// template<typename T>5691// concept ...5692if (Right.is(tok::kw_concept))5693return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always;5694return Style.BreakTemplateDeclarations == FormatStyle::BTDS_Yes ||5695(Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&5696Right.NewlinesBefore > 0);5697}5698if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {5699switch (Style.RequiresClausePosition) {5700case FormatStyle::RCPS_OwnLine:5701case FormatStyle::RCPS_WithPreceding:5702return true;5703default:5704break;5705}5706}5707if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) {5708if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon &&5709(Left.is(TT_CtorInitializerComma) ||5710Right.is(TT_CtorInitializerColon))) {5711return true;5712}57135714if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&5715Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) {5716return true;5717}5718}5719if (Style.PackConstructorInitializers < FormatStyle::PCIS_CurrentLine &&5720Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&5721Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) {5722return true;5723}5724if (Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly) {5725if ((Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon ||5726Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) &&5727Right.is(TT_CtorInitializerColon)) {5728return true;5729}57305731if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&5732Left.is(TT_CtorInitializerColon)) {5733return true;5734}5735}5736// Break only if we have multiple inheritance.5737if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&5738Right.is(TT_InheritanceComma)) {5739return true;5740}5741if (Style.BreakInheritanceList == FormatStyle::BILS_AfterComma &&5742Left.is(TT_InheritanceComma)) {5743return true;5744}5745if (Right.is(tok::string_literal) && Right.TokenText.starts_with("R\"")) {5746// Multiline raw string literals are special wrt. line breaks. The author5747// has made a deliberate choice and might have aligned the contents of the5748// string literal accordingly. Thus, we try keep existing line breaks.5749return Right.IsMultiline && Right.NewlinesBefore > 0;5750}5751if ((Left.is(tok::l_brace) ||5752(Left.is(tok::less) && BeforeLeft && BeforeLeft->is(tok::equal))) &&5753Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {5754// Don't put enums or option definitions onto single lines in protocol5755// buffers.5756return true;5757}5758if (Right.is(TT_InlineASMBrace))5759return Right.HasUnescapedNewline;57605761if (isAllmanBrace(Left) || isAllmanBrace(Right)) {5762auto *FirstNonComment = Line.getFirstNonComment();5763bool AccessSpecifier =5764FirstNonComment && (FirstNonComment->is(Keywords.kw_internal) ||5765FirstNonComment->isAccessSpecifierKeyword());57665767if (Style.BraceWrapping.AfterEnum) {5768if (Line.startsWith(tok::kw_enum) ||5769Line.startsWith(tok::kw_typedef, tok::kw_enum)) {5770return true;5771}5772// Ensure BraceWrapping for `public enum A {`.5773if (AccessSpecifier && FirstNonComment->Next &&5774FirstNonComment->Next->is(tok::kw_enum)) {5775return true;5776}5777}57785779// Ensure BraceWrapping for `public interface A {`.5780if (Style.BraceWrapping.AfterClass &&5781((AccessSpecifier && FirstNonComment->Next &&5782FirstNonComment->Next->is(Keywords.kw_interface)) ||5783Line.startsWith(Keywords.kw_interface))) {5784return true;5785}57865787// Don't attempt to interpret struct return types as structs.5788if (Right.isNot(TT_FunctionLBrace)) {5789return (Line.startsWith(tok::kw_class) &&5790Style.BraceWrapping.AfterClass) ||5791(Line.startsWith(tok::kw_struct) &&5792Style.BraceWrapping.AfterStruct);5793}5794}57955796if (Left.is(TT_ObjCBlockLBrace) &&5797Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {5798return true;5799}58005801// Ensure wrapping after __attribute__((XX)) and @interface etc.5802if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) &&5803Right.is(TT_ObjCDecl)) {5804return true;5805}58065807if (Left.is(TT_LambdaLBrace)) {5808if (IsFunctionArgument(Left) &&5809Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline) {5810return false;5811}58125813if (Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_None ||5814Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline ||5815(!Left.Children.empty() &&5816Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty)) {5817return true;5818}5819}58205821if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&5822(Left.isPointerOrReference() || Left.is(TT_TemplateCloser))) {5823return true;5824}58255826// Put multiple Java annotation on a new line.5827if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&5828Left.is(TT_LeadingJavaAnnotation) &&5829Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&5830(Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {5831return true;5832}58335834if (Right.is(TT_ProtoExtensionLSquare))5835return true;58365837// In text proto instances if a submessage contains at least 2 entries and at5838// least one of them is a submessage, like A { ... B { ... } ... },5839// put all of the entries of A on separate lines by forcing the selector of5840// the submessage B to be put on a newline.5841//5842// Example: these can stay on one line:5843// a { scalar_1: 1 scalar_2: 2 }5844// a { b { key: value } }5845//5846// and these entries need to be on a new line even if putting them all in one5847// line is under the column limit:5848// a {5849// scalar: 15850// b { key: value }5851// }5852//5853// We enforce this by breaking before a submessage field that has previous5854// siblings, *and* breaking before a field that follows a submessage field.5855//5856// Be careful to exclude the case [proto.ext] { ... } since the `]` is5857// the TT_SelectorName there, but we don't want to break inside the brackets.5858//5859// Another edge case is @submessage { key: value }, which is a common5860// substitution placeholder. In this case we want to keep `@` and `submessage`5861// together.5862//5863// We ensure elsewhere that extensions are always on their own line.5864if (Style.isProto() && Right.is(TT_SelectorName) &&5865Right.isNot(tok::r_square) && AfterRight) {5866// Keep `@submessage` together in:5867// @submessage { key: value }5868if (Left.is(tok::at))5869return false;5870// Look for the scope opener after selector in cases like:5871// selector { ...5872// selector: { ...5873// selector: @base { ...5874const auto *LBrace = AfterRight;5875if (LBrace && LBrace->is(tok::colon)) {5876LBrace = LBrace->Next;5877if (LBrace && LBrace->is(tok::at)) {5878LBrace = LBrace->Next;5879if (LBrace)5880LBrace = LBrace->Next;5881}5882}5883if (LBrace &&5884// The scope opener is one of {, [, <:5885// selector { ... }5886// selector [ ... ]5887// selector < ... >5888//5889// In case of selector { ... }, the l_brace is TT_DictLiteral.5890// In case of an empty selector {}, the l_brace is not TT_DictLiteral,5891// so we check for immediately following r_brace.5892((LBrace->is(tok::l_brace) &&5893(LBrace->is(TT_DictLiteral) ||5894(LBrace->Next && LBrace->Next->is(tok::r_brace)))) ||5895LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) {5896// If Left.ParameterCount is 0, then this submessage entry is not the5897// first in its parent submessage, and we want to break before this entry.5898// If Left.ParameterCount is greater than 0, then its parent submessage5899// might contain 1 or more entries and we want to break before this entry5900// if it contains at least 2 entries. We deal with this case later by5901// detecting and breaking before the next entry in the parent submessage.5902if (Left.ParameterCount == 0)5903return true;5904// However, if this submessage is the first entry in its parent5905// submessage, Left.ParameterCount might be 1 in some cases.5906// We deal with this case later by detecting an entry5907// following a closing paren of this submessage.5908}59095910// If this is an entry immediately following a submessage, it will be5911// preceded by a closing paren of that submessage, like in:5912// left---. .---right5913// v v5914// sub: { ... } key: value5915// If there was a comment between `}` an `key` above, then `key` would be5916// put on a new line anyways.5917if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))5918return true;5919}59205921return false;5922}59235924bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,5925const FormatToken &Right) const {5926const FormatToken &Left = *Right.Previous;5927// Language-specific stuff.5928if (Style.isCSharp()) {5929if (Left.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon) ||5930Right.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon)) {5931return false;5932}5933// Only break after commas for generic type constraints.5934if (Line.First->is(TT_CSharpGenericTypeConstraint))5935return Left.is(TT_CSharpGenericTypeConstraintComma);5936// Keep nullable operators attached to their identifiers.5937if (Right.is(TT_CSharpNullable))5938return false;5939} else if (Style.Language == FormatStyle::LK_Java) {5940if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,5941Keywords.kw_implements)) {5942return false;5943}5944if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends,5945Keywords.kw_implements)) {5946return true;5947}5948} else if (Style.isJavaScript()) {5949const FormatToken *NonComment = Right.getPreviousNonComment();5950if (NonComment &&5951(NonComment->isAccessSpecifierKeyword() ||5952NonComment->isOneOf(5953tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,5954tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,5955tok::kw_static, Keywords.kw_readonly, Keywords.kw_override,5956Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set,5957Keywords.kw_async, Keywords.kw_await))) {5958return false; // Otherwise automatic semicolon insertion would trigger.5959}5960if (Right.NestingLevel == 0 &&5961(Left.Tok.getIdentifierInfo() ||5962Left.isOneOf(tok::r_square, tok::r_paren)) &&5963Right.isOneOf(tok::l_square, tok::l_paren)) {5964return false; // Otherwise automatic semicolon insertion would trigger.5965}5966if (NonComment && NonComment->is(tok::identifier) &&5967NonComment->TokenText == "asserts") {5968return false;5969}5970if (Left.is(TT_FatArrow) && Right.is(tok::l_brace))5971return false;5972if (Left.is(TT_JsTypeColon))5973return true;5974// Don't wrap between ":" and "!" of a strict prop init ("field!: type;").5975if (Left.is(tok::exclaim) && Right.is(tok::colon))5976return false;5977// Look for is type annotations like:5978// function f(): a is B { ... }5979// Do not break before is in these cases.5980if (Right.is(Keywords.kw_is)) {5981const FormatToken *Next = Right.getNextNonComment();5982// If `is` is followed by a colon, it's likely that it's a dict key, so5983// ignore it for this check.5984// For example this is common in Polymer:5985// Polymer({5986// is: 'name',5987// ...5988// });5989if (!Next || Next->isNot(tok::colon))5990return false;5991}5992if (Left.is(Keywords.kw_in))5993return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;5994if (Right.is(Keywords.kw_in))5995return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;5996if (Right.is(Keywords.kw_as))5997return false; // must not break before as in 'x as type' casts5998if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {5999// extends and infer can appear as keywords in conditional types:6000// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types6001// do not break before them, as the expressions are subject to ASI.6002return false;6003}6004if (Left.is(Keywords.kw_as))6005return true;6006if (Left.is(TT_NonNullAssertion))6007return true;6008if (Left.is(Keywords.kw_declare) &&6009Right.isOneOf(Keywords.kw_module, tok::kw_namespace,6010Keywords.kw_function, tok::kw_class, tok::kw_enum,6011Keywords.kw_interface, Keywords.kw_type, Keywords.kw_var,6012Keywords.kw_let, tok::kw_const)) {6013// See grammar for 'declare' statements at:6014// https://github.com/Microsoft/TypeScript/blob/main/doc/spec-ARCHIVED.md#A.106015return false;6016}6017if (Left.isOneOf(Keywords.kw_module, tok::kw_namespace) &&6018Right.isOneOf(tok::identifier, tok::string_literal)) {6019return false; // must not break in "module foo { ...}"6020}6021if (Right.is(TT_TemplateString) && Right.closesScope())6022return false;6023// Don't split tagged template literal so there is a break between the tag6024// identifier and template string.6025if (Left.is(tok::identifier) && Right.is(TT_TemplateString))6026return false;6027if (Left.is(TT_TemplateString) && Left.opensScope())6028return true;6029} else if (Style.isTableGen()) {6030// Avoid to break after "def", "class", "let" and so on.6031if (Keywords.isTableGenDefinition(Left))6032return false;6033// Avoid to break after '(' in the cases that is in bang operators.6034if (Right.is(tok::l_paren)) {6035return !Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator,6036TT_TemplateCloser);6037}6038// Avoid to break between the value and its suffix part.6039if (Left.is(TT_TableGenValueSuffix))6040return false;6041// Avoid to break around paste operator.6042if (Left.is(tok::hash) || Right.is(tok::hash))6043return false;6044if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator))6045return false;6046}60476048if (Left.is(tok::at))6049return false;6050if (Left.Tok.getObjCKeywordID() == tok::objc_interface)6051return false;6052if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation))6053return Right.isNot(tok::l_paren);6054if (Right.is(TT_PointerOrReference)) {6055return Line.IsMultiVariableDeclStmt ||6056(getTokenPointerOrReferenceAlignment(Right) ==6057FormatStyle::PAS_Right &&6058(!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName)));6059}6060if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||6061Right.is(tok::kw_operator)) {6062return true;6063}6064if (Left.is(TT_PointerOrReference))6065return false;6066if (Right.isTrailingComment()) {6067// We rely on MustBreakBefore being set correctly here as we should not6068// change the "binding" behavior of a comment.6069// The first comment in a braced lists is always interpreted as belonging to6070// the first list element. Otherwise, it should be placed outside of the6071// list.6072return Left.is(BK_BracedInit) ||6073(Left.is(TT_CtorInitializerColon) && Right.NewlinesBefore > 0 &&6074Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);6075}6076if (Left.is(tok::question) && Right.is(tok::colon))6077return false;6078if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))6079return Style.BreakBeforeTernaryOperators;6080if (Left.is(TT_ConditionalExpr) || Left.is(tok::question))6081return !Style.BreakBeforeTernaryOperators;6082if (Left.is(TT_InheritanceColon))6083return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon;6084if (Right.is(TT_InheritanceColon))6085return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon;6086if (Right.is(TT_ObjCMethodExpr) && Right.isNot(tok::r_square) &&6087Left.isNot(TT_SelectorName)) {6088return true;6089}60906091if (Right.is(tok::colon) &&6092!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) {6093return false;6094}6095if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {6096if (Style.isProto()) {6097if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral())6098return false;6099// Prevent cases like:6100//6101// submessage:6102// { key: valueeeeeeeeeeee }6103//6104// when the snippet does not fit into one line.6105// Prefer:6106//6107// submessage: {6108// key: valueeeeeeeeeeee6109// }6110//6111// instead, even if it is longer by one line.6112//6113// Note that this allows the "{" to go over the column limit6114// when the column limit is just between ":" and "{", but that does6115// not happen too often and alternative formattings in this case are6116// not much better.6117//6118// The code covers the cases:6119//6120// submessage: { ... }6121// submessage: < ... >6122// repeated: [ ... ]6123if (((Right.is(tok::l_brace) || Right.is(tok::less)) &&6124Right.is(TT_DictLiteral)) ||6125Right.is(TT_ArrayInitializerLSquare)) {6126return false;6127}6128}6129return true;6130}6131if (Right.is(tok::r_square) && Right.MatchingParen &&6132Right.MatchingParen->is(TT_ProtoExtensionLSquare)) {6133return false;6134}6135if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&6136Right.Next->is(TT_ObjCMethodExpr))) {6137return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.6138}6139if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)6140return true;6141if (Right.is(tok::kw_concept))6142return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never;6143if (Right.is(TT_RequiresClause))6144return true;6145if (Left.ClosesTemplateDeclaration) {6146return Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave ||6147Right.NewlinesBefore > 0;6148}6149if (Left.is(TT_FunctionAnnotationRParen))6150return true;6151if (Left.ClosesRequiresClause)6152return true;6153if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen,6154TT_OverloadedOperator)) {6155return false;6156}6157if (Left.is(TT_RangeBasedForLoopColon))6158return true;6159if (Right.is(TT_RangeBasedForLoopColon))6160return false;6161if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener))6162return true;6163if ((Left.is(tok::greater) && Right.is(tok::greater)) ||6164(Left.is(tok::less) && Right.is(tok::less))) {6165return false;6166}6167if (Right.is(TT_BinaryOperator) &&6168Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None &&6169(Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All ||6170Right.getPrecedence() != prec::Assignment)) {6171return true;6172}6173if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) ||6174Left.is(tok::kw_operator)) {6175return false;6176}6177if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&6178Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0) {6179return false;6180}6181if (Left.is(tok::equal) && Right.is(tok::l_brace) &&6182!Style.Cpp11BracedListStyle) {6183return false;6184}6185if (Left.is(TT_AttributeLParen) ||6186(Left.is(tok::l_paren) && Left.is(TT_TypeDeclarationParen))) {6187return false;6188}6189if (Left.is(tok::l_paren) && Left.Previous &&6190(Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen))) {6191return false;6192}6193if (Right.is(TT_ImplicitStringLiteral))6194return false;61956196if (Right.is(TT_TemplateCloser))6197return false;6198if (Right.is(tok::r_square) && Right.MatchingParen &&6199Right.MatchingParen->is(TT_LambdaLSquare)) {6200return false;6201}62026203// We only break before r_brace if there was a corresponding break before6204// the l_brace, which is tracked by BreakBeforeClosingBrace.6205if (Right.is(tok::r_brace)) {6206return Right.MatchingParen && (Right.MatchingParen->is(BK_Block) ||6207(Right.isBlockIndentedInitRBrace(Style)));6208}62096210// We only break before r_paren if we're in a block indented context.6211if (Right.is(tok::r_paren)) {6212if (Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent ||6213!Right.MatchingParen) {6214return false;6215}6216auto Next = Right.Next;6217if (Next && Next->is(tok::r_paren))6218Next = Next->Next;6219if (Next && Next->is(tok::l_paren))6220return false;6221const FormatToken *Previous = Right.MatchingParen->Previous;6222return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf()));6223}62246225// Allow breaking after a trailing annotation, e.g. after a method6226// declaration.6227if (Left.is(TT_TrailingAnnotation)) {6228return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,6229tok::less, tok::coloncolon);6230}62316232if (Right.isAttribute())6233return true;62346235if (Right.is(tok::l_square) && Right.is(TT_AttributeSquare))6236return Left.isNot(TT_AttributeSquare);62376238if (Left.is(tok::identifier) && Right.is(tok::string_literal))6239return true;62406241if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))6242return true;62436244if (Left.is(TT_CtorInitializerColon)) {6245return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&6246(!Right.isTrailingComment() || Right.NewlinesBefore > 0);6247}6248if (Right.is(TT_CtorInitializerColon))6249return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;6250if (Left.is(TT_CtorInitializerComma) &&6251Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {6252return false;6253}6254if (Right.is(TT_CtorInitializerComma) &&6255Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {6256return true;6257}6258if (Left.is(TT_InheritanceComma) &&6259Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) {6260return false;6261}6262if (Right.is(TT_InheritanceComma) &&6263Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) {6264return true;6265}6266if (Left.is(TT_ArrayInitializerLSquare))6267return true;6268if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const))6269return true;6270if ((Left.isBinaryOperator() || Left.is(TT_BinaryOperator)) &&6271!Left.isOneOf(tok::arrowstar, tok::lessless) &&6272Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All &&6273(Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||6274Left.getPrecedence() == prec::Assignment)) {6275return true;6276}6277if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||6278(Left.is(tok::r_square) && Right.is(TT_AttributeSquare))) {6279return false;6280}62816282auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;6283if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) {6284if (isAllmanLambdaBrace(Left))6285return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);6286if (isAllmanLambdaBrace(Right))6287return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);6288}62896290if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) {6291switch (Style.AllowBreakBeforeNoexceptSpecifier) {6292case FormatStyle::BBNSS_Never:6293return false;6294case FormatStyle::BBNSS_Always:6295return true;6296case FormatStyle::BBNSS_OnlyWithParen:6297return Right.Next && Right.Next->is(tok::l_paren);6298}6299}63006301return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,6302tok::kw_class, tok::kw_struct, tok::comment) ||6303Right.isMemberAccess() ||6304Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,6305tok::colon, tok::l_square, tok::at) ||6306(Left.is(tok::r_paren) &&6307Right.isOneOf(tok::identifier, tok::kw_const)) ||6308(Left.is(tok::l_paren) && Right.isNot(tok::r_paren)) ||6309(Left.is(TT_TemplateOpener) && Right.isNot(TT_TemplateCloser));6310}63116312void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {6313llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel6314<< ", T=" << Line.Type << ", C=" << Line.IsContinuation6315<< "):\n";6316const FormatToken *Tok = Line.First;6317while (Tok) {6318llvm::errs() << " M=" << Tok->MustBreakBefore6319<< " C=" << Tok->CanBreakBefore6320<< " T=" << getTokenTypeName(Tok->getType())6321<< " S=" << Tok->SpacesRequiredBefore6322<< " F=" << Tok->Finalized << " B=" << Tok->BlockParameterCount6323<< " BK=" << Tok->getBlockKind() << " P=" << Tok->SplitPenalty6324<< " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength6325<< " PPK=" << Tok->getPackingKind() << " FakeLParens=";6326for (prec::Level LParen : Tok->FakeLParens)6327llvm::errs() << LParen << "/";6328llvm::errs() << " FakeRParens=" << Tok->FakeRParens;6329llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo();6330llvm::errs() << " Text='" << Tok->TokenText << "'\n";6331if (!Tok->Next)6332assert(Tok == Line.Last);6333Tok = Tok->Next;6334}6335llvm::errs() << "----\n";6336}63376338FormatStyle::PointerAlignmentStyle6339TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {6340assert(Reference.isOneOf(tok::amp, tok::ampamp));6341switch (Style.ReferenceAlignment) {6342case FormatStyle::RAS_Pointer:6343return Style.PointerAlignment;6344case FormatStyle::RAS_Left:6345return FormatStyle::PAS_Left;6346case FormatStyle::RAS_Right:6347return FormatStyle::PAS_Right;6348case FormatStyle::RAS_Middle:6349return FormatStyle::PAS_Middle;6350}6351assert(0); //"Unhandled value of ReferenceAlignment"6352return Style.PointerAlignment;6353}63546355FormatStyle::PointerAlignmentStyle6356TokenAnnotator::getTokenPointerOrReferenceAlignment(6357const FormatToken &PointerOrReference) const {6358if (PointerOrReference.isOneOf(tok::amp, tok::ampamp)) {6359switch (Style.ReferenceAlignment) {6360case FormatStyle::RAS_Pointer:6361return Style.PointerAlignment;6362case FormatStyle::RAS_Left:6363return FormatStyle::PAS_Left;6364case FormatStyle::RAS_Right:6365return FormatStyle::PAS_Right;6366case FormatStyle::RAS_Middle:6367return FormatStyle::PAS_Middle;6368}6369}6370assert(PointerOrReference.is(tok::star));6371return Style.PointerAlignment;6372}63736374} // namespace format6375} // namespace clang637663776378