1*06f32e7eSjoerg //===--- FormatToken.h - Format C++ code ------------------------*- C++ -*-===// 2*06f32e7eSjoerg // 3*06f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information. 5*06f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06f32e7eSjoerg // 7*06f32e7eSjoerg //===----------------------------------------------------------------------===// 8*06f32e7eSjoerg /// 9*06f32e7eSjoerg /// \file 10*06f32e7eSjoerg /// This file contains the declaration of the FormatToken, a wrapper 11*06f32e7eSjoerg /// around Token with additional information related to formatting. 12*06f32e7eSjoerg /// 13*06f32e7eSjoerg //===----------------------------------------------------------------------===// 14*06f32e7eSjoerg 15*06f32e7eSjoerg #ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H 16*06f32e7eSjoerg #define LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H 17*06f32e7eSjoerg 18*06f32e7eSjoerg #include "clang/Basic/IdentifierTable.h" 19*06f32e7eSjoerg #include "clang/Basic/OperatorPrecedence.h" 20*06f32e7eSjoerg #include "clang/Format/Format.h" 21*06f32e7eSjoerg #include "clang/Lex/Lexer.h" 22*06f32e7eSjoerg #include <memory> 23*06f32e7eSjoerg #include <unordered_set> 24*06f32e7eSjoerg 25*06f32e7eSjoerg namespace clang { 26*06f32e7eSjoerg namespace format { 27*06f32e7eSjoerg 28*06f32e7eSjoerg #define LIST_TOKEN_TYPES \ 29*06f32e7eSjoerg TYPE(ArrayInitializerLSquare) \ 30*06f32e7eSjoerg TYPE(ArraySubscriptLSquare) \ 31*06f32e7eSjoerg TYPE(AttributeColon) \ 32*06f32e7eSjoerg TYPE(AttributeParen) \ 33*06f32e7eSjoerg TYPE(AttributeSquare) \ 34*06f32e7eSjoerg TYPE(BinaryOperator) \ 35*06f32e7eSjoerg TYPE(BitFieldColon) \ 36*06f32e7eSjoerg TYPE(BlockComment) \ 37*06f32e7eSjoerg TYPE(CastRParen) \ 38*06f32e7eSjoerg TYPE(ConditionalExpr) \ 39*06f32e7eSjoerg TYPE(ConflictAlternative) \ 40*06f32e7eSjoerg TYPE(ConflictEnd) \ 41*06f32e7eSjoerg TYPE(ConflictStart) \ 42*06f32e7eSjoerg TYPE(CtorInitializerColon) \ 43*06f32e7eSjoerg TYPE(CtorInitializerComma) \ 44*06f32e7eSjoerg TYPE(DesignatedInitializerLSquare) \ 45*06f32e7eSjoerg TYPE(DesignatedInitializerPeriod) \ 46*06f32e7eSjoerg TYPE(DictLiteral) \ 47*06f32e7eSjoerg TYPE(ForEachMacro) \ 48*06f32e7eSjoerg TYPE(FunctionAnnotationRParen) \ 49*06f32e7eSjoerg TYPE(FunctionDeclarationName) \ 50*06f32e7eSjoerg TYPE(FunctionLBrace) \ 51*06f32e7eSjoerg TYPE(FunctionTypeLParen) \ 52*06f32e7eSjoerg TYPE(ImplicitStringLiteral) \ 53*06f32e7eSjoerg TYPE(InheritanceColon) \ 54*06f32e7eSjoerg TYPE(InheritanceComma) \ 55*06f32e7eSjoerg TYPE(InlineASMBrace) \ 56*06f32e7eSjoerg TYPE(InlineASMColon) \ 57*06f32e7eSjoerg TYPE(JavaAnnotation) \ 58*06f32e7eSjoerg TYPE(JsComputedPropertyName) \ 59*06f32e7eSjoerg TYPE(JsExponentiation) \ 60*06f32e7eSjoerg TYPE(JsExponentiationEqual) \ 61*06f32e7eSjoerg TYPE(JsFatArrow) \ 62*06f32e7eSjoerg TYPE(JsNonNullAssertion) \ 63*06f32e7eSjoerg TYPE(JsPrivateIdentifier) \ 64*06f32e7eSjoerg TYPE(JsTypeColon) \ 65*06f32e7eSjoerg TYPE(JsTypeOperator) \ 66*06f32e7eSjoerg TYPE(JsTypeOptionalQuestion) \ 67*06f32e7eSjoerg TYPE(LambdaArrow) \ 68*06f32e7eSjoerg TYPE(LambdaLBrace) \ 69*06f32e7eSjoerg TYPE(LambdaLSquare) \ 70*06f32e7eSjoerg TYPE(LeadingJavaAnnotation) \ 71*06f32e7eSjoerg TYPE(LineComment) \ 72*06f32e7eSjoerg TYPE(MacroBlockBegin) \ 73*06f32e7eSjoerg TYPE(MacroBlockEnd) \ 74*06f32e7eSjoerg TYPE(NamespaceMacro) \ 75*06f32e7eSjoerg TYPE(ObjCBlockLBrace) \ 76*06f32e7eSjoerg TYPE(ObjCBlockLParen) \ 77*06f32e7eSjoerg TYPE(ObjCDecl) \ 78*06f32e7eSjoerg TYPE(ObjCForIn) \ 79*06f32e7eSjoerg TYPE(ObjCMethodExpr) \ 80*06f32e7eSjoerg TYPE(ObjCMethodSpecifier) \ 81*06f32e7eSjoerg TYPE(ObjCProperty) \ 82*06f32e7eSjoerg TYPE(ObjCStringLiteral) \ 83*06f32e7eSjoerg TYPE(OverloadedOperator) \ 84*06f32e7eSjoerg TYPE(OverloadedOperatorLParen) \ 85*06f32e7eSjoerg TYPE(PointerOrReference) \ 86*06f32e7eSjoerg TYPE(PureVirtualSpecifier) \ 87*06f32e7eSjoerg TYPE(RangeBasedForLoopColon) \ 88*06f32e7eSjoerg TYPE(RegexLiteral) \ 89*06f32e7eSjoerg TYPE(SelectorName) \ 90*06f32e7eSjoerg TYPE(StartOfName) \ 91*06f32e7eSjoerg TYPE(StatementMacro) \ 92*06f32e7eSjoerg TYPE(StructuredBindingLSquare) \ 93*06f32e7eSjoerg TYPE(TemplateCloser) \ 94*06f32e7eSjoerg TYPE(TemplateOpener) \ 95*06f32e7eSjoerg TYPE(TemplateString) \ 96*06f32e7eSjoerg TYPE(ProtoExtensionLSquare) \ 97*06f32e7eSjoerg TYPE(TrailingAnnotation) \ 98*06f32e7eSjoerg TYPE(TrailingReturnArrow) \ 99*06f32e7eSjoerg TYPE(TrailingUnaryOperator) \ 100*06f32e7eSjoerg TYPE(TypenameMacro) \ 101*06f32e7eSjoerg TYPE(UnaryOperator) \ 102*06f32e7eSjoerg TYPE(CSharpStringLiteral) \ 103*06f32e7eSjoerg TYPE(CSharpNullCoalescing) \ 104*06f32e7eSjoerg TYPE(Unknown) 105*06f32e7eSjoerg 106*06f32e7eSjoerg enum TokenType { 107*06f32e7eSjoerg #define TYPE(X) TT_##X, 108*06f32e7eSjoerg LIST_TOKEN_TYPES 109*06f32e7eSjoerg #undef TYPE 110*06f32e7eSjoerg NUM_TOKEN_TYPES 111*06f32e7eSjoerg }; 112*06f32e7eSjoerg 113*06f32e7eSjoerg /// Determines the name of a token type. 114*06f32e7eSjoerg const char *getTokenTypeName(TokenType Type); 115*06f32e7eSjoerg 116*06f32e7eSjoerg // Represents what type of block a set of braces open. 117*06f32e7eSjoerg enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit }; 118*06f32e7eSjoerg 119*06f32e7eSjoerg // The packing kind of a function's parameters. 120*06f32e7eSjoerg enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive }; 121*06f32e7eSjoerg 122*06f32e7eSjoerg enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break }; 123*06f32e7eSjoerg 124*06f32e7eSjoerg class TokenRole; 125*06f32e7eSjoerg class AnnotatedLine; 126*06f32e7eSjoerg 127*06f32e7eSjoerg /// A wrapper around a \c Token storing information about the 128*06f32e7eSjoerg /// whitespace characters preceding it. 129*06f32e7eSjoerg struct FormatToken { 130*06f32e7eSjoerg FormatToken() {} 131*06f32e7eSjoerg 132*06f32e7eSjoerg /// The \c Token. 133*06f32e7eSjoerg Token Tok; 134*06f32e7eSjoerg 135*06f32e7eSjoerg /// The number of newlines immediately before the \c Token. 136*06f32e7eSjoerg /// 137*06f32e7eSjoerg /// This can be used to determine what the user wrote in the original code 138*06f32e7eSjoerg /// and thereby e.g. leave an empty line between two function definitions. 139*06f32e7eSjoerg unsigned NewlinesBefore = 0; 140*06f32e7eSjoerg 141*06f32e7eSjoerg /// Whether there is at least one unescaped newline before the \c 142*06f32e7eSjoerg /// Token. 143*06f32e7eSjoerg bool HasUnescapedNewline = false; 144*06f32e7eSjoerg 145*06f32e7eSjoerg /// The range of the whitespace immediately preceding the \c Token. 146*06f32e7eSjoerg SourceRange WhitespaceRange; 147*06f32e7eSjoerg 148*06f32e7eSjoerg /// The offset just past the last '\n' in this token's leading 149*06f32e7eSjoerg /// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'. 150*06f32e7eSjoerg unsigned LastNewlineOffset = 0; 151*06f32e7eSjoerg 152*06f32e7eSjoerg /// The width of the non-whitespace parts of the token (or its first 153*06f32e7eSjoerg /// line for multi-line tokens) in columns. 154*06f32e7eSjoerg /// We need this to correctly measure number of columns a token spans. 155*06f32e7eSjoerg unsigned ColumnWidth = 0; 156*06f32e7eSjoerg 157*06f32e7eSjoerg /// Contains the width in columns of the last line of a multi-line 158*06f32e7eSjoerg /// token. 159*06f32e7eSjoerg unsigned LastLineColumnWidth = 0; 160*06f32e7eSjoerg 161*06f32e7eSjoerg /// Whether the token text contains newlines (escaped or not). 162*06f32e7eSjoerg bool IsMultiline = false; 163*06f32e7eSjoerg 164*06f32e7eSjoerg /// Indicates that this is the first token of the file. 165*06f32e7eSjoerg bool IsFirst = false; 166*06f32e7eSjoerg 167*06f32e7eSjoerg /// Whether there must be a line break before this token. 168*06f32e7eSjoerg /// 169*06f32e7eSjoerg /// This happens for example when a preprocessor directive ended directly 170*06f32e7eSjoerg /// before the token. 171*06f32e7eSjoerg bool MustBreakBefore = false; 172*06f32e7eSjoerg 173*06f32e7eSjoerg /// The raw text of the token. 174*06f32e7eSjoerg /// 175*06f32e7eSjoerg /// Contains the raw token text without leading whitespace and without leading 176*06f32e7eSjoerg /// escaped newlines. 177*06f32e7eSjoerg StringRef TokenText; 178*06f32e7eSjoerg 179*06f32e7eSjoerg /// Set to \c true if this token is an unterminated literal. 180*06f32e7eSjoerg bool IsUnterminatedLiteral = 0; 181*06f32e7eSjoerg 182*06f32e7eSjoerg /// Contains the kind of block if this token is a brace. 183*06f32e7eSjoerg BraceBlockKind BlockKind = BK_Unknown; 184*06f32e7eSjoerg 185*06f32e7eSjoerg TokenType Type = TT_Unknown; 186*06f32e7eSjoerg 187*06f32e7eSjoerg /// The number of spaces that should be inserted before this token. 188*06f32e7eSjoerg unsigned SpacesRequiredBefore = 0; 189*06f32e7eSjoerg 190*06f32e7eSjoerg /// \c true if it is allowed to break before this token. 191*06f32e7eSjoerg bool CanBreakBefore = false; 192*06f32e7eSjoerg 193*06f32e7eSjoerg /// \c true if this is the ">" of "template<..>". 194*06f32e7eSjoerg bool ClosesTemplateDeclaration = false; 195*06f32e7eSjoerg 196*06f32e7eSjoerg /// Number of parameters, if this is "(", "[" or "<". 197*06f32e7eSjoerg unsigned ParameterCount = 0; 198*06f32e7eSjoerg 199*06f32e7eSjoerg /// Number of parameters that are nested blocks, 200*06f32e7eSjoerg /// if this is "(", "[" or "<". 201*06f32e7eSjoerg unsigned BlockParameterCount = 0; 202*06f32e7eSjoerg 203*06f32e7eSjoerg /// If this is a bracket ("<", "(", "[" or "{"), contains the kind of 204*06f32e7eSjoerg /// the surrounding bracket. 205*06f32e7eSjoerg tok::TokenKind ParentBracket = tok::unknown; 206*06f32e7eSjoerg 207*06f32e7eSjoerg /// A token can have a special role that can carry extra information 208*06f32e7eSjoerg /// about the token's formatting. 209*06f32e7eSjoerg std::unique_ptr<TokenRole> Role; 210*06f32e7eSjoerg 211*06f32e7eSjoerg /// If this is an opening parenthesis, how are the parameters packed? 212*06f32e7eSjoerg ParameterPackingKind PackingKind = PPK_Inconclusive; 213*06f32e7eSjoerg 214*06f32e7eSjoerg /// The total length of the unwrapped line up to and including this 215*06f32e7eSjoerg /// token. 216*06f32e7eSjoerg unsigned TotalLength = 0; 217*06f32e7eSjoerg 218*06f32e7eSjoerg /// The original 0-based column of this token, including expanded tabs. 219*06f32e7eSjoerg /// The configured TabWidth is used as tab width. 220*06f32e7eSjoerg unsigned OriginalColumn = 0; 221*06f32e7eSjoerg 222*06f32e7eSjoerg /// The length of following tokens until the next natural split point, 223*06f32e7eSjoerg /// or the next token that can be broken. 224*06f32e7eSjoerg unsigned UnbreakableTailLength = 0; 225*06f32e7eSjoerg 226*06f32e7eSjoerg // FIXME: Come up with a 'cleaner' concept. 227*06f32e7eSjoerg /// The binding strength of a token. This is a combined value of 228*06f32e7eSjoerg /// operator precedence, parenthesis nesting, etc. 229*06f32e7eSjoerg unsigned BindingStrength = 0; 230*06f32e7eSjoerg 231*06f32e7eSjoerg /// The nesting level of this token, i.e. the number of surrounding (), 232*06f32e7eSjoerg /// [], {} or <>. 233*06f32e7eSjoerg unsigned NestingLevel = 0; 234*06f32e7eSjoerg 235*06f32e7eSjoerg /// The indent level of this token. Copied from the surrounding line. 236*06f32e7eSjoerg unsigned IndentLevel = 0; 237*06f32e7eSjoerg 238*06f32e7eSjoerg /// Penalty for inserting a line break before this token. 239*06f32e7eSjoerg unsigned SplitPenalty = 0; 240*06f32e7eSjoerg 241*06f32e7eSjoerg /// If this is the first ObjC selector name in an ObjC method 242*06f32e7eSjoerg /// definition or call, this contains the length of the longest name. 243*06f32e7eSjoerg /// 244*06f32e7eSjoerg /// This being set to 0 means that the selectors should not be colon-aligned, 245*06f32e7eSjoerg /// e.g. because several of them are block-type. 246*06f32e7eSjoerg unsigned LongestObjCSelectorName = 0; 247*06f32e7eSjoerg 248*06f32e7eSjoerg /// If this is the first ObjC selector name in an ObjC method 249*06f32e7eSjoerg /// definition or call, this contains the number of parts that the whole 250*06f32e7eSjoerg /// selector consist of. 251*06f32e7eSjoerg unsigned ObjCSelectorNameParts = 0; 252*06f32e7eSjoerg 253*06f32e7eSjoerg /// The 0-based index of the parameter/argument. For ObjC it is set 254*06f32e7eSjoerg /// for the selector name token. 255*06f32e7eSjoerg /// For now calculated only for ObjC. 256*06f32e7eSjoerg unsigned ParameterIndex = 0; 257*06f32e7eSjoerg 258*06f32e7eSjoerg /// Stores the number of required fake parentheses and the 259*06f32e7eSjoerg /// corresponding operator precedence. 260*06f32e7eSjoerg /// 261*06f32e7eSjoerg /// If multiple fake parentheses start at a token, this vector stores them in 262*06f32e7eSjoerg /// reverse order, i.e. inner fake parenthesis first. 263*06f32e7eSjoerg SmallVector<prec::Level, 4> FakeLParens; 264*06f32e7eSjoerg /// Insert this many fake ) after this token for correct indentation. 265*06f32e7eSjoerg unsigned FakeRParens = 0; 266*06f32e7eSjoerg 267*06f32e7eSjoerg /// \c true if this token starts a binary expression, i.e. has at least 268*06f32e7eSjoerg /// one fake l_paren with a precedence greater than prec::Unknown. 269*06f32e7eSjoerg bool StartsBinaryExpression = false; 270*06f32e7eSjoerg /// \c true if this token ends a binary expression. 271*06f32e7eSjoerg bool EndsBinaryExpression = false; 272*06f32e7eSjoerg 273*06f32e7eSjoerg /// If this is an operator (or "."/"->") in a sequence of operators 274*06f32e7eSjoerg /// with the same precedence, contains the 0-based operator index. 275*06f32e7eSjoerg unsigned OperatorIndex = 0; 276*06f32e7eSjoerg 277*06f32e7eSjoerg /// If this is an operator (or "."/"->") in a sequence of operators 278*06f32e7eSjoerg /// with the same precedence, points to the next operator. 279*06f32e7eSjoerg FormatToken *NextOperator = nullptr; 280*06f32e7eSjoerg 281*06f32e7eSjoerg /// Is this token part of a \c DeclStmt defining multiple variables? 282*06f32e7eSjoerg /// 283*06f32e7eSjoerg /// Only set if \c Type == \c TT_StartOfName. 284*06f32e7eSjoerg bool PartOfMultiVariableDeclStmt = false; 285*06f32e7eSjoerg 286*06f32e7eSjoerg /// Does this line comment continue a line comment section? 287*06f32e7eSjoerg /// 288*06f32e7eSjoerg /// Only set to true if \c Type == \c TT_LineComment. 289*06f32e7eSjoerg bool ContinuesLineCommentSection = false; 290*06f32e7eSjoerg 291*06f32e7eSjoerg /// If this is a bracket, this points to the matching one. 292*06f32e7eSjoerg FormatToken *MatchingParen = nullptr; 293*06f32e7eSjoerg 294*06f32e7eSjoerg /// The previous token in the unwrapped line. 295*06f32e7eSjoerg FormatToken *Previous = nullptr; 296*06f32e7eSjoerg 297*06f32e7eSjoerg /// The next token in the unwrapped line. 298*06f32e7eSjoerg FormatToken *Next = nullptr; 299*06f32e7eSjoerg 300*06f32e7eSjoerg /// If this token starts a block, this contains all the unwrapped lines 301*06f32e7eSjoerg /// in it. 302*06f32e7eSjoerg SmallVector<AnnotatedLine *, 1> Children; 303*06f32e7eSjoerg 304*06f32e7eSjoerg /// Stores the formatting decision for the token once it was made. 305*06f32e7eSjoerg FormatDecision Decision = FD_Unformatted; 306*06f32e7eSjoerg 307*06f32e7eSjoerg /// If \c true, this token has been fully formatted (indented and 308*06f32e7eSjoerg /// potentially re-formatted inside), and we do not allow further formatting 309*06f32e7eSjoerg /// changes. 310*06f32e7eSjoerg bool Finalized = false; 311*06f32e7eSjoerg 312*06f32e7eSjoerg bool is(tok::TokenKind Kind) const { return Tok.is(Kind); } 313*06f32e7eSjoerg bool is(TokenType TT) const { return Type == TT; } 314*06f32e7eSjoerg bool is(const IdentifierInfo *II) const { 315*06f32e7eSjoerg return II && II == Tok.getIdentifierInfo(); 316*06f32e7eSjoerg } 317*06f32e7eSjoerg bool is(tok::PPKeywordKind Kind) const { 318*06f32e7eSjoerg return Tok.getIdentifierInfo() && 319*06f32e7eSjoerg Tok.getIdentifierInfo()->getPPKeywordID() == Kind; 320*06f32e7eSjoerg } 321*06f32e7eSjoerg template <typename A, typename B> bool isOneOf(A K1, B K2) const { 322*06f32e7eSjoerg return is(K1) || is(K2); 323*06f32e7eSjoerg } 324*06f32e7eSjoerg template <typename A, typename B, typename... Ts> 325*06f32e7eSjoerg bool isOneOf(A K1, B K2, Ts... Ks) const { 326*06f32e7eSjoerg return is(K1) || isOneOf(K2, Ks...); 327*06f32e7eSjoerg } 328*06f32e7eSjoerg template <typename T> bool isNot(T Kind) const { return !is(Kind); } 329*06f32e7eSjoerg 330*06f32e7eSjoerg bool isIf(bool AllowConstexprMacro = true) const { 331*06f32e7eSjoerg return is(tok::kw_if) || endsSequence(tok::kw_constexpr, tok::kw_if) || 332*06f32e7eSjoerg (endsSequence(tok::identifier, tok::kw_if) && AllowConstexprMacro); 333*06f32e7eSjoerg } 334*06f32e7eSjoerg 335*06f32e7eSjoerg bool closesScopeAfterBlock() const { 336*06f32e7eSjoerg if (BlockKind == BK_Block) 337*06f32e7eSjoerg return true; 338*06f32e7eSjoerg if (closesScope()) 339*06f32e7eSjoerg return Previous->closesScopeAfterBlock(); 340*06f32e7eSjoerg return false; 341*06f32e7eSjoerg } 342*06f32e7eSjoerg 343*06f32e7eSjoerg /// \c true if this token starts a sequence with the given tokens in order, 344*06f32e7eSjoerg /// following the ``Next`` pointers, ignoring comments. 345*06f32e7eSjoerg template <typename A, typename... Ts> 346*06f32e7eSjoerg bool startsSequence(A K1, Ts... Tokens) const { 347*06f32e7eSjoerg return startsSequenceInternal(K1, Tokens...); 348*06f32e7eSjoerg } 349*06f32e7eSjoerg 350*06f32e7eSjoerg /// \c true if this token ends a sequence with the given tokens in order, 351*06f32e7eSjoerg /// following the ``Previous`` pointers, ignoring comments. 352*06f32e7eSjoerg /// For example, given tokens [T1, T2, T3], the function returns true if 353*06f32e7eSjoerg /// 3 tokens ending at this (ignoring comments) are [T3, T2, T1]. In other 354*06f32e7eSjoerg /// words, the tokens passed to this function need to the reverse of the 355*06f32e7eSjoerg /// order the tokens appear in code. 356*06f32e7eSjoerg template <typename A, typename... Ts> 357*06f32e7eSjoerg bool endsSequence(A K1, Ts... Tokens) const { 358*06f32e7eSjoerg return endsSequenceInternal(K1, Tokens...); 359*06f32e7eSjoerg } 360*06f32e7eSjoerg 361*06f32e7eSjoerg bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); } 362*06f32e7eSjoerg 363*06f32e7eSjoerg bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const { 364*06f32e7eSjoerg return Tok.isObjCAtKeyword(Kind); 365*06f32e7eSjoerg } 366*06f32e7eSjoerg 367*06f32e7eSjoerg bool isAccessSpecifier(bool ColonRequired = true) const { 368*06f32e7eSjoerg return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) && 369*06f32e7eSjoerg (!ColonRequired || (Next && Next->is(tok::colon))); 370*06f32e7eSjoerg } 371*06f32e7eSjoerg 372*06f32e7eSjoerg /// Determine whether the token is a simple-type-specifier. 373*06f32e7eSjoerg bool isSimpleTypeSpecifier() const; 374*06f32e7eSjoerg 375*06f32e7eSjoerg bool isObjCAccessSpecifier() const { 376*06f32e7eSjoerg return is(tok::at) && Next && 377*06f32e7eSjoerg (Next->isObjCAtKeyword(tok::objc_public) || 378*06f32e7eSjoerg Next->isObjCAtKeyword(tok::objc_protected) || 379*06f32e7eSjoerg Next->isObjCAtKeyword(tok::objc_package) || 380*06f32e7eSjoerg Next->isObjCAtKeyword(tok::objc_private)); 381*06f32e7eSjoerg } 382*06f32e7eSjoerg 383*06f32e7eSjoerg /// Returns whether \p Tok is ([{ or an opening < of a template or in 384*06f32e7eSjoerg /// protos. 385*06f32e7eSjoerg bool opensScope() const { 386*06f32e7eSjoerg if (is(TT_TemplateString) && TokenText.endswith("${")) 387*06f32e7eSjoerg return true; 388*06f32e7eSjoerg if (is(TT_DictLiteral) && is(tok::less)) 389*06f32e7eSjoerg return true; 390*06f32e7eSjoerg return isOneOf(tok::l_paren, tok::l_brace, tok::l_square, 391*06f32e7eSjoerg TT_TemplateOpener); 392*06f32e7eSjoerg } 393*06f32e7eSjoerg /// Returns whether \p Tok is )]} or a closing > of a template or in 394*06f32e7eSjoerg /// protos. 395*06f32e7eSjoerg bool closesScope() const { 396*06f32e7eSjoerg if (is(TT_TemplateString) && TokenText.startswith("}")) 397*06f32e7eSjoerg return true; 398*06f32e7eSjoerg if (is(TT_DictLiteral) && is(tok::greater)) 399*06f32e7eSjoerg return true; 400*06f32e7eSjoerg return isOneOf(tok::r_paren, tok::r_brace, tok::r_square, 401*06f32e7eSjoerg TT_TemplateCloser); 402*06f32e7eSjoerg } 403*06f32e7eSjoerg 404*06f32e7eSjoerg /// Returns \c true if this is a "." or "->" accessing a member. 405*06f32e7eSjoerg bool isMemberAccess() const { 406*06f32e7eSjoerg return isOneOf(tok::arrow, tok::period, tok::arrowstar) && 407*06f32e7eSjoerg !isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow, 408*06f32e7eSjoerg TT_LambdaArrow); 409*06f32e7eSjoerg } 410*06f32e7eSjoerg 411*06f32e7eSjoerg bool isUnaryOperator() const { 412*06f32e7eSjoerg switch (Tok.getKind()) { 413*06f32e7eSjoerg case tok::plus: 414*06f32e7eSjoerg case tok::plusplus: 415*06f32e7eSjoerg case tok::minus: 416*06f32e7eSjoerg case tok::minusminus: 417*06f32e7eSjoerg case tok::exclaim: 418*06f32e7eSjoerg case tok::tilde: 419*06f32e7eSjoerg case tok::kw_sizeof: 420*06f32e7eSjoerg case tok::kw_alignof: 421*06f32e7eSjoerg return true; 422*06f32e7eSjoerg default: 423*06f32e7eSjoerg return false; 424*06f32e7eSjoerg } 425*06f32e7eSjoerg } 426*06f32e7eSjoerg 427*06f32e7eSjoerg bool isBinaryOperator() const { 428*06f32e7eSjoerg // Comma is a binary operator, but does not behave as such wrt. formatting. 429*06f32e7eSjoerg return getPrecedence() > prec::Comma; 430*06f32e7eSjoerg } 431*06f32e7eSjoerg 432*06f32e7eSjoerg bool isTrailingComment() const { 433*06f32e7eSjoerg return is(tok::comment) && 434*06f32e7eSjoerg (is(TT_LineComment) || !Next || Next->NewlinesBefore > 0); 435*06f32e7eSjoerg } 436*06f32e7eSjoerg 437*06f32e7eSjoerg /// Returns \c true if this is a keyword that can be used 438*06f32e7eSjoerg /// like a function call (e.g. sizeof, typeid, ...). 439*06f32e7eSjoerg bool isFunctionLikeKeyword() const { 440*06f32e7eSjoerg switch (Tok.getKind()) { 441*06f32e7eSjoerg case tok::kw_throw: 442*06f32e7eSjoerg case tok::kw_typeid: 443*06f32e7eSjoerg case tok::kw_return: 444*06f32e7eSjoerg case tok::kw_sizeof: 445*06f32e7eSjoerg case tok::kw_alignof: 446*06f32e7eSjoerg case tok::kw_alignas: 447*06f32e7eSjoerg case tok::kw_decltype: 448*06f32e7eSjoerg case tok::kw_noexcept: 449*06f32e7eSjoerg case tok::kw_static_assert: 450*06f32e7eSjoerg case tok::kw___attribute: 451*06f32e7eSjoerg return true; 452*06f32e7eSjoerg default: 453*06f32e7eSjoerg return false; 454*06f32e7eSjoerg } 455*06f32e7eSjoerg } 456*06f32e7eSjoerg 457*06f32e7eSjoerg /// Returns \c true if this is a string literal that's like a label, 458*06f32e7eSjoerg /// e.g. ends with "=" or ":". 459*06f32e7eSjoerg bool isLabelString() const { 460*06f32e7eSjoerg if (!is(tok::string_literal)) 461*06f32e7eSjoerg return false; 462*06f32e7eSjoerg StringRef Content = TokenText; 463*06f32e7eSjoerg if (Content.startswith("\"") || Content.startswith("'")) 464*06f32e7eSjoerg Content = Content.drop_front(1); 465*06f32e7eSjoerg if (Content.endswith("\"") || Content.endswith("'")) 466*06f32e7eSjoerg Content = Content.drop_back(1); 467*06f32e7eSjoerg Content = Content.trim(); 468*06f32e7eSjoerg return Content.size() > 1 && 469*06f32e7eSjoerg (Content.back() == ':' || Content.back() == '='); 470*06f32e7eSjoerg } 471*06f32e7eSjoerg 472*06f32e7eSjoerg /// Returns actual token start location without leading escaped 473*06f32e7eSjoerg /// newlines and whitespace. 474*06f32e7eSjoerg /// 475*06f32e7eSjoerg /// This can be different to Tok.getLocation(), which includes leading escaped 476*06f32e7eSjoerg /// newlines. 477*06f32e7eSjoerg SourceLocation getStartOfNonWhitespace() const { 478*06f32e7eSjoerg return WhitespaceRange.getEnd(); 479*06f32e7eSjoerg } 480*06f32e7eSjoerg 481*06f32e7eSjoerg prec::Level getPrecedence() const { 482*06f32e7eSjoerg return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true, 483*06f32e7eSjoerg /*CPlusPlus11=*/true); 484*06f32e7eSjoerg } 485*06f32e7eSjoerg 486*06f32e7eSjoerg /// Returns the previous token ignoring comments. 487*06f32e7eSjoerg FormatToken *getPreviousNonComment() const { 488*06f32e7eSjoerg FormatToken *Tok = Previous; 489*06f32e7eSjoerg while (Tok && Tok->is(tok::comment)) 490*06f32e7eSjoerg Tok = Tok->Previous; 491*06f32e7eSjoerg return Tok; 492*06f32e7eSjoerg } 493*06f32e7eSjoerg 494*06f32e7eSjoerg /// Returns the next token ignoring comments. 495*06f32e7eSjoerg const FormatToken *getNextNonComment() const { 496*06f32e7eSjoerg const FormatToken *Tok = Next; 497*06f32e7eSjoerg while (Tok && Tok->is(tok::comment)) 498*06f32e7eSjoerg Tok = Tok->Next; 499*06f32e7eSjoerg return Tok; 500*06f32e7eSjoerg } 501*06f32e7eSjoerg 502*06f32e7eSjoerg /// Returns \c true if this tokens starts a block-type list, i.e. a 503*06f32e7eSjoerg /// list that should be indented with a block indent. 504*06f32e7eSjoerg bool opensBlockOrBlockTypeList(const FormatStyle &Style) const { 505*06f32e7eSjoerg if (is(TT_TemplateString) && opensScope()) 506*06f32e7eSjoerg return true; 507*06f32e7eSjoerg return is(TT_ArrayInitializerLSquare) || is(TT_ProtoExtensionLSquare) || 508*06f32e7eSjoerg (is(tok::l_brace) && 509*06f32e7eSjoerg (BlockKind == BK_Block || is(TT_DictLiteral) || 510*06f32e7eSjoerg (!Style.Cpp11BracedListStyle && NestingLevel == 0))) || 511*06f32e7eSjoerg (is(tok::less) && (Style.Language == FormatStyle::LK_Proto || 512*06f32e7eSjoerg Style.Language == FormatStyle::LK_TextProto)); 513*06f32e7eSjoerg } 514*06f32e7eSjoerg 515*06f32e7eSjoerg /// Returns whether the token is the left square bracket of a C++ 516*06f32e7eSjoerg /// structured binding declaration. 517*06f32e7eSjoerg bool isCppStructuredBinding(const FormatStyle &Style) const { 518*06f32e7eSjoerg if (!Style.isCpp() || isNot(tok::l_square)) 519*06f32e7eSjoerg return false; 520*06f32e7eSjoerg const FormatToken *T = this; 521*06f32e7eSjoerg do { 522*06f32e7eSjoerg T = T->getPreviousNonComment(); 523*06f32e7eSjoerg } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp, 524*06f32e7eSjoerg tok::ampamp)); 525*06f32e7eSjoerg return T && T->is(tok::kw_auto); 526*06f32e7eSjoerg } 527*06f32e7eSjoerg 528*06f32e7eSjoerg /// Same as opensBlockOrBlockTypeList, but for the closing token. 529*06f32e7eSjoerg bool closesBlockOrBlockTypeList(const FormatStyle &Style) const { 530*06f32e7eSjoerg if (is(TT_TemplateString) && closesScope()) 531*06f32e7eSjoerg return true; 532*06f32e7eSjoerg return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style); 533*06f32e7eSjoerg } 534*06f32e7eSjoerg 535*06f32e7eSjoerg /// Return the actual namespace token, if this token starts a namespace 536*06f32e7eSjoerg /// block. 537*06f32e7eSjoerg const FormatToken *getNamespaceToken() const { 538*06f32e7eSjoerg const FormatToken *NamespaceTok = this; 539*06f32e7eSjoerg if (is(tok::comment)) 540*06f32e7eSjoerg NamespaceTok = NamespaceTok->getNextNonComment(); 541*06f32e7eSjoerg // Detect "(inline|export)? namespace" in the beginning of a line. 542*06f32e7eSjoerg if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export)) 543*06f32e7eSjoerg NamespaceTok = NamespaceTok->getNextNonComment(); 544*06f32e7eSjoerg return NamespaceTok && 545*06f32e7eSjoerg NamespaceTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) 546*06f32e7eSjoerg ? NamespaceTok 547*06f32e7eSjoerg : nullptr; 548*06f32e7eSjoerg } 549*06f32e7eSjoerg 550*06f32e7eSjoerg private: 551*06f32e7eSjoerg // Disallow copying. 552*06f32e7eSjoerg FormatToken(const FormatToken &) = delete; 553*06f32e7eSjoerg void operator=(const FormatToken &) = delete; 554*06f32e7eSjoerg 555*06f32e7eSjoerg template <typename A, typename... Ts> 556*06f32e7eSjoerg bool startsSequenceInternal(A K1, Ts... Tokens) const { 557*06f32e7eSjoerg if (is(tok::comment) && Next) 558*06f32e7eSjoerg return Next->startsSequenceInternal(K1, Tokens...); 559*06f32e7eSjoerg return is(K1) && Next && Next->startsSequenceInternal(Tokens...); 560*06f32e7eSjoerg } 561*06f32e7eSjoerg 562*06f32e7eSjoerg template <typename A> bool startsSequenceInternal(A K1) const { 563*06f32e7eSjoerg if (is(tok::comment) && Next) 564*06f32e7eSjoerg return Next->startsSequenceInternal(K1); 565*06f32e7eSjoerg return is(K1); 566*06f32e7eSjoerg } 567*06f32e7eSjoerg 568*06f32e7eSjoerg template <typename A, typename... Ts> bool endsSequenceInternal(A K1) const { 569*06f32e7eSjoerg if (is(tok::comment) && Previous) 570*06f32e7eSjoerg return Previous->endsSequenceInternal(K1); 571*06f32e7eSjoerg return is(K1); 572*06f32e7eSjoerg } 573*06f32e7eSjoerg 574*06f32e7eSjoerg template <typename A, typename... Ts> 575*06f32e7eSjoerg bool endsSequenceInternal(A K1, Ts... Tokens) const { 576*06f32e7eSjoerg if (is(tok::comment) && Previous) 577*06f32e7eSjoerg return Previous->endsSequenceInternal(K1, Tokens...); 578*06f32e7eSjoerg return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...); 579*06f32e7eSjoerg } 580*06f32e7eSjoerg }; 581*06f32e7eSjoerg 582*06f32e7eSjoerg class ContinuationIndenter; 583*06f32e7eSjoerg struct LineState; 584*06f32e7eSjoerg 585*06f32e7eSjoerg class TokenRole { 586*06f32e7eSjoerg public: 587*06f32e7eSjoerg TokenRole(const FormatStyle &Style) : Style(Style) {} 588*06f32e7eSjoerg virtual ~TokenRole(); 589*06f32e7eSjoerg 590*06f32e7eSjoerg /// After the \c TokenAnnotator has finished annotating all the tokens, 591*06f32e7eSjoerg /// this function precomputes required information for formatting. 592*06f32e7eSjoerg virtual void precomputeFormattingInfos(const FormatToken *Token); 593*06f32e7eSjoerg 594*06f32e7eSjoerg /// Apply the special formatting that the given role demands. 595*06f32e7eSjoerg /// 596*06f32e7eSjoerg /// Assumes that the token having this role is already formatted. 597*06f32e7eSjoerg /// 598*06f32e7eSjoerg /// Continues formatting from \p State leaving indentation to \p Indenter and 599*06f32e7eSjoerg /// returns the total penalty that this formatting incurs. 600*06f32e7eSjoerg virtual unsigned formatFromToken(LineState &State, 601*06f32e7eSjoerg ContinuationIndenter *Indenter, 602*06f32e7eSjoerg bool DryRun) { 603*06f32e7eSjoerg return 0; 604*06f32e7eSjoerg } 605*06f32e7eSjoerg 606*06f32e7eSjoerg /// Same as \c formatFromToken, but assumes that the first token has 607*06f32e7eSjoerg /// already been set thereby deciding on the first line break. 608*06f32e7eSjoerg virtual unsigned formatAfterToken(LineState &State, 609*06f32e7eSjoerg ContinuationIndenter *Indenter, 610*06f32e7eSjoerg bool DryRun) { 611*06f32e7eSjoerg return 0; 612*06f32e7eSjoerg } 613*06f32e7eSjoerg 614*06f32e7eSjoerg /// Notifies the \c Role that a comma was found. 615*06f32e7eSjoerg virtual void CommaFound(const FormatToken *Token) {} 616*06f32e7eSjoerg 617*06f32e7eSjoerg virtual const FormatToken *lastComma() { return nullptr; } 618*06f32e7eSjoerg 619*06f32e7eSjoerg protected: 620*06f32e7eSjoerg const FormatStyle &Style; 621*06f32e7eSjoerg }; 622*06f32e7eSjoerg 623*06f32e7eSjoerg class CommaSeparatedList : public TokenRole { 624*06f32e7eSjoerg public: 625*06f32e7eSjoerg CommaSeparatedList(const FormatStyle &Style) 626*06f32e7eSjoerg : TokenRole(Style), HasNestedBracedList(false) {} 627*06f32e7eSjoerg 628*06f32e7eSjoerg void precomputeFormattingInfos(const FormatToken *Token) override; 629*06f32e7eSjoerg 630*06f32e7eSjoerg unsigned formatAfterToken(LineState &State, ContinuationIndenter *Indenter, 631*06f32e7eSjoerg bool DryRun) override; 632*06f32e7eSjoerg 633*06f32e7eSjoerg unsigned formatFromToken(LineState &State, ContinuationIndenter *Indenter, 634*06f32e7eSjoerg bool DryRun) override; 635*06f32e7eSjoerg 636*06f32e7eSjoerg /// Adds \p Token as the next comma to the \c CommaSeparated list. 637*06f32e7eSjoerg void CommaFound(const FormatToken *Token) override { 638*06f32e7eSjoerg Commas.push_back(Token); 639*06f32e7eSjoerg } 640*06f32e7eSjoerg 641*06f32e7eSjoerg const FormatToken *lastComma() override { 642*06f32e7eSjoerg if (Commas.empty()) 643*06f32e7eSjoerg return nullptr; 644*06f32e7eSjoerg return Commas.back(); 645*06f32e7eSjoerg } 646*06f32e7eSjoerg 647*06f32e7eSjoerg private: 648*06f32e7eSjoerg /// A struct that holds information on how to format a given list with 649*06f32e7eSjoerg /// a specific number of columns. 650*06f32e7eSjoerg struct ColumnFormat { 651*06f32e7eSjoerg /// The number of columns to use. 652*06f32e7eSjoerg unsigned Columns; 653*06f32e7eSjoerg 654*06f32e7eSjoerg /// The total width in characters. 655*06f32e7eSjoerg unsigned TotalWidth; 656*06f32e7eSjoerg 657*06f32e7eSjoerg /// The number of lines required for this format. 658*06f32e7eSjoerg unsigned LineCount; 659*06f32e7eSjoerg 660*06f32e7eSjoerg /// The size of each column in characters. 661*06f32e7eSjoerg SmallVector<unsigned, 8> ColumnSizes; 662*06f32e7eSjoerg }; 663*06f32e7eSjoerg 664*06f32e7eSjoerg /// Calculate which \c ColumnFormat fits best into 665*06f32e7eSjoerg /// \p RemainingCharacters. 666*06f32e7eSjoerg const ColumnFormat *getColumnFormat(unsigned RemainingCharacters) const; 667*06f32e7eSjoerg 668*06f32e7eSjoerg /// The ordered \c FormatTokens making up the commas of this list. 669*06f32e7eSjoerg SmallVector<const FormatToken *, 8> Commas; 670*06f32e7eSjoerg 671*06f32e7eSjoerg /// The length of each of the list's items in characters including the 672*06f32e7eSjoerg /// trailing comma. 673*06f32e7eSjoerg SmallVector<unsigned, 8> ItemLengths; 674*06f32e7eSjoerg 675*06f32e7eSjoerg /// Precomputed formats that can be used for this list. 676*06f32e7eSjoerg SmallVector<ColumnFormat, 4> Formats; 677*06f32e7eSjoerg 678*06f32e7eSjoerg bool HasNestedBracedList; 679*06f32e7eSjoerg }; 680*06f32e7eSjoerg 681*06f32e7eSjoerg /// Encapsulates keywords that are context sensitive or for languages not 682*06f32e7eSjoerg /// properly supported by Clang's lexer. 683*06f32e7eSjoerg struct AdditionalKeywords { 684*06f32e7eSjoerg AdditionalKeywords(IdentifierTable &IdentTable) { 685*06f32e7eSjoerg kw_final = &IdentTable.get("final"); 686*06f32e7eSjoerg kw_override = &IdentTable.get("override"); 687*06f32e7eSjoerg kw_in = &IdentTable.get("in"); 688*06f32e7eSjoerg kw_of = &IdentTable.get("of"); 689*06f32e7eSjoerg kw_CF_CLOSED_ENUM = &IdentTable.get("CF_CLOSED_ENUM"); 690*06f32e7eSjoerg kw_CF_ENUM = &IdentTable.get("CF_ENUM"); 691*06f32e7eSjoerg kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS"); 692*06f32e7eSjoerg kw_NS_CLOSED_ENUM = &IdentTable.get("NS_CLOSED_ENUM"); 693*06f32e7eSjoerg kw_NS_ENUM = &IdentTable.get("NS_ENUM"); 694*06f32e7eSjoerg kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS"); 695*06f32e7eSjoerg 696*06f32e7eSjoerg kw_as = &IdentTable.get("as"); 697*06f32e7eSjoerg kw_async = &IdentTable.get("async"); 698*06f32e7eSjoerg kw_await = &IdentTable.get("await"); 699*06f32e7eSjoerg kw_declare = &IdentTable.get("declare"); 700*06f32e7eSjoerg kw_finally = &IdentTable.get("finally"); 701*06f32e7eSjoerg kw_from = &IdentTable.get("from"); 702*06f32e7eSjoerg kw_function = &IdentTable.get("function"); 703*06f32e7eSjoerg kw_get = &IdentTable.get("get"); 704*06f32e7eSjoerg kw_import = &IdentTable.get("import"); 705*06f32e7eSjoerg kw_infer = &IdentTable.get("infer"); 706*06f32e7eSjoerg kw_is = &IdentTable.get("is"); 707*06f32e7eSjoerg kw_let = &IdentTable.get("let"); 708*06f32e7eSjoerg kw_module = &IdentTable.get("module"); 709*06f32e7eSjoerg kw_readonly = &IdentTable.get("readonly"); 710*06f32e7eSjoerg kw_set = &IdentTable.get("set"); 711*06f32e7eSjoerg kw_type = &IdentTable.get("type"); 712*06f32e7eSjoerg kw_typeof = &IdentTable.get("typeof"); 713*06f32e7eSjoerg kw_var = &IdentTable.get("var"); 714*06f32e7eSjoerg kw_yield = &IdentTable.get("yield"); 715*06f32e7eSjoerg 716*06f32e7eSjoerg kw_abstract = &IdentTable.get("abstract"); 717*06f32e7eSjoerg kw_assert = &IdentTable.get("assert"); 718*06f32e7eSjoerg kw_extends = &IdentTable.get("extends"); 719*06f32e7eSjoerg kw_implements = &IdentTable.get("implements"); 720*06f32e7eSjoerg kw_instanceof = &IdentTable.get("instanceof"); 721*06f32e7eSjoerg kw_interface = &IdentTable.get("interface"); 722*06f32e7eSjoerg kw_native = &IdentTable.get("native"); 723*06f32e7eSjoerg kw_package = &IdentTable.get("package"); 724*06f32e7eSjoerg kw_synchronized = &IdentTable.get("synchronized"); 725*06f32e7eSjoerg kw_throws = &IdentTable.get("throws"); 726*06f32e7eSjoerg kw___except = &IdentTable.get("__except"); 727*06f32e7eSjoerg kw___has_include = &IdentTable.get("__has_include"); 728*06f32e7eSjoerg kw___has_include_next = &IdentTable.get("__has_include_next"); 729*06f32e7eSjoerg 730*06f32e7eSjoerg kw_mark = &IdentTable.get("mark"); 731*06f32e7eSjoerg 732*06f32e7eSjoerg kw_extend = &IdentTable.get("extend"); 733*06f32e7eSjoerg kw_option = &IdentTable.get("option"); 734*06f32e7eSjoerg kw_optional = &IdentTable.get("optional"); 735*06f32e7eSjoerg kw_repeated = &IdentTable.get("repeated"); 736*06f32e7eSjoerg kw_required = &IdentTable.get("required"); 737*06f32e7eSjoerg kw_returns = &IdentTable.get("returns"); 738*06f32e7eSjoerg 739*06f32e7eSjoerg kw_signals = &IdentTable.get("signals"); 740*06f32e7eSjoerg kw_qsignals = &IdentTable.get("Q_SIGNALS"); 741*06f32e7eSjoerg kw_slots = &IdentTable.get("slots"); 742*06f32e7eSjoerg kw_qslots = &IdentTable.get("Q_SLOTS"); 743*06f32e7eSjoerg 744*06f32e7eSjoerg // C# keywords 745*06f32e7eSjoerg kw_dollar = &IdentTable.get("dollar"); 746*06f32e7eSjoerg kw_base = &IdentTable.get("base"); 747*06f32e7eSjoerg kw_byte = &IdentTable.get("byte"); 748*06f32e7eSjoerg kw_checked = &IdentTable.get("checked"); 749*06f32e7eSjoerg kw_decimal = &IdentTable.get("decimal"); 750*06f32e7eSjoerg kw_delegate = &IdentTable.get("delegate"); 751*06f32e7eSjoerg kw_event = &IdentTable.get("event"); 752*06f32e7eSjoerg kw_fixed = &IdentTable.get("fixed"); 753*06f32e7eSjoerg kw_foreach = &IdentTable.get("foreach"); 754*06f32e7eSjoerg kw_implicit = &IdentTable.get("implicit"); 755*06f32e7eSjoerg kw_internal = &IdentTable.get("internal"); 756*06f32e7eSjoerg kw_lock = &IdentTable.get("lock"); 757*06f32e7eSjoerg kw_null = &IdentTable.get("null"); 758*06f32e7eSjoerg kw_object = &IdentTable.get("object"); 759*06f32e7eSjoerg kw_out = &IdentTable.get("out"); 760*06f32e7eSjoerg kw_params = &IdentTable.get("params"); 761*06f32e7eSjoerg kw_ref = &IdentTable.get("ref"); 762*06f32e7eSjoerg kw_string = &IdentTable.get("string"); 763*06f32e7eSjoerg kw_stackalloc = &IdentTable.get("stackalloc"); 764*06f32e7eSjoerg kw_sbyte = &IdentTable.get("sbyte"); 765*06f32e7eSjoerg kw_sealed = &IdentTable.get("sealed"); 766*06f32e7eSjoerg kw_uint = &IdentTable.get("uint"); 767*06f32e7eSjoerg kw_ulong = &IdentTable.get("ulong"); 768*06f32e7eSjoerg kw_unchecked = &IdentTable.get("unchecked"); 769*06f32e7eSjoerg kw_unsafe = &IdentTable.get("unsafe"); 770*06f32e7eSjoerg kw_ushort = &IdentTable.get("ushort"); 771*06f32e7eSjoerg 772*06f32e7eSjoerg // Keep this at the end of the constructor to make sure everything here 773*06f32e7eSjoerg // is 774*06f32e7eSjoerg // already initialized. 775*06f32e7eSjoerg JsExtraKeywords = std::unordered_set<IdentifierInfo *>( 776*06f32e7eSjoerg {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from, 777*06f32e7eSjoerg kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly, 778*06f32e7eSjoerg kw_set, kw_type, kw_typeof, kw_var, kw_yield, 779*06f32e7eSjoerg // Keywords from the Java section. 780*06f32e7eSjoerg kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface}); 781*06f32e7eSjoerg 782*06f32e7eSjoerg CSharpExtraKeywords = std::unordered_set<IdentifierInfo *>( 783*06f32e7eSjoerg {kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate, kw_event, 784*06f32e7eSjoerg kw_fixed, kw_foreach, kw_implicit, kw_in, kw_interface, kw_internal, 785*06f32e7eSjoerg kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override, kw_params, 786*06f32e7eSjoerg kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte, kw_sealed, 787*06f32e7eSjoerg kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort, 788*06f32e7eSjoerg // Keywords from the JavaScript section. 789*06f32e7eSjoerg kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from, 790*06f32e7eSjoerg kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly, 791*06f32e7eSjoerg kw_set, kw_type, kw_typeof, kw_var, kw_yield, 792*06f32e7eSjoerg // Keywords from the Java section. 793*06f32e7eSjoerg kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface}); 794*06f32e7eSjoerg } 795*06f32e7eSjoerg 796*06f32e7eSjoerg // Context sensitive keywords. 797*06f32e7eSjoerg IdentifierInfo *kw_final; 798*06f32e7eSjoerg IdentifierInfo *kw_override; 799*06f32e7eSjoerg IdentifierInfo *kw_in; 800*06f32e7eSjoerg IdentifierInfo *kw_of; 801*06f32e7eSjoerg IdentifierInfo *kw_CF_CLOSED_ENUM; 802*06f32e7eSjoerg IdentifierInfo *kw_CF_ENUM; 803*06f32e7eSjoerg IdentifierInfo *kw_CF_OPTIONS; 804*06f32e7eSjoerg IdentifierInfo *kw_NS_CLOSED_ENUM; 805*06f32e7eSjoerg IdentifierInfo *kw_NS_ENUM; 806*06f32e7eSjoerg IdentifierInfo *kw_NS_OPTIONS; 807*06f32e7eSjoerg IdentifierInfo *kw___except; 808*06f32e7eSjoerg IdentifierInfo *kw___has_include; 809*06f32e7eSjoerg IdentifierInfo *kw___has_include_next; 810*06f32e7eSjoerg 811*06f32e7eSjoerg // JavaScript keywords. 812*06f32e7eSjoerg IdentifierInfo *kw_as; 813*06f32e7eSjoerg IdentifierInfo *kw_async; 814*06f32e7eSjoerg IdentifierInfo *kw_await; 815*06f32e7eSjoerg IdentifierInfo *kw_declare; 816*06f32e7eSjoerg IdentifierInfo *kw_finally; 817*06f32e7eSjoerg IdentifierInfo *kw_from; 818*06f32e7eSjoerg IdentifierInfo *kw_function; 819*06f32e7eSjoerg IdentifierInfo *kw_get; 820*06f32e7eSjoerg IdentifierInfo *kw_import; 821*06f32e7eSjoerg IdentifierInfo *kw_infer; 822*06f32e7eSjoerg IdentifierInfo *kw_is; 823*06f32e7eSjoerg IdentifierInfo *kw_let; 824*06f32e7eSjoerg IdentifierInfo *kw_module; 825*06f32e7eSjoerg IdentifierInfo *kw_readonly; 826*06f32e7eSjoerg IdentifierInfo *kw_set; 827*06f32e7eSjoerg IdentifierInfo *kw_type; 828*06f32e7eSjoerg IdentifierInfo *kw_typeof; 829*06f32e7eSjoerg IdentifierInfo *kw_var; 830*06f32e7eSjoerg IdentifierInfo *kw_yield; 831*06f32e7eSjoerg 832*06f32e7eSjoerg // Java keywords. 833*06f32e7eSjoerg IdentifierInfo *kw_abstract; 834*06f32e7eSjoerg IdentifierInfo *kw_assert; 835*06f32e7eSjoerg IdentifierInfo *kw_extends; 836*06f32e7eSjoerg IdentifierInfo *kw_implements; 837*06f32e7eSjoerg IdentifierInfo *kw_instanceof; 838*06f32e7eSjoerg IdentifierInfo *kw_interface; 839*06f32e7eSjoerg IdentifierInfo *kw_native; 840*06f32e7eSjoerg IdentifierInfo *kw_package; 841*06f32e7eSjoerg IdentifierInfo *kw_synchronized; 842*06f32e7eSjoerg IdentifierInfo *kw_throws; 843*06f32e7eSjoerg 844*06f32e7eSjoerg // Pragma keywords. 845*06f32e7eSjoerg IdentifierInfo *kw_mark; 846*06f32e7eSjoerg 847*06f32e7eSjoerg // Proto keywords. 848*06f32e7eSjoerg IdentifierInfo *kw_extend; 849*06f32e7eSjoerg IdentifierInfo *kw_option; 850*06f32e7eSjoerg IdentifierInfo *kw_optional; 851*06f32e7eSjoerg IdentifierInfo *kw_repeated; 852*06f32e7eSjoerg IdentifierInfo *kw_required; 853*06f32e7eSjoerg IdentifierInfo *kw_returns; 854*06f32e7eSjoerg 855*06f32e7eSjoerg // QT keywords. 856*06f32e7eSjoerg IdentifierInfo *kw_signals; 857*06f32e7eSjoerg IdentifierInfo *kw_qsignals; 858*06f32e7eSjoerg IdentifierInfo *kw_slots; 859*06f32e7eSjoerg IdentifierInfo *kw_qslots; 860*06f32e7eSjoerg 861*06f32e7eSjoerg // C# keywords 862*06f32e7eSjoerg IdentifierInfo *kw_dollar; 863*06f32e7eSjoerg IdentifierInfo *kw_base; 864*06f32e7eSjoerg IdentifierInfo *kw_byte; 865*06f32e7eSjoerg IdentifierInfo *kw_checked; 866*06f32e7eSjoerg IdentifierInfo *kw_decimal; 867*06f32e7eSjoerg IdentifierInfo *kw_delegate; 868*06f32e7eSjoerg IdentifierInfo *kw_event; 869*06f32e7eSjoerg IdentifierInfo *kw_fixed; 870*06f32e7eSjoerg IdentifierInfo *kw_foreach; 871*06f32e7eSjoerg IdentifierInfo *kw_implicit; 872*06f32e7eSjoerg IdentifierInfo *kw_internal; 873*06f32e7eSjoerg 874*06f32e7eSjoerg IdentifierInfo *kw_lock; 875*06f32e7eSjoerg IdentifierInfo *kw_null; 876*06f32e7eSjoerg IdentifierInfo *kw_object; 877*06f32e7eSjoerg IdentifierInfo *kw_out; 878*06f32e7eSjoerg 879*06f32e7eSjoerg IdentifierInfo *kw_params; 880*06f32e7eSjoerg 881*06f32e7eSjoerg IdentifierInfo *kw_ref; 882*06f32e7eSjoerg IdentifierInfo *kw_string; 883*06f32e7eSjoerg IdentifierInfo *kw_stackalloc; 884*06f32e7eSjoerg IdentifierInfo *kw_sbyte; 885*06f32e7eSjoerg IdentifierInfo *kw_sealed; 886*06f32e7eSjoerg IdentifierInfo *kw_uint; 887*06f32e7eSjoerg IdentifierInfo *kw_ulong; 888*06f32e7eSjoerg IdentifierInfo *kw_unchecked; 889*06f32e7eSjoerg IdentifierInfo *kw_unsafe; 890*06f32e7eSjoerg IdentifierInfo *kw_ushort; 891*06f32e7eSjoerg 892*06f32e7eSjoerg /// Returns \c true if \p Tok is a true JavaScript identifier, returns 893*06f32e7eSjoerg /// \c false if it is a keyword or a pseudo keyword. 894*06f32e7eSjoerg bool IsJavaScriptIdentifier(const FormatToken &Tok) const { 895*06f32e7eSjoerg return Tok.is(tok::identifier) && 896*06f32e7eSjoerg JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) == 897*06f32e7eSjoerg JsExtraKeywords.end(); 898*06f32e7eSjoerg } 899*06f32e7eSjoerg 900*06f32e7eSjoerg /// Returns \c true if \p Tok is a C# keyword, returns 901*06f32e7eSjoerg /// \c false if it is a anything else. 902*06f32e7eSjoerg bool isCSharpKeyword(const FormatToken &Tok) const { 903*06f32e7eSjoerg switch (Tok.Tok.getKind()) { 904*06f32e7eSjoerg case tok::kw_bool: 905*06f32e7eSjoerg case tok::kw_break: 906*06f32e7eSjoerg case tok::kw_case: 907*06f32e7eSjoerg case tok::kw_catch: 908*06f32e7eSjoerg case tok::kw_char: 909*06f32e7eSjoerg case tok::kw_class: 910*06f32e7eSjoerg case tok::kw_const: 911*06f32e7eSjoerg case tok::kw_continue: 912*06f32e7eSjoerg case tok::kw_default: 913*06f32e7eSjoerg case tok::kw_do: 914*06f32e7eSjoerg case tok::kw_double: 915*06f32e7eSjoerg case tok::kw_else: 916*06f32e7eSjoerg case tok::kw_enum: 917*06f32e7eSjoerg case tok::kw_explicit: 918*06f32e7eSjoerg case tok::kw_extern: 919*06f32e7eSjoerg case tok::kw_false: 920*06f32e7eSjoerg case tok::kw_float: 921*06f32e7eSjoerg case tok::kw_for: 922*06f32e7eSjoerg case tok::kw_goto: 923*06f32e7eSjoerg case tok::kw_if: 924*06f32e7eSjoerg case tok::kw_int: 925*06f32e7eSjoerg case tok::kw_long: 926*06f32e7eSjoerg case tok::kw_namespace: 927*06f32e7eSjoerg case tok::kw_new: 928*06f32e7eSjoerg case tok::kw_operator: 929*06f32e7eSjoerg case tok::kw_private: 930*06f32e7eSjoerg case tok::kw_protected: 931*06f32e7eSjoerg case tok::kw_public: 932*06f32e7eSjoerg case tok::kw_return: 933*06f32e7eSjoerg case tok::kw_short: 934*06f32e7eSjoerg case tok::kw_sizeof: 935*06f32e7eSjoerg case tok::kw_static: 936*06f32e7eSjoerg case tok::kw_struct: 937*06f32e7eSjoerg case tok::kw_switch: 938*06f32e7eSjoerg case tok::kw_this: 939*06f32e7eSjoerg case tok::kw_throw: 940*06f32e7eSjoerg case tok::kw_true: 941*06f32e7eSjoerg case tok::kw_try: 942*06f32e7eSjoerg case tok::kw_typeof: 943*06f32e7eSjoerg case tok::kw_using: 944*06f32e7eSjoerg case tok::kw_virtual: 945*06f32e7eSjoerg case tok::kw_void: 946*06f32e7eSjoerg case tok::kw_volatile: 947*06f32e7eSjoerg case tok::kw_while: 948*06f32e7eSjoerg return true; 949*06f32e7eSjoerg default: 950*06f32e7eSjoerg return Tok.is(tok::identifier) && 951*06f32e7eSjoerg CSharpExtraKeywords.find(Tok.Tok.getIdentifierInfo()) == 952*06f32e7eSjoerg CSharpExtraKeywords.end(); 953*06f32e7eSjoerg } 954*06f32e7eSjoerg } 955*06f32e7eSjoerg 956*06f32e7eSjoerg private: 957*06f32e7eSjoerg /// The JavaScript keywords beyond the C++ keyword set. 958*06f32e7eSjoerg std::unordered_set<IdentifierInfo *> JsExtraKeywords; 959*06f32e7eSjoerg 960*06f32e7eSjoerg /// The C# keywords beyond the C++ keyword set 961*06f32e7eSjoerg std::unordered_set<IdentifierInfo *> CSharpExtraKeywords; 962*06f32e7eSjoerg }; 963*06f32e7eSjoerg 964*06f32e7eSjoerg } // namespace format 965*06f32e7eSjoerg } // namespace clang 966*06f32e7eSjoerg 967*06f32e7eSjoerg #endif 968