6582 lines · cpp
1//===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements a token annotator, i.e. creates11/// \c AnnotatedTokens out of \c FormatTokens with required extra information.12///13//===----------------------------------------------------------------------===//14 15#include "TokenAnnotator.h"16#include "FormatToken.h"17#include "clang/Basic/TokenKinds.h"18#include "llvm/ADT/SmallPtrSet.h"19#include "llvm/Support/Debug.h"20 21#define DEBUG_TYPE "format-token-annotator"22 23namespace clang {24namespace format {25 26static bool mustBreakAfterAttributes(const FormatToken &Tok,27 const FormatStyle &Style) {28 switch (Style.BreakAfterAttributes) {29 case FormatStyle::ABS_Always:30 return true;31 case FormatStyle::ABS_Leave:32 return Tok.NewlinesBefore > 0;33 default:34 return false;35 }36}37 38namespace {39 40/// Returns \c true if the line starts with a token that can start a statement41/// with an initializer.42static bool startsWithInitStatement(const AnnotatedLine &Line) {43 return Line.startsWith(tok::kw_for) || Line.startsWith(tok::kw_if) ||44 Line.startsWith(tok::kw_switch);45}46 47/// 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) {59 return Tok.Tok.getIdentifierInfo();60}61 62/// With `Left` being '(', check if we're at either `[...](` or63/// `[...]<...>(`, where the [ opens a lambda capture list.64// FIXME: this doesn't cover attributes/constraints before the l_paren.65static bool isLambdaParameterList(const FormatToken *Left) {66 // Skip <...> if present.67 if (Left->Previous && Left->Previous->is(tok::greater) &&68 Left->Previous->MatchingParen &&69 Left->Previous->MatchingParen->is(TT_TemplateOpener)) {70 Left = Left->Previous->MatchingParen;71 }72 73 // Check for `[...]`.74 return Left->Previous && Left->Previous->is(tok::r_square) &&75 Left->Previous->MatchingParen &&76 Left->Previous->MatchingParen->is(TT_LambdaLSquare);77}78 79/// Returns \c true if the token is followed by a boolean condition, \c false80/// otherwise.81static bool isKeywordWithCondition(const FormatToken &Tok) {82 return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,83 tok::kw_constexpr, tok::kw_catch);84}85 86/// Returns \c true if the token starts a C++ attribute, \c false otherwise.87static bool isCppAttribute(bool IsCpp, const FormatToken &Tok) {88 if (!IsCpp || !Tok.startsSequence(tok::l_square, tok::l_square))89 return false;90 // The first square bracket is part of an ObjC array literal91 if (Tok.Previous && Tok.Previous->is(tok::at))92 return false;93 const FormatToken *AttrTok = Tok.Next->Next;94 if (!AttrTok)95 return false;96 // C++17 '[[using ns: foo, bar(baz, blech)]]'97 // We assume nobody will name an ObjC variable 'using'.98 if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))99 return true;100 if (AttrTok->isNot(tok::identifier))101 return false;102 while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {103 // ObjC message send. We assume nobody will use : in a C++11 attribute104 // specifier parameter, although this is technically valid:105 // [[foo(:)]].106 if (AttrTok->is(tok::colon) ||107 AttrTok->startsSequence(tok::identifier, tok::identifier) ||108 AttrTok->startsSequence(tok::r_paren, tok::identifier)) {109 return false;110 }111 if (AttrTok->is(tok::ellipsis))112 return true;113 AttrTok = AttrTok->Next;114 }115 return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);116}117 118/// A parser that gathers additional information about tokens.119///120/// The \c TokenAnnotator tries to match parenthesis and square brakets and121/// store a parenthesis levels. It also tries to resolve matching "<" and ">"122/// into template parameter lists.123class AnnotatingParser {124public:125 AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,126 const AdditionalKeywords &Keywords,127 SmallVector<ScopeType> &Scopes)128 : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),129 IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),130 Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) {131 Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));132 resetTokenMetadata();133 }134 135private:136 ScopeType getScopeType(const FormatToken &Token) const {137 switch (Token.getType()) {138 case TT_ClassLBrace:139 case TT_StructLBrace:140 case TT_UnionLBrace:141 return ST_Class;142 case TT_CompoundRequirementLBrace:143 return ST_CompoundRequirement;144 default:145 return ST_Other;146 }147 }148 149 bool parseAngle() {150 if (!CurrentToken)151 return false;152 153 auto *Left = CurrentToken->Previous; // The '<'.154 if (!Left)155 return false;156 157 if (NonTemplateLess.count(Left) > 0)158 return false;159 160 const auto *BeforeLess = Left->Previous;161 162 if (BeforeLess) {163 if (BeforeLess->Tok.isLiteral())164 return false;165 if (BeforeLess->is(tok::r_brace))166 return false;167 if (BeforeLess->is(tok::r_paren) && Contexts.size() > 1 &&168 !(BeforeLess->MatchingParen &&169 BeforeLess->MatchingParen->is(TT_OverloadedOperatorLParen))) {170 return false;171 }172 if (BeforeLess->is(tok::kw_operator) && CurrentToken->is(tok::l_paren))173 return false;174 }175 176 Left->ParentBracket = Contexts.back().ContextKind;177 ScopedContextCreator ContextCreator(*this, tok::less, 12);178 Contexts.back().IsExpression = false;179 180 // If there's a template keyword before the opening angle bracket, this is a181 // template parameter, not an argument.182 if (BeforeLess && BeforeLess->isNot(tok::kw_template))183 Contexts.back().ContextType = Context::TemplateArgument;184 185 if (Style.isJava() && CurrentToken->is(tok::question))186 next();187 188 for (bool SeenTernaryOperator = false, MaybeAngles = true; CurrentToken;) {189 const bool InExpr = Contexts[Contexts.size() - 2].IsExpression;190 if (CurrentToken->is(tok::greater)) {191 const auto *Next = CurrentToken->Next;192 if (CurrentToken->isNot(TT_TemplateCloser)) {193 // Try to do a better job at looking for ">>" within the condition of194 // a statement. Conservatively insert spaces between consecutive ">"195 // tokens to prevent splitting right shift operators and potentially196 // altering program semantics. This check is overly conservative and197 // will prevent spaces from being inserted in select nested template198 // parameter cases, but should not alter program semantics.199 if (Next && Next->is(tok::greater) &&200 Left->ParentBracket != tok::less &&201 CurrentToken->getStartOfNonWhitespace() ==202 Next->getStartOfNonWhitespace().getLocWithOffset(-1)) {203 return false;204 }205 if (InExpr && SeenTernaryOperator &&206 (!Next || Next->isNoneOf(tok::l_paren, tok::l_brace))) {207 return false;208 }209 if (!MaybeAngles)210 return false;211 }212 Left->MatchingParen = CurrentToken;213 CurrentToken->MatchingParen = Left;214 // In TT_Proto, we must distignuish between:215 // map<key, value>216 // msg < item: data >217 // msg: < item: data >218 // In TT_TextProto, map<key, value> does not occur.219 if (Style.isTextProto() ||220 (Style.Language == FormatStyle::LK_Proto && BeforeLess &&221 BeforeLess->isOneOf(TT_SelectorName, TT_DictLiteral))) {222 CurrentToken->setType(TT_DictLiteral);223 } else {224 CurrentToken->setType(TT_TemplateCloser);225 CurrentToken->Tok.setLength(1);226 }227 if (Next && Next->Tok.isLiteral())228 return false;229 next();230 return true;231 }232 if (BeforeLess && BeforeLess->is(TT_TemplateName)) {233 next();234 continue;235 }236 if (CurrentToken->is(tok::question) && Style.isJava()) {237 next();238 continue;239 }240 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace))241 return false;242 const 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.249 if (MaybeAngles && InExpr && !Line.startsWith(tok::kw_template) &&250 Prev.is(TT_BinaryOperator) &&251 Prev.isOneOf(tok::pipepipe, tok::ampamp)) {252 MaybeAngles = false;253 }254 if (Prev.isOneOf(tok::question, tok::colon) && !Style.isProto())255 SeenTernaryOperator = true;256 updateParameterCount(Left, CurrentToken);257 if (Style.Language == FormatStyle::LK_Proto) {258 if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) {259 if (CurrentToken->is(tok::colon) ||260 (CurrentToken->isOneOf(tok::l_brace, tok::less) &&261 Previous->isNot(tok::colon))) {262 Previous->setType(TT_SelectorName);263 }264 }265 } else if (Style.isTableGen()) {266 if (CurrentToken->isOneOf(tok::comma, tok::equal)) {267 // They appear as separators. Unless they are not in class definition.268 next();269 continue;270 }271 // In angle, there must be Value like tokens. Types are also able to be272 // parsed in the same way with Values.273 if (!parseTableGenValue())274 return false;275 continue;276 }277 if (!consumeToken())278 return false;279 }280 return false;281 }282 283 bool parseUntouchableParens() {284 while (CurrentToken) {285 CurrentToken->Finalized = true;286 switch (CurrentToken->Tok.getKind()) {287 case tok::l_paren:288 next();289 if (!parseUntouchableParens())290 return false;291 continue;292 case tok::r_paren:293 next();294 return true;295 default:296 // no-op297 break;298 }299 next();300 }301 return false;302 }303 304 bool parseParens(bool IsIf = false) {305 if (!CurrentToken)306 return false;307 assert(CurrentToken->Previous && "Unknown previous token");308 FormatToken &OpeningParen = *CurrentToken->Previous;309 assert(OpeningParen.is(tok::l_paren));310 FormatToken *PrevNonComment = OpeningParen.getPreviousNonComment();311 OpeningParen.ParentBracket = Contexts.back().ContextKind;312 ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);313 314 // FIXME: This is a bit of a hack. Do better.315 Contexts.back().ColonIsForRangeExpr =316 Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;317 318 if (OpeningParen.Previous &&319 OpeningParen.Previous->is(TT_UntouchableMacroFunc)) {320 OpeningParen.Finalized = true;321 return parseUntouchableParens();322 }323 324 bool StartsObjCSelector = false;325 if (!Style.isVerilog()) {326 if (FormatToken *MaybeSel = OpeningParen.Previous) {327 // @selector( starts a selector.328 if (MaybeSel->is(tok::objc_selector) && MaybeSel->Previous &&329 MaybeSel->Previous->is(tok::at)) {330 StartsObjCSelector = true;331 }332 }333 }334 335 if (OpeningParen.is(TT_OverloadedOperatorLParen)) {336 // Find the previous kw_operator token.337 FormatToken *Prev = &OpeningParen;338 while (Prev->isNot(tok::kw_operator)) {339 Prev = Prev->Previous;340 assert(Prev && "Expect a kw_operator prior to the OperatorLParen!");341 }342 343 // If faced with "a.operator*(argument)" or "a->operator*(argument)",344 // i.e. the operator is called as a member function,345 // then the argument must be an expression.346 bool OperatorCalledAsMemberFunction =347 Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow);348 Contexts.back().IsExpression = OperatorCalledAsMemberFunction;349 } else if (OpeningParen.is(TT_VerilogInstancePortLParen)) {350 Contexts.back().IsExpression = true;351 Contexts.back().ContextType = Context::VerilogInstancePortList;352 } else if (Style.isJavaScript() &&353 (Line.startsWith(Keywords.kw_type, tok::identifier) ||354 Line.startsWith(tok::kw_export, Keywords.kw_type,355 tok::identifier))) {356 // type X = (...);357 // export type X = (...);358 Contexts.back().IsExpression = false;359 } else if (OpeningParen.Previous &&360 (OpeningParen.Previous->isOneOf(361 tok::kw_noexcept, tok::kw_explicit, tok::kw_while,362 tok::l_paren, tok::comma, TT_CastRParen,363 TT_BinaryOperator) ||364 OpeningParen.Previous->isIf())) {365 // if and while usually contain expressions.366 Contexts.back().IsExpression = true;367 } else if (Style.isJavaScript() && OpeningParen.Previous &&368 (OpeningParen.Previous->is(Keywords.kw_function) ||369 (OpeningParen.Previous->endsSequence(tok::identifier,370 Keywords.kw_function)))) {371 // function(...) or function f(...)372 Contexts.back().IsExpression = false;373 } else if (Style.isJavaScript() && OpeningParen.Previous &&374 OpeningParen.Previous->is(TT_JsTypeColon)) {375 // let x: (SomeType);376 Contexts.back().IsExpression = false;377 } else if (isLambdaParameterList(&OpeningParen)) {378 // This is a parameter list of a lambda expression.379 OpeningParen.setType(TT_LambdaDefinitionLParen);380 Contexts.back().IsExpression = false;381 } else if (OpeningParen.is(TT_RequiresExpressionLParen)) {382 Contexts.back().IsExpression = false;383 } else if (OpeningParen.Previous &&384 OpeningParen.Previous->is(tok::kw__Generic)) {385 Contexts.back().ContextType = Context::C11GenericSelection;386 Contexts.back().IsExpression = true;387 } else if (OpeningParen.Previous &&388 OpeningParen.Previous->TokenText == "Q_PROPERTY") {389 Contexts.back().ContextType = Context::QtProperty;390 Contexts.back().IsExpression = false;391 } else if (Line.InPPDirective &&392 (!OpeningParen.Previous ||393 OpeningParen.Previous->isNot(tok::identifier))) {394 Contexts.back().IsExpression = true;395 } else if (Contexts[Contexts.size() - 2].CaretFound) {396 // This is the parameter list of an ObjC block.397 Contexts.back().IsExpression = false;398 } else if (OpeningParen.Previous &&399 OpeningParen.Previous->is(TT_ForEachMacro)) {400 // The first argument to a foreach macro is a declaration.401 Contexts.back().ContextType = Context::ForEachMacro;402 Contexts.back().IsExpression = false;403 } else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen &&404 OpeningParen.Previous->MatchingParen->isOneOf(405 TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {406 Contexts.back().IsExpression = false;407 } else if (!Line.MustBeDeclaration &&408 (!Line.InPPDirective || (Line.InMacroBody && !Scopes.empty()))) {409 bool IsForOrCatch =410 OpeningParen.Previous &&411 OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch);412 Contexts.back().IsExpression = !IsForOrCatch;413 }414 415 if (Style.isTableGen()) {416 if (FormatToken *Prev = OpeningParen.Previous) {417 if (Prev->is(TT_TableGenCondOperator)) {418 Contexts.back().IsTableGenCondOpe = true;419 Contexts.back().IsExpression = true;420 } else if (Contexts.size() > 1 &&421 Contexts[Contexts.size() - 2].IsTableGenBangOpe) {422 // Hack to handle bang operators. The parent context's flag423 // was set by parseTableGenSimpleValue().424 // We have to specify the context outside because the prev of "(" may425 // be ">", not the bang operator in this case.426 Contexts.back().IsTableGenBangOpe = true;427 Contexts.back().IsExpression = true;428 } else {429 // Otherwise, this paren seems DAGArg.430 if (!parseTableGenDAGArg())431 return false;432 return parseTableGenDAGArgAndList(&OpeningParen);433 }434 }435 }436 437 // Infer the role of the l_paren based on the previous token if we haven't438 // detected one yet.439 if (PrevNonComment && OpeningParen.is(TT_Unknown)) {440 if (PrevNonComment->isAttribute()) {441 OpeningParen.setType(TT_AttributeLParen);442 } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,443 tok::kw_typeof,444#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,445#include "clang/Basic/TransformTypeTraits.def"446 tok::kw__Atomic)) {447 OpeningParen.setType(TT_TypeDeclarationParen);448 // decltype() and typeof() usually contain expressions.449 if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))450 Contexts.back().IsExpression = true;451 }452 }453 454 if (StartsObjCSelector)455 OpeningParen.setType(TT_ObjCSelector);456 457 const bool IsStaticAssert =458 PrevNonComment && PrevNonComment->is(tok::kw_static_assert);459 if (IsStaticAssert)460 Contexts.back().InStaticAssertFirstArgument = true;461 462 // MightBeFunctionType and ProbablyFunctionType are used for463 // function pointer and reference types as well as Objective-C464 // block types:465 //466 // void (*FunctionPointer)(void);467 // void (&FunctionReference)(void);468 // void (&&FunctionReference)(void);469 // void (^ObjCBlock)(void);470 bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;471 bool ProbablyFunctionType =472 CurrentToken->isPointerOrReference() || CurrentToken->is(tok::caret);473 bool HasMultipleLines = false;474 bool HasMultipleParametersOnALine = false;475 bool MightBeObjCForRangeLoop =476 OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for);477 FormatToken *PossibleObjCForInToken = nullptr;478 while (CurrentToken) {479 const auto &Prev = *CurrentToken->Previous;480 const auto *PrevPrev = Prev.Previous;481 if (Prev.is(TT_PointerOrReference) &&482 PrevPrev->isOneOf(tok::l_paren, tok::coloncolon)) {483 ProbablyFunctionType = true;484 }485 if (CurrentToken->is(tok::comma))486 MightBeFunctionType = false;487 if (Prev.is(TT_BinaryOperator))488 Contexts.back().IsExpression = true;489 if (CurrentToken->is(tok::r_paren)) {490 if (Prev.is(TT_PointerOrReference) &&491 (PrevPrev == &OpeningParen || PrevPrev->is(tok::coloncolon))) {492 MightBeFunctionType = true;493 }494 if (OpeningParen.isNot(TT_CppCastLParen) && MightBeFunctionType &&495 ProbablyFunctionType && CurrentToken->Next &&496 (CurrentToken->Next->is(tok::l_paren) ||497 (CurrentToken->Next->is(tok::l_square) &&498 (Line.MustBeDeclaration ||499 (PrevNonComment && PrevNonComment->isTypeName(LangOpts)))))) {500 OpeningParen.setType(OpeningParen.Next->is(tok::caret)501 ? TT_ObjCBlockLParen502 : TT_FunctionTypeLParen);503 }504 OpeningParen.MatchingParen = CurrentToken;505 CurrentToken->MatchingParen = &OpeningParen;506 507 if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&508 OpeningParen.Previous && OpeningParen.Previous->is(tok::l_paren)) {509 // Detect the case where macros are used to generate lambdas or510 // function bodies, e.g.:511 // auto my_lambda = MACRO((Type *type, int i) { .. body .. });512 for (FormatToken *Tok = &OpeningParen; Tok != CurrentToken;513 Tok = Tok->Next) {514 if (Tok->is(TT_BinaryOperator) && Tok->isPointerOrReference())515 Tok->setType(TT_PointerOrReference);516 }517 }518 519 if (StartsObjCSelector) {520 CurrentToken->setType(TT_ObjCSelector);521 if (Contexts.back().FirstObjCSelectorName) {522 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =523 Contexts.back().LongestObjCSelectorName;524 }525 }526 527 if (OpeningParen.is(TT_AttributeLParen))528 CurrentToken->setType(TT_AttributeRParen);529 if (OpeningParen.is(TT_TypeDeclarationParen))530 CurrentToken->setType(TT_TypeDeclarationParen);531 if (OpeningParen.Previous &&532 OpeningParen.Previous->is(TT_JavaAnnotation)) {533 CurrentToken->setType(TT_JavaAnnotation);534 }535 if (OpeningParen.Previous &&536 OpeningParen.Previous->is(TT_LeadingJavaAnnotation)) {537 CurrentToken->setType(TT_LeadingJavaAnnotation);538 }539 540 if (!HasMultipleLines)541 OpeningParen.setPackingKind(PPK_Inconclusive);542 else if (HasMultipleParametersOnALine)543 OpeningParen.setPackingKind(PPK_BinPacked);544 else545 OpeningParen.setPackingKind(PPK_OnePerLine);546 547 next();548 return true;549 }550 if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))551 return false;552 553 if (CurrentToken->is(tok::l_brace) && OpeningParen.is(TT_ObjCBlockLParen))554 OpeningParen.setType(TT_Unknown);555 if (CurrentToken->is(tok::comma) && CurrentToken->Next &&556 !CurrentToken->Next->HasUnescapedNewline &&557 !CurrentToken->Next->isTrailingComment()) {558 HasMultipleParametersOnALine = true;559 }560 bool ProbablyFunctionTypeLParen =561 (CurrentToken->is(tok::l_paren) && CurrentToken->Next &&562 CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));563 if ((Prev.isOneOf(tok::kw_const, tok::kw_auto) ||564 Prev.isTypeName(LangOpts)) &&565 !(CurrentToken->is(tok::l_brace) ||566 (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {567 Contexts.back().IsExpression = false;568 }569 if (CurrentToken->isOneOf(tok::semi, tok::colon)) {570 MightBeObjCForRangeLoop = false;571 if (PossibleObjCForInToken) {572 PossibleObjCForInToken->setType(TT_Unknown);573 PossibleObjCForInToken = nullptr;574 }575 }576 if (IsIf && CurrentToken->is(tok::semi)) {577 for (auto *Tok = OpeningParen.Next;578 Tok != CurrentToken &&579 Tok->isNoneOf(tok::equal, tok::l_paren, tok::l_brace);580 Tok = Tok->Next) {581 if (Tok->isPointerOrReference())582 Tok->setFinalizedType(TT_PointerOrReference);583 }584 }585 if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) {586 PossibleObjCForInToken = CurrentToken;587 PossibleObjCForInToken->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.591 if (CurrentToken->is(tok::comma)) {592 if (IsStaticAssert)593 Contexts.back().InStaticAssertFirstArgument = false;594 else595 Contexts.back().CanBeExpression = true;596 }597 598 if (Style.isTableGen()) {599 if (CurrentToken->is(tok::comma)) {600 if (Contexts.back().IsTableGenCondOpe)601 CurrentToken->setType(TT_TableGenCondOperatorComma);602 next();603 } else if (CurrentToken->is(tok::colon)) {604 if (Contexts.back().IsTableGenCondOpe)605 CurrentToken->setType(TT_TableGenCondOperatorColon);606 next();607 }608 // In TableGen there must be Values in parens.609 if (!parseTableGenValue())610 return false;611 continue;612 }613 614 FormatToken *Tok = CurrentToken;615 if (!consumeToken())616 return false;617 updateParameterCount(&OpeningParen, Tok);618 if (CurrentToken && CurrentToken->HasUnescapedNewline)619 HasMultipleLines = true;620 }621 return false;622 }623 624 bool isCSharpAttributeSpecifier(const FormatToken &Tok) {625 if (!Style.isCSharp())626 return false;627 628 // `identifier[i]` is not an attribute.629 if (Tok.Previous && Tok.Previous->is(tok::identifier))630 return false;631 632 // Chains of [] in `identifier[i][j][k]` are not attributes.633 if (Tok.Previous && Tok.Previous->is(tok::r_square)) {634 auto *MatchingParen = Tok.Previous->MatchingParen;635 if (!MatchingParen || MatchingParen->is(TT_ArraySubscriptLSquare))636 return false;637 }638 639 const FormatToken *AttrTok = Tok.Next;640 if (!AttrTok)641 return false;642 643 // Just an empty declaration e.g. string [].644 if (AttrTok->is(tok::r_square))645 return false;646 647 // Move along the tokens inbetween the '[' and ']' e.g. [STAThread].648 while (AttrTok && AttrTok->isNot(tok::r_square))649 AttrTok = AttrTok->Next;650 651 if (!AttrTok)652 return false;653 654 // Allow an attribute to be the only content of a file.655 AttrTok = AttrTok->Next;656 if (!AttrTok)657 return true;658 659 // Limit this to being an access modifier that follows.660 if (AttrTok->isAccessSpecifierKeyword() ||661 AttrTok->isOneOf(tok::comment, tok::kw_class, tok::kw_static,662 tok::l_square, Keywords.kw_internal)) {663 return true;664 }665 666 // incase its a [XXX] retval func(....667 if (AttrTok->Next &&668 AttrTok->Next->startsSequence(tok::identifier, tok::l_paren)) {669 return true;670 }671 672 return false;673 }674 675 bool parseSquare() {676 if (!CurrentToken)677 return false;678 679 // A '[' could be an index subscript (after an identifier or after680 // ')' or ']'), it could be the start of an Objective-C method681 // expression, it could the start of an Objective-C array literal,682 // or it could be a C++ attribute specifier [[foo::bar]].683 FormatToken *Left = CurrentToken->Previous;684 Left->ParentBracket = Contexts.back().ContextKind;685 FormatToken *Parent = Left->getPreviousNonComment();686 687 // Cases where '>' is followed by '['.688 // In C++, this can happen either in array of templates (foo<int>[10])689 // or when array is a nested template type (unique_ptr<type1<type2>[]>).690 bool CppArrayTemplates =691 IsCpp && Parent && Parent->is(TT_TemplateCloser) &&692 (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||693 Contexts.back().ContextType == Context::TemplateArgument);694 695 const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;696 const bool IsCpp11AttributeSpecifier =697 isCppAttribute(IsCpp, *Left) || IsInnerSquare;698 699 // Treat C# Attributes [STAThread] much like C++ attributes [[...]].700 bool IsCSharpAttributeSpecifier =701 isCSharpAttributeSpecifier(*Left) ||702 Contexts.back().InCSharpAttributeSpecifier;703 704 bool InsideInlineASM = Line.startsWith(tok::kw_asm);705 bool IsCppStructuredBinding = Left->isCppStructuredBinding(IsCpp);706 bool StartsObjCMethodExpr =707 !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&708 IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&709 Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&710 CurrentToken->isNoneOf(tok::l_brace, tok::r_square) &&711 // Do not consider '[' after a comma inside a braced initializer the712 // start of an ObjC method expression. In braced initializer lists,713 // commas are list separators and should not trigger ObjC parsing.714 (!Parent || !Parent->is(tok::comma) ||715 Contexts.back().ContextKind != tok::l_brace) &&716 (!Parent ||717 Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,718 tok::kw_return, tok::kw_throw) ||719 Parent->isUnaryOperator() ||720 // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.721 Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||722 (getBinOpPrecedence(Parent->Tok.getKind(), true, true) >723 prec::Unknown));724 bool ColonFound = false;725 726 unsigned BindingIncrease = 1;727 if (IsCppStructuredBinding) {728 Left->setType(TT_StructuredBindingLSquare);729 } else if (Left->is(TT_Unknown)) {730 if (StartsObjCMethodExpr) {731 Left->setType(TT_ObjCMethodExpr);732 } else if (InsideInlineASM) {733 Left->setType(TT_InlineASMSymbolicNameLSquare);734 } else if (IsCpp11AttributeSpecifier) {735 if (!IsInnerSquare) {736 Left->setType(TT_AttributeLSquare);737 if (Left->Previous)738 Left->Previous->EndsCppAttributeGroup = false;739 }740 } else if (Style.isJavaScript() && Parent &&741 Contexts.back().ContextKind == tok::l_brace &&742 Parent->isOneOf(tok::l_brace, tok::comma)) {743 Left->setType(TT_JsComputedPropertyName);744 } else if (IsCpp && Contexts.back().ContextKind == tok::l_brace &&745 Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {746 Left->setType(TT_DesignatedInitializerLSquare);747 } else if (IsCSharpAttributeSpecifier) {748 Left->setType(TT_AttributeLSquare);749 } else if (CurrentToken->is(tok::r_square) && Parent &&750 Parent->is(TT_TemplateCloser)) {751 Left->setType(TT_ArraySubscriptLSquare);752 } else if (Style.isProto()) {753 // Square braces in LK_Proto can either be message field attributes:754 //755 // optional Aaa aaa = 1 [756 // (aaa) = aaa757 // ];758 //759 // extensions 123 [760 // (aaa) = aaa761 // ];762 //763 // or text proto extensions (in options):764 //765 // option (Aaa.options) = {766 // [type.type/type] {767 // key: value768 // }769 // }770 //771 // or repeated fields (in options):772 //773 // option (Aaa.options) = {774 // keys: [ 1, 2, 3 ]775 // }776 //777 // In the first and the third case we want to spread the contents inside778 // the square braces; in the second we want to keep them inline.779 Left->setType(TT_ArrayInitializerLSquare);780 if (!Left->endsSequence(tok::l_square, tok::numeric_constant,781 tok::equal) &&782 !Left->endsSequence(tok::l_square, tok::numeric_constant,783 tok::identifier) &&784 !Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) {785 Left->setType(TT_ProtoExtensionLSquare);786 BindingIncrease = 10;787 }788 } else if (!CppArrayTemplates && Parent &&789 Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,790 tok::comma, tok::l_paren, tok::l_square,791 tok::question, tok::colon, tok::kw_return,792 // Should only be relevant to JavaScript:793 tok::kw_default)) {794 Left->setType(TT_ArrayInitializerLSquare);795 } else {796 BindingIncrease = 10;797 Left->setType(TT_ArraySubscriptLSquare);798 }799 }800 801 ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);802 Contexts.back().IsExpression = true;803 if (Style.isJavaScript() && Parent && Parent->is(TT_JsTypeColon))804 Contexts.back().IsExpression = false;805 806 Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;807 Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;808 Contexts.back().InCSharpAttributeSpecifier = IsCSharpAttributeSpecifier;809 810 while (CurrentToken) {811 if (CurrentToken->is(tok::r_square)) {812 if (IsCpp11AttributeSpecifier && !IsInnerSquare) {813 CurrentToken->setType(TT_AttributeRSquare);814 CurrentToken->EndsCppAttributeGroup = true;815 }816 if (IsCSharpAttributeSpecifier) {817 CurrentToken->setType(TT_AttributeRSquare);818 } else if (((CurrentToken->Next &&819 CurrentToken->Next->is(tok::l_paren)) ||820 (CurrentToken->Previous &&821 CurrentToken->Previous->Previous == Left)) &&822 Left->is(TT_ObjCMethodExpr)) {823 // An ObjC method call is rarely followed by an open parenthesis. It824 // also can't be composed of just one token, unless it's a macro that825 // will be expanded to more tokens.826 // FIXME: Do we incorrectly label ":" with this?827 StartsObjCMethodExpr = false;828 Left->setType(TT_Unknown);829 }830 if (StartsObjCMethodExpr && CurrentToken->Previous != Left) {831 CurrentToken->setType(TT_ObjCMethodExpr);832 // If we haven't seen a colon yet, make sure the last identifier833 // before the r_square is tagged as a selector name component.834 if (!ColonFound && CurrentToken->Previous &&835 CurrentToken->Previous->is(TT_Unknown) &&836 canBeObjCSelectorComponent(*CurrentToken->Previous)) {837 CurrentToken->Previous->setType(TT_SelectorName);838 }839 // determineStarAmpUsage() thinks that '*' '[' is allocating an840 // array of pointers, but if '[' starts a selector then '*' is a841 // binary operator.842 if (Parent && Parent->is(TT_PointerOrReference))843 Parent->overwriteFixedType(TT_BinaryOperator);844 }845 Left->MatchingParen = CurrentToken;846 CurrentToken->MatchingParen = Left;847 // FirstObjCSelectorName is set when a colon is found. This does848 // not work, however, when the method has no parameters.849 // Here, we set FirstObjCSelectorName when the end of the method call is850 // reached, in case it was not set already.851 if (!Contexts.back().FirstObjCSelectorName) {852 FormatToken *Previous = CurrentToken->getPreviousNonComment();853 if (Previous && Previous->is(TT_SelectorName)) {854 Previous->ObjCSelectorNameParts = 1;855 Contexts.back().FirstObjCSelectorName = Previous;856 }857 } else {858 Left->ParameterCount =859 Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;860 }861 if (Contexts.back().FirstObjCSelectorName) {862 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =863 Contexts.back().LongestObjCSelectorName;864 if (Left->BlockParameterCount > 1)865 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0;866 }867 if (Style.isTableGen() && Left->is(TT_TableGenListOpener))868 CurrentToken->setType(TT_TableGenListCloser);869 next();870 return true;871 }872 if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))873 return false;874 if (CurrentToken->is(tok::colon)) {875 if (IsCpp11AttributeSpecifier &&876 CurrentToken->endsSequence(tok::colon, tok::identifier,877 tok::kw_using)) {878 // Remember that this is a [[using ns: foo]] C++ attribute, so we879 // don't add a space before the colon (unlike other colons).880 CurrentToken->setType(TT_AttributeColon);881 } else if (!Style.isVerilog() && !Line.InPragmaDirective &&882 Left->isOneOf(TT_ArraySubscriptLSquare,883 TT_DesignatedInitializerLSquare)) {884 Left->setType(TT_ObjCMethodExpr);885 StartsObjCMethodExpr = true;886 Contexts.back().ColonIsObjCMethodExpr = true;887 if (Parent && Parent->is(tok::r_paren)) {888 // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.889 Parent->setType(TT_CastRParen);890 }891 }892 ColonFound = true;893 }894 if (CurrentToken->is(tok::comma) && Left->is(TT_ObjCMethodExpr) &&895 !ColonFound) {896 Left->setType(TT_ArrayInitializerLSquare);897 }898 FormatToken *Tok = CurrentToken;899 if (Style.isTableGen()) {900 if (CurrentToken->isOneOf(tok::comma, tok::minus, tok::ellipsis)) {901 // '-' and '...' appears as a separator in slice.902 next();903 } else {904 // In TableGen there must be a list of Values in square brackets.905 // It must be ValueList or SliceElements.906 if (!parseTableGenValue())907 return false;908 }909 updateParameterCount(Left, Tok);910 continue;911 }912 if (!consumeToken())913 return false;914 updateParameterCount(Left, Tok);915 }916 return false;917 }918 919 void skipToNextNonComment() {920 next();921 while (CurrentToken && CurrentToken->is(tok::comment))922 next();923 }924 925 // Simplified parser for TableGen Value. Returns true on success.926 // It consists of SimpleValues, SimpleValues with Suffixes, and Value followed927 // by '#', paste operator.928 // There also exists the case the Value is parsed as NameValue.929 // In this case, the Value ends if '{' is found.930 bool parseTableGenValue(bool ParseNameMode = false) {931 if (!CurrentToken)932 return false;933 while (CurrentToken->is(tok::comment))934 next();935 if (!parseTableGenSimpleValue())936 return false;937 if (!CurrentToken)938 return true;939 // Value "#" [Value]940 if (CurrentToken->is(tok::hash)) {941 if (CurrentToken->Next &&942 CurrentToken->Next->isOneOf(tok::colon, tok::semi, tok::l_brace)) {943 // Trailing paste operator.944 // These are only the allowed cases in TGParser::ParseValue().945 CurrentToken->setType(TT_TableGenTrailingPasteOperator);946 next();947 return true;948 }949 FormatToken *HashTok = CurrentToken;950 skipToNextNonComment();951 HashTok->setType(TT_Unknown);952 if (!parseTableGenValue(ParseNameMode))953 return false;954 if (!CurrentToken)955 return true;956 }957 // In name mode, '{' is regarded as the end of the value.958 // See TGParser::ParseValue in TGParser.cpp959 if (ParseNameMode && CurrentToken->is(tok::l_brace))960 return true;961 // These tokens indicates this is a value with suffixes.962 if (CurrentToken->isOneOf(tok::l_brace, tok::l_square, tok::period)) {963 CurrentToken->setType(TT_TableGenValueSuffix);964 FormatToken *Suffix = CurrentToken;965 skipToNextNonComment();966 if (Suffix->is(tok::l_square))967 return parseSquare();968 if (Suffix->is(tok::l_brace)) {969 Scopes.push_back(getScopeType(*Suffix));970 return parseBrace();971 }972 }973 return true;974 }975 976 // TokVarName ::= "$" ualpha (ualpha | "0"..."9")*977 // Appears as a part of DagArg.978 // This does not change the current token on fail.979 bool tryToParseTableGenTokVar() {980 if (!CurrentToken)981 return false;982 if (CurrentToken->is(tok::identifier) &&983 CurrentToken->TokenText.front() == '$') {984 skipToNextNonComment();985 return true;986 }987 return false;988 }989 990 // DagArg ::= Value [":" TokVarName] | TokVarName991 // Appears as a part of SimpleValue6.992 bool parseTableGenDAGArg(bool AlignColon = false) {993 if (tryToParseTableGenTokVar())994 return true;995 if (parseTableGenValue()) {996 if (CurrentToken && CurrentToken->is(tok::colon)) {997 if (AlignColon)998 CurrentToken->setType(TT_TableGenDAGArgListColonToAlign);999 else1000 CurrentToken->setType(TT_TableGenDAGArgListColon);1001 skipToNextNonComment();1002 return tryToParseTableGenTokVar();1003 }1004 return true;1005 }1006 return false;1007 }1008 1009 // Judge if the token is a operator ID to insert line break in DAGArg.1010 // That is, TableGenBreakingDAGArgOperators is empty (by the definition of the1011 // option) or the token is in the list.1012 bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) {1013 auto &Opes = Style.TableGenBreakingDAGArgOperators;1014 // If the list is empty, all operators are breaking operators.1015 if (Opes.empty())1016 return true;1017 // Otherwise, the operator is limited to normal identifiers.1018 if (Tok.isNot(tok::identifier) ||1019 Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {1020 return false;1021 }1022 // The case next is colon, it is not a operator of identifier.1023 if (!Tok.Next || Tok.Next->is(tok::colon))1024 return false;1025 return llvm::is_contained(Opes, Tok.TokenText.str());1026 }1027 1028 // SimpleValue6 ::= "(" DagArg [DagArgList] ")"1029 // This parses SimpleValue 6's inside part of "(" ")"1030 bool parseTableGenDAGArgAndList(FormatToken *Opener) {1031 FormatToken *FirstTok = CurrentToken;1032 if (!parseTableGenDAGArg())1033 return false;1034 bool BreakInside = false;1035 if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) {1036 // Specialized detection for DAGArgOperator, that determines the way of1037 // line break for this DAGArg elements.1038 if (isTableGenDAGArgBreakingOperator(*FirstTok)) {1039 // Special case for identifier DAGArg operator.1040 BreakInside = true;1041 Opener->setType(TT_TableGenDAGArgOpenerToBreak);1042 if (FirstTok->isOneOf(TT_TableGenBangOperator,1043 TT_TableGenCondOperator)) {1044 // Special case for bang/cond operators. Set the whole operator as1045 // the DAGArg operator. Always break after it.1046 CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak);1047 } else if (FirstTok->is(tok::identifier)) {1048 if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll)1049 FirstTok->setType(TT_TableGenDAGArgOperatorToBreak);1050 else1051 FirstTok->setType(TT_TableGenDAGArgOperatorID);1052 }1053 }1054 }1055 // Parse the [DagArgList] part1056 return parseTableGenDAGArgList(Opener, BreakInside);1057 }1058 1059 // DagArgList ::= "," DagArg [DagArgList]1060 // This parses SimpleValue 6's [DagArgList] part.1061 bool parseTableGenDAGArgList(FormatToken *Opener, bool BreakInside) {1062 ScopedContextCreator ContextCreator(*this, tok::l_paren, 0);1063 Contexts.back().IsTableGenDAGArgList = true;1064 bool FirstDAGArgListElm = true;1065 while (CurrentToken) {1066 if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) {1067 CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak1068 : TT_TableGenDAGArgListComma);1069 skipToNextNonComment();1070 }1071 if (CurrentToken && CurrentToken->is(tok::r_paren)) {1072 CurrentToken->setType(TT_TableGenDAGArgCloser);1073 Opener->MatchingParen = CurrentToken;1074 CurrentToken->MatchingParen = Opener;1075 skipToNextNonComment();1076 return true;1077 }1078 if (!parseTableGenDAGArg(1079 BreakInside &&1080 Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) {1081 return false;1082 }1083 FirstDAGArgListElm = false;1084 }1085 return false;1086 }1087 1088 bool parseTableGenSimpleValue() {1089 assert(Style.isTableGen());1090 if (!CurrentToken)1091 return false;1092 FormatToken *Tok = CurrentToken;1093 skipToNextNonComment();1094 // SimpleValue 1, 2, 3: Literals1095 if (Tok->isOneOf(tok::numeric_constant, tok::string_literal,1096 TT_TableGenMultiLineString, tok::kw_true, tok::kw_false,1097 tok::question, tok::kw_int)) {1098 return true;1099 }1100 // SimpleValue 4: ValueList, Type1101 if (Tok->is(tok::l_brace)) {1102 Scopes.push_back(getScopeType(*Tok));1103 return parseBrace();1104 }1105 // SimpleValue 5: List initializer1106 if (Tok->is(tok::l_square)) {1107 Tok->setType(TT_TableGenListOpener);1108 if (!parseSquare())1109 return false;1110 if (Tok->is(tok::less)) {1111 CurrentToken->setType(TT_TemplateOpener);1112 return parseAngle();1113 }1114 return true;1115 }1116 // SimpleValue 6: DAGArg [DAGArgList]1117 // SimpleValue6 ::= "(" DagArg [DagArgList] ")"1118 if (Tok->is(tok::l_paren)) {1119 Tok->setType(TT_TableGenDAGArgOpener);1120 // Nested DAGArg requires space before '(' as separator.1121 if (Contexts.back().IsTableGenDAGArgList)1122 Tok->SpacesRequiredBefore = 1;1123 return parseTableGenDAGArgAndList(Tok);1124 }1125 // SimpleValue 9: Bang operator1126 if (Tok->is(TT_TableGenBangOperator)) {1127 if (CurrentToken && CurrentToken->is(tok::less)) {1128 CurrentToken->setType(TT_TemplateOpener);1129 skipToNextNonComment();1130 if (!parseAngle())1131 return false;1132 }1133 if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1134 return false;1135 next();1136 // FIXME: Hack using inheritance to child context1137 Contexts.back().IsTableGenBangOpe = true;1138 bool Result = parseParens();1139 Contexts.back().IsTableGenBangOpe = false;1140 return Result;1141 }1142 // SimpleValue 9: Cond operator1143 if (Tok->is(TT_TableGenCondOperator)) {1144 if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1145 return false;1146 next();1147 return parseParens();1148 }1149 // We have to check identifier at the last because the kind of bang/cond1150 // operators are also identifier.1151 // SimpleValue 7: Identifiers1152 if (Tok->is(tok::identifier)) {1153 // SimpleValue 8: Anonymous record1154 if (CurrentToken && CurrentToken->is(tok::less)) {1155 CurrentToken->setType(TT_TemplateOpener);1156 skipToNextNonComment();1157 return parseAngle();1158 }1159 return true;1160 }1161 1162 return false;1163 }1164 1165 bool couldBeInStructArrayInitializer() const {1166 if (Contexts.size() < 2)1167 return false;1168 // We want to back up no more then 2 context levels i.e.1169 // . { { <-1170 const auto End = std::next(Contexts.rbegin(), 2);1171 auto Last = Contexts.rbegin();1172 unsigned Depth = 0;1173 for (; Last != End; ++Last)1174 if (Last->ContextKind == tok::l_brace)1175 ++Depth;1176 return Depth == 2 && Last->ContextKind != tok::l_brace;1177 }1178 1179 bool parseBrace() {1180 if (!CurrentToken)1181 return true;1182 1183 assert(CurrentToken->Previous);1184 FormatToken &OpeningBrace = *CurrentToken->Previous;1185 assert(OpeningBrace.is(tok::l_brace));1186 OpeningBrace.ParentBracket = Contexts.back().ContextKind;1187 1188 if (Contexts.back().CaretFound)1189 OpeningBrace.overwriteFixedType(TT_ObjCBlockLBrace);1190 Contexts.back().CaretFound = false;1191 1192 ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);1193 Contexts.back().ColonIsDictLiteral = true;1194 if (OpeningBrace.is(BK_BracedInit))1195 Contexts.back().IsExpression = true;1196 if (Style.isJavaScript() && OpeningBrace.Previous &&1197 OpeningBrace.Previous->is(TT_JsTypeColon)) {1198 Contexts.back().IsExpression = false;1199 }1200 if (Style.isVerilog() &&1201 (!OpeningBrace.getPreviousNonComment() ||1202 OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) {1203 Contexts.back().VerilogMayBeConcatenation = true;1204 }1205 if (Style.isTableGen())1206 Contexts.back().ColonIsDictLiteral = false;1207 1208 unsigned CommaCount = 0;1209 while (CurrentToken) {1210 if (CurrentToken->is(tok::r_brace)) {1211 assert(!Scopes.empty());1212 assert(Scopes.back() == getScopeType(OpeningBrace));1213 Scopes.pop_back();1214 assert(OpeningBrace.Optional == CurrentToken->Optional);1215 OpeningBrace.MatchingParen = CurrentToken;1216 CurrentToken->MatchingParen = &OpeningBrace;1217 if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {1218 if (OpeningBrace.ParentBracket == tok::l_brace &&1219 couldBeInStructArrayInitializer() && CommaCount > 0) {1220 Contexts.back().ContextType = Context::StructArrayInitializer;1221 }1222 }1223 next();1224 return true;1225 }1226 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))1227 return false;1228 updateParameterCount(&OpeningBrace, CurrentToken);1229 if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {1230 FormatToken *Previous = CurrentToken->getPreviousNonComment();1231 if (Previous->is(TT_JsTypeOptionalQuestion))1232 Previous = Previous->getPreviousNonComment();1233 if ((CurrentToken->is(tok::colon) && !Style.isTableGen() &&1234 (!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||1235 Style.isProto()) {1236 OpeningBrace.setType(TT_DictLiteral);1237 if (Previous->Tok.getIdentifierInfo() ||1238 Previous->is(tok::string_literal)) {1239 Previous->setType(TT_SelectorName);1240 }1241 }1242 if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) &&1243 !Style.isTableGen()) {1244 OpeningBrace.setType(TT_DictLiteral);1245 } else if (Style.isJavaScript()) {1246 OpeningBrace.overwriteFixedType(TT_DictLiteral);1247 }1248 }1249 if (CurrentToken->is(tok::comma)) {1250 if (Style.isJavaScript())1251 OpeningBrace.overwriteFixedType(TT_DictLiteral);1252 ++CommaCount;1253 }1254 if (!consumeToken())1255 return false;1256 }1257 return true;1258 }1259 1260 void updateParameterCount(FormatToken *Left, FormatToken *Current) {1261 // For ObjC methods, the number of parameters is calculated differently as1262 // method declarations have a different structure (the parameters are not1263 // inside a bracket scope).1264 if (Current->is(tok::l_brace) && Current->is(BK_Block))1265 ++Left->BlockParameterCount;1266 if (Current->is(tok::comma)) {1267 ++Left->ParameterCount;1268 if (!Left->Role)1269 Left->Role.reset(new CommaSeparatedList(Style));1270 Left->Role->CommaFound(Current);1271 } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {1272 Left->ParameterCount = 1;1273 }1274 }1275 1276 bool parseConditional() {1277 while (CurrentToken) {1278 if (CurrentToken->is(tok::colon) && CurrentToken->is(TT_Unknown)) {1279 CurrentToken->setType(TT_ConditionalExpr);1280 next();1281 return true;1282 }1283 if (!consumeToken())1284 return false;1285 }1286 return false;1287 }1288 1289 bool parseTemplateDeclaration() {1290 if (!CurrentToken || CurrentToken->isNot(tok::less))1291 return false;1292 1293 CurrentToken->setType(TT_TemplateOpener);1294 next();1295 1296 TemplateDeclarationDepth++;1297 const bool WellFormed = parseAngle();1298 TemplateDeclarationDepth--;1299 if (!WellFormed)1300 return false;1301 1302 if (CurrentToken && TemplateDeclarationDepth == 0)1303 CurrentToken->Previous->ClosesTemplateDeclaration = true;1304 1305 return true;1306 }1307 1308 bool consumeToken() {1309 if (IsCpp) {1310 const auto *Prev = CurrentToken->getPreviousNonComment();1311 if (Prev && Prev->is(TT_AttributeRSquare) &&1312 CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case,1313 tok::kw_default, tok::kw_for, tok::kw_while) &&1314 mustBreakAfterAttributes(*CurrentToken, Style)) {1315 CurrentToken->MustBreakBefore = true;1316 }1317 }1318 FormatToken *Tok = CurrentToken;1319 next();1320 // In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal1321 // operators.1322 if (Tok->is(TT_VerilogTableItem))1323 return true;1324 // Multi-line string itself is a single annotated token.1325 if (Tok->is(TT_TableGenMultiLineString))1326 return true;1327 auto *Prev = Tok->getPreviousNonComment();1328 auto *Next = Tok->getNextNonComment();1329 switch (bool IsIf = false; Tok->Tok.getKind()) {1330 case tok::plus:1331 case tok::minus:1332 if (!Prev && Line.MustBeDeclaration)1333 Tok->setType(TT_ObjCMethodSpecifier);1334 break;1335 case tok::colon:1336 if (!Prev)1337 return false;1338 // Goto labels and case labels are already identified in1339 // UnwrappedLineParser.1340 if (Tok->isTypeFinalized())1341 break;1342 // Colons from ?: are handled in parseConditional().1343 if (Style.isJavaScript()) {1344 if (Contexts.back().ColonIsForRangeExpr || // colon in for loop1345 (Contexts.size() == 1 && // switch/case labels1346 Line.First->isNoneOf(tok::kw_enum, tok::kw_case)) ||1347 Contexts.back().ContextKind == tok::l_paren || // function params1348 Contexts.back().ContextKind == tok::l_square || // array type1349 (!Contexts.back().IsExpression &&1350 Contexts.back().ContextKind == tok::l_brace) || // object type1351 (Contexts.size() == 1 &&1352 Line.MustBeDeclaration)) { // method/property declaration1353 Contexts.back().IsExpression = false;1354 Tok->setType(TT_JsTypeColon);1355 break;1356 }1357 } else if (Style.isCSharp()) {1358 if (Contexts.back().InCSharpAttributeSpecifier) {1359 Tok->setType(TT_AttributeColon);1360 break;1361 }1362 if (Contexts.back().ContextKind == tok::l_paren) {1363 Tok->setType(TT_CSharpNamedArgumentColon);1364 break;1365 }1366 } else if (Style.isVerilog() && Tok->isNot(TT_BinaryOperator)) {1367 // The distribution weight operators are labeled1368 // TT_BinaryOperator by the lexer.1369 if (Keywords.isVerilogEnd(*Prev) || Keywords.isVerilogBegin(*Prev)) {1370 Tok->setType(TT_VerilogBlockLabelColon);1371 } else if (Contexts.back().ContextKind == tok::l_square) {1372 Tok->setType(TT_BitFieldColon);1373 } else if (Contexts.back().ColonIsDictLiteral) {1374 Tok->setType(TT_DictLiteral);1375 } else if (Contexts.size() == 1) {1376 // In Verilog a case label doesn't have the case keyword. We1377 // assume a colon following an expression is a case label.1378 // Colons from ?: are annotated in parseConditional().1379 Tok->setType(TT_CaseLabelColon);1380 if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))1381 --Line.Level;1382 }1383 break;1384 }1385 if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||1386 Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||1387 Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {1388 Tok->setType(TT_ModulePartitionColon);1389 } else if (Line.First->is(tok::kw_asm)) {1390 Tok->setType(TT_InlineASMColon);1391 } else if (Contexts.back().ColonIsDictLiteral || Style.isProto()) {1392 Tok->setType(TT_DictLiteral);1393 if (Style.isTextProto())1394 Prev->setType(TT_SelectorName);1395 } else if (Contexts.back().ColonIsObjCMethodExpr ||1396 Line.startsWith(TT_ObjCMethodSpecifier)) {1397 Tok->setType(TT_ObjCMethodExpr);1398 const auto *PrevPrev = Prev->Previous;1399 // Ensure we tag all identifiers in method declarations as1400 // TT_SelectorName.1401 bool UnknownIdentifierInMethodDeclaration =1402 Line.startsWith(TT_ObjCMethodSpecifier) &&1403 Prev->is(tok::identifier) && Prev->is(TT_Unknown);1404 if (!PrevPrev ||1405 // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.1406 !(PrevPrev->is(TT_CastRParen) ||1407 (PrevPrev->is(TT_ObjCMethodExpr) && PrevPrev->is(tok::colon))) ||1408 PrevPrev->is(tok::r_square) ||1409 Contexts.back().LongestObjCSelectorName == 0 ||1410 UnknownIdentifierInMethodDeclaration) {1411 Prev->setType(TT_SelectorName);1412 if (!Contexts.back().FirstObjCSelectorName)1413 Contexts.back().FirstObjCSelectorName = Prev;1414 else if (Prev->ColumnWidth > Contexts.back().LongestObjCSelectorName)1415 Contexts.back().LongestObjCSelectorName = Prev->ColumnWidth;1416 Prev->ParameterIndex =1417 Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;1418 ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;1419 }1420 } else if (Contexts.back().ColonIsForRangeExpr) {1421 Tok->setType(TT_RangeBasedForLoopColon);1422 for (auto *Token = Prev;1423 Token && Token->isNoneOf(tok::semi, tok::l_paren);1424 Token = Token->Previous) {1425 if (Token->isPointerOrReference())1426 Token->setFinalizedType(TT_PointerOrReference);1427 }1428 } else if (Contexts.back().ContextType == Context::C11GenericSelection) {1429 Tok->setType(TT_GenericSelectionColon);1430 if (Prev->isPointerOrReference())1431 Prev->setFinalizedType(TT_PointerOrReference);1432 } else if ((CurrentToken && CurrentToken->is(tok::numeric_constant)) ||1433 (Prev->is(TT_StartOfName) && !Scopes.empty() &&1434 Scopes.back() == ST_Class)) {1435 Tok->setType(TT_BitFieldColon);1436 } else if (Contexts.size() == 1 &&1437 Line.getFirstNonComment()->isNoneOf(tok::kw_enum, tok::kw_case,1438 tok::kw_default) &&1439 !Line.startsWith(tok::kw_typedef, tok::kw_enum)) {1440 if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept) ||1441 Prev->ClosesRequiresClause) {1442 Tok->setType(TT_CtorInitializerColon);1443 } else if (Prev->is(tok::kw_try)) {1444 // Member initializer list within function try block.1445 FormatToken *PrevPrev = Prev->getPreviousNonComment();1446 if (!PrevPrev)1447 break;1448 if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))1449 Tok->setType(TT_CtorInitializerColon);1450 } else {1451 Tok->setType(TT_InheritanceColon);1452 if (Prev->isAccessSpecifierKeyword())1453 Line.Type = LT_AccessModifier;1454 }1455 } else if (canBeObjCSelectorComponent(*Prev) && Next &&1456 (Next->isOneOf(tok::r_paren, tok::comma) ||1457 (canBeObjCSelectorComponent(*Next) && Next->Next &&1458 Next->Next->is(tok::colon)))) {1459 // This handles a special macro in ObjC code where selectors including1460 // the colon are passed as macro arguments.1461 Tok->setType(TT_ObjCSelector);1462 }1463 break;1464 case tok::pipe:1465 case tok::amp:1466 // | and & in declarations/type expressions represent union and1467 // intersection types, respectively.1468 if (Style.isJavaScript() && !Contexts.back().IsExpression)1469 Tok->setType(TT_JsTypeOperator);1470 break;1471 case tok::kw_if:1472 if (Style.isTableGen()) {1473 // In TableGen it has the form 'if' <value> 'then'.1474 if (!parseTableGenValue())1475 return false;1476 if (CurrentToken && CurrentToken->is(Keywords.kw_then))1477 next(); // skip then1478 break;1479 }1480 if (CurrentToken &&1481 CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {1482 next();1483 }1484 IsIf = true;1485 [[fallthrough]];1486 case tok::kw_while:1487 if (CurrentToken && CurrentToken->is(tok::l_paren)) {1488 next();1489 if (!parseParens(IsIf))1490 return false;1491 }1492 break;1493 case tok::kw_for:1494 if (Style.isJavaScript()) {1495 // x.for and {for: ...}1496 if ((Prev && Prev->is(tok::period)) || (Next && Next->is(tok::colon)))1497 break;1498 // JS' for await ( ...1499 if (CurrentToken && CurrentToken->is(Keywords.kw_await))1500 next();1501 }1502 if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await))1503 next();1504 Contexts.back().ColonIsForRangeExpr = true;1505 if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1506 return false;1507 next();1508 if (!parseParens())1509 return false;1510 break;1511 case tok::l_paren:1512 // When faced with 'operator()()', the kw_operator handler incorrectly1513 // marks the first l_paren as a OverloadedOperatorLParen. Here, we make1514 // the first two parens OverloadedOperators and the second l_paren an1515 // OverloadedOperatorLParen.1516 if (Prev && Prev->is(tok::r_paren) && Prev->MatchingParen &&1517 Prev->MatchingParen->is(TT_OverloadedOperatorLParen)) {1518 Prev->setType(TT_OverloadedOperator);1519 Prev->MatchingParen->setType(TT_OverloadedOperator);1520 Tok->setType(TT_OverloadedOperatorLParen);1521 }1522 1523 if (Style.isVerilog()) {1524 // Identify the parameter list and port list in a module instantiation.1525 // This is still needed when we already have1526 // UnwrappedLineParser::parseVerilogHierarchyHeader because that1527 // function is only responsible for the definition, not the1528 // instantiation.1529 auto IsInstancePort = [&]() {1530 const FormatToken *PrevPrev;1531 // In the following example all 4 left parentheses will be treated as1532 // 'TT_VerilogInstancePortLParen'.1533 //1534 // module_x instance_1(port_1); // Case A.1535 // module_x #(parameter_1) // Case B.1536 // instance_2(port_1), // Case C.1537 // instance_3(port_1); // Case D.1538 if (!Prev || !(PrevPrev = Prev->getPreviousNonComment()))1539 return false;1540 // Case A.1541 if (Keywords.isVerilogIdentifier(*Prev) &&1542 Keywords.isVerilogIdentifier(*PrevPrev)) {1543 return true;1544 }1545 // Case B.1546 if (Prev->is(Keywords.kw_verilogHash) &&1547 Keywords.isVerilogIdentifier(*PrevPrev)) {1548 return true;1549 }1550 // Case C.1551 if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::r_paren))1552 return true;1553 // Case D.1554 if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::comma)) {1555 const FormatToken *PrevParen = PrevPrev->getPreviousNonComment();1556 if (PrevParen && PrevParen->is(tok::r_paren) &&1557 PrevParen->MatchingParen &&1558 PrevParen->MatchingParen->is(TT_VerilogInstancePortLParen)) {1559 return true;1560 }1561 }1562 return false;1563 };1564 1565 if (IsInstancePort())1566 Tok->setType(TT_VerilogInstancePortLParen);1567 }1568 1569 if (!parseParens())1570 return false;1571 if (Line.MustBeDeclaration && Contexts.size() == 1 &&1572 !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&1573 !Line.startsWith(tok::l_paren) &&1574 Tok->isNoneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {1575 if (!Prev ||1576 (!Prev->isAttribute() &&1577 Prev->isNoneOf(TT_RequiresClause, TT_LeadingJavaAnnotation,1578 TT_BinaryOperator))) {1579 Line.MightBeFunctionDecl = true;1580 Tok->MightBeFunctionDeclParen = true;1581 }1582 }1583 break;1584 case tok::l_square:1585 if (Style.isTableGen())1586 Tok->setType(TT_TableGenListOpener);1587 if (!parseSquare())1588 return false;1589 break;1590 case tok::l_brace:1591 if (IsCpp) {1592 if (Tok->is(TT_RequiresExpressionLBrace))1593 Line.Type = LT_RequiresExpression;1594 } else if (Style.isTextProto()) {1595 if (Prev && Prev->isNot(TT_DictLiteral))1596 Prev->setType(TT_SelectorName);1597 }1598 Scopes.push_back(getScopeType(*Tok));1599 if (!parseBrace())1600 return false;1601 break;1602 case tok::less:1603 if (parseAngle()) {1604 Tok->setType(TT_TemplateOpener);1605 // In TT_Proto, we must distignuish between:1606 // map<key, value>1607 // msg < item: data >1608 // msg: < item: data >1609 // In TT_TextProto, map<key, value> does not occur.1610 if (Style.isTextProto() ||1611 (Style.Language == FormatStyle::LK_Proto && Prev &&1612 Prev->isOneOf(TT_SelectorName, TT_DictLiteral))) {1613 Tok->setType(TT_DictLiteral);1614 if (Prev && Prev->isNot(TT_DictLiteral))1615 Prev->setType(TT_SelectorName);1616 }1617 if (Style.isTableGen())1618 Tok->setType(TT_TemplateOpener);1619 } else {1620 Tok->setType(TT_BinaryOperator);1621 NonTemplateLess.insert(Tok);1622 CurrentToken = Tok;1623 next();1624 }1625 break;1626 case tok::r_paren:1627 case tok::r_square:1628 return false;1629 case tok::r_brace:1630 // Don't pop scope when encountering unbalanced r_brace.1631 if (!Scopes.empty())1632 Scopes.pop_back();1633 // Lines can start with '}'.1634 if (Prev)1635 return false;1636 break;1637 case tok::greater:1638 if (!Style.isTextProto() && Tok->is(TT_Unknown))1639 Tok->setType(TT_BinaryOperator);1640 if (Prev && Prev->is(TT_TemplateCloser))1641 Tok->SpacesRequiredBefore = 1;1642 break;1643 case tok::kw_operator:1644 if (Style.isProto())1645 break;1646 // Handle C++ user-defined conversion function.1647 if (IsCpp && CurrentToken) {1648 const auto *Info = CurrentToken->Tok.getIdentifierInfo();1649 // What follows Tok is an identifier or a non-operator keyword.1650 if (Info && !(CurrentToken->isPlacementOperator() ||1651 CurrentToken->is(tok::kw_co_await) ||1652 Info->isCPlusPlusOperatorKeyword())) {1653 FormatToken *LParen;1654 if (CurrentToken->startsSequence(tok::kw_decltype, tok::l_paren,1655 tok::kw_auto, tok::r_paren)) {1656 // Skip `decltype(auto)`.1657 LParen = CurrentToken->Next->Next->Next->Next;1658 } else {1659 // Skip to l_paren.1660 for (LParen = CurrentToken->Next;1661 LParen && LParen->isNot(tok::l_paren); LParen = LParen->Next) {1662 if (LParen->isPointerOrReference())1663 LParen->setFinalizedType(TT_PointerOrReference);1664 }1665 }1666 if (LParen && LParen->is(tok::l_paren)) {1667 if (!Contexts.back().IsExpression) {1668 Tok->setFinalizedType(TT_FunctionDeclarationName);1669 LParen->setFinalizedType(TT_FunctionDeclarationLParen);1670 }1671 break;1672 }1673 }1674 }1675 while (CurrentToken &&1676 CurrentToken->isNoneOf(tok::l_paren, tok::semi, tok::r_paren)) {1677 if (CurrentToken->isOneOf(tok::star, tok::amp))1678 CurrentToken->setType(TT_PointerOrReference);1679 auto Next = CurrentToken->getNextNonComment();1680 if (!Next)1681 break;1682 if (Next->is(tok::less))1683 next();1684 else1685 consumeToken();1686 if (!CurrentToken)1687 break;1688 auto Previous = CurrentToken->getPreviousNonComment();1689 assert(Previous);1690 if (CurrentToken->is(tok::comma) && Previous->isNot(tok::kw_operator))1691 break;1692 if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator, tok::comma,1693 tok::arrow) ||1694 Previous->isPointerOrReference() ||1695 // User defined literal.1696 Previous->TokenText.starts_with("\"\"")) {1697 Previous->setType(TT_OverloadedOperator);1698 if (CurrentToken->isOneOf(tok::less, tok::greater))1699 break;1700 }1701 }1702 if (CurrentToken && CurrentToken->is(tok::l_paren))1703 CurrentToken->setType(TT_OverloadedOperatorLParen);1704 if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))1705 CurrentToken->Previous->setType(TT_OverloadedOperator);1706 break;1707 case tok::question:1708 if (Style.isJavaScript() && Next &&1709 Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,1710 tok::r_brace, tok::r_square)) {1711 // Question marks before semicolons, colons, etc. indicate optional1712 // types (fields, parameters), e.g.1713 // function(x?: string, y?) {...}1714 // class X { y?; }1715 Tok->setType(TT_JsTypeOptionalQuestion);1716 break;1717 }1718 // Declarations cannot be conditional expressions, this can only be part1719 // of a type declaration.1720 if (Line.MustBeDeclaration && !Contexts.back().IsExpression &&1721 Style.isJavaScript()) {1722 break;1723 }1724 if (Style.isCSharp()) {1725 // `Type?)`, `Type?>`, `Type? name;`, and `Type? name =` can only be1726 // nullable types.1727 if (Next && (Next->isOneOf(tok::r_paren, tok::greater) ||1728 Next->startsSequence(tok::identifier, tok::semi) ||1729 Next->startsSequence(tok::identifier, tok::equal))) {1730 Tok->setType(TT_CSharpNullable);1731 break;1732 }1733 1734 // Line.MustBeDeclaration will be true for `Type? name;`.1735 // But not1736 // cond ? "A" : "B";1737 // cond ? id : "B";1738 // cond ? cond2 ? "A" : "B" : "C";1739 if (!Contexts.back().IsExpression && Line.MustBeDeclaration &&1740 (!Next || Next->isNoneOf(tok::identifier, tok::string_literal) ||1741 !Next->Next || Next->Next->isNoneOf(tok::colon, tok::question))) {1742 Tok->setType(TT_CSharpNullable);1743 break;1744 }1745 }1746 parseConditional();1747 break;1748 case tok::kw_template:1749 parseTemplateDeclaration();1750 break;1751 case tok::comma:1752 switch (Contexts.back().ContextType) {1753 case Context::CtorInitializer:1754 Tok->setType(TT_CtorInitializerComma);1755 break;1756 case Context::InheritanceList:1757 Tok->setType(TT_InheritanceComma);1758 break;1759 case Context::VerilogInstancePortList:1760 Tok->setType(TT_VerilogInstancePortComma);1761 break;1762 default:1763 if (Style.isVerilog() && Contexts.size() == 1 &&1764 Line.startsWith(Keywords.kw_assign)) {1765 Tok->setFinalizedType(TT_VerilogAssignComma);1766 } else if (Contexts.back().FirstStartOfName &&1767 (Contexts.size() == 1 || startsWithInitStatement(Line))) {1768 Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;1769 Line.IsMultiVariableDeclStmt = true;1770 }1771 break;1772 }1773 if (Contexts.back().ContextType == Context::ForEachMacro)1774 Contexts.back().IsExpression = true;1775 break;1776 case tok::kw_default:1777 // Unindent case labels.1778 if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) &&1779 (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) {1780 --Line.Level;1781 }1782 break;1783 case tok::identifier:1784 if (Tok->isOneOf(Keywords.kw___has_include,1785 Keywords.kw___has_include_next)) {1786 parseHasInclude();1787 }1788 if (IsCpp) {1789 if (Next && Next->is(tok::l_paren) && Prev &&1790 Prev->isOneOf(tok::kw___cdecl, tok::kw___stdcall,1791 tok::kw___fastcall, tok::kw___thiscall,1792 tok::kw___regcall, tok::kw___vectorcall)) {1793 Tok->setFinalizedType(TT_FunctionDeclarationName);1794 Next->setFinalizedType(TT_FunctionDeclarationLParen);1795 }1796 } else if (Style.isCSharp()) {1797 if (Tok->is(Keywords.kw_where) && Next && Next->isNot(tok::l_paren)) {1798 Tok->setType(TT_CSharpGenericTypeConstraint);1799 parseCSharpGenericTypeConstraint();1800 if (!Prev)1801 Line.IsContinuation = true;1802 }1803 } else if (Style.isTableGen()) {1804 if (Tok->is(Keywords.kw_assert)) {1805 if (!parseTableGenValue())1806 return false;1807 } else if (Tok->isOneOf(Keywords.kw_def, Keywords.kw_defm) &&1808 (!Next || Next->isNoneOf(tok::colon, tok::l_brace))) {1809 // The case NameValue appears.1810 if (!parseTableGenValue(true))1811 return false;1812 }1813 }1814 if (Style.AllowBreakBeforeQtProperty &&1815 Contexts.back().ContextType == Context::QtProperty &&1816 Tok->isQtProperty()) {1817 Tok->setFinalizedType(TT_QtProperty);1818 }1819 break;1820 case tok::arrow:1821 if (Tok->isNot(TT_LambdaArrow) && Prev && Prev->is(tok::kw_noexcept))1822 Tok->setType(TT_TrailingReturnArrow);1823 break;1824 case tok::equal:1825 // In TableGen, there must be a value after "=";1826 if (Style.isTableGen() && !parseTableGenValue())1827 return false;1828 break;1829 default:1830 break;1831 }1832 return true;1833 }1834 1835 void parseCSharpGenericTypeConstraint() {1836 int OpenAngleBracketsCount = 0;1837 while (CurrentToken) {1838 if (CurrentToken->is(tok::less)) {1839 // parseAngle is too greedy and will consume the whole line.1840 CurrentToken->setType(TT_TemplateOpener);1841 ++OpenAngleBracketsCount;1842 next();1843 } else if (CurrentToken->is(tok::greater)) {1844 CurrentToken->setType(TT_TemplateCloser);1845 --OpenAngleBracketsCount;1846 next();1847 } else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) {1848 // We allow line breaks after GenericTypeConstraintComma's1849 // so do not flag commas in Generics as GenericTypeConstraintComma's.1850 CurrentToken->setType(TT_CSharpGenericTypeConstraintComma);1851 next();1852 } else if (CurrentToken->is(Keywords.kw_where)) {1853 CurrentToken->setType(TT_CSharpGenericTypeConstraint);1854 next();1855 } else if (CurrentToken->is(tok::colon)) {1856 CurrentToken->setType(TT_CSharpGenericTypeConstraintColon);1857 next();1858 } else {1859 next();1860 }1861 }1862 }1863 1864 void parseIncludeDirective() {1865 if (CurrentToken && CurrentToken->is(tok::less)) {1866 next();1867 while (CurrentToken) {1868 // Mark tokens up to the trailing line comments as implicit string1869 // literals.1870 if (CurrentToken->isNot(tok::comment) &&1871 !CurrentToken->TokenText.starts_with("//")) {1872 CurrentToken->setType(TT_ImplicitStringLiteral);1873 }1874 next();1875 }1876 }1877 }1878 1879 void parseWarningOrError() {1880 next();1881 // We still want to format the whitespace left of the first token of the1882 // warning or error.1883 next();1884 while (CurrentToken) {1885 CurrentToken->setType(TT_ImplicitStringLiteral);1886 next();1887 }1888 }1889 1890 void parsePragma() {1891 next(); // Consume "pragma".1892 if (CurrentToken &&1893 CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option,1894 Keywords.kw_region)) {1895 bool IsMarkOrRegion =1896 CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_region);1897 next();1898 next(); // Consume first token (so we fix leading whitespace).1899 while (CurrentToken) {1900 if (IsMarkOrRegion || CurrentToken->Previous->is(TT_BinaryOperator))1901 CurrentToken->setType(TT_ImplicitStringLiteral);1902 next();1903 }1904 }1905 }1906 1907 void parseHasInclude() {1908 if (!CurrentToken || CurrentToken->isNot(tok::l_paren))1909 return;1910 next(); // '('1911 parseIncludeDirective();1912 next(); // ')'1913 }1914 1915 LineType parsePreprocessorDirective() {1916 bool IsFirstToken = CurrentToken->IsFirst;1917 LineType Type = LT_PreprocessorDirective;1918 next();1919 if (!CurrentToken)1920 return Type;1921 1922 if (Style.isJavaScript() && IsFirstToken) {1923 // JavaScript files can contain shebang lines of the form:1924 // #!/usr/bin/env node1925 // Treat these like C++ #include directives.1926 while (CurrentToken) {1927 // Tokens cannot be comments here.1928 CurrentToken->setType(TT_ImplicitStringLiteral);1929 next();1930 }1931 return LT_ImportStatement;1932 }1933 1934 if (CurrentToken->is(tok::numeric_constant)) {1935 CurrentToken->SpacesRequiredBefore = 1;1936 return Type;1937 }1938 // Hashes in the middle of a line can lead to any strange token1939 // sequence.1940 if (!CurrentToken->Tok.getIdentifierInfo())1941 return Type;1942 // In Verilog macro expansions start with a backtick just like preprocessor1943 // directives. Thus we stop if the word is not a preprocessor directive.1944 if (Style.isVerilog() && !Keywords.isVerilogPPDirective(*CurrentToken))1945 return LT_Invalid;1946 switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {1947 case tok::pp_include:1948 case tok::pp_include_next:1949 case tok::pp_import:1950 next();1951 parseIncludeDirective();1952 Type = LT_ImportStatement;1953 break;1954 case tok::pp_error:1955 case tok::pp_warning:1956 parseWarningOrError();1957 break;1958 case tok::pp_pragma:1959 parsePragma();1960 break;1961 case tok::pp_if:1962 case tok::pp_elif:1963 Contexts.back().IsExpression = true;1964 next();1965 if (CurrentToken)1966 CurrentToken->SpacesRequiredBefore = 1;1967 parseLine();1968 break;1969 default:1970 break;1971 }1972 while (CurrentToken) {1973 FormatToken *Tok = CurrentToken;1974 next();1975 if (Tok->is(tok::l_paren)) {1976 parseParens();1977 } else if (Tok->isOneOf(Keywords.kw___has_include,1978 Keywords.kw___has_include_next)) {1979 parseHasInclude();1980 }1981 }1982 return Type;1983 }1984 1985public:1986 LineType parseLine() {1987 if (!CurrentToken)1988 return LT_Invalid;1989 NonTemplateLess.clear();1990 if (!Line.InMacroBody && CurrentToken->is(tok::hash)) {1991 // We were not yet allowed to use C++17 optional when this was being1992 // written. So we used LT_Invalid to mark that the line is not a1993 // preprocessor directive.1994 auto Type = parsePreprocessorDirective();1995 if (Type != LT_Invalid)1996 return Type;1997 }1998 1999 // Directly allow to 'import <string-literal>' to support protocol buffer2000 // definitions (github.com/google/protobuf) or missing "#" (either way we2001 // should not break the line).2002 IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();2003 if ((Style.isJava() && CurrentToken->is(Keywords.kw_package)) ||2004 (!Style.isVerilog() && Info &&2005 Info->getPPKeywordID() == tok::pp_import && CurrentToken->Next &&2006 CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier,2007 tok::kw_static))) {2008 next();2009 parseIncludeDirective();2010 return LT_ImportStatement;2011 }2012 2013 // If this line starts and ends in '<' and '>', respectively, it is likely2014 // part of "#define <a/b.h>".2015 if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) {2016 parseIncludeDirective();2017 return LT_ImportStatement;2018 }2019 2020 // In .proto files, top-level options and package statements are very2021 // similar to import statements and should not be line-wrapped.2022 if (Style.Language == FormatStyle::LK_Proto && Line.Level == 0 &&2023 CurrentToken->isOneOf(Keywords.kw_option, Keywords.kw_package)) {2024 next();2025 if (CurrentToken && CurrentToken->is(tok::identifier)) {2026 while (CurrentToken)2027 next();2028 return LT_ImportStatement;2029 }2030 }2031 2032 bool KeywordVirtualFound = false;2033 bool ImportStatement = false;2034 2035 // import {...} from '...';2036 if (Style.isJavaScript() && CurrentToken->is(Keywords.kw_import))2037 ImportStatement = true;2038 2039 while (CurrentToken) {2040 if (CurrentToken->is(tok::kw_virtual))2041 KeywordVirtualFound = true;2042 if (Style.isJavaScript()) {2043 // export {...} from '...';2044 // An export followed by "from 'some string';" is a re-export from2045 // another module identified by a URI and is treated as a2046 // LT_ImportStatement (i.e. prevent wraps on it for long URIs).2047 // Just "export {...};" or "export class ..." should not be treated as2048 // an import in this sense.2049 if (Line.First->is(tok::kw_export) &&2050 CurrentToken->is(Keywords.kw_from) && CurrentToken->Next &&2051 CurrentToken->Next->isStringLiteral()) {2052 ImportStatement = true;2053 }2054 if (isClosureImportStatement(*CurrentToken))2055 ImportStatement = true;2056 }2057 if (!consumeToken())2058 return LT_Invalid;2059 }2060 if (const auto Type = Line.Type; Type == LT_AccessModifier ||2061 Type == LT_RequiresExpression ||2062 Type == LT_SimpleRequirement) {2063 return Type;2064 }2065 if (KeywordVirtualFound)2066 return LT_VirtualFunctionDecl;2067 if (ImportStatement)2068 return LT_ImportStatement;2069 2070 if (Line.startsWith(TT_ObjCMethodSpecifier)) {2071 if (Contexts.back().FirstObjCSelectorName) {2072 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =2073 Contexts.back().LongestObjCSelectorName;2074 }2075 return LT_ObjCMethodDecl;2076 }2077 2078 for (const auto &ctx : Contexts)2079 if (ctx.ContextType == Context::StructArrayInitializer)2080 return LT_ArrayOfStructInitializer;2081 2082 return LT_Other;2083 }2084 2085private:2086 bool isClosureImportStatement(const FormatToken &Tok) {2087 // FIXME: Closure-library specific stuff should not be hard-coded but be2088 // configurable.2089 return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&2090 Tok.Next->Next &&2091 (Tok.Next->Next->TokenText == "module" ||2092 Tok.Next->Next->TokenText == "provide" ||2093 Tok.Next->Next->TokenText == "require" ||2094 Tok.Next->Next->TokenText == "requireType" ||2095 Tok.Next->Next->TokenText == "forwardDeclare") &&2096 Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);2097 }2098 2099 void resetTokenMetadata() {2100 if (!CurrentToken)2101 return;2102 2103 // Reset token type in case we have already looked at it and then2104 // recovered from an error (e.g. failure to find the matching >).2105 if (!CurrentToken->isTypeFinalized() &&2106 CurrentToken->isNoneOf(2107 TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro,2108 TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,2109 TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,2110 TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,2111 TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,2112 TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro,2113 TT_FunctionLikeOrFreestandingMacro, TT_ClassLBrace, TT_EnumLBrace,2114 TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,2115 TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,2116 TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,2117 TT_CompoundRequirementLBrace, TT_BracedListLBrace,2118 TT_FunctionLikeMacro)) {2119 CurrentToken->setType(TT_Unknown);2120 }2121 CurrentToken->Role.reset();2122 CurrentToken->MatchingParen = nullptr;2123 CurrentToken->FakeLParens.clear();2124 CurrentToken->FakeRParens = 0;2125 }2126 2127 void next() {2128 if (!CurrentToken)2129 return;2130 2131 CurrentToken->NestingLevel = Contexts.size() - 1;2132 CurrentToken->BindingStrength = Contexts.back().BindingStrength;2133 modifyContext(*CurrentToken);2134 determineTokenType(*CurrentToken);2135 CurrentToken = CurrentToken->Next;2136 2137 resetTokenMetadata();2138 }2139 2140 /// A struct to hold information valid in a specific context, e.g.2141 /// a pair of parenthesis.2142 struct Context {2143 Context(tok::TokenKind ContextKind, unsigned BindingStrength,2144 bool IsExpression)2145 : ContextKind(ContextKind), BindingStrength(BindingStrength),2146 IsExpression(IsExpression) {}2147 2148 tok::TokenKind ContextKind;2149 unsigned BindingStrength;2150 bool IsExpression;2151 unsigned LongestObjCSelectorName = 0;2152 bool ColonIsForRangeExpr = false;2153 bool ColonIsDictLiteral = false;2154 bool ColonIsObjCMethodExpr = false;2155 FormatToken *FirstObjCSelectorName = nullptr;2156 FormatToken *FirstStartOfName = nullptr;2157 bool CanBeExpression = true;2158 bool CaretFound = false;2159 bool InCpp11AttributeSpecifier = false;2160 bool InCSharpAttributeSpecifier = false;2161 bool InStaticAssertFirstArgument = false;2162 bool VerilogAssignmentFound = false;2163 // Whether the braces may mean concatenation instead of structure or array2164 // literal.2165 bool VerilogMayBeConcatenation = false;2166 bool IsTableGenDAGArgList = false;2167 bool IsTableGenBangOpe = false;2168 bool IsTableGenCondOpe = false;2169 enum {2170 Unknown,2171 // Like the part after `:` in a constructor.2172 // Context(...) : IsExpression(IsExpression)2173 CtorInitializer,2174 // Like in the parentheses in a foreach.2175 ForEachMacro,2176 // Like the inheritance list in a class declaration.2177 // class Input : public IO2178 InheritanceList,2179 // Like in the braced list.2180 // int x[] = {};2181 StructArrayInitializer,2182 // Like in `static_cast<int>`.2183 TemplateArgument,2184 // C11 _Generic selection.2185 C11GenericSelection,2186 QtProperty,2187 // Like in the outer parentheses in `ffnand ff1(.q());`.2188 VerilogInstancePortList,2189 } ContextType = Unknown;2190 };2191 2192 /// Puts a new \c Context onto the stack \c Contexts for the lifetime2193 /// of each instance.2194 struct ScopedContextCreator {2195 AnnotatingParser &P;2196 2197 ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,2198 unsigned Increase)2199 : P(P) {2200 P.Contexts.push_back(Context(ContextKind,2201 P.Contexts.back().BindingStrength + Increase,2202 P.Contexts.back().IsExpression));2203 }2204 2205 ~ScopedContextCreator() {2206 if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {2207 if (P.Contexts.back().ContextType == Context::StructArrayInitializer) {2208 P.Contexts.pop_back();2209 P.Contexts.back().ContextType = Context::StructArrayInitializer;2210 return;2211 }2212 }2213 P.Contexts.pop_back();2214 }2215 };2216 2217 void modifyContext(const FormatToken &Current) {2218 auto AssignmentStartsExpression = [&]() {2219 if (Current.getPrecedence() != prec::Assignment)2220 return false;2221 2222 if (Line.First->isOneOf(tok::kw_using, tok::kw_return))2223 return false;2224 if (Line.First->is(tok::kw_template)) {2225 assert(Current.Previous);2226 if (Current.Previous->is(tok::kw_operator)) {2227 // `template ... operator=` cannot be an expression.2228 return false;2229 }2230 2231 // `template` keyword can start a variable template.2232 const FormatToken *Tok = Line.First->getNextNonComment();2233 assert(Tok); // Current token is on the same line.2234 if (Tok->isNot(TT_TemplateOpener)) {2235 // Explicit template instantiations do not have `<>`.2236 return false;2237 }2238 2239 // This is the default value of a template parameter, determine if it's2240 // type or non-type.2241 if (Contexts.back().ContextKind == tok::less) {2242 assert(Current.Previous->Previous);2243 return Current.Previous->Previous->isNoneOf(tok::kw_typename,2244 tok::kw_class);2245 }2246 2247 Tok = Tok->MatchingParen;2248 if (!Tok)2249 return false;2250 Tok = Tok->getNextNonComment();2251 if (!Tok)2252 return false;2253 2254 if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct,2255 tok::kw_using)) {2256 return false;2257 }2258 2259 return true;2260 }2261 2262 // Type aliases use `type X = ...;` in TypeScript and can be exported2263 // using `export type ...`.2264 if (Style.isJavaScript() &&2265 (Line.startsWith(Keywords.kw_type, tok::identifier) ||2266 Line.startsWith(tok::kw_export, Keywords.kw_type,2267 tok::identifier))) {2268 return false;2269 }2270 2271 return !Current.Previous || Current.Previous->isNot(tok::kw_operator);2272 };2273 2274 if (AssignmentStartsExpression()) {2275 Contexts.back().IsExpression = true;2276 if (!Line.startsWith(TT_UnaryOperator)) {2277 for (FormatToken *Previous = Current.Previous;2278 Previous && Previous->Previous &&2279 Previous->Previous->isNoneOf(tok::comma, tok::semi);2280 Previous = Previous->Previous) {2281 if (Previous->isOneOf(tok::r_square, tok::r_paren, tok::greater)) {2282 Previous = Previous->MatchingParen;2283 if (!Previous)2284 break;2285 }2286 if (Previous->opensScope())2287 break;2288 if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&2289 Previous->isPointerOrReference() && Previous->Previous &&2290 Previous->Previous->isNot(tok::equal)) {2291 Previous->setType(TT_PointerOrReference);2292 }2293 }2294 }2295 } else if (Current.is(tok::lessless) &&2296 (!Current.Previous ||2297 Current.Previous->isNot(tok::kw_operator))) {2298 Contexts.back().IsExpression = true;2299 } else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {2300 Contexts.back().IsExpression = true;2301 } else if (Current.is(TT_TrailingReturnArrow)) {2302 Contexts.back().IsExpression = false;2303 } else if (Current.isOneOf(TT_LambdaArrow, Keywords.kw_assert)) {2304 Contexts.back().IsExpression = Style.isJava();2305 } else if (Current.Previous &&2306 Current.Previous->is(TT_CtorInitializerColon)) {2307 Contexts.back().IsExpression = true;2308 Contexts.back().ContextType = Context::CtorInitializer;2309 } else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) {2310 Contexts.back().ContextType = Context::InheritanceList;2311 } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {2312 for (FormatToken *Previous = Current.Previous;2313 Previous && Previous->isOneOf(tok::star, tok::amp);2314 Previous = Previous->Previous) {2315 Previous->setType(TT_PointerOrReference);2316 }2317 if (Line.MustBeDeclaration &&2318 Contexts.front().ContextType != Context::CtorInitializer) {2319 Contexts.back().IsExpression = false;2320 }2321 } else if (Current.is(tok::kw_new)) {2322 Contexts.back().CanBeExpression = false;2323 } else if (Current.is(tok::semi) ||2324 (Current.is(tok::exclaim) && Current.Previous &&2325 Current.Previous->isNot(tok::kw_operator))) {2326 // This should be the condition or increment in a for-loop.2327 // But not operator !() (can't use TT_OverloadedOperator here as its not2328 // been annotated yet).2329 Contexts.back().IsExpression = true;2330 }2331 }2332 2333 static FormatToken *untilMatchingParen(FormatToken *Current) {2334 // Used when `MatchingParen` is not yet established.2335 int ParenLevel = 0;2336 while (Current) {2337 if (Current->is(tok::l_paren))2338 ++ParenLevel;2339 if (Current->is(tok::r_paren))2340 --ParenLevel;2341 if (ParenLevel < 1)2342 break;2343 Current = Current->Next;2344 }2345 return Current;2346 }2347 2348 static bool isDeductionGuide(FormatToken &Current) {2349 // Look for a deduction guide template<T> A(...) -> A<...>;2350 if (Current.Previous && Current.Previous->is(tok::r_paren) &&2351 Current.startsSequence(tok::arrow, tok::identifier, tok::less)) {2352 // Find the TemplateCloser.2353 FormatToken *TemplateCloser = Current.Next->Next;2354 int NestingLevel = 0;2355 while (TemplateCloser) {2356 // Skip over an expressions in parens A<(3 < 2)>;2357 if (TemplateCloser->is(tok::l_paren)) {2358 // No Matching Paren yet so skip to matching paren2359 TemplateCloser = untilMatchingParen(TemplateCloser);2360 if (!TemplateCloser)2361 break;2362 }2363 if (TemplateCloser->is(tok::less))2364 ++NestingLevel;2365 if (TemplateCloser->is(tok::greater))2366 --NestingLevel;2367 if (NestingLevel < 1)2368 break;2369 TemplateCloser = TemplateCloser->Next;2370 }2371 // Assuming we have found the end of the template ensure its followed2372 // with a semi-colon.2373 if (TemplateCloser && TemplateCloser->Next &&2374 TemplateCloser->Next->is(tok::semi) &&2375 Current.Previous->MatchingParen) {2376 // Determine if the identifier `A` prior to the A<..>; is the same as2377 // prior to the A(..)2378 FormatToken *LeadingIdentifier =2379 Current.Previous->MatchingParen->Previous;2380 2381 return LeadingIdentifier &&2382 LeadingIdentifier->TokenText == Current.Next->TokenText;2383 }2384 }2385 return false;2386 }2387 2388 void determineTokenType(FormatToken &Current) {2389 if (Current.isNot(TT_Unknown)) {2390 // The token type is already known.2391 return;2392 }2393 2394 if ((Style.isJavaScript() || Style.isCSharp()) &&2395 Current.is(tok::exclaim)) {2396 if (Current.Previous) {2397 bool IsIdentifier =2398 Style.isJavaScript()2399 ? Keywords.isJavaScriptIdentifier(2400 *Current.Previous, /* AcceptIdentifierName= */ true)2401 : Current.Previous->is(tok::identifier);2402 if (IsIdentifier ||2403 Current.Previous->isOneOf(2404 tok::kw_default, tok::kw_namespace, tok::r_paren, tok::r_square,2405 tok::r_brace, tok::kw_false, tok::kw_true, Keywords.kw_type,2406 Keywords.kw_get, Keywords.kw_init, Keywords.kw_set) ||2407 Current.Previous->Tok.isLiteral()) {2408 Current.setType(TT_NonNullAssertion);2409 return;2410 }2411 }2412 if (Current.Next &&2413 Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {2414 Current.setType(TT_NonNullAssertion);2415 return;2416 }2417 }2418 2419 // Line.MightBeFunctionDecl can only be true after the parentheses of a2420 // function declaration have been found. In this case, 'Current' is a2421 // trailing token of this declaration and thus cannot be a name.2422 if ((Style.isJavaScript() || Style.isJava()) &&2423 Current.is(Keywords.kw_instanceof)) {2424 Current.setType(TT_BinaryOperator);2425 } else if (isStartOfName(Current) &&2426 (!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {2427 Contexts.back().FirstStartOfName = &Current;2428 Current.setType(TT_StartOfName);2429 } else if (Current.is(tok::semi)) {2430 // Reset FirstStartOfName after finding a semicolon so that a for loop2431 // with multiple increment statements is not confused with a for loop2432 // having multiple variable declarations.2433 Contexts.back().FirstStartOfName = nullptr;2434 } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {2435 AutoFound = true;2436 } else if (Current.is(tok::arrow) && Style.isJava()) {2437 Current.setType(TT_LambdaArrow);2438 } else if (Current.is(tok::arrow) && Style.isVerilog()) {2439 // The implication operator.2440 Current.setType(TT_BinaryOperator);2441 } else if (Current.is(tok::arrow) && AutoFound &&2442 Line.MightBeFunctionDecl && Current.NestingLevel == 0 &&2443 Current.Previous->isNoneOf(tok::kw_operator, tok::identifier)) {2444 // not auto operator->() -> xxx;2445 Current.setType(TT_TrailingReturnArrow);2446 } else if (Current.is(tok::arrow) && Current.Previous &&2447 Current.Previous->is(tok::r_brace) &&2448 Current.Previous->is(BK_Block)) {2449 // Concept implicit conversion constraint needs to be treated like2450 // a trailing return type ... } -> <type>.2451 Current.setType(TT_TrailingReturnArrow);2452 } else if (isDeductionGuide(Current)) {2453 // Deduction guides trailing arrow " A(...) -> A<T>;".2454 Current.setType(TT_TrailingReturnArrow);2455 } else if (Current.isPointerOrReference()) {2456 Current.setType(determineStarAmpUsage(2457 Current,2458 (Contexts.back().CanBeExpression && Contexts.back().IsExpression) ||2459 Contexts.back().InStaticAssertFirstArgument,2460 Contexts.back().ContextType == Context::TemplateArgument));2461 } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||2462 (Style.isVerilog() && Current.is(tok::pipe))) {2463 Current.setType(determinePlusMinusCaretUsage(Current));2464 if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))2465 Contexts.back().CaretFound = true;2466 } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {2467 Current.setType(determineIncrementUsage(Current));2468 } else if (Current.isOneOf(tok::exclaim, tok::tilde)) {2469 Current.setType(TT_UnaryOperator);2470 } else if (Current.is(tok::question)) {2471 if (Style.isJavaScript() && Line.MustBeDeclaration &&2472 !Contexts.back().IsExpression) {2473 // In JavaScript, `interface X { foo?(): bar; }` is an optional method2474 // on the interface, not a ternary expression.2475 Current.setType(TT_JsTypeOptionalQuestion);2476 } else if (Style.isTableGen()) {2477 // In TableGen, '?' is just an identifier like token.2478 Current.setType(TT_Unknown);2479 } else {2480 Current.setType(TT_ConditionalExpr);2481 }2482 } else if (Current.isBinaryOperator() &&2483 (!Current.Previous || Current.Previous->isNot(tok::l_square)) &&2484 (Current.isNot(tok::greater) && !Style.isTextProto())) {2485 if (Style.isVerilog()) {2486 if (Current.is(tok::lessequal) && Contexts.size() == 1 &&2487 !Contexts.back().VerilogAssignmentFound) {2488 // In Verilog `<=` is assignment if in its own statement. It is a2489 // statement instead of an expression, that is it can not be chained.2490 Current.ForcedPrecedence = prec::Assignment;2491 Current.setFinalizedType(TT_BinaryOperator);2492 }2493 if (Current.getPrecedence() == prec::Assignment)2494 Contexts.back().VerilogAssignmentFound = true;2495 }2496 Current.setType(TT_BinaryOperator);2497 } else if (Current.is(tok::comment)) {2498 if (Current.TokenText.starts_with("/*")) {2499 if (Current.TokenText.ends_with("*/")) {2500 Current.setType(TT_BlockComment);2501 } else {2502 // The lexer has for some reason determined a comment here. But we2503 // cannot really handle it, if it isn't properly terminated.2504 Current.Tok.setKind(tok::unknown);2505 }2506 } else {2507 Current.setType(TT_LineComment);2508 }2509 } else if (Current.is(tok::string_literal)) {2510 if (Style.isVerilog() && Contexts.back().VerilogMayBeConcatenation &&2511 Current.getPreviousNonComment() &&2512 Current.getPreviousNonComment()->isOneOf(tok::comma, tok::l_brace) &&2513 Current.getNextNonComment() &&2514 Current.getNextNonComment()->isOneOf(tok::comma, tok::r_brace)) {2515 Current.setType(TT_StringInConcatenation);2516 }2517 } else if (Current.is(tok::l_paren)) {2518 if (lParenStartsCppCast(Current))2519 Current.setType(TT_CppCastLParen);2520 } else if (Current.is(tok::r_paren)) {2521 if (rParenEndsCast(Current))2522 Current.setType(TT_CastRParen);2523 if (Current.MatchingParen && Current.Next &&2524 !Current.Next->isBinaryOperator() &&2525 Current.Next->isNoneOf(2526 tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma,2527 tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) {2528 if (FormatToken *AfterParen = Current.MatchingParen->Next;2529 AfterParen && AfterParen->isNot(tok::caret)) {2530 // Make sure this isn't the return type of an Obj-C block declaration.2531 if (FormatToken *BeforeParen = Current.MatchingParen->Previous;2532 BeforeParen && BeforeParen->is(tok::identifier) &&2533 BeforeParen->isNot(TT_TypenameMacro) &&2534 BeforeParen->TokenText == BeforeParen->TokenText.upper() &&2535 (!BeforeParen->Previous ||2536 BeforeParen->Previous->ClosesTemplateDeclaration ||2537 BeforeParen->Previous->ClosesRequiresClause)) {2538 Current.setType(TT_FunctionAnnotationRParen);2539 }2540 }2541 }2542 } else if (Current.is(tok::at) && Current.Next && !Style.isJavaScript() &&2543 !Style.isJava()) {2544 // In Java & JavaScript, "@..." is a decorator or annotation. In ObjC, it2545 // marks declarations and properties that need special formatting.2546 switch (Current.Next->Tok.getObjCKeywordID()) {2547 case tok::objc_interface:2548 case tok::objc_implementation:2549 case tok::objc_protocol:2550 Current.setType(TT_ObjCDecl);2551 break;2552 case tok::objc_property:2553 Current.setType(TT_ObjCProperty);2554 break;2555 default:2556 break;2557 }2558 } else if (Current.is(tok::period)) {2559 FormatToken *PreviousNoComment = Current.getPreviousNonComment();2560 if (PreviousNoComment &&2561 PreviousNoComment->isOneOf(tok::comma, tok::l_brace)) {2562 Current.setType(TT_DesignatedInitializerPeriod);2563 } else if (Style.isJava() && Current.Previous &&2564 Current.Previous->isOneOf(TT_JavaAnnotation,2565 TT_LeadingJavaAnnotation)) {2566 Current.setType(Current.Previous->getType());2567 }2568 } else if (canBeObjCSelectorComponent(Current) &&2569 // FIXME(bug 36976): ObjC return types shouldn't use2570 // TT_CastRParen.2571 Current.Previous && Current.Previous->is(TT_CastRParen) &&2572 Current.Previous->MatchingParen &&2573 Current.Previous->MatchingParen->Previous &&2574 Current.Previous->MatchingParen->Previous->is(2575 TT_ObjCMethodSpecifier)) {2576 // This is the first part of an Objective-C selector name. (If there's no2577 // colon after this, this is the only place which annotates the identifier2578 // as a selector.)2579 Current.setType(TT_SelectorName);2580 } else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept,2581 tok::kw_requires) &&2582 Current.Previous &&2583 Current.Previous->isNoneOf(tok::equal, tok::at,2584 TT_CtorInitializerComma,2585 TT_CtorInitializerColon) &&2586 Line.MightBeFunctionDecl && Contexts.size() == 1) {2587 // Line.MightBeFunctionDecl can only be true after the parentheses of a2588 // function declaration have been found.2589 Current.setType(TT_TrailingAnnotation);2590 } else if ((Style.isJava() || Style.isJavaScript()) && Current.Previous) {2591 if (Current.Previous->is(tok::at) &&2592 Current.isNot(Keywords.kw_interface)) {2593 const FormatToken &AtToken = *Current.Previous;2594 const FormatToken *Previous = AtToken.getPreviousNonComment();2595 if (!Previous || Previous->is(TT_LeadingJavaAnnotation))2596 Current.setType(TT_LeadingJavaAnnotation);2597 else2598 Current.setType(TT_JavaAnnotation);2599 } else if (Current.Previous->is(tok::period) &&2600 Current.Previous->isOneOf(TT_JavaAnnotation,2601 TT_LeadingJavaAnnotation)) {2602 Current.setType(Current.Previous->getType());2603 }2604 }2605 }2606 2607 /// Take a guess at whether \p Tok starts a name of a function or2608 /// variable declaration.2609 ///2610 /// This is a heuristic based on whether \p Tok is an identifier following2611 /// something that is likely a type.2612 bool isStartOfName(const FormatToken &Tok) {2613 // Handled in ExpressionParser for Verilog.2614 if (Style.isVerilog())2615 return false;2616 2617 if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))2618 return false;2619 2620 if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName))2621 return false;2622 2623 if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))2624 return false;2625 2626 if (const auto *NextNonComment = Tok.getNextNonComment();2627 (!NextNonComment && !Line.InMacroBody) ||2628 (NextNonComment &&2629 (NextNonComment->isPointerOrReference() ||2630 NextNonComment->isOneOf(TT_ClassHeadName, tok::string_literal) ||2631 (Line.InPragmaDirective && NextNonComment->is(tok::identifier))))) {2632 return false;2633 }2634 2635 if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,2636 Keywords.kw_as)) {2637 return false;2638 }2639 if (Style.isJavaScript() && Tok.Previous->is(Keywords.kw_in))2640 return false;2641 2642 // Skip "const" as it does not have an influence on whether this is a name.2643 FormatToken *PreviousNotConst = Tok.getPreviousNonComment();2644 2645 // For javascript const can be like "let" or "var"2646 if (!Style.isJavaScript())2647 while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))2648 PreviousNotConst = PreviousNotConst->getPreviousNonComment();2649 2650 if (!PreviousNotConst)2651 return false;2652 2653 if (PreviousNotConst->ClosesRequiresClause)2654 return false;2655 2656 if (Style.isTableGen()) {2657 // keywords such as let and def* defines names.2658 if (Keywords.isTableGenDefinition(*PreviousNotConst))2659 return true;2660 // Otherwise C++ style declarations is available only inside the brace.2661 if (Contexts.back().ContextKind != tok::l_brace)2662 return false;2663 }2664 2665 bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&2666 PreviousNotConst->Previous &&2667 PreviousNotConst->Previous->is(tok::hash);2668 2669 if (PreviousNotConst->is(TT_TemplateCloser)) {2670 return PreviousNotConst && PreviousNotConst->MatchingParen &&2671 PreviousNotConst->MatchingParen->Previous &&2672 PreviousNotConst->MatchingParen->Previous->isNoneOf(2673 tok::period, tok::kw_template);2674 }2675 2676 if ((PreviousNotConst->is(tok::r_paren) &&2677 PreviousNotConst->is(TT_TypeDeclarationParen)) ||2678 PreviousNotConst->is(TT_AttributeRParen)) {2679 return true;2680 }2681 2682 // If is a preprocess keyword like #define.2683 if (IsPPKeyword)2684 return false;2685 2686 // int a or auto a.2687 if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) &&2688 PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) {2689 return true;2690 }2691 2692 // *a or &a or &&a.2693 if (PreviousNotConst->is(TT_PointerOrReference) ||2694 PreviousNotConst->endsSequence(tok::coloncolon,2695 TT_PointerOrReference)) {2696 return true;2697 }2698 2699 // MyClass a;2700 if (PreviousNotConst->isTypeName(LangOpts))2701 return true;2702 2703 // type[] a in Java2704 if (Style.isJava() && PreviousNotConst->is(tok::r_square))2705 return true;2706 2707 // const a = in JavaScript.2708 return Style.isJavaScript() && PreviousNotConst->is(tok::kw_const);2709 }2710 2711 /// Determine whether '(' is starting a C++ cast.2712 bool lParenStartsCppCast(const FormatToken &Tok) {2713 // C-style casts are only used in C++.2714 if (!IsCpp)2715 return false;2716 2717 FormatToken *LeftOfParens = Tok.getPreviousNonComment();2718 if (LeftOfParens && LeftOfParens->is(TT_TemplateCloser) &&2719 LeftOfParens->MatchingParen) {2720 auto *Prev = LeftOfParens->MatchingParen->getPreviousNonComment();2721 if (Prev &&2722 Prev->isOneOf(tok::kw_const_cast, tok::kw_dynamic_cast,2723 tok::kw_reinterpret_cast, tok::kw_static_cast)) {2724 // FIXME: Maybe we should handle identifiers ending with "_cast",2725 // e.g. any_cast?2726 return true;2727 }2728 }2729 return false;2730 }2731 2732 /// Determine whether ')' is ending a cast.2733 bool rParenEndsCast(const FormatToken &Tok) {2734 assert(Tok.is(tok::r_paren));2735 2736 if (!Tok.MatchingParen || !Tok.Previous)2737 return false;2738 2739 // C-style casts are only used in C++, C# and Java.2740 if (!IsCpp && !Style.isCSharp() && !Style.isJava())2741 return false;2742 2743 const auto *LParen = Tok.MatchingParen;2744 const auto *BeforeRParen = Tok.Previous;2745 const auto *AfterRParen = Tok.Next;2746 2747 // Empty parens aren't casts and there are no casts at the end of the line.2748 if (BeforeRParen == LParen || !AfterRParen)2749 return false;2750 2751 if (LParen->is(TT_OverloadedOperatorLParen))2752 return false;2753 2754 auto *LeftOfParens = LParen->getPreviousNonComment();2755 if (LeftOfParens) {2756 // If there is a closing parenthesis left of the current2757 // parentheses, look past it as these might be chained casts.2758 if (LeftOfParens->is(tok::r_paren) &&2759 LeftOfParens->isNot(TT_CastRParen)) {2760 if (!LeftOfParens->MatchingParen ||2761 !LeftOfParens->MatchingParen->Previous) {2762 return false;2763 }2764 LeftOfParens = LeftOfParens->MatchingParen->Previous;2765 }2766 2767 if (LeftOfParens->is(tok::r_square)) {2768 // delete[] (void *)ptr;2769 auto MayBeArrayDelete = [](FormatToken *Tok) -> FormatToken * {2770 if (Tok->isNot(tok::r_square))2771 return nullptr;2772 2773 Tok = Tok->getPreviousNonComment();2774 if (!Tok || Tok->isNot(tok::l_square))2775 return nullptr;2776 2777 Tok = Tok->getPreviousNonComment();2778 if (!Tok || Tok->isNot(tok::kw_delete))2779 return nullptr;2780 return Tok;2781 };2782 if (FormatToken *MaybeDelete = MayBeArrayDelete(LeftOfParens))2783 LeftOfParens = MaybeDelete;2784 }2785 2786 // The Condition directly below this one will see the operator arguments2787 // as a (void *foo) cast.2788 // void operator delete(void *foo) ATTRIB;2789 if (LeftOfParens->Tok.getIdentifierInfo() && LeftOfParens->Previous &&2790 LeftOfParens->Previous->is(tok::kw_operator)) {2791 return false;2792 }2793 2794 // If there is an identifier (or with a few exceptions a keyword) right2795 // before the parentheses, this is unlikely to be a cast.2796 if (LeftOfParens->Tok.getIdentifierInfo() &&2797 LeftOfParens->isNoneOf(Keywords.kw_in, tok::kw_return, tok::kw_case,2798 tok::kw_delete, tok::kw_throw)) {2799 return false;2800 }2801 2802 // Certain other tokens right before the parentheses are also signals that2803 // this cannot be a cast.2804 if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator,2805 TT_TemplateCloser, tok::ellipsis)) {2806 return false;2807 }2808 }2809 2810 if (AfterRParen->is(tok::question) ||2811 (AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) {2812 return false;2813 }2814 2815 // `foreach((A a, B b) in someList)` should not be seen as a cast.2816 if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp())2817 return false;2818 2819 // Functions which end with decorations like volatile, noexcept are unlikely2820 // to be casts.2821 if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,2822 tok::kw_requires, tok::kw_throw, tok::arrow,2823 Keywords.kw_override, Keywords.kw_final) ||2824 isCppAttribute(IsCpp, *AfterRParen)) {2825 return false;2826 }2827 2828 // As Java has no function types, a "(" after the ")" likely means that this2829 // is a cast.2830 if (Style.isJava() && AfterRParen->is(tok::l_paren))2831 return true;2832 2833 // If a (non-string) literal follows, this is likely a cast.2834 if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||2835 (AfterRParen->Tok.isLiteral() &&2836 AfterRParen->isNot(tok::string_literal))) {2837 return true;2838 }2839 2840 auto IsNonVariableTemplate = [](const FormatToken &Tok) {2841 if (Tok.isNot(TT_TemplateCloser))2842 return false;2843 const auto *Less = Tok.MatchingParen;2844 if (!Less)2845 return false;2846 const auto *BeforeLess = Less->getPreviousNonComment();2847 return BeforeLess && BeforeLess->isNot(TT_VariableTemplate);2848 };2849 2850 // Heuristically try to determine whether the parentheses contain a type.2851 auto IsQualifiedPointerOrReference = [](const FormatToken *T,2852 const LangOptions &LangOpts) {2853 // This is used to handle cases such as x = (foo *const)&y;2854 assert(!T->isTypeName(LangOpts) && "Should have already been checked");2855 // Strip trailing qualifiers such as const or volatile when checking2856 // whether the parens could be a cast to a pointer/reference type.2857 while (T) {2858 if (T->is(TT_AttributeRParen)) {2859 // Handle `x = (foo *__attribute__((foo)))&v;`:2860 assert(T->is(tok::r_paren));2861 assert(T->MatchingParen);2862 assert(T->MatchingParen->is(tok::l_paren));2863 assert(T->MatchingParen->is(TT_AttributeLParen));2864 if (const auto *Tok = T->MatchingParen->Previous;2865 Tok && Tok->isAttribute()) {2866 T = Tok->Previous;2867 continue;2868 }2869 } else if (T->is(TT_AttributeRSquare)) {2870 // Handle `x = (foo *[[clang::foo]])&v;`:2871 if (T->MatchingParen && T->MatchingParen->Previous) {2872 T = T->MatchingParen->Previous;2873 continue;2874 }2875 } else if (T->canBePointerOrReferenceQualifier()) {2876 T = T->Previous;2877 continue;2878 }2879 break;2880 }2881 return T && T->is(TT_PointerOrReference);2882 };2883 2884 bool ParensAreType = IsNonVariableTemplate(*BeforeRParen) ||2885 BeforeRParen->is(TT_TypeDeclarationParen) ||2886 BeforeRParen->isTypeName(LangOpts) ||2887 IsQualifiedPointerOrReference(BeforeRParen, LangOpts);2888 bool ParensCouldEndDecl =2889 AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);2890 if (ParensAreType && !ParensCouldEndDecl)2891 return true;2892 2893 // At this point, we heuristically assume that there are no casts at the2894 // start of the line. We assume that we have found most cases where there2895 // are by the logic above, e.g. "(void)x;".2896 if (!LeftOfParens)2897 return false;2898 2899 // Certain token types inside the parentheses mean that this can't be a2900 // cast.2901 for (const auto *Token = LParen->Next; Token != &Tok; Token = Token->Next)2902 if (Token->is(TT_BinaryOperator))2903 return false;2904 2905 // If the following token is an identifier or 'this', this is a cast. All2906 // cases where this can be something else are handled above.2907 if (AfterRParen->isOneOf(tok::identifier, tok::kw_this))2908 return true;2909 2910 // Look for a cast `( x ) (`, where x may be a qualified identifier.2911 if (AfterRParen->is(tok::l_paren)) {2912 for (const auto *Prev = BeforeRParen; Prev->is(tok::identifier);) {2913 Prev = Prev->Previous;2914 if (Prev->is(tok::coloncolon))2915 Prev = Prev->Previous;2916 if (Prev == LParen)2917 return true;2918 }2919 }2920 2921 if (!AfterRParen->Next)2922 return false;2923 2924 if (AfterRParen->is(tok::l_brace) &&2925 AfterRParen->getBlockKind() == BK_BracedInit) {2926 return true;2927 }2928 2929 // If the next token after the parenthesis is a unary operator, assume2930 // that this is cast, unless there are unexpected tokens inside the2931 // parenthesis.2932 const bool NextIsAmpOrStar = AfterRParen->isOneOf(tok::amp, tok::star);2933 if (!(AfterRParen->isUnaryOperator() || NextIsAmpOrStar) ||2934 AfterRParen->is(tok::plus) ||2935 AfterRParen->Next->isNoneOf(tok::identifier, tok::numeric_constant)) {2936 return false;2937 }2938 2939 if (NextIsAmpOrStar &&2940 (AfterRParen->Next->is(tok::numeric_constant) || Line.InPPDirective)) {2941 return false;2942 }2943 2944 if (Line.InPPDirective && AfterRParen->is(tok::minus))2945 return false;2946 2947 const auto *Prev = BeforeRParen;2948 2949 // Look for a function pointer type, e.g. `(*)()`.2950 if (Prev->is(tok::r_paren)) {2951 if (Prev->is(TT_CastRParen))2952 return false;2953 Prev = Prev->MatchingParen;2954 if (!Prev)2955 return false;2956 Prev = Prev->Previous;2957 if (!Prev || Prev->isNot(tok::r_paren))2958 return false;2959 Prev = Prev->MatchingParen;2960 return Prev && Prev->is(TT_FunctionTypeLParen);2961 }2962 2963 // Search for unexpected tokens.2964 for (Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous)2965 if (Prev->isNoneOf(tok::kw_const, tok::identifier, tok::coloncolon))2966 return false;2967 2968 return true;2969 }2970 2971 /// Returns true if the token is used as a unary operator.2972 bool determineUnaryOperatorByUsage(const FormatToken &Tok) {2973 const FormatToken *PrevToken = Tok.getPreviousNonComment();2974 if (!PrevToken)2975 return true;2976 2977 // These keywords are deliberately not included here because they may2978 // precede only one of unary star/amp and plus/minus but not both. They are2979 // either included in determineStarAmpUsage or determinePlusMinusCaretUsage.2980 //2981 // @ - It may be followed by a unary `-` in Objective-C literals. We don't2982 // know how they can be followed by a star or amp.2983 if (PrevToken->isOneOf(2984 TT_ConditionalExpr, tok::l_paren, tok::comma, tok::colon, tok::semi,2985 tok::equal, tok::question, tok::l_square, tok::l_brace,2986 tok::kw_case, tok::kw_co_await, tok::kw_co_return, tok::kw_co_yield,2987 tok::kw_delete, tok::kw_return, tok::kw_throw)) {2988 return true;2989 }2990 2991 // We put sizeof here instead of only in determineStarAmpUsage. In the cases2992 // where the unary `+` operator is overloaded, it is reasonable to write2993 // things like `sizeof +x`. Like commit 446d6ec996c6c3.2994 if (PrevToken->is(tok::kw_sizeof))2995 return true;2996 2997 // A sequence of leading unary operators.2998 if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator))2999 return true;3000 3001 // There can't be two consecutive binary operators.3002 if (PrevToken->is(TT_BinaryOperator))3003 return true;3004 3005 return false;3006 }3007 3008 /// Return the type of the given token assuming it is * or &.3009 TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,3010 bool InTemplateArgument) {3011 if (Style.isJavaScript())3012 return TT_BinaryOperator;3013 3014 // && in C# must be a binary operator.3015 if (Style.isCSharp() && Tok.is(tok::ampamp))3016 return TT_BinaryOperator;3017 3018 if (Style.isVerilog()) {3019 // In Verilog, `*` can only be a binary operator. `&` can be either unary3020 // or binary. `*` also includes `*>` in module path declarations in3021 // specify blocks because merged tokens take the type of the first one by3022 // default.3023 if (Tok.is(tok::star))3024 return TT_BinaryOperator;3025 return determineUnaryOperatorByUsage(Tok) ? TT_UnaryOperator3026 : TT_BinaryOperator;3027 }3028 3029 const FormatToken *PrevToken = Tok.getPreviousNonComment();3030 if (!PrevToken)3031 return TT_UnaryOperator;3032 if (PrevToken->isTypeName(LangOpts))3033 return TT_PointerOrReference;3034 if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp))3035 return TT_BinaryOperator;3036 3037 auto *NextToken = Tok.getNextNonComment();3038 if (!NextToken)3039 return TT_PointerOrReference;3040 if (NextToken->is(tok::greater)) {3041 NextToken->setFinalizedType(TT_TemplateCloser);3042 return TT_PointerOrReference;3043 }3044 3045 if (InTemplateArgument && NextToken->is(tok::kw_noexcept))3046 return TT_BinaryOperator;3047 3048 if (NextToken->isOneOf(tok::arrow, tok::equal, tok::comma, tok::r_paren,3049 TT_RequiresClause) ||3050 (NextToken->is(tok::kw_noexcept) && !IsExpression) ||3051 NextToken->canBePointerOrReferenceQualifier() ||3052 (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) {3053 return TT_PointerOrReference;3054 }3055 3056 if (PrevToken->is(tok::coloncolon))3057 return TT_PointerOrReference;3058 3059 if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen))3060 return TT_PointerOrReference;3061 3062 if (determineUnaryOperatorByUsage(Tok))3063 return TT_UnaryOperator;3064 3065 if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))3066 return TT_PointerOrReference;3067 if (NextToken->is(tok::kw_operator) && !IsExpression)3068 return TT_PointerOrReference;3069 if (NextToken->isOneOf(tok::comma, tok::semi))3070 return TT_PointerOrReference;3071 3072 // After right braces, star tokens are likely to be pointers to struct,3073 // union, or class.3074 // struct {} *ptr;3075 // This by itself is not sufficient to distinguish from multiplication3076 // following a brace-initialized expression, as in:3077 // int i = int{42} * 2;3078 // In the struct case, the part of the struct declaration until the `{` and3079 // the `}` are put on separate unwrapped lines; in the brace-initialized3080 // case, the matching `{` is on the same unwrapped line, so check for the3081 // presence of the matching brace to distinguish between those.3082 if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) &&3083 !PrevToken->MatchingParen) {3084 return TT_PointerOrReference;3085 }3086 3087 if (PrevToken->endsSequence(tok::r_square, tok::l_square, tok::kw_delete))3088 return TT_UnaryOperator;3089 3090 if (PrevToken->Tok.isLiteral() ||3091 PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,3092 tok::kw_false, tok::r_brace)) {3093 return TT_BinaryOperator;3094 }3095 3096 const FormatToken *NextNonParen = NextToken;3097 while (NextNonParen && NextNonParen->is(tok::l_paren))3098 NextNonParen = NextNonParen->getNextNonComment();3099 if (NextNonParen && (NextNonParen->Tok.isLiteral() ||3100 NextNonParen->isOneOf(tok::kw_true, tok::kw_false) ||3101 NextNonParen->isUnaryOperator())) {3102 return TT_BinaryOperator;3103 }3104 3105 // If we know we're in a template argument, there are no named declarations.3106 // Thus, having an identifier on the right-hand side indicates a binary3107 // operator.3108 if (InTemplateArgument && NextToken->Tok.isAnyIdentifier())3109 return TT_BinaryOperator;3110 3111 // "&&" followed by "(", "*", or "&" is quite unlikely to be two successive3112 // unary "&".3113 if (Tok.is(tok::ampamp) &&3114 NextToken->isOneOf(tok::l_paren, tok::star, tok::amp)) {3115 return TT_BinaryOperator;3116 }3117 3118 // This catches some cases where evaluation order is used as control flow:3119 // aaa && aaa->f();3120 // Or expressions like:3121 // width * height * length3122 if (NextToken->Tok.isAnyIdentifier()) {3123 auto *NextNextToken = NextToken->getNextNonComment();3124 if (NextNextToken) {3125 if (NextNextToken->is(tok::arrow))3126 return TT_BinaryOperator;3127 if (NextNextToken->isPointerOrReference() &&3128 !NextToken->isObjCLifetimeQualifier(Style)) {3129 NextNextToken->setFinalizedType(TT_BinaryOperator);3130 return TT_BinaryOperator;3131 }3132 }3133 }3134 3135 // It is very unlikely that we are going to find a pointer or reference type3136 // definition on the RHS of an assignment.3137 if (IsExpression && !Contexts.back().CaretFound &&3138 Line.getFirstNonComment()->isNot(3139 TT_RequiresClauseInARequiresExpression)) {3140 return TT_BinaryOperator;3141 }3142 3143 // Opeartors at class scope are likely pointer or reference members.3144 if (!Scopes.empty() && Scopes.back() == ST_Class)3145 return TT_PointerOrReference;3146 3147 // Tokens that indicate member access or chained operator& use.3148 auto IsChainedOperatorAmpOrMember = [](const FormatToken *token) {3149 return !token || token->isOneOf(tok::amp, tok::period, tok::arrow,3150 tok::arrowstar, tok::periodstar);3151 };3152 3153 // It's more likely that & represents operator& than an uninitialized3154 // reference.3155 if (Tok.is(tok::amp) && PrevToken->Tok.isAnyIdentifier() &&3156 IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&3157 NextToken && NextToken->Tok.isAnyIdentifier()) {3158 if (auto NextNext = NextToken->getNextNonComment();3159 NextNext &&3160 (IsChainedOperatorAmpOrMember(NextNext) || NextNext->is(tok::semi))) {3161 return TT_BinaryOperator;3162 }3163 }3164 3165 if (Line.Type == LT_SimpleRequirement ||3166 (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) {3167 return TT_BinaryOperator;3168 }3169 3170 return TT_PointerOrReference;3171 }3172 3173 TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {3174 if (determineUnaryOperatorByUsage(Tok))3175 return TT_UnaryOperator;3176 3177 const FormatToken *PrevToken = Tok.getPreviousNonComment();3178 if (!PrevToken)3179 return TT_UnaryOperator;3180 3181 if (PrevToken->is(tok::at))3182 return TT_UnaryOperator;3183 3184 // Fall back to marking the token as binary operator.3185 return TT_BinaryOperator;3186 }3187 3188 /// Determine whether ++/-- are pre- or post-increments/-decrements.3189 TokenType determineIncrementUsage(const FormatToken &Tok) {3190 const FormatToken *PrevToken = Tok.getPreviousNonComment();3191 if (!PrevToken || PrevToken->is(TT_CastRParen))3192 return TT_UnaryOperator;3193 if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))3194 return TT_TrailingUnaryOperator;3195 3196 return TT_UnaryOperator;3197 }3198 3199 SmallVector<Context, 8> Contexts;3200 3201 const FormatStyle &Style;3202 AnnotatedLine &Line;3203 FormatToken *CurrentToken;3204 bool AutoFound;3205 bool IsCpp;3206 LangOptions LangOpts;3207 const AdditionalKeywords &Keywords;3208 3209 SmallVector<ScopeType> &Scopes;3210 3211 // Set of "<" tokens that do not open a template parameter list. If parseAngle3212 // determines that a specific token can't be a template opener, it will make3213 // same decision irrespective of the decisions for tokens leading up to it.3214 // Store this information to prevent this from causing exponential runtime.3215 llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;3216 3217 int TemplateDeclarationDepth;3218};3219 3220static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;3221static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;3222 3223/// Parses binary expressions by inserting fake parenthesis based on3224/// operator precedence.3225class ExpressionParser {3226public:3227 ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords,3228 AnnotatedLine &Line)3229 : Style(Style), Keywords(Keywords), Line(Line), Current(Line.First) {}3230 3231 /// Parse expressions with the given operator precedence.3232 void parse(int Precedence = 0) {3233 // Skip 'return' and ObjC selector colons as they are not part of a binary3234 // expression.3235 while (Current && (Current->is(tok::kw_return) ||3236 (Current->is(tok::colon) &&3237 Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)))) {3238 next();3239 }3240 3241 if (!Current || Precedence > PrecedenceArrowAndPeriod)3242 return;3243 3244 // Conditional expressions need to be parsed separately for proper nesting.3245 if (Precedence == prec::Conditional) {3246 parseConditionalExpr();3247 return;3248 }3249 3250 // Parse unary operators, which all have a higher precedence than binary3251 // operators.3252 if (Precedence == PrecedenceUnaryOperator) {3253 parseUnaryOperator();3254 return;3255 }3256 3257 FormatToken *Start = Current;3258 FormatToken *LatestOperator = nullptr;3259 unsigned OperatorIndex = 0;3260 // The first name of the current type in a port list.3261 FormatToken *VerilogFirstOfType = nullptr;3262 3263 while (Current) {3264 // In Verilog ports in a module header that don't have a type take the3265 // type of the previous one. For example,3266 // module a(output b,3267 // c,3268 // output d);3269 // In this case there need to be fake parentheses around b and c.3270 if (Style.isVerilog() && Precedence == prec::Comma) {3271 VerilogFirstOfType =3272 verilogGroupDecl(VerilogFirstOfType, LatestOperator);3273 }3274 3275 // Consume operators with higher precedence.3276 parse(Precedence + 1);3277 3278 int CurrentPrecedence = getCurrentPrecedence();3279 if (Style.BreakBinaryOperations == FormatStyle::BBO_OnePerLine &&3280 CurrentPrecedence > prec::Conditional &&3281 CurrentPrecedence < prec::PointerToMember) {3282 // When BreakBinaryOperations is set to BreakAll,3283 // all operations will be on the same line or on individual lines.3284 // Override precedence to avoid adding fake parenthesis which could3285 // group operations of a different precedence level on the same line3286 CurrentPrecedence = prec::Additive;3287 }3288 3289 if (Precedence == CurrentPrecedence && Current &&3290 Current->is(TT_SelectorName)) {3291 if (LatestOperator)3292 addFakeParenthesis(Start, prec::Level(Precedence));3293 Start = Current;3294 }3295 3296 if ((Style.isCSharp() || Style.isJavaScript() || Style.isJava()) &&3297 Precedence == prec::Additive && Current) {3298 // A string can be broken without parentheses around it when it is3299 // already in a sequence of strings joined by `+` signs.3300 FormatToken *Prev = Current->getPreviousNonComment();3301 if (Prev && Prev->is(tok::string_literal) &&3302 (Prev == Start || Prev->endsSequence(tok::string_literal, tok::plus,3303 TT_StringInConcatenation))) {3304 Prev->setType(TT_StringInConcatenation);3305 }3306 }3307 3308 // At the end of the line or when an operator with lower precedence is3309 // found, insert fake parenthesis and return.3310 if (!Current ||3311 (Current->closesScope() &&3312 (Current->MatchingParen || Current->is(TT_TemplateString))) ||3313 (CurrentPrecedence != -1 && CurrentPrecedence < Precedence) ||3314 (CurrentPrecedence == prec::Conditional &&3315 Precedence == prec::Assignment && Current->is(tok::colon))) {3316 break;3317 }3318 3319 // Consume scopes: (), [], <> and {}3320 // In addition to that we handle require clauses as scope, so that the3321 // constraints in that are correctly indented.3322 if (Current->opensScope() ||3323 Current->isOneOf(TT_RequiresClause,3324 TT_RequiresClauseInARequiresExpression)) {3325 // In fragment of a JavaScript template string can look like '}..${' and3326 // thus close a scope and open a new one at the same time.3327 while (Current && (!Current->closesScope() || Current->opensScope())) {3328 next();3329 parse();3330 }3331 next();3332 } else {3333 // Operator found.3334 if (CurrentPrecedence == Precedence) {3335 if (LatestOperator)3336 LatestOperator->NextOperator = Current;3337 LatestOperator = Current;3338 Current->OperatorIndex = OperatorIndex;3339 ++OperatorIndex;3340 }3341 next(/*SkipPastLeadingComments=*/Precedence > 0);3342 }3343 }3344 3345 // Group variables of the same type.3346 if (Style.isVerilog() && Precedence == prec::Comma && VerilogFirstOfType)3347 addFakeParenthesis(VerilogFirstOfType, prec::Comma);3348 3349 if (LatestOperator && (Current || Precedence > 0)) {3350 // The requires clauses do not neccessarily end in a semicolon or a brace,3351 // but just go over to struct/class or a function declaration, we need to3352 // intervene so that the fake right paren is inserted correctly.3353 auto End =3354 (Start->Previous &&3355 Start->Previous->isOneOf(TT_RequiresClause,3356 TT_RequiresClauseInARequiresExpression))3357 ? [this]() {3358 auto Ret = Current ? Current : Line.Last;3359 while (!Ret->ClosesRequiresClause && Ret->Previous)3360 Ret = Ret->Previous;3361 return Ret;3362 }()3363 : nullptr;3364 3365 if (Precedence == PrecedenceArrowAndPeriod) {3366 // Call expressions don't have a binary operator precedence.3367 addFakeParenthesis(Start, prec::Unknown, End);3368 } else {3369 addFakeParenthesis(Start, prec::Level(Precedence), End);3370 }3371 }3372 }3373 3374private:3375 /// Gets the precedence (+1) of the given token for binary operators3376 /// and other tokens that we treat like binary operators.3377 int getCurrentPrecedence() {3378 if (Current) {3379 const FormatToken *NextNonComment = Current->getNextNonComment();3380 if (Current->is(TT_ConditionalExpr))3381 return prec::Conditional;3382 if (NextNonComment && Current->is(TT_SelectorName) &&3383 (NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) ||3384 (Style.isProto() && NextNonComment->is(tok::less)))) {3385 return prec::Assignment;3386 }3387 if (Current->is(TT_JsComputedPropertyName))3388 return prec::Assignment;3389 if (Current->is(TT_LambdaArrow))3390 return prec::Comma;3391 if (Current->is(TT_FatArrow))3392 return prec::Assignment;3393 if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName) ||3394 (Current->is(tok::comment) && NextNonComment &&3395 NextNonComment->is(TT_SelectorName))) {3396 return 0;3397 }3398 if (Current->is(TT_RangeBasedForLoopColon))3399 return prec::Comma;3400 if ((Style.isJava() || Style.isJavaScript()) &&3401 Current->is(Keywords.kw_instanceof)) {3402 return prec::Relational;3403 }3404 if (Style.isJavaScript() &&3405 Current->isOneOf(Keywords.kw_in, Keywords.kw_as)) {3406 return prec::Relational;3407 }3408 if (Current->isOneOf(TT_BinaryOperator, tok::comma))3409 return Current->getPrecedence();3410 if (Current->isOneOf(tok::period, tok::arrow) &&3411 Current->isNot(TT_TrailingReturnArrow)) {3412 return PrecedenceArrowAndPeriod;3413 }3414 if ((Style.isJava() || Style.isJavaScript()) &&3415 Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,3416 Keywords.kw_throws)) {3417 return 0;3418 }3419 // In Verilog case labels are not on separate lines straight out of3420 // UnwrappedLineParser. The colon is not part of an expression.3421 if (Style.isVerilog() && Current->is(tok::colon))3422 return 0;3423 }3424 return -1;3425 }3426 3427 void addFakeParenthesis(FormatToken *Start, prec::Level Precedence,3428 FormatToken *End = nullptr) {3429 // Do not assign fake parenthesis to tokens that are part of an3430 // unexpanded macro call. The line within the macro call contains3431 // the parenthesis and commas, and we will not find operators within3432 // that structure.3433 if (Start->MacroParent)3434 return;3435 3436 Start->FakeLParens.push_back(Precedence);3437 if (Precedence > prec::Unknown)3438 Start->StartsBinaryExpression = true;3439 if (!End && Current)3440 End = Current->getPreviousNonComment();3441 if (End) {3442 ++End->FakeRParens;3443 if (Precedence > prec::Unknown)3444 End->EndsBinaryExpression = true;3445 }3446 }3447 3448 /// Parse unary operator expressions and surround them with fake3449 /// parentheses if appropriate.3450 void parseUnaryOperator() {3451 SmallVector<FormatToken *, 2> Tokens;3452 while (Current && Current->is(TT_UnaryOperator)) {3453 Tokens.push_back(Current);3454 next();3455 }3456 parse(PrecedenceArrowAndPeriod);3457 for (FormatToken *Token : reverse(Tokens)) {3458 // The actual precedence doesn't matter.3459 addFakeParenthesis(Token, prec::Unknown);3460 }3461 }3462 3463 void parseConditionalExpr() {3464 while (Current && Current->isTrailingComment())3465 next();3466 FormatToken *Start = Current;3467 parse(prec::LogicalOr);3468 if (!Current || Current->isNot(tok::question))3469 return;3470 next();3471 parse(prec::Assignment);3472 if (!Current || Current->isNot(TT_ConditionalExpr))3473 return;3474 next();3475 parse(prec::Assignment);3476 addFakeParenthesis(Start, prec::Conditional);3477 }3478 3479 void next(bool SkipPastLeadingComments = true) {3480 if (Current)3481 Current = Current->Next;3482 while (Current &&3483 (Current->NewlinesBefore == 0 || SkipPastLeadingComments) &&3484 Current->isTrailingComment()) {3485 Current = Current->Next;3486 }3487 }3488 3489 // Add fake parenthesis around declarations of the same type for example in a3490 // module prototype. Return the first port / variable of the current type.3491 FormatToken *verilogGroupDecl(FormatToken *FirstOfType,3492 FormatToken *PreviousComma) {3493 if (!Current)3494 return nullptr;3495 3496 FormatToken *Start = Current;3497 3498 // Skip attributes.3499 while (Start->startsSequence(tok::l_paren, tok::star)) {3500 if (!(Start = Start->MatchingParen) ||3501 !(Start = Start->getNextNonComment())) {3502 return nullptr;3503 }3504 }3505 3506 FormatToken *Tok = Start;3507 3508 if (Tok->is(Keywords.kw_assign))3509 Tok = Tok->getNextNonComment();3510 3511 // Skip any type qualifiers to find the first identifier. It may be either a3512 // new type name or a variable name. There can be several type qualifiers3513 // preceding a variable name, and we can not tell them apart by looking at3514 // the word alone since a macro can be defined as either a type qualifier or3515 // a variable name. Thus we use the last word before the dimensions instead3516 // of the first word as the candidate for the variable or type name.3517 FormatToken *First = nullptr;3518 while (Tok) {3519 FormatToken *Next = Tok->getNextNonComment();3520 3521 if (Tok->is(tok::hash)) {3522 // Start of a macro expansion.3523 First = Tok;3524 Tok = Next;3525 if (Tok)3526 Tok = Tok->getNextNonComment();3527 } else if (Tok->is(tok::hashhash)) {3528 // Concatenation. Skip.3529 Tok = Next;3530 if (Tok)3531 Tok = Tok->getNextNonComment();3532 } else if (Keywords.isVerilogQualifier(*Tok) ||3533 Keywords.isVerilogIdentifier(*Tok)) {3534 First = Tok;3535 Tok = Next;3536 // The name may have dots like `interface_foo.modport_foo`.3537 while (Tok && Tok->isOneOf(tok::period, tok::coloncolon) &&3538 (Tok = Tok->getNextNonComment())) {3539 if (Keywords.isVerilogIdentifier(*Tok))3540 Tok = Tok->getNextNonComment();3541 }3542 } else if (!Next) {3543 Tok = nullptr;3544 } else if (Tok->is(tok::l_paren)) {3545 // Make sure the parenthesized list is a drive strength. Otherwise the3546 // statement may be a module instantiation in which case we have already3547 // found the instance name.3548 if (Next->isOneOf(3549 Keywords.kw_highz0, Keywords.kw_highz1, Keywords.kw_large,3550 Keywords.kw_medium, Keywords.kw_pull0, Keywords.kw_pull1,3551 Keywords.kw_small, Keywords.kw_strong0, Keywords.kw_strong1,3552 Keywords.kw_supply0, Keywords.kw_supply1, Keywords.kw_weak0,3553 Keywords.kw_weak1)) {3554 Tok->setType(TT_VerilogStrength);3555 Tok = Tok->MatchingParen;3556 if (Tok) {3557 Tok->setType(TT_VerilogStrength);3558 Tok = Tok->getNextNonComment();3559 }3560 } else {3561 break;3562 }3563 } else if (Tok->is(Keywords.kw_verilogHash)) {3564 // Delay control.3565 if (Next->is(tok::l_paren))3566 Next = Next->MatchingParen;3567 if (Next)3568 Tok = Next->getNextNonComment();3569 } else {3570 break;3571 }3572 }3573 3574 // Find the second identifier. If it exists it will be the name.3575 FormatToken *Second = nullptr;3576 // Dimensions.3577 while (Tok && Tok->is(tok::l_square) && (Tok = Tok->MatchingParen))3578 Tok = Tok->getNextNonComment();3579 if (Tok && (Tok->is(tok::hash) || Keywords.isVerilogIdentifier(*Tok)))3580 Second = Tok;3581 3582 // If the second identifier doesn't exist and there are qualifiers, the type3583 // is implied.3584 FormatToken *TypedName = nullptr;3585 if (Second) {3586 TypedName = Second;3587 if (First && First->is(TT_Unknown))3588 First->setType(TT_VerilogDimensionedTypeName);3589 } else if (First != Start) {3590 // If 'First' is null, then this isn't a declaration, 'TypedName' gets set3591 // to null as intended.3592 TypedName = First;3593 }3594 3595 if (TypedName) {3596 // This is a declaration with a new type.3597 if (TypedName->is(TT_Unknown))3598 TypedName->setType(TT_StartOfName);3599 // Group variables of the previous type.3600 if (FirstOfType && PreviousComma) {3601 PreviousComma->setType(TT_VerilogTypeComma);3602 addFakeParenthesis(FirstOfType, prec::Comma, PreviousComma->Previous);3603 }3604 3605 FirstOfType = TypedName;3606 3607 // Don't let higher precedence handle the qualifiers. For example if we3608 // have:3609 // parameter x = 03610 // We skip `parameter` here. This way the fake parentheses for the3611 // assignment will be around `x = 0`.3612 while (Current && Current != FirstOfType) {3613 if (Current->opensScope()) {3614 next();3615 parse();3616 }3617 next();3618 }3619 }3620 3621 return FirstOfType;3622 }3623 3624 const FormatStyle &Style;3625 const AdditionalKeywords &Keywords;3626 const AnnotatedLine &Line;3627 FormatToken *Current;3628};3629 3630} // end anonymous namespace3631 3632void TokenAnnotator::setCommentLineLevels(3633 SmallVectorImpl<AnnotatedLine *> &Lines) const {3634 const AnnotatedLine *NextNonCommentLine = nullptr;3635 for (AnnotatedLine *Line : reverse(Lines)) {3636 assert(Line->First);3637 3638 // If the comment is currently aligned with the line immediately following3639 // it, that's probably intentional and we should keep it.3640 if (NextNonCommentLine && NextNonCommentLine->First->NewlinesBefore < 2 &&3641 Line->isComment() && !isClangFormatOff(Line->First->TokenText) &&3642 NextNonCommentLine->First->OriginalColumn ==3643 Line->First->OriginalColumn) {3644 const bool PPDirectiveOrImportStmt =3645 NextNonCommentLine->Type == LT_PreprocessorDirective ||3646 NextNonCommentLine->Type == LT_ImportStatement;3647 if (PPDirectiveOrImportStmt)3648 Line->Type = LT_CommentAbovePPDirective;3649 // Align comments for preprocessor lines with the # in column 0 if3650 // preprocessor lines are not indented. Otherwise, align with the next3651 // line.3652 Line->Level = Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&3653 PPDirectiveOrImportStmt3654 ? 03655 : NextNonCommentLine->Level;3656 } else {3657 NextNonCommentLine = Line->First->isNot(tok::r_brace) ? Line : nullptr;3658 }3659 3660 setCommentLineLevels(Line->Children);3661 }3662}3663 3664static unsigned maxNestingDepth(const AnnotatedLine &Line) {3665 unsigned Result = 0;3666 for (const auto *Tok = Line.First; Tok; Tok = Tok->Next)3667 Result = std::max(Result, Tok->NestingLevel);3668 return Result;3669}3670 3671// Returns the name of a function with no return type, e.g. a constructor or3672// destructor.3673static FormatToken *getFunctionName(const AnnotatedLine &Line,3674 FormatToken *&OpeningParen) {3675 for (FormatToken *Tok = Line.getFirstNonComment(), *Name = nullptr; Tok;3676 Tok = Tok->getNextNonComment()) {3677 // Skip C++11 attributes both before and after the function name.3678 if (Tok->is(TT_AttributeLSquare)) {3679 Tok = Tok->MatchingParen;3680 if (!Tok)3681 break;3682 continue;3683 }3684 3685 // Make sure the name is followed by a pair of parentheses.3686 if (Name) {3687 if (Tok->is(tok::l_paren) && Tok->is(TT_Unknown) && Tok->MatchingParen) {3688 OpeningParen = Tok;3689 return Name;3690 }3691 return nullptr;3692 }3693 3694 // Skip keywords that may precede the constructor/destructor name.3695 if (Tok->isOneOf(tok::kw_friend, tok::kw_inline, tok::kw_virtual,3696 tok::kw_constexpr, tok::kw_consteval, tok::kw_explicit)) {3697 continue;3698 }3699 3700 // A qualified name may start from the global namespace.3701 if (Tok->is(tok::coloncolon)) {3702 Tok = Tok->Next;3703 if (!Tok)3704 break;3705 }3706 3707 // Skip to the unqualified part of the name.3708 while (Tok->startsSequence(tok::identifier, tok::coloncolon)) {3709 assert(Tok->Next);3710 Tok = Tok->Next->Next;3711 if (!Tok)3712 return nullptr;3713 }3714 3715 // Skip the `~` if a destructor name.3716 if (Tok->is(tok::tilde)) {3717 Tok = Tok->Next;3718 if (!Tok)3719 break;3720 }3721 3722 // Make sure the name is not already annotated, e.g. as NamespaceMacro.3723 if (Tok->isNot(tok::identifier) || Tok->isNot(TT_Unknown))3724 break;3725 3726 Name = Tok;3727 }3728 3729 return nullptr;3730}3731 3732// Checks if Tok is a constructor/destructor name qualified by its class name.3733static bool isCtorOrDtorName(const FormatToken *Tok) {3734 assert(Tok && Tok->is(tok::identifier));3735 const auto *Prev = Tok->Previous;3736 3737 if (Prev && Prev->is(tok::tilde))3738 Prev = Prev->Previous;3739 3740 if (!Prev || !Prev->endsSequence(tok::coloncolon, tok::identifier))3741 return false;3742 3743 assert(Prev->Previous);3744 return Prev->Previous->TokenText == Tok->TokenText;3745}3746 3747void TokenAnnotator::annotate(AnnotatedLine &Line) {3748 if (!Line.InMacroBody)3749 MacroBodyScopes.clear();3750 3751 auto &ScopeStack = Line.InMacroBody ? MacroBodyScopes : Scopes;3752 AnnotatingParser Parser(Style, Line, Keywords, ScopeStack);3753 Line.Type = Parser.parseLine();3754 3755 if (!Line.Children.empty()) {3756 ScopeStack.push_back(ST_Other);3757 const bool InRequiresExpression = Line.Type == LT_RequiresExpression;3758 for (auto &Child : Line.Children) {3759 if (InRequiresExpression &&3760 Child->First->isNoneOf(tok::kw_typename, tok::kw_requires,3761 TT_CompoundRequirementLBrace)) {3762 Child->Type = LT_SimpleRequirement;3763 }3764 annotate(*Child);3765 }3766 // ScopeStack can become empty if Child has an unmatched `}`.3767 if (!ScopeStack.empty())3768 ScopeStack.pop_back();3769 }3770 3771 // With very deep nesting, ExpressionParser uses lots of stack and the3772 // formatting algorithm is very slow. We're not going to do a good job here3773 // anyway - it's probably generated code being formatted by mistake.3774 // Just skip the whole line.3775 if (maxNestingDepth(Line) > 50)3776 Line.Type = LT_Invalid;3777 3778 if (Line.Type == LT_Invalid)3779 return;3780 3781 ExpressionParser ExprParser(Style, Keywords, Line);3782 ExprParser.parse();3783 3784 if (IsCpp) {3785 FormatToken *OpeningParen = nullptr;3786 auto *Tok = getFunctionName(Line, OpeningParen);3787 if (Tok && ((!ScopeStack.empty() && ScopeStack.back() == ST_Class) ||3788 Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) {3789 Tok->setFinalizedType(TT_CtorDtorDeclName);3790 assert(OpeningParen);3791 OpeningParen->setFinalizedType(TT_FunctionDeclarationLParen);3792 }3793 }3794 3795 if (Line.startsWith(TT_ObjCMethodSpecifier))3796 Line.Type = LT_ObjCMethodDecl;3797 else if (Line.startsWith(TT_ObjCDecl))3798 Line.Type = LT_ObjCDecl;3799 else if (Line.startsWith(TT_ObjCProperty))3800 Line.Type = LT_ObjCProperty;3801 3802 auto *First = Line.First;3803 First->SpacesRequiredBefore = 1;3804 First->CanBreakBefore = First->MustBreakBefore;3805}3806 3807// This function heuristically determines whether 'Current' starts the name of a3808// function declaration.3809static bool isFunctionDeclarationName(const LangOptions &LangOpts,3810 const FormatToken &Current,3811 const AnnotatedLine &Line,3812 FormatToken *&ClosingParen) {3813 if (Current.is(TT_FunctionDeclarationName))3814 return true;3815 3816 if (Current.isNoneOf(tok::identifier, tok::kw_operator))3817 return false;3818 3819 const auto *Prev = Current.getPreviousNonComment();3820 assert(Prev);3821 3822 const auto &Previous = *Prev;3823 3824 if (const auto *PrevPrev = Previous.getPreviousNonComment();3825 PrevPrev && PrevPrev->is(TT_ObjCDecl)) {3826 return false;3827 }3828 3829 auto skipOperatorName =3830 [&LangOpts](const FormatToken *Next) -> const FormatToken * {3831 for (; Next; Next = Next->Next) {3832 if (Next->is(TT_OverloadedOperatorLParen))3833 return Next;3834 if (Next->is(TT_OverloadedOperator))3835 continue;3836 if (Next->isPlacementOperator() || Next->is(tok::kw_co_await)) {3837 // For 'new[]' and 'delete[]'.3838 if (Next->Next &&3839 Next->Next->startsSequence(tok::l_square, tok::r_square)) {3840 Next = Next->Next->Next;3841 }3842 continue;3843 }3844 if (Next->startsSequence(tok::l_square, tok::r_square)) {3845 // For operator[]().3846 Next = Next->Next;3847 continue;3848 }3849 if ((Next->isTypeName(LangOpts) || Next->is(tok::identifier)) &&3850 Next->Next && Next->Next->isPointerOrReference()) {3851 // For operator void*(), operator char*(), operator Foo*().3852 Next = Next->Next;3853 continue;3854 }3855 if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {3856 Next = Next->MatchingParen;3857 continue;3858 }3859 3860 break;3861 }3862 return nullptr;3863 };3864 3865 const auto *Next = Current.Next;3866 const bool IsCpp = LangOpts.CXXOperatorNames || LangOpts.C11;3867 3868 // Find parentheses of parameter list.3869 if (Current.is(tok::kw_operator)) {3870 if (Line.startsWith(tok::kw_friend))3871 return true;3872 if (Previous.Tok.getIdentifierInfo() &&3873 Previous.isNoneOf(tok::kw_return, tok::kw_co_return)) {3874 return true;3875 }3876 if (Previous.is(tok::r_paren) && Previous.is(TT_TypeDeclarationParen)) {3877 assert(Previous.MatchingParen);3878 assert(Previous.MatchingParen->is(tok::l_paren));3879 assert(Previous.MatchingParen->is(TT_TypeDeclarationParen));3880 return true;3881 }3882 if (!Previous.isPointerOrReference() && Previous.isNot(TT_TemplateCloser))3883 return false;3884 Next = skipOperatorName(Next);3885 } else {3886 if (Current.isNot(TT_StartOfName) || Current.NestingLevel != 0)3887 return false;3888 while (Next && Next->startsSequence(tok::hashhash, tok::identifier))3889 Next = Next->Next->Next;3890 for (; Next; Next = Next->Next) {3891 if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {3892 Next = Next->MatchingParen;3893 } else if (Next->is(tok::coloncolon)) {3894 Next = Next->Next;3895 if (!Next)3896 return false;3897 if (Next->is(tok::kw_operator)) {3898 Next = skipOperatorName(Next->Next);3899 break;3900 }3901 if (Next->isNot(tok::identifier))3902 return false;3903 } else if (isCppAttribute(IsCpp, *Next)) {3904 Next = Next->MatchingParen;3905 if (!Next)3906 return false;3907 } else if (Next->is(tok::l_paren)) {3908 break;3909 } else {3910 return false;3911 }3912 }3913 }3914 3915 // Check whether parameter list can belong to a function declaration.3916 if (!Next || Next->isNot(tok::l_paren) || !Next->MatchingParen)3917 return false;3918 ClosingParen = Next->MatchingParen;3919 assert(ClosingParen->is(tok::r_paren));3920 // If the lines ends with "{", this is likely a function definition.3921 if (Line.Last->is(tok::l_brace))3922 return true;3923 if (Next->Next == ClosingParen)3924 return true; // Empty parentheses.3925 // If there is an &/&& after the r_paren, this is likely a function.3926 if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference))3927 return true;3928 3929 // Check for K&R C function definitions (and C++ function definitions with3930 // unnamed parameters), e.g.:3931 // int f(i)3932 // {3933 // return i + 1;3934 // }3935 // bool g(size_t = 0, bool b = false)3936 // {3937 // return !b;3938 // }3939 if (IsCpp && Next->Next && Next->Next->is(tok::identifier) &&3940 !Line.endsWith(tok::semi)) {3941 return true;3942 }3943 3944 for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen;3945 Tok = Tok->Next) {3946 if (Tok->is(TT_TypeDeclarationParen))3947 return true;3948 if (Tok->isOneOf(tok::l_paren, TT_TemplateOpener) && Tok->MatchingParen) {3949 Tok = Tok->MatchingParen;3950 continue;3951 }3952 if (Tok->is(tok::kw_const) || Tok->isTypeName(LangOpts) ||3953 Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) {3954 return true;3955 }3956 if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral())3957 return false;3958 }3959 return false;3960}3961 3962bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {3963 assert(Line.MightBeFunctionDecl);3964 3965 if ((Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevel ||3966 Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevelDefinitions) &&3967 Line.Level > 0) {3968 return false;3969 }3970 3971 switch (Style.BreakAfterReturnType) {3972 case FormatStyle::RTBS_None:3973 case FormatStyle::RTBS_Automatic:3974 case FormatStyle::RTBS_ExceptShortType:3975 return false;3976 case FormatStyle::RTBS_All:3977 case FormatStyle::RTBS_TopLevel:3978 return true;3979 case FormatStyle::RTBS_AllDefinitions:3980 case FormatStyle::RTBS_TopLevelDefinitions:3981 return Line.mightBeFunctionDefinition();3982 }3983 3984 return false;3985}3986 3987void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {3988 if (Line.Computed)3989 return;3990 3991 Line.Computed = true;3992 3993 for (AnnotatedLine *ChildLine : Line.Children)3994 calculateFormattingInformation(*ChildLine);3995 3996 auto *First = Line.First;3997 First->TotalLength = First->IsMultiline3998 ? Style.ColumnLimit3999 : Line.FirstStartColumn + First->ColumnWidth;4000 bool AlignArrayOfStructures =4001 (Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&4002 Line.Type == LT_ArrayOfStructInitializer);4003 if (AlignArrayOfStructures)4004 calculateArrayInitializerColumnList(Line);4005 4006 const auto *FirstNonComment = Line.getFirstNonComment();4007 bool SeenName = false;4008 bool LineIsFunctionDeclaration = false;4009 FormatToken *AfterLastAttribute = nullptr;4010 FormatToken *ClosingParen = nullptr;4011 4012 for (auto *Tok = FirstNonComment && FirstNonComment->isNot(tok::kw_using)4013 ? FirstNonComment->Next4014 : nullptr;4015 Tok && Tok->isNot(BK_BracedInit); Tok = Tok->Next) {4016 if (Tok->is(TT_StartOfName))4017 SeenName = true;4018 if (Tok->Previous->EndsCppAttributeGroup)4019 AfterLastAttribute = Tok;4020 if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);4021 IsCtorOrDtor ||4022 isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) {4023 if (!IsCtorOrDtor)4024 Tok->setFinalizedType(TT_FunctionDeclarationName);4025 LineIsFunctionDeclaration = true;4026 SeenName = true;4027 if (ClosingParen) {4028 auto *OpeningParen = ClosingParen->MatchingParen;4029 assert(OpeningParen);4030 if (OpeningParen->is(TT_Unknown))4031 OpeningParen->setType(TT_FunctionDeclarationLParen);4032 }4033 break;4034 }4035 }4036 4037 if (IsCpp) {4038 if ((LineIsFunctionDeclaration ||4039 (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&4040 Line.endsWith(tok::semi, tok::r_brace)) {4041 auto *Tok = Line.Last->Previous;4042 while (Tok->isNot(tok::r_brace))4043 Tok = Tok->Previous;4044 if (auto *LBrace = Tok->MatchingParen; LBrace && LBrace->is(TT_Unknown)) {4045 assert(LBrace->is(tok::l_brace));4046 Tok->setBlockKind(BK_Block);4047 LBrace->setBlockKind(BK_Block);4048 LBrace->setFinalizedType(TT_FunctionLBrace);4049 }4050 }4051 4052 if (SeenName && AfterLastAttribute &&4053 mustBreakAfterAttributes(*AfterLastAttribute, Style)) {4054 AfterLastAttribute->MustBreakBefore = true;4055 if (LineIsFunctionDeclaration)4056 Line.ReturnTypeWrapped = true;4057 }4058 4059 if (!LineIsFunctionDeclaration) {4060 // Annotate */&/&& in `operator` function calls as binary operators.4061 for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) {4062 if (Tok->isNot(tok::kw_operator))4063 continue;4064 do {4065 Tok = Tok->Next;4066 } while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));4067 if (!Tok || !Tok->MatchingParen)4068 break;4069 const auto *LeftParen = Tok;4070 for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;4071 Tok = Tok->Next) {4072 if (Tok->isNot(tok::identifier))4073 continue;4074 auto *Next = Tok->Next;4075 const bool NextIsBinaryOperator =4076 Next && Next->isPointerOrReference() && Next->Next &&4077 Next->Next->is(tok::identifier);4078 if (!NextIsBinaryOperator)4079 continue;4080 Next->setType(TT_BinaryOperator);4081 Tok = Next;4082 }4083 }4084 } else if (ClosingParen) {4085 for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {4086 if (Tok->is(TT_CtorInitializerColon))4087 break;4088 if (Tok->is(tok::arrow)) {4089 Tok->setType(TT_TrailingReturnArrow);4090 break;4091 }4092 if (Tok->isNot(TT_TrailingAnnotation))4093 continue;4094 const auto *Next = Tok->Next;4095 if (!Next || Next->isNot(tok::l_paren))4096 continue;4097 Tok = Next->MatchingParen;4098 if (!Tok)4099 break;4100 }4101 }4102 }4103 4104 if (First->is(TT_ElseLBrace)) {4105 First->CanBreakBefore = true;4106 First->MustBreakBefore = true;4107 }4108 4109 bool InFunctionDecl = Line.MightBeFunctionDecl;4110 bool InParameterList = false;4111 for (auto *Current = First->Next; Current; Current = Current->Next) {4112 const FormatToken *Prev = Current->Previous;4113 if (Current->is(TT_LineComment)) {4114 if (Prev->is(BK_BracedInit) && Prev->opensScope()) {4115 Current->SpacesRequiredBefore =4116 (Style.Cpp11BracedListStyle == FormatStyle::BLS_AlignFirstComment &&4117 !Style.SpacesInParensOptions.Other)4118 ? 04119 : 1;4120 } else if (Prev->is(TT_VerilogMultiLineListLParen)) {4121 Current->SpacesRequiredBefore = 0;4122 } else {4123 Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;4124 }4125 4126 // If we find a trailing comment, iterate backwards to determine whether4127 // it seems to relate to a specific parameter. If so, break before that4128 // parameter to avoid changing the comment's meaning. E.g. don't move 'b'4129 // to the previous line in:4130 // SomeFunction(a,4131 // b, // comment4132 // c);4133 if (!Current->HasUnescapedNewline) {4134 for (FormatToken *Parameter = Current->Previous; Parameter;4135 Parameter = Parameter->Previous) {4136 if (Parameter->isOneOf(tok::comment, tok::r_brace))4137 break;4138 if (Parameter->Previous && Parameter->Previous->is(tok::comma)) {4139 if (Parameter->Previous->isNot(TT_CtorInitializerComma) &&4140 Parameter->HasUnescapedNewline) {4141 Parameter->MustBreakBefore = true;4142 }4143 break;4144 }4145 }4146 }4147 } else if (!Current->Finalized && Current->SpacesRequiredBefore == 0 &&4148 spaceRequiredBefore(Line, *Current)) {4149 Current->SpacesRequiredBefore = 1;4150 }4151 4152 const auto &Children = Prev->Children;4153 if (!Children.empty() && Children.back()->Last->is(TT_LineComment)) {4154 Current->MustBreakBefore = true;4155 } else {4156 Current->MustBreakBefore =4157 Current->MustBreakBefore || mustBreakBefore(Line, *Current);4158 if (!Current->MustBreakBefore && InFunctionDecl &&4159 Current->is(TT_FunctionDeclarationName)) {4160 Current->MustBreakBefore = mustBreakForReturnType(Line);4161 }4162 }4163 4164 Current->CanBreakBefore =4165 Current->MustBreakBefore || canBreakBefore(Line, *Current);4166 4167 if (Current->is(TT_FunctionDeclarationLParen)) {4168 InParameterList = true;4169 } else if (Current->is(tok::r_paren)) {4170 const auto *LParen = Current->MatchingParen;4171 if (LParen && LParen->is(TT_FunctionDeclarationLParen))4172 InParameterList = false;4173 } else if (InParameterList &&4174 Current->endsSequence(TT_AttributeMacro,4175 TT_PointerOrReference)) {4176 Current->CanBreakBefore = false;4177 }4178 4179 unsigned ChildSize = 0;4180 if (Prev->Children.size() == 1) {4181 FormatToken &LastOfChild = *Prev->Children[0]->Last;4182 ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit4183 : LastOfChild.TotalLength + 1;4184 }4185 if (Current->MustBreakBefore || Prev->Children.size() > 1 ||4186 (Prev->Children.size() == 1 &&4187 Prev->Children[0]->First->MustBreakBefore) ||4188 Current->IsMultiline) {4189 Current->TotalLength = Prev->TotalLength + Style.ColumnLimit;4190 } else {4191 Current->TotalLength = Prev->TotalLength + Current->ColumnWidth +4192 ChildSize + Current->SpacesRequiredBefore;4193 }4194 4195 if (Current->is(TT_ControlStatementLBrace)) {4196 if (Style.ColumnLimit > 0 &&4197 Style.BraceWrapping.AfterControlStatement ==4198 FormatStyle::BWACS_MultiLine &&4199 Line.Level * Style.IndentWidth + Line.Last->TotalLength >4200 Style.ColumnLimit) {4201 Current->CanBreakBefore = true;4202 Current->MustBreakBefore = true;4203 }4204 } else if (Current->is(TT_CtorInitializerColon)) {4205 InFunctionDecl = false;4206 }4207 4208 // FIXME: Only calculate this if CanBreakBefore is true once static4209 // initializers etc. are sorted out.4210 // FIXME: Move magic numbers to a better place.4211 4212 // Reduce penalty for aligning ObjC method arguments using the colon4213 // alignment as this is the canonical way (still prefer fitting everything4214 // into one line if possible). Trying to fit a whole expression into one4215 // line should not force other line breaks (e.g. when ObjC method4216 // expression is a part of other expression).4217 Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl);4218 if (Style.Language == FormatStyle::LK_ObjC &&4219 Current->is(TT_SelectorName) && Current->ParameterIndex > 0) {4220 if (Current->ParameterIndex == 1)4221 Current->SplitPenalty += 5 * Current->BindingStrength;4222 } else {4223 Current->SplitPenalty += 20 * Current->BindingStrength;4224 }4225 }4226 4227 calculateUnbreakableTailLengths(Line);4228 unsigned IndentLevel = Line.Level;4229 for (auto *Current = First; Current; Current = Current->Next) {4230 if (Current->Role)4231 Current->Role->precomputeFormattingInfos(Current);4232 if (Current->MatchingParen &&4233 Current->MatchingParen->opensBlockOrBlockTypeList(Style) &&4234 IndentLevel > 0) {4235 --IndentLevel;4236 }4237 Current->IndentLevel = IndentLevel;4238 if (Current->opensBlockOrBlockTypeList(Style))4239 ++IndentLevel;4240 }4241 4242 LLVM_DEBUG({ printDebugInfo(Line); });4243}4244 4245void TokenAnnotator::calculateUnbreakableTailLengths(4246 AnnotatedLine &Line) const {4247 unsigned UnbreakableTailLength = 0;4248 FormatToken *Current = Line.Last;4249 while (Current) {4250 Current->UnbreakableTailLength = UnbreakableTailLength;4251 if (Current->CanBreakBefore ||4252 Current->isOneOf(tok::comment, tok::string_literal)) {4253 UnbreakableTailLength = 0;4254 } else {4255 UnbreakableTailLength +=4256 Current->ColumnWidth + Current->SpacesRequiredBefore;4257 }4258 Current = Current->Previous;4259 }4260}4261 4262void TokenAnnotator::calculateArrayInitializerColumnList(4263 AnnotatedLine &Line) const {4264 if (Line.First == Line.Last)4265 return;4266 auto *CurrentToken = Line.First;4267 CurrentToken->ArrayInitializerLineStart = true;4268 unsigned Depth = 0;4269 while (CurrentToken && CurrentToken != Line.Last) {4270 if (CurrentToken->is(tok::l_brace)) {4271 CurrentToken->IsArrayInitializer = true;4272 if (CurrentToken->Next)4273 CurrentToken->Next->MustBreakBefore = true;4274 CurrentToken =4275 calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1);4276 } else {4277 CurrentToken = CurrentToken->Next;4278 }4279 }4280}4281 4282FormatToken *TokenAnnotator::calculateInitializerColumnList(4283 AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) const {4284 while (CurrentToken && CurrentToken != Line.Last) {4285 if (CurrentToken->is(tok::l_brace))4286 ++Depth;4287 else if (CurrentToken->is(tok::r_brace))4288 --Depth;4289 if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) {4290 CurrentToken = CurrentToken->Next;4291 if (!CurrentToken)4292 break;4293 CurrentToken->StartsColumn = true;4294 CurrentToken = CurrentToken->Previous;4295 }4296 CurrentToken = CurrentToken->Next;4297 }4298 return CurrentToken;4299}4300 4301unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,4302 const FormatToken &Tok,4303 bool InFunctionDecl) const {4304 const FormatToken &Left = *Tok.Previous;4305 const FormatToken &Right = Tok;4306 4307 if (Left.is(tok::semi))4308 return 0;4309 4310 // Language specific handling.4311 if (Style.isJava()) {4312 if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws))4313 return 1;4314 if (Right.is(Keywords.kw_implements))4315 return 2;4316 if (Left.is(tok::comma) && Left.NestingLevel == 0)4317 return 3;4318 } else if (Style.isJavaScript()) {4319 if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))4320 return 100;4321 if (Left.is(TT_JsTypeColon))4322 return 35;4323 if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) ||4324 (Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) {4325 return 100;4326 }4327 // Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".4328 if (Left.opensScope() && Right.closesScope())4329 return 200;4330 } else if (Style.Language == FormatStyle::LK_Proto) {4331 if (Right.is(tok::l_square))4332 return 1;4333 if (Right.is(tok::period))4334 return 500;4335 }4336 4337 if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))4338 return 1;4339 if (Right.is(tok::l_square)) {4340 if (Left.is(tok::r_square))4341 return 200;4342 // Slightly prefer formatting local lambda definitions like functions.4343 if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))4344 return 35;4345 if (Right.isNoneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,4346 TT_ArrayInitializerLSquare,4347 TT_DesignatedInitializerLSquare, TT_AttributeLSquare)) {4348 return 500;4349 }4350 }4351 4352 if (Left.is(tok::coloncolon))4353 return Style.PenaltyBreakScopeResolution;4354 if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName,4355 tok::kw_operator)) {4356 if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)4357 return 3;4358 if (Left.is(TT_StartOfName))4359 return 110;4360 if (InFunctionDecl && Right.NestingLevel == 0)4361 return Style.PenaltyReturnTypeOnItsOwnLine;4362 return 200;4363 }4364 if (Right.is(TT_PointerOrReference))4365 return 190;4366 if (Right.is(TT_LambdaArrow))4367 return 110;4368 if (Left.is(tok::equal) && Right.is(tok::l_brace))4369 return 160;4370 if (Left.is(TT_CastRParen))4371 return 100;4372 if (Left.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union))4373 return 5000;4374 if (Left.is(tok::comment))4375 return 1000;4376 4377 if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon,4378 TT_CtorInitializerColon)) {4379 return 2;4380 }4381 4382 if (Right.isMemberAccess()) {4383 // Breaking before the "./->" of a chained call/member access is reasonably4384 // cheap, as formatting those with one call per line is generally4385 // desirable. In particular, it should be cheaper to break before the call4386 // than it is to break inside a call's parameters, which could lead to weird4387 // "hanging" indents. The exception is the very last "./->" to support this4388 // frequent pattern:4389 //4390 // aaaaaaaa.aaaaaaaa.bbbbbbb().ccccccccccccccccccccc(4391 // dddddddd);4392 //4393 // which might otherwise be blown up onto many lines. Here, clang-format4394 // won't produce "hanging" indents anyway as there is no other trailing4395 // call.4396 //4397 // Also apply higher penalty is not a call as that might lead to a wrapping4398 // like:4399 //4400 // aaaaaaa4401 // .aaaaaaaaa.bbbbbbbb(cccccccc);4402 const auto *NextOperator = Right.NextOperator;4403 const auto Penalty = Style.PenaltyBreakBeforeMemberAccess;4404 return NextOperator && NextOperator->Previous->closesScope()4405 ? std::min(Penalty, 35u)4406 : Penalty;4407 }4408 4409 if (Right.is(TT_TrailingAnnotation) &&4410 (!Right.Next || Right.Next->isNot(tok::l_paren))) {4411 // Moving trailing annotations to the next line is fine for ObjC method4412 // declarations.4413 if (Line.startsWith(TT_ObjCMethodSpecifier))4414 return 10;4415 // Generally, breaking before a trailing annotation is bad unless it is4416 // function-like. It seems to be especially preferable to keep standard4417 // annotations (i.e. "const", "final" and "override") on the same line.4418 // Use a slightly higher penalty after ")" so that annotations like4419 // "const override" are kept together.4420 bool is_short_annotation = Right.TokenText.size() < 10;4421 return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0);4422 }4423 4424 // In for-loops, prefer breaking at ',' and ';'.4425 if (Line.startsWith(tok::kw_for) && Left.is(tok::equal))4426 return 4;4427 4428 // In Objective-C method expressions, prefer breaking before "param:" over4429 // breaking after it.4430 if (Right.is(TT_SelectorName))4431 return 0;4432 if (Left.is(tok::colon)) {4433 if (Left.is(TT_ObjCMethodExpr))4434 return Line.MightBeFunctionDecl ? 50 : 500;4435 if (Left.is(TT_ObjCSelector))4436 return 500;4437 }4438 4439 // In Objective-C type declarations, avoid breaking after the category's4440 // open paren (we'll prefer breaking after the protocol list's opening4441 // angle bracket, if present).4442 if (Line.Type == LT_ObjCDecl && Left.is(tok::l_paren) && Left.Previous &&4443 Left.Previous->isOneOf(tok::identifier, tok::greater)) {4444 return 500;4445 }4446 4447 if (Left.is(tok::l_paren) && Style.PenaltyBreakOpenParenthesis != 0)4448 return Style.PenaltyBreakOpenParenthesis;4449 if (Left.is(tok::l_paren) && InFunctionDecl && Style.AlignAfterOpenBracket)4450 return 100;4451 if (Left.is(tok::l_paren) && Left.Previous &&4452 (Left.Previous->isOneOf(tok::kw_for, tok::kw__Generic) ||4453 Left.Previous->isIf())) {4454 return 1000;4455 }4456 if (Left.is(tok::equal) && InFunctionDecl)4457 return 110;4458 if (Right.is(tok::r_brace))4459 return 1;4460 if (Left.is(TT_TemplateOpener))4461 return 100;4462 if (Left.opensScope()) {4463 // If we aren't aligning after opening parens/braces we can always break4464 // here unless the style does not want us to place all arguments on the4465 // next line.4466 if (!Style.AlignAfterOpenBracket &&4467 (Left.ParameterCount <= 1 || Style.AllowAllArgumentsOnNextLine)) {4468 return 0;4469 }4470 if (Left.is(tok::l_brace) &&4471 Style.Cpp11BracedListStyle == FormatStyle::BLS_Block) {4472 return 19;4473 }4474 return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter4475 : 19;4476 }4477 if (Left.is(TT_JavaAnnotation))4478 return 50;4479 4480 if (Left.is(TT_UnaryOperator))4481 return 60;4482 if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&4483 Left.Previous->isLabelString() &&4484 (Left.NextOperator || Left.OperatorIndex != 0)) {4485 return 50;4486 }4487 if (Right.is(tok::plus) && Left.isLabelString() &&4488 (Right.NextOperator || Right.OperatorIndex != 0)) {4489 return 25;4490 }4491 if (Left.is(tok::comma))4492 return 1;4493 if (Right.is(tok::lessless) && Left.isLabelString() &&4494 (Right.NextOperator || Right.OperatorIndex != 1)) {4495 return 25;4496 }4497 if (Right.is(tok::lessless)) {4498 // Breaking at a << is really cheap.4499 if (Left.isNot(tok::r_paren) || Right.OperatorIndex > 0) {4500 // Slightly prefer to break before the first one in log-like statements.4501 return 2;4502 }4503 return 1;4504 }4505 if (Left.ClosesTemplateDeclaration)4506 return Style.PenaltyBreakTemplateDeclaration;4507 if (Left.ClosesRequiresClause)4508 return 0;4509 if (Left.is(TT_ConditionalExpr))4510 return prec::Conditional;4511 prec::Level Level = Left.getPrecedence();4512 if (Level == prec::Unknown)4513 Level = Right.getPrecedence();4514 if (Level == prec::Assignment)4515 return Style.PenaltyBreakAssignment;4516 if (Level != prec::Unknown)4517 return Level;4518 4519 return 3;4520}4521 4522bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {4523 if (Style.SpaceBeforeParens == FormatStyle::SBPO_Always)4524 return true;4525 if (Right.is(TT_OverloadedOperatorLParen) &&4526 Style.SpaceBeforeParensOptions.AfterOverloadedOperator) {4527 return true;4528 }4529 if (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses &&4530 Right.ParameterCount > 0) {4531 return true;4532 }4533 return false;4534}4535 4536bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,4537 const FormatToken &Left,4538 const FormatToken &Right) const {4539 if (Left.is(tok::kw_return) &&4540 Right.isNoneOf(tok::semi, tok::r_paren, tok::hashhash)) {4541 return true;4542 }4543 if (Left.is(tok::kw_throw) && Right.is(tok::l_paren) && Right.MatchingParen &&4544 Right.MatchingParen->is(TT_CastRParen)) {4545 return true;4546 }4547 if (Left.is(Keywords.kw_assert) && Style.isJava())4548 return true;4549 if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&4550 Left.is(tok::objc_property)) {4551 return true;4552 }4553 if (Right.is(tok::hashhash))4554 return Left.is(tok::hash);4555 if (Left.isOneOf(tok::hashhash, tok::hash))4556 return Right.is(tok::hash);4557 if (Style.SpacesInParens == FormatStyle::SIPO_Custom) {4558 if (Left.is(tok::l_paren) && Right.is(tok::r_paren))4559 return Style.SpacesInParensOptions.InEmptyParentheses;4560 if (Style.SpacesInParensOptions.ExceptDoubleParentheses &&4561 Left.is(tok::r_paren) && Right.is(tok::r_paren)) {4562 auto *InnerLParen = Left.MatchingParen;4563 if (InnerLParen && InnerLParen->Previous == Right.MatchingParen) {4564 InnerLParen->SpacesRequiredBefore = 0;4565 return false;4566 }4567 }4568 const FormatToken *LeftParen = nullptr;4569 if (Left.is(tok::l_paren))4570 LeftParen = &Left;4571 else if (Right.is(tok::r_paren) && Right.MatchingParen)4572 LeftParen = Right.MatchingParen;4573 if (LeftParen && (LeftParen->is(TT_ConditionLParen) ||4574 (LeftParen->Previous &&4575 isKeywordWithCondition(*LeftParen->Previous)))) {4576 return Style.SpacesInParensOptions.InConditionalStatements;4577 }4578 }4579 4580 // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {}4581 if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace,4582 // function return type 'auto'4583 TT_FunctionTypeLParen)) {4584 return true;4585 }4586 4587 // auto{x} auto(x)4588 if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))4589 return false;4590 4591 const auto *BeforeLeft = Left.Previous;4592 4593 // operator co_await(x)4594 if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft &&4595 BeforeLeft->is(tok::kw_operator)) {4596 return false;4597 }4598 // co_await (x), co_yield (x), co_return (x)4599 if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) &&4600 Right.isNoneOf(tok::semi, tok::r_paren)) {4601 return true;4602 }4603 4604 if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) {4605 return (Right.is(TT_CastRParen) ||4606 (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))4607 ? Style.SpacesInParensOptions.InCStyleCasts4608 : Style.SpacesInParensOptions.Other;4609 }4610 if (Right.isOneOf(tok::semi, tok::comma))4611 return false;4612 if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) {4613 bool IsLightweightGeneric = Right.MatchingParen &&4614 Right.MatchingParen->Next &&4615 Right.MatchingParen->Next->is(tok::colon);4616 return !IsLightweightGeneric && Style.ObjCSpaceBeforeProtocolList;4617 }4618 if (Right.is(tok::less) && Left.is(tok::kw_template))4619 return Style.SpaceAfterTemplateKeyword;4620 if (Left.isOneOf(tok::exclaim, tok::tilde))4621 return false;4622 if (Left.is(tok::at) &&4623 Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,4624 tok::numeric_constant, tok::l_paren, tok::l_brace,4625 tok::kw_true, tok::kw_false)) {4626 return false;4627 }4628 if (Left.is(tok::colon))4629 return Left.isNoneOf(TT_ObjCSelector, TT_ObjCMethodExpr);4630 if (Left.is(tok::coloncolon))4631 return false;4632 if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {4633 if (Style.isTextProto() ||4634 (Style.Language == FormatStyle::LK_Proto &&4635 (Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) {4636 // Format empty list as `<>`.4637 if (Left.is(tok::less) && Right.is(tok::greater))4638 return false;4639 return Style.Cpp11BracedListStyle == FormatStyle::BLS_Block;4640 }4641 // Don't attempt to format operator<(), as it is handled later.4642 if (Right.isNot(TT_OverloadedOperatorLParen))4643 return false;4644 }4645 if (Right.is(tok::ellipsis)) {4646 return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft &&4647 BeforeLeft->is(tok::kw_case));4648 }4649 if (Left.is(tok::l_square) && Right.is(tok::amp))4650 return Style.SpacesInSquareBrackets;4651 if (Right.is(TT_PointerOrReference)) {4652 if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) {4653 if (!Left.MatchingParen)4654 return true;4655 FormatToken *TokenBeforeMatchingParen =4656 Left.MatchingParen->getPreviousNonComment();4657 if (!TokenBeforeMatchingParen || Left.isNot(TT_TypeDeclarationParen))4658 return true;4659 }4660 // Add a space if the previous token is a pointer qualifier or the closing4661 // parenthesis of __attribute__(()) expression and the style requires spaces4662 // after pointer qualifiers.4663 if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After ||4664 Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&4665 (Left.is(TT_AttributeRParen) ||4666 Left.canBePointerOrReferenceQualifier())) {4667 return true;4668 }4669 if (Left.Tok.isLiteral())4670 return true;4671 // for (auto a = 0, b = 0; const auto & c : {1, 2, 3})4672 if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next &&4673 Right.Next->Next->is(TT_RangeBasedForLoopColon)) {4674 return getTokenPointerOrReferenceAlignment(Right) !=4675 FormatStyle::PAS_Left;4676 }4677 return Left.isNoneOf(TT_PointerOrReference, tok::l_paren) &&4678 (getTokenPointerOrReferenceAlignment(Right) !=4679 FormatStyle::PAS_Left ||4680 (Line.IsMultiVariableDeclStmt &&4681 (Left.NestingLevel == 0 ||4682 (Left.NestingLevel == 1 && startsWithInitStatement(Line)))));4683 }4684 if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&4685 (Left.isNot(TT_PointerOrReference) ||4686 (getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right &&4687 !Line.IsMultiVariableDeclStmt))) {4688 return true;4689 }4690 if (Left.is(TT_PointerOrReference)) {4691 // Add a space if the next token is a pointer qualifier and the style4692 // requires spaces before pointer qualifiers.4693 if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||4694 Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&4695 Right.canBePointerOrReferenceQualifier()) {4696 return true;4697 }4698 // & 14699 if (Right.Tok.isLiteral())4700 return true;4701 // & /* comment4702 if (Right.is(TT_BlockComment))4703 return true;4704 // foo() -> const Bar * override/final4705 // S::foo() & noexcept/requires4706 if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, tok::kw_noexcept,4707 TT_RequiresClause) &&4708 Right.isNot(TT_StartOfName)) {4709 return true;4710 }4711 // & {4712 if (Right.is(tok::l_brace) && Right.is(BK_Block))4713 return true;4714 // for (auto a = 0, b = 0; const auto& c : {1, 2, 3})4715 if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next &&4716 Right.Next->is(TT_RangeBasedForLoopColon)) {4717 return getTokenPointerOrReferenceAlignment(Left) !=4718 FormatStyle::PAS_Right;4719 }4720 if (Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,4721 tok::l_paren)) {4722 return false;4723 }4724 if (getTokenPointerOrReferenceAlignment(Left) == FormatStyle::PAS_Right)4725 return false;4726 // FIXME: Setting IsMultiVariableDeclStmt for the whole line is error-prone,4727 // because it does not take into account nested scopes like lambdas.4728 // In multi-variable declaration statements, attach */& to the variable4729 // independently of the style. However, avoid doing it if we are in a nested4730 // scope, e.g. lambda. We still need to special-case statements with4731 // initializers.4732 if (Line.IsMultiVariableDeclStmt &&4733 (Left.NestingLevel == Line.First->NestingLevel ||4734 ((Left.NestingLevel == Line.First->NestingLevel + 1) &&4735 startsWithInitStatement(Line)))) {4736 return false;4737 }4738 if (!BeforeLeft)4739 return false;4740 if (BeforeLeft->is(tok::coloncolon)) {4741 if (Left.isNot(tok::star))4742 return false;4743 assert(Style.PointerAlignment != FormatStyle::PAS_Right);4744 if (!Right.startsSequence(tok::identifier, tok::r_paren))4745 return true;4746 assert(Right.Next);4747 const auto *LParen = Right.Next->MatchingParen;4748 return !LParen || LParen->isNot(TT_FunctionTypeLParen);4749 }4750 return BeforeLeft->isNoneOf(tok::l_paren, tok::l_square);4751 }4752 // Ensure right pointer alignment with ellipsis e.g. int *...P4753 if (Left.is(tok::ellipsis) && BeforeLeft &&4754 BeforeLeft->isPointerOrReference()) {4755 return Style.PointerAlignment != FormatStyle::PAS_Right;4756 }4757 4758 if (Right.is(tok::star) && Left.is(tok::l_paren))4759 return false;4760 if (Left.is(tok::star) && Right.isPointerOrReference())4761 return false;4762 if (Right.isPointerOrReference()) {4763 const FormatToken *Previous = &Left;4764 while (Previous && Previous->isNot(tok::kw_operator)) {4765 if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) {4766 Previous = Previous->getPreviousNonComment();4767 continue;4768 }4769 if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) {4770 Previous = Previous->MatchingParen->getPreviousNonComment();4771 continue;4772 }4773 if (Previous->is(tok::coloncolon)) {4774 Previous = Previous->getPreviousNonComment();4775 continue;4776 }4777 break;4778 }4779 // Space between the type and the * in:4780 // operator void*()4781 // operator char*()4782 // operator void const*()4783 // operator void volatile*()4784 // operator /*comment*/ const char*()4785 // operator volatile /*comment*/ char*()4786 // operator Foo*()4787 // operator C<T>*()4788 // operator std::Foo*()4789 // operator C<T>::D<U>*()4790 // dependent on PointerAlignment style.4791 if (Previous) {4792 if (Previous->endsSequence(tok::kw_operator))4793 return Style.PointerAlignment != FormatStyle::PAS_Left;4794 if (Previous->isOneOf(tok::kw_const, tok::kw_volatile)) {4795 return (Style.PointerAlignment != FormatStyle::PAS_Left) ||4796 (Style.SpaceAroundPointerQualifiers ==4797 FormatStyle::SAPQ_After) ||4798 (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);4799 }4800 }4801 }4802 if (Style.isCSharp() && Left.is(Keywords.kw_is) && Right.is(tok::l_square))4803 return true;4804 const auto SpaceRequiredForArrayInitializerLSquare =4805 [](const FormatToken &LSquareTok, const FormatStyle &Style) {4806 return Style.SpacesInContainerLiterals ||4807 (Style.isProto() &&4808 Style.Cpp11BracedListStyle == FormatStyle::BLS_Block &&4809 LSquareTok.endsSequence(tok::l_square, tok::colon,4810 TT_SelectorName));4811 };4812 if (Left.is(tok::l_square)) {4813 return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&4814 SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||4815 (Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare,4816 TT_LambdaLSquare) &&4817 Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));4818 }4819 if (Right.is(tok::r_square)) {4820 return Right.MatchingParen &&4821 ((Right.MatchingParen->is(TT_ArrayInitializerLSquare) &&4822 SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen,4823 Style)) ||4824 (Style.SpacesInSquareBrackets &&4825 Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,4826 TT_StructuredBindingLSquare,4827 TT_LambdaLSquare)));4828 }4829 if (Right.is(tok::l_square) &&4830 Right.isNoneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,4831 TT_DesignatedInitializerLSquare,4832 TT_StructuredBindingLSquare, TT_AttributeLSquare) &&4833 Left.isNoneOf(tok::numeric_constant, TT_DictLiteral) &&4834 !(Left.isNot(tok::r_square) && Style.SpaceBeforeSquareBrackets &&4835 Right.is(TT_ArraySubscriptLSquare))) {4836 return false;4837 }4838 if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||4839 (Right.is(tok::r_brace) && Right.MatchingParen &&4840 Right.MatchingParen->isNot(BK_Block))) {4841 return Style.Cpp11BracedListStyle == FormatStyle::BLS_Block ||4842 Style.SpacesInParensOptions.Other;4843 }4844 if (Left.is(TT_BlockComment)) {4845 // No whitespace in x(/*foo=*/1), except for JavaScript.4846 return Style.isJavaScript() || !Left.TokenText.ends_with("=*/");4847 }4848 4849 // Space between template and attribute.4850 // e.g. template <typename T> [[nodiscard]] ...4851 if (Left.is(TT_TemplateCloser) && Right.is(TT_AttributeLSquare))4852 return true;4853 // Space before parentheses common for all languages4854 if (Right.is(tok::l_paren)) {4855 if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))4856 return spaceRequiredBeforeParens(Right);4857 if (Left.isOneOf(TT_RequiresClause,4858 TT_RequiresClauseInARequiresExpression)) {4859 return Style.SpaceBeforeParensOptions.AfterRequiresInClause ||4860 spaceRequiredBeforeParens(Right);4861 }4862 if (Left.is(TT_RequiresExpression)) {4863 return Style.SpaceBeforeParensOptions.AfterRequiresInExpression ||4864 spaceRequiredBeforeParens(Right);4865 }4866 if (Left.isOneOf(TT_AttributeRParen, TT_AttributeRSquare))4867 return true;4868 if (Left.is(TT_ForEachMacro)) {4869 return Style.SpaceBeforeParensOptions.AfterForeachMacros ||4870 spaceRequiredBeforeParens(Right);4871 }4872 if (Left.is(TT_IfMacro)) {4873 return Style.SpaceBeforeParensOptions.AfterIfMacros ||4874 spaceRequiredBeforeParens(Right);4875 }4876 if (Style.SpaceBeforeParens == FormatStyle::SBPO_Custom &&4877 Left.isPlacementOperator() &&4878 Right.isNot(TT_OverloadedOperatorLParen) &&4879 !(Line.MightBeFunctionDecl && Left.is(TT_FunctionDeclarationName))) {4880 const auto *RParen = Right.MatchingParen;4881 return Style.SpaceBeforeParensOptions.AfterPlacementOperator ||4882 (RParen && RParen->is(TT_CastRParen));4883 }4884 if (Line.Type == LT_ObjCDecl)4885 return true;4886 if (Left.is(tok::semi))4887 return true;4888 if (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while, tok::kw_switch,4889 tok::kw_case, TT_ForEachMacro, TT_ObjCForIn) ||4890 Left.isIf(Line.Type != LT_PreprocessorDirective) ||4891 Right.is(TT_ConditionLParen)) {4892 return Style.SpaceBeforeParensOptions.AfterControlStatements ||4893 spaceRequiredBeforeParens(Right);4894 }4895 4896 // TODO add Operator overloading specific Options to4897 // SpaceBeforeParensOptions4898 if (Right.is(TT_OverloadedOperatorLParen))4899 return spaceRequiredBeforeParens(Right);4900 // Function declaration or definition4901 if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) {4902 if (spaceRequiredBeforeParens(Right))4903 return true;4904 const auto &Options = Style.SpaceBeforeParensOptions;4905 return Line.mightBeFunctionDefinition()4906 ? Options.AfterFunctionDefinitionName4907 : Options.AfterFunctionDeclarationName;4908 }4909 // Lambda4910 if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) &&4911 Left.MatchingParen && Left.MatchingParen->is(TT_LambdaLSquare)) {4912 return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||4913 spaceRequiredBeforeParens(Right);4914 }4915 if (!BeforeLeft || BeforeLeft->isNoneOf(tok::period, tok::arrow)) {4916 if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) {4917 return Style.SpaceBeforeParensOptions.AfterControlStatements ||4918 spaceRequiredBeforeParens(Right);4919 }4920 if (Left.isPlacementOperator() ||4921 (Left.is(tok::r_square) && Left.MatchingParen &&4922 Left.MatchingParen->Previous &&4923 Left.MatchingParen->Previous->is(tok::kw_delete))) {4924 return Style.SpaceBeforeParens != FormatStyle::SBPO_Never ||4925 spaceRequiredBeforeParens(Right);4926 }4927 }4928 // Handle builtins like identifiers.4929 if (Line.Type != LT_PreprocessorDirective &&4930 (Left.Tok.getIdentifierInfo() || Left.is(tok::r_paren))) {4931 return spaceRequiredBeforeParens(Right);4932 }4933 return false;4934 }4935 if (Left.is(tok::at) && Right.isNot(tok::objc_not_keyword))4936 return false;4937 if (Right.is(TT_UnaryOperator)) {4938 return Left.isNoneOf(tok::l_paren, tok::l_square, tok::at) &&4939 (Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr));4940 }4941 // No space between the variable name and the initializer list.4942 // A a1{1};4943 // Verilog doesn't have such syntax, but it has word operators that are C++4944 // identifiers like `a inside {b, c}`. So the rule is not applicable.4945 if (!Style.isVerilog() &&4946 (Left.isOneOf(tok::identifier, tok::greater, tok::r_square,4947 tok::r_paren) ||4948 Left.isTypeName(LangOpts)) &&4949 Right.is(tok::l_brace) && Right.getNextNonComment() &&4950 Right.isNot(BK_Block)) {4951 return false;4952 }4953 if (Left.is(tok::period) || Right.is(tok::period))4954 return false;4955 // u#str, U#str, L#str, u8#str4956 // uR#str, UR#str, LR#str, u8R#str4957 if (Right.is(tok::hash) && Left.is(tok::identifier) &&4958 (Left.TokenText == "L" || Left.TokenText == "u" ||4959 Left.TokenText == "U" || Left.TokenText == "u8" ||4960 Left.TokenText == "LR" || Left.TokenText == "uR" ||4961 Left.TokenText == "UR" || Left.TokenText == "u8R")) {4962 return false;4963 }4964 if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&4965 Left.MatchingParen->Previous &&4966 Left.MatchingParen->Previous->isOneOf(tok::period, tok::coloncolon)) {4967 // Java call to generic function with explicit type:4968 // A.<B<C<...>>>DoSomething();4969 // A::<B<C<...>>>DoSomething(); // With a Java 8 method reference.4970 return false;4971 }4972 if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))4973 return false;4974 if (Left.is(tok::l_brace) && Left.endsSequence(TT_DictLiteral, tok::at)) {4975 // Objective-C dictionary literal -> no space after opening brace.4976 return false;4977 }4978 if (Right.is(tok::r_brace) && Right.MatchingParen &&4979 Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at)) {4980 // Objective-C dictionary literal -> no space before closing brace.4981 return false;4982 }4983 if (Right.is(TT_TrailingAnnotation) && Right.isOneOf(tok::amp, tok::ampamp) &&4984 Left.isOneOf(tok::kw_const, tok::kw_volatile) &&4985 (!Right.Next || Right.Next->is(tok::semi))) {4986 // Match const and volatile ref-qualifiers without any additional4987 // qualifiers such as4988 // void Fn() const &;4989 return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;4990 }4991 4992 return true;4993}4994 4995bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,4996 const FormatToken &Right) const {4997 const FormatToken &Left = *Right.Previous;4998 4999 // If the token is finalized don't touch it (as it could be in a5000 // clang-format-off section).5001 if (Left.Finalized)5002 return Right.hasWhitespaceBefore();5003 5004 const bool IsVerilog = Style.isVerilog();5005 assert(!IsVerilog || !IsCpp);5006 5007 // Never ever merge two words.5008 if (Keywords.isWordLike(Right, IsVerilog) &&5009 Keywords.isWordLike(Left, IsVerilog)) {5010 return true;5011 }5012 5013 // Leave a space between * and /* to avoid C4138 `comment end` found outside5014 // of comment.5015 if (Left.is(tok::star) && Right.is(tok::comment))5016 return true;5017 5018 if (Left.is(tok::l_brace) && Right.is(tok::r_brace) &&5019 Left.Children.empty()) {5020 if (Left.is(BK_Block))5021 return Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never;5022 if (Style.Cpp11BracedListStyle != FormatStyle::BLS_Block) {5023 return Style.SpacesInParens == FormatStyle::SIPO_Custom &&5024 Style.SpacesInParensOptions.InEmptyParentheses;5025 }5026 return Style.SpaceInEmptyBraces == FormatStyle::SIEB_Always;5027 }5028 5029 const auto *BeforeLeft = Left.Previous;5030 5031 if (IsCpp) {5032 if (Left.is(TT_OverloadedOperator) &&5033 Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {5034 return true;5035 }5036 // Space between UDL and dot: auto b = 4s .count();5037 if (Right.is(tok::period) && Left.is(tok::numeric_constant))5038 return true;5039 // Space between import <iostream>.5040 // or import .....;5041 if (Left.is(Keywords.kw_import) &&5042 Right.isOneOf(tok::less, tok::ellipsis) &&5043 (!BeforeLeft || BeforeLeft->is(tok::kw_export))) {5044 return true;5045 }5046 // Space between `module :` and `import :`.5047 if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&5048 Right.is(TT_ModulePartitionColon)) {5049 return true;5050 }5051 5052 if (Right.is(TT_AfterPPDirective))5053 return true;5054 5055 // No space between import foo:bar but keep a space between import :bar;5056 if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))5057 return false;5058 // No space between :bar;5059 if (Left.is(TT_ModulePartitionColon) &&5060 Right.isOneOf(tok::identifier, tok::kw_private)) {5061 return false;5062 }5063 if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&5064 Line.First->is(Keywords.kw_import)) {5065 return false;5066 }5067 // Space in __attribute__((attr)) ::type.5068 if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) &&5069 Right.is(tok::coloncolon)) {5070 return true;5071 }5072 5073 if (Left.is(tok::kw_operator))5074 return Right.is(tok::coloncolon) || Style.SpaceAfterOperatorKeyword;5075 if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&5076 !Left.opensScope() && Style.SpaceBeforeCpp11BracedList) {5077 return true;5078 }5079 if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) &&5080 Right.is(TT_TemplateOpener)) {5081 return true;5082 }5083 // C++ Core Guidelines suppression tag, e.g. `[[suppress(type.5)]]`.5084 if (Left.is(tok::identifier) && Right.is(tok::numeric_constant))5085 return Right.TokenText[0] != '.';5086 // `Left` is a keyword (including C++ alternative operator) or identifier.5087 if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral())5088 return true;5089 } else if (Style.isProto()) {5090 if (Right.is(tok::period) && !(BeforeLeft && BeforeLeft->is(tok::period)) &&5091 Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,5092 Keywords.kw_repeated, Keywords.kw_extend)) {5093 return true;5094 }5095 if (Right.is(tok::l_paren) &&5096 Left.isOneOf(Keywords.kw_returns, Keywords.kw_option)) {5097 return true;5098 }5099 if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))5100 return true;5101 // Slashes occur in text protocol extension syntax: [type/type] { ... }.5102 if (Left.is(tok::slash) || Right.is(tok::slash))5103 return false;5104 if (Left.MatchingParen &&5105 Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&5106 Right.isOneOf(tok::l_brace, tok::less)) {5107 return Style.Cpp11BracedListStyle == FormatStyle::BLS_Block;5108 }5109 // A percent is probably part of a formatting specification, such as %lld.5110 if (Left.is(tok::percent))5111 return false;5112 // Preserve the existence of a space before a percent for cases like 0x%04x5113 // and "%d %d"5114 if (Left.is(tok::numeric_constant) && Right.is(tok::percent))5115 return Right.hasWhitespaceBefore();5116 } else if (Style.isJson()) {5117 if (Right.is(tok::colon) && Left.is(tok::string_literal))5118 return Style.SpaceBeforeJsonColon;5119 } else if (Style.isCSharp()) {5120 // Require spaces around '{' and before '}' unless they appear in5121 // interpolated strings. Interpolated strings are merged into a single token5122 // so cannot have spaces inserted by this function.5123 5124 // No space between 'this' and '['5125 if (Left.is(tok::kw_this) && Right.is(tok::l_square))5126 return false;5127 5128 // No space between 'new' and '('5129 if (Left.is(tok::kw_new) && Right.is(tok::l_paren))5130 return false;5131 5132 // Space before { (including space within '{ {').5133 if (Right.is(tok::l_brace))5134 return true;5135 5136 // Spaces inside braces.5137 if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))5138 return true;5139 5140 if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))5141 return true;5142 5143 // Spaces around '=>'.5144 if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow))5145 return true;5146 5147 // No spaces around attribute target colons5148 if (Left.is(TT_AttributeColon) || Right.is(TT_AttributeColon))5149 return false;5150 5151 // space between type and variable e.g. Dictionary<string,string> foo;5152 if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))5153 return true;5154 5155 // spaces inside square brackets.5156 if (Left.is(tok::l_square) || Right.is(tok::r_square))5157 return Style.SpacesInSquareBrackets;5158 5159 // No space before ? in nullable types.5160 if (Right.is(TT_CSharpNullable))5161 return false;5162 5163 // No space before null forgiving '!'.5164 if (Right.is(TT_NonNullAssertion))5165 return false;5166 5167 // No space between consecutive commas '[,,]'.5168 if (Left.is(tok::comma) && Right.is(tok::comma))5169 return false;5170 5171 // space after var in `var (key, value)`5172 if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))5173 return true;5174 5175 // space between keywords and paren e.g. "using ("5176 if (Right.is(tok::l_paren)) {5177 if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when,5178 Keywords.kw_lock)) {5179 return Style.SpaceBeforeParensOptions.AfterControlStatements ||5180 spaceRequiredBeforeParens(Right);5181 }5182 }5183 5184 // space between method modifier and opening parenthesis of a tuple return5185 // type5186 if ((Left.isAccessSpecifierKeyword() ||5187 Left.isOneOf(tok::kw_virtual, tok::kw_extern, tok::kw_static,5188 Keywords.kw_internal, Keywords.kw_abstract,5189 Keywords.kw_sealed, Keywords.kw_override,5190 Keywords.kw_async, Keywords.kw_unsafe)) &&5191 Right.is(tok::l_paren)) {5192 return true;5193 }5194 } else if (Style.isJavaScript()) {5195 if (Left.is(TT_FatArrow))5196 return true;5197 // for await ( ...5198 if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && BeforeLeft &&5199 BeforeLeft->is(tok::kw_for)) {5200 return true;5201 }5202 if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&5203 Right.MatchingParen) {5204 const FormatToken *Next = Right.MatchingParen->getNextNonComment();5205 // An async arrow function, for example: `x = async () => foo();`,5206 // as opposed to calling a function called async: `x = async();`5207 if (Next && Next->is(TT_FatArrow))5208 return true;5209 }5210 if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) ||5211 (Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) {5212 return false;5213 }5214 // In tagged template literals ("html`bar baz`"), there is no space between5215 // the tag identifier and the template string.5216 if (Keywords.isJavaScriptIdentifier(Left,5217 /* AcceptIdentifierName= */ false) &&5218 Right.is(TT_TemplateString)) {5219 return false;5220 }5221 if (Right.is(tok::star) &&5222 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield)) {5223 return false;5224 }5225 if (Right.isOneOf(tok::l_brace, tok::l_square) &&5226 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,5227 Keywords.kw_extends, Keywords.kw_implements)) {5228 return true;5229 }5230 if (Right.is(tok::l_paren)) {5231 // JS methods can use some keywords as names (e.g. `delete()`).5232 if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())5233 return false;5234 // Valid JS method names can include keywords, e.g. `foo.delete()` or5235 // `bar.instanceof()`. Recognize call positions by preceding period.5236 if (BeforeLeft && BeforeLeft->is(tok::period) &&5237 Left.Tok.getIdentifierInfo()) {5238 return false;5239 }5240 // Additional unary JavaScript operators that need a space after.5241 if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,5242 tok::kw_void)) {5243 return true;5244 }5245 }5246 // `foo as const;` casts into a const type.5247 if (Left.endsSequence(tok::kw_const, Keywords.kw_as))5248 return false;5249 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,5250 tok::kw_const) ||5251 // "of" is only a keyword if it appears after another identifier5252 // (e.g. as "const x of y" in a for loop), or after a destructuring5253 // operation (const [x, y] of z, const {a, b} of c).5254 (Left.is(Keywords.kw_of) && BeforeLeft &&5255 BeforeLeft->isOneOf(tok::identifier, tok::r_square, tok::r_brace))) &&5256 (!BeforeLeft || BeforeLeft->isNot(tok::period))) {5257 return true;5258 }5259 if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && BeforeLeft &&5260 BeforeLeft->is(tok::period) && Right.is(tok::l_paren)) {5261 return false;5262 }5263 if (Left.is(Keywords.kw_as) &&5264 Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) {5265 return true;5266 }5267 if (Left.is(tok::kw_default) && BeforeLeft &&5268 BeforeLeft->is(tok::kw_export)) {5269 return true;5270 }5271 if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))5272 return true;5273 if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))5274 return false;5275 if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))5276 return false;5277 if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) &&5278 Line.First->isOneOf(Keywords.kw_import, tok::kw_export)) {5279 return false;5280 }5281 if (Left.is(tok::ellipsis))5282 return false;5283 if (Left.is(TT_TemplateCloser) &&5284 Right.isNoneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,5285 Keywords.kw_implements, Keywords.kw_extends)) {5286 // Type assertions ('<type>expr') are not followed by whitespace. Other5287 // locations that should have whitespace following are identified by the5288 // above set of follower tokens.5289 return false;5290 }5291 if (Right.is(TT_NonNullAssertion))5292 return false;5293 if (Left.is(TT_NonNullAssertion) &&5294 Right.isOneOf(Keywords.kw_as, Keywords.kw_in)) {5295 return true; // "x! as string", "x! in y"5296 }5297 } else if (Style.isJava()) {5298 if (Left.is(TT_CaseLabelArrow) || Right.is(TT_CaseLabelArrow))5299 return true;5300 if (Left.is(tok::r_square) && Right.is(tok::l_brace))5301 return true;5302 // spaces inside square brackets.5303 if (Left.is(tok::l_square) || Right.is(tok::r_square))5304 return Style.SpacesInSquareBrackets;5305 5306 if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) {5307 return Style.SpaceBeforeParensOptions.AfterControlStatements ||5308 spaceRequiredBeforeParens(Right);5309 }5310 if ((Left.isAccessSpecifierKeyword() ||5311 Left.isOneOf(tok::kw_static, Keywords.kw_final, Keywords.kw_abstract,5312 Keywords.kw_native)) &&5313 Right.is(TT_TemplateOpener)) {5314 return true;5315 }5316 } else if (IsVerilog) {5317 // An escaped identifier ends with whitespace.5318 if (Left.is(tok::identifier) && Left.TokenText[0] == '\\')5319 return true;5320 // Add space between things in a primitive's state table unless in a5321 // transition like `(0?)`.5322 if ((Left.is(TT_VerilogTableItem) &&5323 Right.isNoneOf(tok::r_paren, tok::semi)) ||5324 (Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) {5325 const FormatToken *Next = Right.getNextNonComment();5326 return !(Next && Next->is(tok::r_paren));5327 }5328 // Don't add space within a delay like `#0`.5329 if (Left.isNot(TT_BinaryOperator) &&5330 Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) {5331 return false;5332 }5333 // Add space after a delay.5334 if (Right.isNot(tok::semi) &&5335 (Left.endsSequence(tok::numeric_constant, Keywords.kw_verilogHash) ||5336 Left.endsSequence(tok::numeric_constant,5337 Keywords.kw_verilogHashHash) ||5338 (Left.is(tok::r_paren) && Left.MatchingParen &&5339 Left.MatchingParen->endsSequence(tok::l_paren, tok::at)))) {5340 return true;5341 }5342 // Don't add embedded spaces in a number literal like `16'h1?ax` or an array5343 // literal like `'{}`.5344 if (Left.is(Keywords.kw_apostrophe) ||5345 (Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) {5346 return false;5347 }5348 // Add spaces around the implication operator `->`.5349 if (Left.is(tok::arrow) || Right.is(tok::arrow))5350 return true;5351 // Don't add spaces between two at signs. Like in a coverage event.5352 // Don't add spaces between at and a sensitivity list like5353 // `@(posedge clk)`.5354 if (Left.is(tok::at) && Right.isOneOf(tok::l_paren, tok::star, tok::at))5355 return false;5356 // Add space between the type name and dimension like `logic [1:0]`.5357 if (Right.is(tok::l_square) &&5358 Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) {5359 return true;5360 }5361 // In a tagged union expression, there should be a space after the tag.5362 if (Right.isOneOf(tok::period, Keywords.kw_apostrophe) &&5363 Keywords.isVerilogIdentifier(Left) && Left.getPreviousNonComment() &&5364 Left.getPreviousNonComment()->is(Keywords.kw_tagged)) {5365 return true;5366 }5367 // Don't add spaces between a casting type and the quote or repetition count5368 // and the brace. The case of tagged union expressions is handled by the5369 // previous rule.5370 if ((Right.is(Keywords.kw_apostrophe) ||5371 (Right.is(BK_BracedInit) && Right.is(tok::l_brace))) &&5372 Left.isNoneOf(Keywords.kw_assign, Keywords.kw_unique) &&5373 !Keywords.isVerilogWordOperator(Left) &&5374 (Left.isOneOf(tok::r_square, tok::r_paren, tok::r_brace,5375 tok::numeric_constant) ||5376 Keywords.isWordLike(Left))) {5377 return false;5378 }5379 // Don't add spaces in imports like `import foo::*;`.5380 if ((Right.is(tok::star) && Left.is(tok::coloncolon)) ||5381 (Left.is(tok::star) && Right.is(tok::semi))) {5382 return false;5383 }5384 // Add space in attribute like `(* ASYNC_REG = "TRUE" *)`.5385 if (Left.endsSequence(tok::star, tok::l_paren) && Right.is(tok::identifier))5386 return true;5387 // Add space before drive strength like in `wire (strong1, pull0)`.5388 if (Right.is(tok::l_paren) && Right.is(TT_VerilogStrength))5389 return true;5390 // Don't add space in a streaming concatenation like `{>>{j}}`.5391 if ((Left.is(tok::l_brace) &&5392 Right.isOneOf(tok::lessless, tok::greatergreater)) ||5393 (Left.endsSequence(tok::lessless, tok::l_brace) ||5394 Left.endsSequence(tok::greatergreater, tok::l_brace))) {5395 return false;5396 }5397 } else if (Style.isTableGen()) {5398 // Avoid to connect [ and {. [{ is start token of multiline string.5399 if (Left.is(tok::l_square) && Right.is(tok::l_brace))5400 return true;5401 if (Left.is(tok::r_brace) && Right.is(tok::r_square))5402 return true;5403 // Do not insert around colon in DAGArg and cond operator.5404 if (Right.isOneOf(TT_TableGenDAGArgListColon,5405 TT_TableGenDAGArgListColonToAlign) ||5406 Left.isOneOf(TT_TableGenDAGArgListColon,5407 TT_TableGenDAGArgListColonToAlign)) {5408 return false;5409 }5410 if (Right.is(TT_TableGenCondOperatorColon))5411 return false;5412 if (Left.isOneOf(TT_TableGenDAGArgOperatorID,5413 TT_TableGenDAGArgOperatorToBreak) &&5414 Right.isNot(TT_TableGenDAGArgCloser)) {5415 return true;5416 }5417 // Do not insert bang operators and consequent openers.5418 if (Right.isOneOf(tok::l_paren, tok::less) &&5419 Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {5420 return false;5421 }5422 // Trailing paste requires space before '{' or ':', the case in name values.5423 // Not before ';', the case in normal values.5424 if (Left.is(TT_TableGenTrailingPasteOperator) &&5425 Right.isOneOf(tok::l_brace, tok::colon)) {5426 return true;5427 }5428 // Otherwise paste operator does not prefer space around.5429 if (Left.is(tok::hash) || Right.is(tok::hash))5430 return false;5431 // Sure not to connect after defining keywords.5432 if (Keywords.isTableGenDefinition(Left))5433 return true;5434 }5435 5436 if (Left.is(TT_ImplicitStringLiteral))5437 return Right.hasWhitespaceBefore();5438 if (Line.Type == LT_ObjCMethodDecl) {5439 if (Left.is(TT_ObjCMethodSpecifier))5440 return true;5441 if (Left.is(tok::r_paren) && Left.isNot(TT_AttributeRParen) &&5442 canBeObjCSelectorComponent(Right)) {5443 // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a5444 // keyword in Objective-C, and '+ (instancetype)new;' is a standard class5445 // method declaration.5446 return false;5447 }5448 }5449 if (Line.Type == LT_ObjCProperty &&5450 (Right.is(tok::equal) || Left.is(tok::equal))) {5451 return false;5452 }5453 5454 if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||5455 Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) {5456 return true;5457 }5458 if (Left.is(tok::comma) && Right.isNot(TT_OverloadedOperatorLParen) &&5459 // In an unexpanded macro call we only find the parentheses and commas5460 // in a line; the commas and closing parenthesis do not require a space.5461 (Left.Children.empty() || !Left.MacroParent)) {5462 return true;5463 }5464 if (Right.is(tok::comma))5465 return false;5466 if (Right.is(TT_ObjCBlockLParen))5467 return true;5468 if (Right.is(TT_CtorInitializerColon))5469 return Style.SpaceBeforeCtorInitializerColon;5470 if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)5471 return false;5472 if (Right.is(TT_RangeBasedForLoopColon) &&5473 !Style.SpaceBeforeRangeBasedForLoopColon) {5474 return false;5475 }5476 if (Left.is(TT_BitFieldColon)) {5477 return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||5478 Style.BitFieldColonSpacing == FormatStyle::BFCS_After;5479 }5480 if (Right.is(tok::colon)) {5481 if (Right.is(TT_CaseLabelColon))5482 return Style.SpaceBeforeCaseColon;5483 if (Right.is(TT_GotoLabelColon))5484 return false;5485 // `private:` and `public:`.5486 if (!Right.getNextNonComment())5487 return false;5488 if (Right.isOneOf(TT_ObjCSelector, TT_ObjCMethodExpr))5489 return false;5490 if (Left.is(tok::question))5491 return false;5492 if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))5493 return false;5494 if (Right.is(TT_DictLiteral))5495 return Style.SpacesInContainerLiterals;5496 if (Right.is(TT_AttributeColon))5497 return false;5498 if (Right.is(TT_CSharpNamedArgumentColon))5499 return false;5500 if (Right.is(TT_GenericSelectionColon))5501 return false;5502 if (Right.is(TT_BitFieldColon)) {5503 return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||5504 Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;5505 }5506 return true;5507 }5508 // Do not merge "- -" into "--".5509 if ((Left.isOneOf(tok::minus, tok::minusminus) &&5510 Right.isOneOf(tok::minus, tok::minusminus)) ||5511 (Left.isOneOf(tok::plus, tok::plusplus) &&5512 Right.isOneOf(tok::plus, tok::plusplus))) {5513 return true;5514 }5515 if (Left.is(TT_UnaryOperator)) {5516 // Lambda captures allow for a lone &, so "&]" needs to be properly5517 // handled.5518 if (Left.is(tok::amp) && Right.is(tok::r_square))5519 return Style.SpacesInSquareBrackets;5520 if (Left.isNot(tok::exclaim))5521 return false;5522 if (Left.TokenText == "!")5523 return Style.SpaceAfterLogicalNot;5524 assert(Left.TokenText == "not");5525 return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) ||5526 (Right.is(tok::l_paren) && Style.SpaceBeforeParensOptions.AfterNot);5527 }5528 5529 // If the next token is a binary operator or a selector name, we have5530 // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.5531 if (Left.is(TT_CastRParen)) {5532 return Style.SpaceAfterCStyleCast ||5533 Right.isOneOf(TT_BinaryOperator, TT_SelectorName);5534 }5535 5536 auto ShouldAddSpacesInAngles = [this, &Right]() {5537 if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)5538 return true;5539 if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)5540 return Right.hasWhitespaceBefore();5541 return false;5542 };5543 5544 if (Left.is(tok::greater) && Right.is(tok::greater)) {5545 if (Style.isTextProto() ||5546 (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral))) {5547 return Style.Cpp11BracedListStyle == FormatStyle::BLS_Block;5548 }5549 return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&5550 ((Style.Standard < FormatStyle::LS_Cpp11) ||5551 ShouldAddSpacesInAngles());5552 }5553 if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||5554 Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||5555 (Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod))) {5556 return false;5557 }5558 if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&5559 Right.getPrecedence() == prec::Assignment) {5560 return false;5561 }5562 if (Style.isJava() && Right.is(tok::coloncolon) &&5563 Left.isOneOf(tok::identifier, tok::kw_this)) {5564 return false;5565 }5566 if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) {5567 // Generally don't remove existing spaces between an identifier and "::".5568 // The identifier might actually be a macro name such as ALWAYS_INLINE. If5569 // this turns out to be too lenient, add analysis of the identifier itself.5570 return Right.hasWhitespaceBefore();5571 }5572 if (Right.is(tok::coloncolon) &&5573 Left.isNoneOf(tok::l_brace, tok::comment, tok::l_paren)) {5574 // Put a space between < and :: in vector< ::std::string >5575 return (Left.is(TT_TemplateOpener) &&5576 ((Style.Standard < FormatStyle::LS_Cpp11) ||5577 ShouldAddSpacesInAngles())) ||5578 Left.isNoneOf(tok::l_paren, tok::r_paren, tok::l_square,5579 tok::kw___super, TT_TemplateOpener,5580 TT_TemplateCloser) ||5581 (Left.is(tok::l_paren) && Style.SpacesInParensOptions.Other);5582 }5583 if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))5584 return ShouldAddSpacesInAngles();5585 if (Left.is(tok::r_paren) && Left.isNot(TT_TypeDeclarationParen) &&5586 Right.is(TT_PointerOrReference) && Right.isOneOf(tok::amp, tok::ampamp)) {5587 return true;5588 }5589 // Space before TT_StructuredBindingLSquare.5590 if (Right.is(TT_StructuredBindingLSquare)) {5591 return Left.isNoneOf(tok::amp, tok::ampamp) ||5592 getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right;5593 }5594 // Space before & or && following a TT_StructuredBindingLSquare.5595 if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&5596 Right.isOneOf(tok::amp, tok::ampamp)) {5597 return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;5598 }5599 if ((Right.is(TT_BinaryOperator) && Left.isNot(tok::l_paren)) ||5600 (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&5601 Right.isNot(tok::r_paren))) {5602 return true;5603 }5604 if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&5605 Left.MatchingParen &&5606 Left.MatchingParen->is(TT_OverloadedOperatorLParen)) {5607 return false;5608 }5609 if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&5610 Line.Type == LT_ImportStatement) {5611 return true;5612 }5613 if (Right.is(TT_TrailingUnaryOperator))5614 return false;5615 if (Left.is(TT_RegexLiteral))5616 return false;5617 return spaceRequiredBetween(Line, Left, Right);5618}5619 5620// Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.5621static bool isAllmanBrace(const FormatToken &Tok) {5622 return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&5623 Tok.isNoneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);5624}5625 5626// Returns 'true' if 'Tok' is a function argument.5627static bool IsFunctionArgument(const FormatToken &Tok) {5628 return Tok.MatchingParen && Tok.MatchingParen->Next &&5629 Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren,5630 tok::r_brace);5631}5632 5633static bool5634isEmptyLambdaAllowed(const FormatToken &Tok,5635 FormatStyle::ShortLambdaStyle ShortLambdaOption) {5636 return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;5637}5638 5639static bool isAllmanLambdaBrace(const FormatToken &Tok) {5640 return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&5641 Tok.isNoneOf(TT_ObjCBlockLBrace, TT_DictLiteral);5642}5643 5644bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,5645 const FormatToken &Right) const {5646 if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0 &&5647 (!Style.RemoveEmptyLinesInUnwrappedLines || &Right == Line.First)) {5648 return true;5649 }5650 5651 const FormatToken &Left = *Right.Previous;5652 5653 if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&5654 Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&5655 Left.ParameterCount > 0) {5656 return true;5657 }5658 5659 // Ignores the first parameter as this will be handled separately by5660 // BreakFunctionDefinitionParameters or AlignAfterOpenBracket.5661 if (Style.BinPackParameters == FormatStyle::BPPS_AlwaysOnePerLine &&5662 Line.MightBeFunctionDecl && !Left.opensScope() &&5663 startsNextParameter(Right, Style)) {5664 return true;5665 }5666 5667 const auto *BeforeLeft = Left.Previous;5668 const auto *AfterRight = Right.Next;5669 5670 if (Style.isCSharp()) {5671 if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&5672 Style.BraceWrapping.AfterFunction) {5673 return true;5674 }5675 if (Right.is(TT_CSharpNamedArgumentColon) ||5676 Left.is(TT_CSharpNamedArgumentColon)) {5677 return false;5678 }5679 if (Right.is(TT_CSharpGenericTypeConstraint))5680 return true;5681 if (AfterRight && AfterRight->is(TT_FatArrow) &&5682 (Right.is(tok::numeric_constant) ||5683 (Right.is(tok::identifier) && Right.TokenText == "_"))) {5684 return true;5685 }5686 5687 // Break after C# [...] and before public/protected/private/internal.5688 if (Left.is(TT_AttributeRSquare) &&5689 (Right.isAccessSpecifier(/*ColonRequired=*/false) ||5690 Right.is(Keywords.kw_internal))) {5691 return true;5692 }5693 // Break between ] and [ but only when there are really 2 attributes.5694 if (Left.is(TT_AttributeRSquare) && Right.is(TT_AttributeLSquare))5695 return true;5696 } else if (Style.isJavaScript()) {5697 // FIXME: This might apply to other languages and token kinds.5698 if (Right.is(tok::string_literal) && Left.is(tok::plus) && BeforeLeft &&5699 BeforeLeft->is(tok::string_literal)) {5700 return true;5701 }5702 if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&5703 BeforeLeft && BeforeLeft->is(tok::equal) &&5704 Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,5705 tok::kw_const) &&5706 // kw_var/kw_let are pseudo-tokens that are tok::identifier, so match5707 // above.5708 Line.First->isNoneOf(Keywords.kw_var, Keywords.kw_let)) {5709 // Object literals on the top level of a file are treated as "enum-style".5710 // Each key/value pair is put on a separate line, instead of bin-packing.5711 return true;5712 }5713 if (Left.is(tok::l_brace) && Line.Level == 0 &&5714 (Line.startsWith(tok::kw_enum) ||5715 Line.startsWith(tok::kw_const, tok::kw_enum) ||5716 Line.startsWith(tok::kw_export, tok::kw_enum) ||5717 Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum))) {5718 // JavaScript top-level enum key/value pairs are put on separate lines5719 // instead of bin-packing.5720 return true;5721 }5722 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && BeforeLeft &&5723 BeforeLeft->is(TT_FatArrow)) {5724 // JS arrow function (=> {...}).5725 switch (Style.AllowShortLambdasOnASingleLine) {5726 case FormatStyle::SLS_All:5727 return false;5728 case FormatStyle::SLS_None:5729 return true;5730 case FormatStyle::SLS_Empty:5731 return !Left.Children.empty();5732 case FormatStyle::SLS_Inline:5733 // allow one-lining inline (e.g. in function call args) and empty arrow5734 // functions.5735 return (Left.NestingLevel == 0 && Line.Level == 0) &&5736 !Left.Children.empty();5737 }5738 llvm_unreachable("Unknown FormatStyle::ShortLambdaStyle enum");5739 }5740 5741 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&5742 !Left.Children.empty()) {5743 // Support AllowShortFunctionsOnASingleLine for JavaScript.5744 return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||5745 Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||5746 (Left.NestingLevel == 0 && Line.Level == 0 &&5747 Style.AllowShortFunctionsOnASingleLine &5748 FormatStyle::SFS_InlineOnly);5749 }5750 } else if (Style.isJava()) {5751 if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight &&5752 AfterRight->is(tok::string_literal)) {5753 return true;5754 }5755 } else if (Style.isVerilog()) {5756 // Break between assignments.5757 if (Left.is(TT_VerilogAssignComma))5758 return true;5759 // Break between ports of different types.5760 if (Left.is(TT_VerilogTypeComma))5761 return true;5762 // Break between ports in a module instantiation and after the parameter5763 // list.5764 if (Style.VerilogBreakBetweenInstancePorts &&5765 (Left.is(TT_VerilogInstancePortComma) ||5766 (Left.is(tok::r_paren) && Keywords.isVerilogIdentifier(Right) &&5767 Left.MatchingParen &&5768 Left.MatchingParen->is(TT_VerilogInstancePortLParen)))) {5769 return true;5770 }5771 // Break after labels. In Verilog labels don't have the 'case' keyword, so5772 // it is hard to identify them in UnwrappedLineParser.5773 if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))5774 return true;5775 } else if (Style.BreakAdjacentStringLiterals &&5776 (IsCpp || Style.isProto() || Style.isTableGen())) {5777 if (Left.isStringLiteral() && Right.isStringLiteral())5778 return true;5779 }5780 5781 // Basic JSON newline processing.5782 if (Style.isJson()) {5783 // Always break after a JSON record opener.5784 // {5785 // }5786 if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace))5787 return true;5788 // Always break after a JSON array opener based on BreakArrays.5789 if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&5790 Right.isNot(tok::r_square)) ||5791 Left.is(tok::comma)) {5792 if (Right.is(tok::l_brace))5793 return true;5794 // scan to the right if an we see an object or an array inside5795 // then break.5796 for (const auto *Tok = &Right; Tok; Tok = Tok->Next) {5797 if (Tok->isOneOf(tok::l_brace, tok::l_square))5798 return true;5799 if (Tok->isOneOf(tok::r_brace, tok::r_square))5800 break;5801 }5802 return Style.BreakArrays;5803 }5804 } else if (Style.isTableGen()) {5805 // Break the comma in side cond operators.5806 // !cond(case1:1,5807 // case2:0);5808 if (Left.is(TT_TableGenCondOperatorComma))5809 return true;5810 if (Left.is(TT_TableGenDAGArgOperatorToBreak) &&5811 Right.isNot(TT_TableGenDAGArgCloser)) {5812 return true;5813 }5814 if (Left.is(TT_TableGenDAGArgListCommaToBreak))5815 return true;5816 if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen &&5817 Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) &&5818 &Left != Right.MatchingParen->Next) {5819 // Check to avoid empty DAGArg such as (ins).5820 return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll;5821 }5822 }5823 5824 if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&5825 Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always) {5826 return true;5827 }5828 5829 // If the last token before a '}', ']', or ')' is a comma or a trailing5830 // comment, the intention is to insert a line break after it in order to make5831 // shuffling around entries easier. Import statements, especially in5832 // JavaScript, can be an exception to this rule.5833 if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) {5834 const FormatToken *BeforeClosingBrace = nullptr;5835 if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||5836 (Style.isJavaScript() && Left.is(tok::l_paren))) &&5837 Left.isNot(BK_Block) && Left.MatchingParen) {5838 BeforeClosingBrace = Left.MatchingParen->Previous;5839 } else if (Right.MatchingParen &&5840 (Right.MatchingParen->isOneOf(tok::l_brace,5841 TT_ArrayInitializerLSquare) ||5842 (Style.isJavaScript() &&5843 Right.MatchingParen->is(tok::l_paren)))) {5844 BeforeClosingBrace = &Left;5845 }5846 if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||5847 BeforeClosingBrace->isTrailingComment())) {5848 return true;5849 }5850 }5851 5852 if (Right.is(tok::comment)) {5853 return Left.isNoneOf(BK_BracedInit, TT_CtorInitializerColon) &&5854 Right.NewlinesBefore > 0 && Right.HasUnescapedNewline;5855 }5856 if (Left.isTrailingComment())5857 return true;5858 if (Left.IsUnterminatedLiteral)5859 return true;5860 5861 if (BeforeLeft && BeforeLeft->is(tok::lessless) &&5862 Left.is(tok::string_literal) && Right.is(tok::lessless) && AfterRight &&5863 AfterRight->is(tok::string_literal)) {5864 return Right.NewlinesBefore > 0;5865 }5866 5867 if (Right.is(TT_RequiresClause)) {5868 switch (Style.RequiresClausePosition) {5869 case FormatStyle::RCPS_OwnLine:5870 case FormatStyle::RCPS_OwnLineWithBrace:5871 case FormatStyle::RCPS_WithFollowing:5872 return true;5873 default:5874 break;5875 }5876 }5877 // Can break after template<> declaration5878 if (Left.ClosesTemplateDeclaration && Left.MatchingParen &&5879 Left.MatchingParen->NestingLevel == 0) {5880 // Put concepts on the next line e.g.5881 // template<typename T>5882 // concept ...5883 if (Right.is(tok::kw_concept))5884 return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always;5885 return Style.BreakTemplateDeclarations == FormatStyle::BTDS_Yes ||5886 (Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&5887 Right.NewlinesBefore > 0);5888 }5889 if (Left.ClosesRequiresClause) {5890 switch (Style.RequiresClausePosition) {5891 case FormatStyle::RCPS_OwnLine:5892 case FormatStyle::RCPS_WithPreceding:5893 return Right.isNot(tok::semi);5894 case FormatStyle::RCPS_OwnLineWithBrace:5895 return Right.isNoneOf(tok::semi, tok::l_brace);5896 default:5897 break;5898 }5899 }5900 if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) {5901 if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon &&5902 (Left.is(TT_CtorInitializerComma) ||5903 Right.is(TT_CtorInitializerColon))) {5904 return true;5905 }5906 5907 if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&5908 Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) {5909 return true;5910 }5911 }5912 if (Style.PackConstructorInitializers < FormatStyle::PCIS_CurrentLine &&5913 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&5914 Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) {5915 return true;5916 }5917 if (Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly) {5918 if ((Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon ||5919 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) &&5920 Right.is(TT_CtorInitializerColon)) {5921 return true;5922 }5923 5924 if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&5925 Left.is(TT_CtorInitializerColon)) {5926 return true;5927 }5928 }5929 // Break only if we have multiple inheritance.5930 if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&5931 Right.is(TT_InheritanceComma)) {5932 return true;5933 }5934 if (Style.BreakInheritanceList == FormatStyle::BILS_AfterComma &&5935 Left.is(TT_InheritanceComma)) {5936 return true;5937 }5938 if (Right.is(tok::string_literal) && Right.TokenText.starts_with("R\"")) {5939 // Multiline raw string literals are special wrt. line breaks. The author5940 // has made a deliberate choice and might have aligned the contents of the5941 // string literal accordingly. Thus, we try keep existing line breaks.5942 return Right.IsMultiline && Right.NewlinesBefore > 0;5943 }5944 if ((Left.is(tok::l_brace) ||5945 (Left.is(tok::less) && BeforeLeft && BeforeLeft->is(tok::equal))) &&5946 Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {5947 // Don't put enums or option definitions onto single lines in protocol5948 // buffers.5949 return true;5950 }5951 if (Right.is(TT_InlineASMBrace))5952 return Right.HasUnescapedNewline;5953 5954 if (isAllmanBrace(Left) || isAllmanBrace(Right)) {5955 auto *FirstNonComment = Line.getFirstNonComment();5956 bool AccessSpecifier =5957 FirstNonComment && (FirstNonComment->is(Keywords.kw_internal) ||5958 FirstNonComment->isAccessSpecifierKeyword());5959 5960 if (Style.BraceWrapping.AfterEnum) {5961 if (Line.startsWith(tok::kw_enum) ||5962 Line.startsWith(tok::kw_typedef, tok::kw_enum)) {5963 return true;5964 }5965 // Ensure BraceWrapping for `public enum A {`.5966 if (AccessSpecifier && FirstNonComment->Next &&5967 FirstNonComment->Next->is(tok::kw_enum)) {5968 return true;5969 }5970 }5971 5972 // Ensure BraceWrapping for `public interface A {`.5973 if (Style.BraceWrapping.AfterClass &&5974 ((AccessSpecifier && FirstNonComment->Next &&5975 FirstNonComment->Next->is(Keywords.kw_interface)) ||5976 Line.startsWith(Keywords.kw_interface))) {5977 return true;5978 }5979 5980 // Don't attempt to interpret struct return types as structs.5981 if (Right.isNot(TT_FunctionLBrace)) {5982 return (Line.startsWith(tok::kw_class) &&5983 Style.BraceWrapping.AfterClass) ||5984 (Line.startsWith(tok::kw_struct) &&5985 Style.BraceWrapping.AfterStruct);5986 }5987 }5988 5989 if (Left.is(TT_ObjCBlockLBrace) &&5990 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {5991 return true;5992 }5993 5994 // Ensure wrapping after __attribute__((XX)) and @interface etc.5995 if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) &&5996 Right.is(TT_ObjCDecl)) {5997 return true;5998 }5999 6000 if (Left.is(TT_LambdaLBrace)) {6001 if (IsFunctionArgument(Left) &&6002 Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline) {6003 return false;6004 }6005 6006 if (Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_None ||6007 Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline ||6008 (!Left.Children.empty() &&6009 Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty)) {6010 return true;6011 }6012 }6013 6014 if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&6015 (Left.isPointerOrReference() || Left.is(TT_TemplateCloser))) {6016 return true;6017 }6018 6019 // Put multiple Java annotation on a new line.6020 if ((Style.isJava() || Style.isJavaScript()) &&6021 Left.is(TT_LeadingJavaAnnotation) &&6022 Right.isNoneOf(TT_LeadingJavaAnnotation, tok::l_paren) &&6023 (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {6024 return true;6025 }6026 6027 if (Right.is(TT_ProtoExtensionLSquare))6028 return true;6029 6030 // In text proto instances if a submessage contains at least 2 entries and at6031 // least one of them is a submessage, like A { ... B { ... } ... },6032 // put all of the entries of A on separate lines by forcing the selector of6033 // the submessage B to be put on a newline.6034 //6035 // Example: these can stay on one line:6036 // a { scalar_1: 1 scalar_2: 2 }6037 // a { b { key: value } }6038 //6039 // and these entries need to be on a new line even if putting them all in one6040 // line is under the column limit:6041 // a {6042 // scalar: 16043 // b { key: value }6044 // }6045 //6046 // We enforce this by breaking before a submessage field that has previous6047 // siblings, *and* breaking before a field that follows a submessage field.6048 //6049 // Be careful to exclude the case [proto.ext] { ... } since the `]` is6050 // the TT_SelectorName there, but we don't want to break inside the brackets.6051 //6052 // Another edge case is @submessage { key: value }, which is a common6053 // substitution placeholder. In this case we want to keep `@` and `submessage`6054 // together.6055 //6056 // We ensure elsewhere that extensions are always on their own line.6057 if (Style.isProto() && Right.is(TT_SelectorName) &&6058 Right.isNot(tok::r_square) && AfterRight) {6059 // Keep `@submessage` together in:6060 // @submessage { key: value }6061 if (Left.is(tok::at))6062 return false;6063 // Look for the scope opener after selector in cases like:6064 // selector { ...6065 // selector: { ...6066 // selector: @base { ...6067 const auto *LBrace = AfterRight;6068 if (LBrace && LBrace->is(tok::colon)) {6069 LBrace = LBrace->Next;6070 if (LBrace && LBrace->is(tok::at)) {6071 LBrace = LBrace->Next;6072 if (LBrace)6073 LBrace = LBrace->Next;6074 }6075 }6076 if (LBrace &&6077 // The scope opener is one of {, [, <:6078 // selector { ... }6079 // selector [ ... ]6080 // selector < ... >6081 //6082 // In case of selector { ... }, the l_brace is TT_DictLiteral.6083 // In case of an empty selector {}, the l_brace is not TT_DictLiteral,6084 // so we check for immediately following r_brace.6085 ((LBrace->is(tok::l_brace) &&6086 (LBrace->is(TT_DictLiteral) ||6087 (LBrace->Next && LBrace->Next->is(tok::r_brace)))) ||6088 LBrace->isOneOf(TT_ArrayInitializerLSquare, tok::less))) {6089 // If Left.ParameterCount is 0, then this submessage entry is not the6090 // first in its parent submessage, and we want to break before this entry.6091 // If Left.ParameterCount is greater than 0, then its parent submessage6092 // might contain 1 or more entries and we want to break before this entry6093 // if it contains at least 2 entries. We deal with this case later by6094 // detecting and breaking before the next entry in the parent submessage.6095 if (Left.ParameterCount == 0)6096 return true;6097 // However, if this submessage is the first entry in its parent6098 // submessage, Left.ParameterCount might be 1 in some cases.6099 // We deal with this case later by detecting an entry6100 // following a closing paren of this submessage.6101 }6102 6103 // If this is an entry immediately following a submessage, it will be6104 // preceded by a closing paren of that submessage, like in:6105 // left---. .---right6106 // v v6107 // sub: { ... } key: value6108 // If there was a comment between `}` an `key` above, then `key` would be6109 // put on a new line anyways.6110 if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))6111 return true;6112 }6113 6114 return false;6115}6116 6117bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,6118 const FormatToken &Right) const {6119 const FormatToken &Left = *Right.Previous;6120 // Language-specific stuff.6121 if (Style.isCSharp()) {6122 if (Left.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon) ||6123 Right.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon)) {6124 return false;6125 }6126 // Only break after commas for generic type constraints.6127 if (Line.First->is(TT_CSharpGenericTypeConstraint))6128 return Left.is(TT_CSharpGenericTypeConstraintComma);6129 // Keep nullable operators attached to their identifiers.6130 if (Right.is(TT_CSharpNullable))6131 return false;6132 } else if (Style.isJava()) {6133 if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,6134 Keywords.kw_implements)) {6135 return false;6136 }6137 if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends,6138 Keywords.kw_implements)) {6139 return true;6140 }6141 } else if (Style.isJavaScript()) {6142 const FormatToken *NonComment = Right.getPreviousNonComment();6143 if (NonComment &&6144 (NonComment->isAccessSpecifierKeyword() ||6145 NonComment->isOneOf(6146 tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,6147 tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,6148 tok::kw_static, Keywords.kw_readonly, Keywords.kw_override,6149 Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set,6150 Keywords.kw_async, Keywords.kw_await))) {6151 return false; // Otherwise automatic semicolon insertion would trigger.6152 }6153 if (Right.NestingLevel == 0 &&6154 (Left.Tok.getIdentifierInfo() ||6155 Left.isOneOf(tok::r_square, tok::r_paren)) &&6156 Right.isOneOf(tok::l_square, tok::l_paren)) {6157 return false; // Otherwise automatic semicolon insertion would trigger.6158 }6159 if (NonComment && NonComment->is(tok::identifier) &&6160 NonComment->TokenText == "asserts") {6161 return false;6162 }6163 if (Left.is(TT_FatArrow) && Right.is(tok::l_brace))6164 return false;6165 if (Left.is(TT_JsTypeColon))6166 return true;6167 // Don't wrap between ":" and "!" of a strict prop init ("field!: type;").6168 if (Left.is(tok::exclaim) && Right.is(tok::colon))6169 return false;6170 // Look for is type annotations like:6171 // function f(): a is B { ... }6172 // Do not break before is in these cases.6173 if (Right.is(Keywords.kw_is)) {6174 const FormatToken *Next = Right.getNextNonComment();6175 // If `is` is followed by a colon, it's likely that it's a dict key, so6176 // ignore it for this check.6177 // For example this is common in Polymer:6178 // Polymer({6179 // is: 'name',6180 // ...6181 // });6182 if (!Next || Next->isNot(tok::colon))6183 return false;6184 }6185 if (Left.is(Keywords.kw_in))6186 return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;6187 if (Right.is(Keywords.kw_in))6188 return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;6189 if (Right.is(Keywords.kw_as))6190 return false; // must not break before as in 'x as type' casts6191 if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {6192 // extends and infer can appear as keywords in conditional types:6193 // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types6194 // do not break before them, as the expressions are subject to ASI.6195 return false;6196 }6197 if (Left.is(Keywords.kw_as))6198 return true;6199 if (Left.is(TT_NonNullAssertion))6200 return true;6201 if (Left.is(Keywords.kw_declare) &&6202 Right.isOneOf(Keywords.kw_module, tok::kw_namespace,6203 Keywords.kw_function, tok::kw_class, tok::kw_enum,6204 Keywords.kw_interface, Keywords.kw_type, Keywords.kw_var,6205 Keywords.kw_let, tok::kw_const)) {6206 // See grammar for 'declare' statements at:6207 // https://github.com/Microsoft/TypeScript/blob/main/doc/spec-ARCHIVED.md#A.106208 return false;6209 }6210 if (Left.isOneOf(Keywords.kw_module, tok::kw_namespace) &&6211 Right.isOneOf(tok::identifier, tok::string_literal)) {6212 return false; // must not break in "module foo { ...}"6213 }6214 if (Right.is(TT_TemplateString) && Right.closesScope())6215 return false;6216 // Don't split tagged template literal so there is a break between the tag6217 // identifier and template string.6218 if (Left.is(tok::identifier) && Right.is(TT_TemplateString))6219 return false;6220 if (Left.is(TT_TemplateString) && Left.opensScope())6221 return true;6222 } else if (Style.isTableGen()) {6223 // Avoid to break after "def", "class", "let" and so on.6224 if (Keywords.isTableGenDefinition(Left))6225 return false;6226 // Avoid to break after '(' in the cases that is in bang operators.6227 if (Right.is(tok::l_paren)) {6228 return Left.isNoneOf(TT_TableGenBangOperator, TT_TableGenCondOperator,6229 TT_TemplateCloser);6230 }6231 // Avoid to break between the value and its suffix part.6232 if (Left.is(TT_TableGenValueSuffix))6233 return false;6234 // Avoid to break around paste operator.6235 if (Left.is(tok::hash) || Right.is(tok::hash))6236 return false;6237 if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator))6238 return false;6239 }6240 6241 // We can break before an r_brace if there was a break after the matching6242 // l_brace, which is tracked by BreakBeforeClosingBrace, or if we are in a6243 // block-indented initialization list.6244 if (Right.is(tok::r_brace)) {6245 return Right.MatchingParen && (Right.MatchingParen->is(BK_Block) ||6246 (Right.isBlockIndentedInitRBrace(Style)));6247 }6248 6249 // We can break before r_paren if we're in a block indented context or6250 // a control statement with an explicit style option.6251 if (Right.is(tok::r_paren)) {6252 if (!Right.MatchingParen)6253 return false;6254 auto Next = Right.Next;6255 if (Next && Next->is(tok::r_paren))6256 Next = Next->Next;6257 if (Next && Next->is(tok::l_paren))6258 return false;6259 const FormatToken *Previous = Right.MatchingParen->Previous;6260 if (!Previous)6261 return false;6262 if (Previous->isIf())6263 return Style.BreakBeforeCloseBracketIf;6264 if (Previous->isLoop(Style))6265 return Style.BreakBeforeCloseBracketLoop;6266 if (Previous->is(tok::kw_switch))6267 return Style.BreakBeforeCloseBracketSwitch;6268 return Style.BreakBeforeCloseBracketFunction;6269 }6270 6271 if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) &&6272 Right.is(TT_TrailingAnnotation) &&6273 Style.BreakBeforeCloseBracketFunction) {6274 return false;6275 }6276 6277 if (Right.is(TT_TemplateCloser))6278 return Style.BreakBeforeTemplateCloser;6279 6280 if (Left.isOneOf(tok::at, tok::objc_interface))6281 return false;6282 if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation))6283 return Right.isNot(tok::l_paren);6284 if (Right.is(TT_PointerOrReference)) {6285 return Line.IsMultiVariableDeclStmt ||6286 (getTokenPointerOrReferenceAlignment(Right) ==6287 FormatStyle::PAS_Right &&6288 !(Right.Next &&6289 Right.Next->isOneOf(TT_FunctionDeclarationName, tok::kw_const)));6290 }6291 if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName,6292 TT_ClassHeadName, TT_QtProperty, tok::kw_operator)) {6293 return true;6294 }6295 if (Left.is(TT_PointerOrReference))6296 return false;6297 if (Right.isTrailingComment()) {6298 // We rely on MustBreakBefore being set correctly here as we should not6299 // change the "binding" behavior of a comment.6300 // The first comment in a braced lists is always interpreted as belonging to6301 // the first list element. Otherwise, it should be placed outside of the6302 // list.6303 return Left.is(BK_BracedInit) ||6304 (Left.is(TT_CtorInitializerColon) && Right.NewlinesBefore > 0 &&6305 Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);6306 }6307 if (Left.is(tok::question) && Right.is(tok::colon))6308 return false;6309 if (Right.isOneOf(TT_ConditionalExpr, tok::question))6310 return Style.BreakBeforeTernaryOperators;6311 if (Left.isOneOf(TT_ConditionalExpr, tok::question))6312 return !Style.BreakBeforeTernaryOperators;6313 if (Left.is(TT_InheritanceColon))6314 return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon;6315 if (Right.is(TT_InheritanceColon))6316 return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon;6317 // When the method parameter has no name, allow breaking before the colon.6318 if (Right.is(TT_ObjCMethodExpr) && Right.isNot(tok::r_square) &&6319 Left.isNot(TT_SelectorName)) {6320 return true;6321 }6322 6323 if (Right.is(tok::colon) &&6324 Right.isNoneOf(TT_CtorInitializerColon, TT_InlineASMColon,6325 TT_BitFieldColon)) {6326 return false;6327 }6328 if (Left.is(tok::colon) && Left.isOneOf(TT_ObjCSelector, TT_ObjCMethodExpr))6329 return true;6330 if (Left.is(tok::colon) && Left.is(TT_DictLiteral)) {6331 if (Style.isProto()) {6332 if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral())6333 return false;6334 // Prevent cases like:6335 //6336 // submessage:6337 // { key: valueeeeeeeeeeee }6338 //6339 // when the snippet does not fit into one line.6340 // Prefer:6341 //6342 // submessage: {6343 // key: valueeeeeeeeeeee6344 // }6345 //6346 // instead, even if it is longer by one line.6347 //6348 // Note that this allows the "{" to go over the column limit6349 // when the column limit is just between ":" and "{", but that does6350 // not happen too often and alternative formattings in this case are6351 // not much better.6352 //6353 // The code covers the cases:6354 //6355 // submessage: { ... }6356 // submessage: < ... >6357 // repeated: [ ... ]6358 if ((Right.isOneOf(tok::l_brace, tok::less) &&6359 Right.is(TT_DictLiteral)) ||6360 Right.is(TT_ArrayInitializerLSquare)) {6361 return false;6362 }6363 }6364 return true;6365 }6366 if (Right.is(tok::r_square) && Right.MatchingParen &&6367 Right.MatchingParen->is(TT_ProtoExtensionLSquare)) {6368 return false;6369 }6370 if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&6371 Right.Next->is(TT_ObjCMethodExpr))) {6372 return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.6373 }6374 if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)6375 return true;6376 if (Right.is(tok::kw_concept))6377 return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never;6378 if (Right.is(TT_RequiresClause))6379 return true;6380 if (Left.ClosesTemplateDeclaration) {6381 return Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave ||6382 Right.NewlinesBefore > 0;6383 }6384 if (Left.is(TT_FunctionAnnotationRParen))6385 return true;6386 if (Left.ClosesRequiresClause)6387 return true;6388 if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen,6389 TT_OverloadedOperator)) {6390 return false;6391 }6392 if (Left.is(TT_RangeBasedForLoopColon))6393 return true;6394 if (Right.is(TT_RangeBasedForLoopColon))6395 return false;6396 if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener))6397 return true;6398 if ((Left.is(tok::greater) && Right.is(tok::greater)) ||6399 (Left.is(tok::less) && Right.is(tok::less))) {6400 return false;6401 }6402 if (Right.is(TT_BinaryOperator) &&6403 Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None &&6404 (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All ||6405 Right.getPrecedence() != prec::Assignment)) {6406 return true;6407 }6408 if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator, tok::kw_operator))6409 return false;6410 if (Left.is(tok::equal) && Right.isNoneOf(tok::kw_default, tok::kw_delete) &&6411 Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0) {6412 return false;6413 }6414 if (Left.is(tok::equal) && Right.is(tok::l_brace) &&6415 Style.Cpp11BracedListStyle == FormatStyle::BLS_Block) {6416 return false;6417 }6418 if (Left.is(TT_AttributeLParen) ||6419 (Left.is(tok::l_paren) && Left.is(TT_TypeDeclarationParen))) {6420 return false;6421 }6422 if (Left.is(tok::l_paren) && Left.Previous &&6423 (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen))) {6424 return false;6425 }6426 if (Right.is(TT_ImplicitStringLiteral))6427 return false;6428 6429 if (Right.is(tok::r_square) && Right.MatchingParen &&6430 Right.MatchingParen->is(TT_LambdaLSquare)) {6431 return false;6432 }6433 6434 // Allow breaking after a trailing annotation, e.g. after a method6435 // declaration.6436 if (Left.is(TT_TrailingAnnotation)) {6437 return Right.isNoneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,6438 tok::less, tok::coloncolon);6439 }6440 6441 if (Right.isAttribute())6442 return true;6443 6444 if (Right.is(TT_AttributeLSquare)) {6445 assert(Left.isNot(tok::l_square));6446 return true;6447 }6448 6449 if (Left.is(tok::identifier) && Right.is(tok::string_literal))6450 return true;6451 6452 if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))6453 return true;6454 6455 if (Left.is(TT_CtorInitializerColon)) {6456 return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&6457 (!Right.isTrailingComment() || Right.NewlinesBefore > 0);6458 }6459 if (Right.is(TT_CtorInitializerColon))6460 return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;6461 if (Left.is(TT_CtorInitializerComma) &&6462 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {6463 return false;6464 }6465 if (Right.is(TT_CtorInitializerComma) &&6466 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {6467 return true;6468 }6469 if (Left.is(TT_InheritanceComma) &&6470 Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) {6471 return false;6472 }6473 if (Right.is(TT_InheritanceComma) &&6474 Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) {6475 return true;6476 }6477 if (Left.is(TT_ArrayInitializerLSquare))6478 return true;6479 if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const))6480 return true;6481 if ((Left.isBinaryOperator() || Left.is(TT_BinaryOperator)) &&6482 Left.isNoneOf(tok::arrowstar, tok::lessless) &&6483 Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All &&6484 (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||6485 Left.getPrecedence() == prec::Assignment)) {6486 return true;6487 }6488 if (Left.is(TT_AttributeLSquare) && Right.is(tok::l_square)) {6489 assert(Right.isNot(TT_AttributeLSquare));6490 return false;6491 }6492 if (Left.is(tok::r_square) && Right.is(TT_AttributeRSquare)) {6493 assert(Left.isNot(TT_AttributeRSquare));6494 return false;6495 }6496 6497 auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;6498 if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) {6499 if (isAllmanLambdaBrace(Left))6500 return !isEmptyLambdaAllowed(Left, ShortLambdaOption);6501 if (isAllmanLambdaBrace(Right))6502 return !isEmptyLambdaAllowed(Right, ShortLambdaOption);6503 }6504 6505 if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) {6506 switch (Style.AllowBreakBeforeNoexceptSpecifier) {6507 case FormatStyle::BBNSS_Never:6508 return false;6509 case FormatStyle::BBNSS_Always:6510 return true;6511 case FormatStyle::BBNSS_OnlyWithParen:6512 return Right.Next && Right.Next->is(tok::l_paren);6513 }6514 }6515 6516 return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,6517 tok::kw_class, tok::kw_struct, tok::comment) ||6518 Right.isMemberAccess() ||6519 Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,6520 tok::colon, tok::l_square, tok::at) ||6521 (Left.is(tok::r_paren) &&6522 Right.isOneOf(tok::identifier, tok::kw_const)) ||6523 (Left.is(tok::l_paren) && Right.isNot(tok::r_paren)) ||6524 (Left.is(TT_TemplateOpener) && Right.isNot(TT_TemplateCloser));6525}6526 6527void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {6528 llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel6529 << ", T=" << Line.Type << ", C=" << Line.IsContinuation6530 << "):\n";6531 const FormatToken *Tok = Line.First;6532 while (Tok) {6533 llvm::errs() << " I=" << Tok->IndentLevel << " M=" << Tok->MustBreakBefore6534 << " C=" << Tok->CanBreakBefore6535 << " T=" << getTokenTypeName(Tok->getType())6536 << " S=" << Tok->SpacesRequiredBefore6537 << " F=" << Tok->Finalized << " B=" << Tok->BlockParameterCount6538 << " BK=" << Tok->getBlockKind() << " P=" << Tok->SplitPenalty6539 << " Name=" << Tok->Tok.getName() << " N=" << Tok->NestingLevel6540 << " L=" << Tok->TotalLength6541 << " PPK=" << Tok->getPackingKind() << " FakeLParens=";6542 for (prec::Level LParen : Tok->FakeLParens)6543 llvm::errs() << LParen << "/";6544 llvm::errs() << " FakeRParens=" << Tok->FakeRParens;6545 llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo();6546 llvm::errs() << " Text='" << Tok->TokenText << "'\n";6547 if (!Tok->Next)6548 assert(Tok == Line.Last);6549 Tok = Tok->Next;6550 }6551 llvm::errs() << "----\n";6552}6553 6554FormatStyle::PointerAlignmentStyle6555TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {6556 assert(Reference.isOneOf(tok::amp, tok::ampamp));6557 switch (Style.ReferenceAlignment) {6558 case FormatStyle::RAS_Pointer:6559 return Style.PointerAlignment;6560 case FormatStyle::RAS_Left:6561 return FormatStyle::PAS_Left;6562 case FormatStyle::RAS_Right:6563 return FormatStyle::PAS_Right;6564 case FormatStyle::RAS_Middle:6565 return FormatStyle::PAS_Middle;6566 }6567 assert(0); //"Unhandled value of ReferenceAlignment"6568 return Style.PointerAlignment;6569}6570 6571FormatStyle::PointerAlignmentStyle6572TokenAnnotator::getTokenPointerOrReferenceAlignment(6573 const FormatToken &PointerOrReference) const {6574 if (PointerOrReference.isOneOf(tok::amp, tok::ampamp))6575 return getTokenReferenceAlignment(PointerOrReference);6576 assert(PointerOrReference.is(tok::star));6577 return Style.PointerAlignment;6578}6579 6580} // namespace format6581} // namespace clang6582