106f32e7eSjoerg //===--- FormatToken.h - Format C++ code ------------------------*- C++ -*-===// 206f32e7eSjoerg // 306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information. 506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606f32e7eSjoerg // 706f32e7eSjoerg //===----------------------------------------------------------------------===// 806f32e7eSjoerg /// 906f32e7eSjoerg /// \file 1006f32e7eSjoerg /// This file contains the declaration of the FormatToken, a wrapper 1106f32e7eSjoerg /// around Token with additional information related to formatting. 1206f32e7eSjoerg /// 1306f32e7eSjoerg //===----------------------------------------------------------------------===// 1406f32e7eSjoerg 1506f32e7eSjoerg #ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H 1606f32e7eSjoerg #define LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H 1706f32e7eSjoerg 1806f32e7eSjoerg #include "clang/Basic/IdentifierTable.h" 1906f32e7eSjoerg #include "clang/Basic/OperatorPrecedence.h" 2006f32e7eSjoerg #include "clang/Format/Format.h" 2106f32e7eSjoerg #include "clang/Lex/Lexer.h" 2206f32e7eSjoerg #include <memory> 2306f32e7eSjoerg #include <unordered_set> 2406f32e7eSjoerg 2506f32e7eSjoerg namespace clang { 2606f32e7eSjoerg namespace format { 2706f32e7eSjoerg 2806f32e7eSjoerg #define LIST_TOKEN_TYPES \ 2906f32e7eSjoerg TYPE(ArrayInitializerLSquare) \ 3006f32e7eSjoerg TYPE(ArraySubscriptLSquare) \ 3106f32e7eSjoerg TYPE(AttributeColon) \ 32*13fbcb42Sjoerg TYPE(AttributeMacro) \ 3306f32e7eSjoerg TYPE(AttributeParen) \ 3406f32e7eSjoerg TYPE(AttributeSquare) \ 3506f32e7eSjoerg TYPE(BinaryOperator) \ 3606f32e7eSjoerg TYPE(BitFieldColon) \ 3706f32e7eSjoerg TYPE(BlockComment) \ 3806f32e7eSjoerg TYPE(CastRParen) \ 3906f32e7eSjoerg TYPE(ConditionalExpr) \ 4006f32e7eSjoerg TYPE(ConflictAlternative) \ 4106f32e7eSjoerg TYPE(ConflictEnd) \ 4206f32e7eSjoerg TYPE(ConflictStart) \ 43*13fbcb42Sjoerg TYPE(ConstraintJunctions) \ 4406f32e7eSjoerg TYPE(CtorInitializerColon) \ 4506f32e7eSjoerg TYPE(CtorInitializerComma) \ 4606f32e7eSjoerg TYPE(DesignatedInitializerLSquare) \ 4706f32e7eSjoerg TYPE(DesignatedInitializerPeriod) \ 4806f32e7eSjoerg TYPE(DictLiteral) \ 49*13fbcb42Sjoerg TYPE(FatArrow) \ 5006f32e7eSjoerg TYPE(ForEachMacro) \ 5106f32e7eSjoerg TYPE(FunctionAnnotationRParen) \ 5206f32e7eSjoerg TYPE(FunctionDeclarationName) \ 5306f32e7eSjoerg TYPE(FunctionLBrace) \ 5406f32e7eSjoerg TYPE(FunctionTypeLParen) \ 5506f32e7eSjoerg TYPE(ImplicitStringLiteral) \ 5606f32e7eSjoerg TYPE(InheritanceColon) \ 5706f32e7eSjoerg TYPE(InheritanceComma) \ 5806f32e7eSjoerg TYPE(InlineASMBrace) \ 5906f32e7eSjoerg TYPE(InlineASMColon) \ 60*13fbcb42Sjoerg TYPE(InlineASMSymbolicNameLSquare) \ 6106f32e7eSjoerg TYPE(JavaAnnotation) \ 6206f32e7eSjoerg TYPE(JsComputedPropertyName) \ 6306f32e7eSjoerg TYPE(JsExponentiation) \ 6406f32e7eSjoerg TYPE(JsExponentiationEqual) \ 65*13fbcb42Sjoerg TYPE(JsPipePipeEqual) \ 6606f32e7eSjoerg TYPE(JsPrivateIdentifier) \ 6706f32e7eSjoerg TYPE(JsTypeColon) \ 6806f32e7eSjoerg TYPE(JsTypeOperator) \ 6906f32e7eSjoerg TYPE(JsTypeOptionalQuestion) \ 70*13fbcb42Sjoerg TYPE(JsAndAndEqual) \ 7106f32e7eSjoerg TYPE(LambdaArrow) \ 7206f32e7eSjoerg TYPE(LambdaLBrace) \ 7306f32e7eSjoerg TYPE(LambdaLSquare) \ 7406f32e7eSjoerg TYPE(LeadingJavaAnnotation) \ 7506f32e7eSjoerg TYPE(LineComment) \ 7606f32e7eSjoerg TYPE(MacroBlockBegin) \ 7706f32e7eSjoerg TYPE(MacroBlockEnd) \ 7806f32e7eSjoerg TYPE(NamespaceMacro) \ 79*13fbcb42Sjoerg TYPE(NonNullAssertion) \ 80*13fbcb42Sjoerg TYPE(NullCoalescingEqual) \ 81*13fbcb42Sjoerg TYPE(NullCoalescingOperator) \ 82*13fbcb42Sjoerg TYPE(NullPropagatingOperator) \ 8306f32e7eSjoerg TYPE(ObjCBlockLBrace) \ 8406f32e7eSjoerg TYPE(ObjCBlockLParen) \ 8506f32e7eSjoerg TYPE(ObjCDecl) \ 8606f32e7eSjoerg TYPE(ObjCForIn) \ 8706f32e7eSjoerg TYPE(ObjCMethodExpr) \ 8806f32e7eSjoerg TYPE(ObjCMethodSpecifier) \ 8906f32e7eSjoerg TYPE(ObjCProperty) \ 9006f32e7eSjoerg TYPE(ObjCStringLiteral) \ 9106f32e7eSjoerg TYPE(OverloadedOperator) \ 9206f32e7eSjoerg TYPE(OverloadedOperatorLParen) \ 9306f32e7eSjoerg TYPE(PointerOrReference) \ 9406f32e7eSjoerg TYPE(PureVirtualSpecifier) \ 9506f32e7eSjoerg TYPE(RangeBasedForLoopColon) \ 9606f32e7eSjoerg TYPE(RegexLiteral) \ 9706f32e7eSjoerg TYPE(SelectorName) \ 9806f32e7eSjoerg TYPE(StartOfName) \ 99*13fbcb42Sjoerg TYPE(StatementAttributeLikeMacro) \ 10006f32e7eSjoerg TYPE(StatementMacro) \ 10106f32e7eSjoerg TYPE(StructuredBindingLSquare) \ 10206f32e7eSjoerg TYPE(TemplateCloser) \ 10306f32e7eSjoerg TYPE(TemplateOpener) \ 10406f32e7eSjoerg TYPE(TemplateString) \ 10506f32e7eSjoerg TYPE(ProtoExtensionLSquare) \ 10606f32e7eSjoerg TYPE(TrailingAnnotation) \ 10706f32e7eSjoerg TYPE(TrailingReturnArrow) \ 10806f32e7eSjoerg TYPE(TrailingUnaryOperator) \ 109*13fbcb42Sjoerg TYPE(TypeDeclarationParen) \ 11006f32e7eSjoerg TYPE(TypenameMacro) \ 11106f32e7eSjoerg TYPE(UnaryOperator) \ 112*13fbcb42Sjoerg TYPE(UntouchableMacroFunc) \ 11306f32e7eSjoerg TYPE(CSharpStringLiteral) \ 114*13fbcb42Sjoerg TYPE(CSharpNamedArgumentColon) \ 115*13fbcb42Sjoerg TYPE(CSharpNullable) \ 116*13fbcb42Sjoerg TYPE(CSharpNullConditionalLSquare) \ 117*13fbcb42Sjoerg TYPE(CSharpGenericTypeConstraint) \ 118*13fbcb42Sjoerg TYPE(CSharpGenericTypeConstraintColon) \ 119*13fbcb42Sjoerg TYPE(CSharpGenericTypeConstraintComma) \ 12006f32e7eSjoerg TYPE(Unknown) 12106f32e7eSjoerg 122*13fbcb42Sjoerg /// Determines the semantic type of a syntactic token, e.g. whether "<" is a 123*13fbcb42Sjoerg /// template opener or binary operator. 124*13fbcb42Sjoerg enum TokenType : uint8_t { 12506f32e7eSjoerg #define TYPE(X) TT_##X, 12606f32e7eSjoerg LIST_TOKEN_TYPES 12706f32e7eSjoerg #undef TYPE 12806f32e7eSjoerg NUM_TOKEN_TYPES 12906f32e7eSjoerg }; 13006f32e7eSjoerg 13106f32e7eSjoerg /// Determines the name of a token type. 13206f32e7eSjoerg const char *getTokenTypeName(TokenType Type); 13306f32e7eSjoerg 13406f32e7eSjoerg // Represents what type of block a set of braces open. 13506f32e7eSjoerg enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit }; 13606f32e7eSjoerg 13706f32e7eSjoerg // The packing kind of a function's parameters. 13806f32e7eSjoerg enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive }; 13906f32e7eSjoerg 14006f32e7eSjoerg enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break }; 14106f32e7eSjoerg 142*13fbcb42Sjoerg /// Roles a token can take in a configured macro expansion. 143*13fbcb42Sjoerg enum MacroRole { 144*13fbcb42Sjoerg /// The token was expanded from a macro argument when formatting the expanded 145*13fbcb42Sjoerg /// token sequence. 146*13fbcb42Sjoerg MR_ExpandedArg, 147*13fbcb42Sjoerg /// The token is part of a macro argument that was previously formatted as 148*13fbcb42Sjoerg /// expansion when formatting the unexpanded macro call. 149*13fbcb42Sjoerg MR_UnexpandedArg, 150*13fbcb42Sjoerg /// The token was expanded from a macro definition, and is not visible as part 151*13fbcb42Sjoerg /// of the macro call. 152*13fbcb42Sjoerg MR_Hidden, 153*13fbcb42Sjoerg }; 154*13fbcb42Sjoerg 155*13fbcb42Sjoerg struct FormatToken; 156*13fbcb42Sjoerg 157*13fbcb42Sjoerg /// Contains information on the token's role in a macro expansion. 158*13fbcb42Sjoerg /// 159*13fbcb42Sjoerg /// Given the following definitions: 160*13fbcb42Sjoerg /// A(X) = [ X ] 161*13fbcb42Sjoerg /// B(X) = < X > 162*13fbcb42Sjoerg /// C(X) = X 163*13fbcb42Sjoerg /// 164*13fbcb42Sjoerg /// Consider the macro call: 165*13fbcb42Sjoerg /// A({B(C(C(x)))}) -> [{<x>}] 166*13fbcb42Sjoerg /// 167*13fbcb42Sjoerg /// In this case, the tokens of the unexpanded macro call will have the 168*13fbcb42Sjoerg /// following relevant entries in their macro context (note that formatting 169*13fbcb42Sjoerg /// the unexpanded macro call happens *after* formatting the expanded macro 170*13fbcb42Sjoerg /// call): 171*13fbcb42Sjoerg /// A( { B( C( C(x) ) ) } ) 172*13fbcb42Sjoerg /// Role: NN U NN NN NNUN N N U N (N=None, U=UnexpandedArg) 173*13fbcb42Sjoerg /// 174*13fbcb42Sjoerg /// [ { < x > } ] 175*13fbcb42Sjoerg /// Role: H E H E H E H (H=Hidden, E=ExpandedArg) 176*13fbcb42Sjoerg /// ExpandedFrom[0]: A A A A A A A 177*13fbcb42Sjoerg /// ExpandedFrom[1]: B B B 178*13fbcb42Sjoerg /// ExpandedFrom[2]: C 179*13fbcb42Sjoerg /// ExpandedFrom[3]: C 180*13fbcb42Sjoerg /// StartOfExpansion: 1 0 1 2 0 0 0 181*13fbcb42Sjoerg /// EndOfExpansion: 0 0 0 2 1 0 1 182*13fbcb42Sjoerg struct MacroExpansion { MacroExpansionMacroExpansion183*13fbcb42Sjoerg MacroExpansion(MacroRole Role) : Role(Role) {} 184*13fbcb42Sjoerg 185*13fbcb42Sjoerg /// The token's role in the macro expansion. 186*13fbcb42Sjoerg /// When formatting an expanded macro, all tokens that are part of macro 187*13fbcb42Sjoerg /// arguments will be MR_ExpandedArg, while all tokens that are not visible in 188*13fbcb42Sjoerg /// the macro call will be MR_Hidden. 189*13fbcb42Sjoerg /// When formatting an unexpanded macro call, all tokens that are part of 190*13fbcb42Sjoerg /// macro arguments will be MR_UnexpandedArg. 191*13fbcb42Sjoerg MacroRole Role; 192*13fbcb42Sjoerg 193*13fbcb42Sjoerg /// The stack of macro call identifier tokens this token was expanded from. 194*13fbcb42Sjoerg llvm::SmallVector<FormatToken *, 1> ExpandedFrom; 195*13fbcb42Sjoerg 196*13fbcb42Sjoerg /// The number of expansions of which this macro is the first entry. 197*13fbcb42Sjoerg unsigned StartOfExpansion = 0; 198*13fbcb42Sjoerg 199*13fbcb42Sjoerg /// The number of currently open expansions in \c ExpandedFrom this macro is 200*13fbcb42Sjoerg /// the last token in. 201*13fbcb42Sjoerg unsigned EndOfExpansion = 0; 202*13fbcb42Sjoerg }; 203*13fbcb42Sjoerg 20406f32e7eSjoerg class TokenRole; 20506f32e7eSjoerg class AnnotatedLine; 20606f32e7eSjoerg 20706f32e7eSjoerg /// A wrapper around a \c Token storing information about the 20806f32e7eSjoerg /// whitespace characters preceding it. 20906f32e7eSjoerg struct FormatToken { FormatTokenFormatToken210*13fbcb42Sjoerg FormatToken() 211*13fbcb42Sjoerg : HasUnescapedNewline(false), IsMultiline(false), IsFirst(false), 212*13fbcb42Sjoerg MustBreakBefore(false), IsUnterminatedLiteral(false), 213*13fbcb42Sjoerg CanBreakBefore(false), ClosesTemplateDeclaration(false), 214*13fbcb42Sjoerg StartsBinaryExpression(false), EndsBinaryExpression(false), 215*13fbcb42Sjoerg PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false), 216*13fbcb42Sjoerg Finalized(false), BlockKind(BK_Unknown), Decision(FD_Unformatted), 217*13fbcb42Sjoerg PackingKind(PPK_Inconclusive), Type(TT_Unknown) {} 21806f32e7eSjoerg 21906f32e7eSjoerg /// The \c Token. 22006f32e7eSjoerg Token Tok; 22106f32e7eSjoerg 222*13fbcb42Sjoerg /// The raw text of the token. 223*13fbcb42Sjoerg /// 224*13fbcb42Sjoerg /// Contains the raw token text without leading whitespace and without leading 225*13fbcb42Sjoerg /// escaped newlines. 226*13fbcb42Sjoerg StringRef TokenText; 227*13fbcb42Sjoerg 228*13fbcb42Sjoerg /// A token can have a special role that can carry extra information 229*13fbcb42Sjoerg /// about the token's formatting. 230*13fbcb42Sjoerg /// FIXME: Make FormatToken for parsing and AnnotatedToken two different 231*13fbcb42Sjoerg /// classes and make this a unique_ptr in the AnnotatedToken class. 232*13fbcb42Sjoerg std::shared_ptr<TokenRole> Role; 233*13fbcb42Sjoerg 234*13fbcb42Sjoerg /// The range of the whitespace immediately preceding the \c Token. 235*13fbcb42Sjoerg SourceRange WhitespaceRange; 236*13fbcb42Sjoerg 237*13fbcb42Sjoerg /// Whether there is at least one unescaped newline before the \c 238*13fbcb42Sjoerg /// Token. 239*13fbcb42Sjoerg unsigned HasUnescapedNewline : 1; 240*13fbcb42Sjoerg 241*13fbcb42Sjoerg /// Whether the token text contains newlines (escaped or not). 242*13fbcb42Sjoerg unsigned IsMultiline : 1; 243*13fbcb42Sjoerg 244*13fbcb42Sjoerg /// Indicates that this is the first token of the file. 245*13fbcb42Sjoerg unsigned IsFirst : 1; 246*13fbcb42Sjoerg 247*13fbcb42Sjoerg /// Whether there must be a line break before this token. 248*13fbcb42Sjoerg /// 249*13fbcb42Sjoerg /// This happens for example when a preprocessor directive ended directly 250*13fbcb42Sjoerg /// before the token. 251*13fbcb42Sjoerg unsigned MustBreakBefore : 1; 252*13fbcb42Sjoerg 253*13fbcb42Sjoerg /// Set to \c true if this token is an unterminated literal. 254*13fbcb42Sjoerg unsigned IsUnterminatedLiteral : 1; 255*13fbcb42Sjoerg 256*13fbcb42Sjoerg /// \c true if it is allowed to break before this token. 257*13fbcb42Sjoerg unsigned CanBreakBefore : 1; 258*13fbcb42Sjoerg 259*13fbcb42Sjoerg /// \c true if this is the ">" of "template<..>". 260*13fbcb42Sjoerg unsigned ClosesTemplateDeclaration : 1; 261*13fbcb42Sjoerg 262*13fbcb42Sjoerg /// \c true if this token starts a binary expression, i.e. has at least 263*13fbcb42Sjoerg /// one fake l_paren with a precedence greater than prec::Unknown. 264*13fbcb42Sjoerg unsigned StartsBinaryExpression : 1; 265*13fbcb42Sjoerg /// \c true if this token ends a binary expression. 266*13fbcb42Sjoerg unsigned EndsBinaryExpression : 1; 267*13fbcb42Sjoerg 268*13fbcb42Sjoerg /// Is this token part of a \c DeclStmt defining multiple variables? 269*13fbcb42Sjoerg /// 270*13fbcb42Sjoerg /// Only set if \c Type == \c TT_StartOfName. 271*13fbcb42Sjoerg unsigned PartOfMultiVariableDeclStmt : 1; 272*13fbcb42Sjoerg 273*13fbcb42Sjoerg /// Does this line comment continue a line comment section? 274*13fbcb42Sjoerg /// 275*13fbcb42Sjoerg /// Only set to true if \c Type == \c TT_LineComment. 276*13fbcb42Sjoerg unsigned ContinuesLineCommentSection : 1; 277*13fbcb42Sjoerg 278*13fbcb42Sjoerg /// If \c true, this token has been fully formatted (indented and 279*13fbcb42Sjoerg /// potentially re-formatted inside), and we do not allow further formatting 280*13fbcb42Sjoerg /// changes. 281*13fbcb42Sjoerg unsigned Finalized : 1; 282*13fbcb42Sjoerg 283*13fbcb42Sjoerg private: 284*13fbcb42Sjoerg /// Contains the kind of block if this token is a brace. 285*13fbcb42Sjoerg unsigned BlockKind : 2; 286*13fbcb42Sjoerg 287*13fbcb42Sjoerg public: getBlockKindFormatToken288*13fbcb42Sjoerg BraceBlockKind getBlockKind() const { 289*13fbcb42Sjoerg return static_cast<BraceBlockKind>(BlockKind); 290*13fbcb42Sjoerg } setBlockKindFormatToken291*13fbcb42Sjoerg void setBlockKind(BraceBlockKind BBK) { 292*13fbcb42Sjoerg BlockKind = BBK; 293*13fbcb42Sjoerg assert(getBlockKind() == BBK && "BraceBlockKind overflow!"); 294*13fbcb42Sjoerg } 295*13fbcb42Sjoerg 296*13fbcb42Sjoerg private: 297*13fbcb42Sjoerg /// Stores the formatting decision for the token once it was made. 298*13fbcb42Sjoerg unsigned Decision : 2; 299*13fbcb42Sjoerg 300*13fbcb42Sjoerg public: getDecisionFormatToken301*13fbcb42Sjoerg FormatDecision getDecision() const { 302*13fbcb42Sjoerg return static_cast<FormatDecision>(Decision); 303*13fbcb42Sjoerg } setDecisionFormatToken304*13fbcb42Sjoerg void setDecision(FormatDecision D) { 305*13fbcb42Sjoerg Decision = D; 306*13fbcb42Sjoerg assert(getDecision() == D && "FormatDecision overflow!"); 307*13fbcb42Sjoerg } 308*13fbcb42Sjoerg 309*13fbcb42Sjoerg private: 310*13fbcb42Sjoerg /// If this is an opening parenthesis, how are the parameters packed? 311*13fbcb42Sjoerg unsigned PackingKind : 2; 312*13fbcb42Sjoerg 313*13fbcb42Sjoerg public: getPackingKindFormatToken314*13fbcb42Sjoerg ParameterPackingKind getPackingKind() const { 315*13fbcb42Sjoerg return static_cast<ParameterPackingKind>(PackingKind); 316*13fbcb42Sjoerg } setPackingKindFormatToken317*13fbcb42Sjoerg void setPackingKind(ParameterPackingKind K) { 318*13fbcb42Sjoerg PackingKind = K; 319*13fbcb42Sjoerg assert(getPackingKind() == K && "ParameterPackingKind overflow!"); 320*13fbcb42Sjoerg } 321*13fbcb42Sjoerg 322*13fbcb42Sjoerg private: 323*13fbcb42Sjoerg TokenType Type; 324*13fbcb42Sjoerg 325*13fbcb42Sjoerg public: 326*13fbcb42Sjoerg /// Returns the token's type, e.g. whether "<" is a template opener or 327*13fbcb42Sjoerg /// binary operator. getTypeFormatToken328*13fbcb42Sjoerg TokenType getType() const { return Type; } setTypeFormatToken329*13fbcb42Sjoerg void setType(TokenType T) { Type = T; } 330*13fbcb42Sjoerg 33106f32e7eSjoerg /// The number of newlines immediately before the \c Token. 33206f32e7eSjoerg /// 33306f32e7eSjoerg /// This can be used to determine what the user wrote in the original code 33406f32e7eSjoerg /// and thereby e.g. leave an empty line between two function definitions. 33506f32e7eSjoerg unsigned NewlinesBefore = 0; 33606f32e7eSjoerg 33706f32e7eSjoerg /// The offset just past the last '\n' in this token's leading 33806f32e7eSjoerg /// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'. 33906f32e7eSjoerg unsigned LastNewlineOffset = 0; 34006f32e7eSjoerg 34106f32e7eSjoerg /// The width of the non-whitespace parts of the token (or its first 34206f32e7eSjoerg /// line for multi-line tokens) in columns. 34306f32e7eSjoerg /// We need this to correctly measure number of columns a token spans. 34406f32e7eSjoerg unsigned ColumnWidth = 0; 34506f32e7eSjoerg 34606f32e7eSjoerg /// Contains the width in columns of the last line of a multi-line 34706f32e7eSjoerg /// token. 34806f32e7eSjoerg unsigned LastLineColumnWidth = 0; 34906f32e7eSjoerg 35006f32e7eSjoerg /// The number of spaces that should be inserted before this token. 35106f32e7eSjoerg unsigned SpacesRequiredBefore = 0; 35206f32e7eSjoerg 35306f32e7eSjoerg /// Number of parameters, if this is "(", "[" or "<". 35406f32e7eSjoerg unsigned ParameterCount = 0; 35506f32e7eSjoerg 35606f32e7eSjoerg /// Number of parameters that are nested blocks, 35706f32e7eSjoerg /// if this is "(", "[" or "<". 35806f32e7eSjoerg unsigned BlockParameterCount = 0; 35906f32e7eSjoerg 36006f32e7eSjoerg /// If this is a bracket ("<", "(", "[" or "{"), contains the kind of 36106f32e7eSjoerg /// the surrounding bracket. 36206f32e7eSjoerg tok::TokenKind ParentBracket = tok::unknown; 36306f32e7eSjoerg 36406f32e7eSjoerg /// The total length of the unwrapped line up to and including this 36506f32e7eSjoerg /// token. 36606f32e7eSjoerg unsigned TotalLength = 0; 36706f32e7eSjoerg 36806f32e7eSjoerg /// The original 0-based column of this token, including expanded tabs. 36906f32e7eSjoerg /// The configured TabWidth is used as tab width. 37006f32e7eSjoerg unsigned OriginalColumn = 0; 37106f32e7eSjoerg 37206f32e7eSjoerg /// The length of following tokens until the next natural split point, 37306f32e7eSjoerg /// or the next token that can be broken. 37406f32e7eSjoerg unsigned UnbreakableTailLength = 0; 37506f32e7eSjoerg 37606f32e7eSjoerg // FIXME: Come up with a 'cleaner' concept. 37706f32e7eSjoerg /// The binding strength of a token. This is a combined value of 37806f32e7eSjoerg /// operator precedence, parenthesis nesting, etc. 37906f32e7eSjoerg unsigned BindingStrength = 0; 38006f32e7eSjoerg 38106f32e7eSjoerg /// The nesting level of this token, i.e. the number of surrounding (), 38206f32e7eSjoerg /// [], {} or <>. 38306f32e7eSjoerg unsigned NestingLevel = 0; 38406f32e7eSjoerg 38506f32e7eSjoerg /// The indent level of this token. Copied from the surrounding line. 38606f32e7eSjoerg unsigned IndentLevel = 0; 38706f32e7eSjoerg 38806f32e7eSjoerg /// Penalty for inserting a line break before this token. 38906f32e7eSjoerg unsigned SplitPenalty = 0; 39006f32e7eSjoerg 39106f32e7eSjoerg /// If this is the first ObjC selector name in an ObjC method 39206f32e7eSjoerg /// definition or call, this contains the length of the longest name. 39306f32e7eSjoerg /// 39406f32e7eSjoerg /// This being set to 0 means that the selectors should not be colon-aligned, 39506f32e7eSjoerg /// e.g. because several of them are block-type. 39606f32e7eSjoerg unsigned LongestObjCSelectorName = 0; 39706f32e7eSjoerg 39806f32e7eSjoerg /// If this is the first ObjC selector name in an ObjC method 39906f32e7eSjoerg /// definition or call, this contains the number of parts that the whole 40006f32e7eSjoerg /// selector consist of. 40106f32e7eSjoerg unsigned ObjCSelectorNameParts = 0; 40206f32e7eSjoerg 40306f32e7eSjoerg /// The 0-based index of the parameter/argument. For ObjC it is set 40406f32e7eSjoerg /// for the selector name token. 40506f32e7eSjoerg /// For now calculated only for ObjC. 40606f32e7eSjoerg unsigned ParameterIndex = 0; 40706f32e7eSjoerg 40806f32e7eSjoerg /// Stores the number of required fake parentheses and the 40906f32e7eSjoerg /// corresponding operator precedence. 41006f32e7eSjoerg /// 41106f32e7eSjoerg /// If multiple fake parentheses start at a token, this vector stores them in 41206f32e7eSjoerg /// reverse order, i.e. inner fake parenthesis first. 41306f32e7eSjoerg SmallVector<prec::Level, 4> FakeLParens; 41406f32e7eSjoerg /// Insert this many fake ) after this token for correct indentation. 41506f32e7eSjoerg unsigned FakeRParens = 0; 41606f32e7eSjoerg 41706f32e7eSjoerg /// If this is an operator (or "."/"->") in a sequence of operators 41806f32e7eSjoerg /// with the same precedence, contains the 0-based operator index. 41906f32e7eSjoerg unsigned OperatorIndex = 0; 42006f32e7eSjoerg 42106f32e7eSjoerg /// If this is an operator (or "."/"->") in a sequence of operators 42206f32e7eSjoerg /// with the same precedence, points to the next operator. 42306f32e7eSjoerg FormatToken *NextOperator = nullptr; 42406f32e7eSjoerg 42506f32e7eSjoerg /// If this is a bracket, this points to the matching one. 42606f32e7eSjoerg FormatToken *MatchingParen = nullptr; 42706f32e7eSjoerg 42806f32e7eSjoerg /// The previous token in the unwrapped line. 42906f32e7eSjoerg FormatToken *Previous = nullptr; 43006f32e7eSjoerg 43106f32e7eSjoerg /// The next token in the unwrapped line. 43206f32e7eSjoerg FormatToken *Next = nullptr; 43306f32e7eSjoerg 43406f32e7eSjoerg /// If this token starts a block, this contains all the unwrapped lines 43506f32e7eSjoerg /// in it. 43606f32e7eSjoerg SmallVector<AnnotatedLine *, 1> Children; 43706f32e7eSjoerg 438*13fbcb42Sjoerg // Contains all attributes related to how this token takes part 439*13fbcb42Sjoerg // in a configured macro expansion. 440*13fbcb42Sjoerg llvm::Optional<MacroExpansion> MacroCtx; 44106f32e7eSjoerg isFormatToken44206f32e7eSjoerg bool is(tok::TokenKind Kind) const { return Tok.is(Kind); } isFormatToken443*13fbcb42Sjoerg bool is(TokenType TT) const { return getType() == TT; } isFormatToken44406f32e7eSjoerg bool is(const IdentifierInfo *II) const { 44506f32e7eSjoerg return II && II == Tok.getIdentifierInfo(); 44606f32e7eSjoerg } isFormatToken44706f32e7eSjoerg bool is(tok::PPKeywordKind Kind) const { 44806f32e7eSjoerg return Tok.getIdentifierInfo() && 44906f32e7eSjoerg Tok.getIdentifierInfo()->getPPKeywordID() == Kind; 45006f32e7eSjoerg } isFormatToken451*13fbcb42Sjoerg bool is(BraceBlockKind BBK) const { return getBlockKind() == BBK; } isFormatToken452*13fbcb42Sjoerg bool is(ParameterPackingKind PPK) const { return getPackingKind() == PPK; } 453*13fbcb42Sjoerg isOneOfFormatToken45406f32e7eSjoerg template <typename A, typename B> bool isOneOf(A K1, B K2) const { 45506f32e7eSjoerg return is(K1) || is(K2); 45606f32e7eSjoerg } 45706f32e7eSjoerg template <typename A, typename B, typename... Ts> isOneOfFormatToken45806f32e7eSjoerg bool isOneOf(A K1, B K2, Ts... Ks) const { 45906f32e7eSjoerg return is(K1) || isOneOf(K2, Ks...); 46006f32e7eSjoerg } isNotFormatToken46106f32e7eSjoerg template <typename T> bool isNot(T Kind) const { return !is(Kind); } 46206f32e7eSjoerg 46306f32e7eSjoerg bool isIf(bool AllowConstexprMacro = true) const { 46406f32e7eSjoerg return is(tok::kw_if) || endsSequence(tok::kw_constexpr, tok::kw_if) || 46506f32e7eSjoerg (endsSequence(tok::identifier, tok::kw_if) && AllowConstexprMacro); 46606f32e7eSjoerg } 46706f32e7eSjoerg closesScopeAfterBlockFormatToken46806f32e7eSjoerg bool closesScopeAfterBlock() const { 469*13fbcb42Sjoerg if (getBlockKind() == BK_Block) 47006f32e7eSjoerg return true; 47106f32e7eSjoerg if (closesScope()) 47206f32e7eSjoerg return Previous->closesScopeAfterBlock(); 47306f32e7eSjoerg return false; 47406f32e7eSjoerg } 47506f32e7eSjoerg 47606f32e7eSjoerg /// \c true if this token starts a sequence with the given tokens in order, 47706f32e7eSjoerg /// following the ``Next`` pointers, ignoring comments. 47806f32e7eSjoerg template <typename A, typename... Ts> startsSequenceFormatToken47906f32e7eSjoerg bool startsSequence(A K1, Ts... Tokens) const { 48006f32e7eSjoerg return startsSequenceInternal(K1, Tokens...); 48106f32e7eSjoerg } 48206f32e7eSjoerg 48306f32e7eSjoerg /// \c true if this token ends a sequence with the given tokens in order, 48406f32e7eSjoerg /// following the ``Previous`` pointers, ignoring comments. 48506f32e7eSjoerg /// For example, given tokens [T1, T2, T3], the function returns true if 48606f32e7eSjoerg /// 3 tokens ending at this (ignoring comments) are [T3, T2, T1]. In other 48706f32e7eSjoerg /// words, the tokens passed to this function need to the reverse of the 48806f32e7eSjoerg /// order the tokens appear in code. 48906f32e7eSjoerg template <typename A, typename... Ts> endsSequenceFormatToken49006f32e7eSjoerg bool endsSequence(A K1, Ts... Tokens) const { 49106f32e7eSjoerg return endsSequenceInternal(K1, Tokens...); 49206f32e7eSjoerg } 49306f32e7eSjoerg isStringLiteralFormatToken49406f32e7eSjoerg bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); } 49506f32e7eSjoerg isObjCAtKeywordFormatToken49606f32e7eSjoerg bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const { 49706f32e7eSjoerg return Tok.isObjCAtKeyword(Kind); 49806f32e7eSjoerg } 49906f32e7eSjoerg 50006f32e7eSjoerg bool isAccessSpecifier(bool ColonRequired = true) const { 50106f32e7eSjoerg return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) && 50206f32e7eSjoerg (!ColonRequired || (Next && Next->is(tok::colon))); 50306f32e7eSjoerg } 50406f32e7eSjoerg canBePointerOrReferenceQualifierFormatToken505*13fbcb42Sjoerg bool canBePointerOrReferenceQualifier() const { 506*13fbcb42Sjoerg return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile, 507*13fbcb42Sjoerg tok::kw___attribute, tok::kw__Nonnull, tok::kw__Nullable, 508*13fbcb42Sjoerg tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64, 509*13fbcb42Sjoerg TT_AttributeMacro); 510*13fbcb42Sjoerg } 511*13fbcb42Sjoerg 51206f32e7eSjoerg /// Determine whether the token is a simple-type-specifier. 51306f32e7eSjoerg bool isSimpleTypeSpecifier() const; 51406f32e7eSjoerg isObjCAccessSpecifierFormatToken51506f32e7eSjoerg bool isObjCAccessSpecifier() const { 51606f32e7eSjoerg return is(tok::at) && Next && 51706f32e7eSjoerg (Next->isObjCAtKeyword(tok::objc_public) || 51806f32e7eSjoerg Next->isObjCAtKeyword(tok::objc_protected) || 51906f32e7eSjoerg Next->isObjCAtKeyword(tok::objc_package) || 52006f32e7eSjoerg Next->isObjCAtKeyword(tok::objc_private)); 52106f32e7eSjoerg } 52206f32e7eSjoerg 52306f32e7eSjoerg /// Returns whether \p Tok is ([{ or an opening < of a template or in 52406f32e7eSjoerg /// protos. opensScopeFormatToken52506f32e7eSjoerg bool opensScope() const { 52606f32e7eSjoerg if (is(TT_TemplateString) && TokenText.endswith("${")) 52706f32e7eSjoerg return true; 52806f32e7eSjoerg if (is(TT_DictLiteral) && is(tok::less)) 52906f32e7eSjoerg return true; 53006f32e7eSjoerg return isOneOf(tok::l_paren, tok::l_brace, tok::l_square, 53106f32e7eSjoerg TT_TemplateOpener); 53206f32e7eSjoerg } 53306f32e7eSjoerg /// Returns whether \p Tok is )]} or a closing > of a template or in 53406f32e7eSjoerg /// protos. closesScopeFormatToken53506f32e7eSjoerg bool closesScope() const { 53606f32e7eSjoerg if (is(TT_TemplateString) && TokenText.startswith("}")) 53706f32e7eSjoerg return true; 53806f32e7eSjoerg if (is(TT_DictLiteral) && is(tok::greater)) 53906f32e7eSjoerg return true; 54006f32e7eSjoerg return isOneOf(tok::r_paren, tok::r_brace, tok::r_square, 54106f32e7eSjoerg TT_TemplateCloser); 54206f32e7eSjoerg } 54306f32e7eSjoerg 54406f32e7eSjoerg /// Returns \c true if this is a "." or "->" accessing a member. isMemberAccessFormatToken54506f32e7eSjoerg bool isMemberAccess() const { 54606f32e7eSjoerg return isOneOf(tok::arrow, tok::period, tok::arrowstar) && 54706f32e7eSjoerg !isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow, 548*13fbcb42Sjoerg TT_LambdaArrow, TT_LeadingJavaAnnotation); 54906f32e7eSjoerg } 55006f32e7eSjoerg isUnaryOperatorFormatToken55106f32e7eSjoerg bool isUnaryOperator() const { 55206f32e7eSjoerg switch (Tok.getKind()) { 55306f32e7eSjoerg case tok::plus: 55406f32e7eSjoerg case tok::plusplus: 55506f32e7eSjoerg case tok::minus: 55606f32e7eSjoerg case tok::minusminus: 55706f32e7eSjoerg case tok::exclaim: 55806f32e7eSjoerg case tok::tilde: 55906f32e7eSjoerg case tok::kw_sizeof: 56006f32e7eSjoerg case tok::kw_alignof: 56106f32e7eSjoerg return true; 56206f32e7eSjoerg default: 56306f32e7eSjoerg return false; 56406f32e7eSjoerg } 56506f32e7eSjoerg } 56606f32e7eSjoerg isBinaryOperatorFormatToken56706f32e7eSjoerg bool isBinaryOperator() const { 56806f32e7eSjoerg // Comma is a binary operator, but does not behave as such wrt. formatting. 56906f32e7eSjoerg return getPrecedence() > prec::Comma; 57006f32e7eSjoerg } 57106f32e7eSjoerg isTrailingCommentFormatToken57206f32e7eSjoerg bool isTrailingComment() const { 57306f32e7eSjoerg return is(tok::comment) && 57406f32e7eSjoerg (is(TT_LineComment) || !Next || Next->NewlinesBefore > 0); 57506f32e7eSjoerg } 57606f32e7eSjoerg 57706f32e7eSjoerg /// Returns \c true if this is a keyword that can be used 57806f32e7eSjoerg /// like a function call (e.g. sizeof, typeid, ...). isFunctionLikeKeywordFormatToken57906f32e7eSjoerg bool isFunctionLikeKeyword() const { 58006f32e7eSjoerg switch (Tok.getKind()) { 58106f32e7eSjoerg case tok::kw_throw: 58206f32e7eSjoerg case tok::kw_typeid: 58306f32e7eSjoerg case tok::kw_return: 58406f32e7eSjoerg case tok::kw_sizeof: 58506f32e7eSjoerg case tok::kw_alignof: 58606f32e7eSjoerg case tok::kw_alignas: 58706f32e7eSjoerg case tok::kw_decltype: 58806f32e7eSjoerg case tok::kw_noexcept: 58906f32e7eSjoerg case tok::kw_static_assert: 590*13fbcb42Sjoerg case tok::kw__Atomic: 59106f32e7eSjoerg case tok::kw___attribute: 592*13fbcb42Sjoerg case tok::kw___underlying_type: 593*13fbcb42Sjoerg case tok::kw_requires: 59406f32e7eSjoerg return true; 59506f32e7eSjoerg default: 59606f32e7eSjoerg return false; 59706f32e7eSjoerg } 59806f32e7eSjoerg } 59906f32e7eSjoerg 60006f32e7eSjoerg /// Returns \c true if this is a string literal that's like a label, 60106f32e7eSjoerg /// e.g. ends with "=" or ":". isLabelStringFormatToken60206f32e7eSjoerg bool isLabelString() const { 60306f32e7eSjoerg if (!is(tok::string_literal)) 60406f32e7eSjoerg return false; 60506f32e7eSjoerg StringRef Content = TokenText; 60606f32e7eSjoerg if (Content.startswith("\"") || Content.startswith("'")) 60706f32e7eSjoerg Content = Content.drop_front(1); 60806f32e7eSjoerg if (Content.endswith("\"") || Content.endswith("'")) 60906f32e7eSjoerg Content = Content.drop_back(1); 61006f32e7eSjoerg Content = Content.trim(); 61106f32e7eSjoerg return Content.size() > 1 && 61206f32e7eSjoerg (Content.back() == ':' || Content.back() == '='); 61306f32e7eSjoerg } 61406f32e7eSjoerg 61506f32e7eSjoerg /// Returns actual token start location without leading escaped 61606f32e7eSjoerg /// newlines and whitespace. 61706f32e7eSjoerg /// 61806f32e7eSjoerg /// This can be different to Tok.getLocation(), which includes leading escaped 61906f32e7eSjoerg /// newlines. getStartOfNonWhitespaceFormatToken62006f32e7eSjoerg SourceLocation getStartOfNonWhitespace() const { 62106f32e7eSjoerg return WhitespaceRange.getEnd(); 62206f32e7eSjoerg } 62306f32e7eSjoerg getPrecedenceFormatToken62406f32e7eSjoerg prec::Level getPrecedence() const { 62506f32e7eSjoerg return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true, 62606f32e7eSjoerg /*CPlusPlus11=*/true); 62706f32e7eSjoerg } 62806f32e7eSjoerg 62906f32e7eSjoerg /// Returns the previous token ignoring comments. getPreviousNonCommentFormatToken63006f32e7eSjoerg FormatToken *getPreviousNonComment() const { 63106f32e7eSjoerg FormatToken *Tok = Previous; 63206f32e7eSjoerg while (Tok && Tok->is(tok::comment)) 63306f32e7eSjoerg Tok = Tok->Previous; 63406f32e7eSjoerg return Tok; 63506f32e7eSjoerg } 63606f32e7eSjoerg 63706f32e7eSjoerg /// Returns the next token ignoring comments. getNextNonCommentFormatToken63806f32e7eSjoerg const FormatToken *getNextNonComment() const { 63906f32e7eSjoerg const FormatToken *Tok = Next; 64006f32e7eSjoerg while (Tok && Tok->is(tok::comment)) 64106f32e7eSjoerg Tok = Tok->Next; 64206f32e7eSjoerg return Tok; 64306f32e7eSjoerg } 64406f32e7eSjoerg 64506f32e7eSjoerg /// Returns \c true if this tokens starts a block-type list, i.e. a 64606f32e7eSjoerg /// list that should be indented with a block indent. opensBlockOrBlockTypeListFormatToken64706f32e7eSjoerg bool opensBlockOrBlockTypeList(const FormatStyle &Style) const { 648*13fbcb42Sjoerg // C# Does not indent object initialisers as continuations. 649*13fbcb42Sjoerg if (is(tok::l_brace) && getBlockKind() == BK_BracedInit && Style.isCSharp()) 650*13fbcb42Sjoerg return true; 65106f32e7eSjoerg if (is(TT_TemplateString) && opensScope()) 65206f32e7eSjoerg return true; 65306f32e7eSjoerg return is(TT_ArrayInitializerLSquare) || is(TT_ProtoExtensionLSquare) || 65406f32e7eSjoerg (is(tok::l_brace) && 655*13fbcb42Sjoerg (getBlockKind() == BK_Block || is(TT_DictLiteral) || 65606f32e7eSjoerg (!Style.Cpp11BracedListStyle && NestingLevel == 0))) || 65706f32e7eSjoerg (is(tok::less) && (Style.Language == FormatStyle::LK_Proto || 65806f32e7eSjoerg Style.Language == FormatStyle::LK_TextProto)); 65906f32e7eSjoerg } 66006f32e7eSjoerg 66106f32e7eSjoerg /// Returns whether the token is the left square bracket of a C++ 66206f32e7eSjoerg /// structured binding declaration. isCppStructuredBindingFormatToken66306f32e7eSjoerg bool isCppStructuredBinding(const FormatStyle &Style) const { 66406f32e7eSjoerg if (!Style.isCpp() || isNot(tok::l_square)) 66506f32e7eSjoerg return false; 66606f32e7eSjoerg const FormatToken *T = this; 66706f32e7eSjoerg do { 66806f32e7eSjoerg T = T->getPreviousNonComment(); 66906f32e7eSjoerg } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp, 67006f32e7eSjoerg tok::ampamp)); 67106f32e7eSjoerg return T && T->is(tok::kw_auto); 67206f32e7eSjoerg } 67306f32e7eSjoerg 67406f32e7eSjoerg /// Same as opensBlockOrBlockTypeList, but for the closing token. closesBlockOrBlockTypeListFormatToken67506f32e7eSjoerg bool closesBlockOrBlockTypeList(const FormatStyle &Style) const { 67606f32e7eSjoerg if (is(TT_TemplateString) && closesScope()) 67706f32e7eSjoerg return true; 67806f32e7eSjoerg return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style); 67906f32e7eSjoerg } 68006f32e7eSjoerg 68106f32e7eSjoerg /// Return the actual namespace token, if this token starts a namespace 68206f32e7eSjoerg /// block. getNamespaceTokenFormatToken68306f32e7eSjoerg const FormatToken *getNamespaceToken() const { 68406f32e7eSjoerg const FormatToken *NamespaceTok = this; 68506f32e7eSjoerg if (is(tok::comment)) 68606f32e7eSjoerg NamespaceTok = NamespaceTok->getNextNonComment(); 68706f32e7eSjoerg // Detect "(inline|export)? namespace" in the beginning of a line. 68806f32e7eSjoerg if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export)) 68906f32e7eSjoerg NamespaceTok = NamespaceTok->getNextNonComment(); 69006f32e7eSjoerg return NamespaceTok && 69106f32e7eSjoerg NamespaceTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) 69206f32e7eSjoerg ? NamespaceTok 69306f32e7eSjoerg : nullptr; 69406f32e7eSjoerg } 69506f32e7eSjoerg copyFromFormatToken696*13fbcb42Sjoerg void copyFrom(const FormatToken &Tok) { *this = Tok; } 697*13fbcb42Sjoerg 69806f32e7eSjoerg private: 699*13fbcb42Sjoerg // Only allow copying via the explicit copyFrom method. 70006f32e7eSjoerg FormatToken(const FormatToken &) = delete; 701*13fbcb42Sjoerg FormatToken &operator=(const FormatToken &) = default; 70206f32e7eSjoerg 70306f32e7eSjoerg template <typename A, typename... Ts> startsSequenceInternalFormatToken70406f32e7eSjoerg bool startsSequenceInternal(A K1, Ts... Tokens) const { 70506f32e7eSjoerg if (is(tok::comment) && Next) 70606f32e7eSjoerg return Next->startsSequenceInternal(K1, Tokens...); 70706f32e7eSjoerg return is(K1) && Next && Next->startsSequenceInternal(Tokens...); 70806f32e7eSjoerg } 70906f32e7eSjoerg startsSequenceInternalFormatToken71006f32e7eSjoerg template <typename A> bool startsSequenceInternal(A K1) const { 71106f32e7eSjoerg if (is(tok::comment) && Next) 71206f32e7eSjoerg return Next->startsSequenceInternal(K1); 71306f32e7eSjoerg return is(K1); 71406f32e7eSjoerg } 71506f32e7eSjoerg endsSequenceInternalFormatToken71606f32e7eSjoerg template <typename A, typename... Ts> bool endsSequenceInternal(A K1) const { 71706f32e7eSjoerg if (is(tok::comment) && Previous) 71806f32e7eSjoerg return Previous->endsSequenceInternal(K1); 71906f32e7eSjoerg return is(K1); 72006f32e7eSjoerg } 72106f32e7eSjoerg 72206f32e7eSjoerg template <typename A, typename... Ts> endsSequenceInternalFormatToken72306f32e7eSjoerg bool endsSequenceInternal(A K1, Ts... Tokens) const { 72406f32e7eSjoerg if (is(tok::comment) && Previous) 72506f32e7eSjoerg return Previous->endsSequenceInternal(K1, Tokens...); 72606f32e7eSjoerg return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...); 72706f32e7eSjoerg } 72806f32e7eSjoerg }; 72906f32e7eSjoerg 73006f32e7eSjoerg class ContinuationIndenter; 73106f32e7eSjoerg struct LineState; 73206f32e7eSjoerg 73306f32e7eSjoerg class TokenRole { 73406f32e7eSjoerg public: TokenRole(const FormatStyle & Style)73506f32e7eSjoerg TokenRole(const FormatStyle &Style) : Style(Style) {} 73606f32e7eSjoerg virtual ~TokenRole(); 73706f32e7eSjoerg 73806f32e7eSjoerg /// After the \c TokenAnnotator has finished annotating all the tokens, 73906f32e7eSjoerg /// this function precomputes required information for formatting. 74006f32e7eSjoerg virtual void precomputeFormattingInfos(const FormatToken *Token); 74106f32e7eSjoerg 74206f32e7eSjoerg /// Apply the special formatting that the given role demands. 74306f32e7eSjoerg /// 74406f32e7eSjoerg /// Assumes that the token having this role is already formatted. 74506f32e7eSjoerg /// 74606f32e7eSjoerg /// Continues formatting from \p State leaving indentation to \p Indenter and 74706f32e7eSjoerg /// returns the total penalty that this formatting incurs. formatFromToken(LineState & State,ContinuationIndenter * Indenter,bool DryRun)74806f32e7eSjoerg virtual unsigned formatFromToken(LineState &State, 74906f32e7eSjoerg ContinuationIndenter *Indenter, 75006f32e7eSjoerg bool DryRun) { 75106f32e7eSjoerg return 0; 75206f32e7eSjoerg } 75306f32e7eSjoerg 75406f32e7eSjoerg /// Same as \c formatFromToken, but assumes that the first token has 75506f32e7eSjoerg /// already been set thereby deciding on the first line break. formatAfterToken(LineState & State,ContinuationIndenter * Indenter,bool DryRun)75606f32e7eSjoerg virtual unsigned formatAfterToken(LineState &State, 75706f32e7eSjoerg ContinuationIndenter *Indenter, 75806f32e7eSjoerg bool DryRun) { 75906f32e7eSjoerg return 0; 76006f32e7eSjoerg } 76106f32e7eSjoerg 76206f32e7eSjoerg /// Notifies the \c Role that a comma was found. CommaFound(const FormatToken * Token)76306f32e7eSjoerg virtual void CommaFound(const FormatToken *Token) {} 76406f32e7eSjoerg lastComma()76506f32e7eSjoerg virtual const FormatToken *lastComma() { return nullptr; } 76606f32e7eSjoerg 76706f32e7eSjoerg protected: 76806f32e7eSjoerg const FormatStyle &Style; 76906f32e7eSjoerg }; 77006f32e7eSjoerg 77106f32e7eSjoerg class CommaSeparatedList : public TokenRole { 77206f32e7eSjoerg public: CommaSeparatedList(const FormatStyle & Style)77306f32e7eSjoerg CommaSeparatedList(const FormatStyle &Style) 77406f32e7eSjoerg : TokenRole(Style), HasNestedBracedList(false) {} 77506f32e7eSjoerg 77606f32e7eSjoerg void precomputeFormattingInfos(const FormatToken *Token) override; 77706f32e7eSjoerg 77806f32e7eSjoerg unsigned formatAfterToken(LineState &State, ContinuationIndenter *Indenter, 77906f32e7eSjoerg bool DryRun) override; 78006f32e7eSjoerg 78106f32e7eSjoerg unsigned formatFromToken(LineState &State, ContinuationIndenter *Indenter, 78206f32e7eSjoerg bool DryRun) override; 78306f32e7eSjoerg 78406f32e7eSjoerg /// Adds \p Token as the next comma to the \c CommaSeparated list. CommaFound(const FormatToken * Token)78506f32e7eSjoerg void CommaFound(const FormatToken *Token) override { 78606f32e7eSjoerg Commas.push_back(Token); 78706f32e7eSjoerg } 78806f32e7eSjoerg lastComma()78906f32e7eSjoerg const FormatToken *lastComma() override { 79006f32e7eSjoerg if (Commas.empty()) 79106f32e7eSjoerg return nullptr; 79206f32e7eSjoerg return Commas.back(); 79306f32e7eSjoerg } 79406f32e7eSjoerg 79506f32e7eSjoerg private: 79606f32e7eSjoerg /// A struct that holds information on how to format a given list with 79706f32e7eSjoerg /// a specific number of columns. 79806f32e7eSjoerg struct ColumnFormat { 79906f32e7eSjoerg /// The number of columns to use. 80006f32e7eSjoerg unsigned Columns; 80106f32e7eSjoerg 80206f32e7eSjoerg /// The total width in characters. 80306f32e7eSjoerg unsigned TotalWidth; 80406f32e7eSjoerg 80506f32e7eSjoerg /// The number of lines required for this format. 80606f32e7eSjoerg unsigned LineCount; 80706f32e7eSjoerg 80806f32e7eSjoerg /// The size of each column in characters. 80906f32e7eSjoerg SmallVector<unsigned, 8> ColumnSizes; 81006f32e7eSjoerg }; 81106f32e7eSjoerg 81206f32e7eSjoerg /// Calculate which \c ColumnFormat fits best into 81306f32e7eSjoerg /// \p RemainingCharacters. 81406f32e7eSjoerg const ColumnFormat *getColumnFormat(unsigned RemainingCharacters) const; 81506f32e7eSjoerg 81606f32e7eSjoerg /// The ordered \c FormatTokens making up the commas of this list. 81706f32e7eSjoerg SmallVector<const FormatToken *, 8> Commas; 81806f32e7eSjoerg 81906f32e7eSjoerg /// The length of each of the list's items in characters including the 82006f32e7eSjoerg /// trailing comma. 82106f32e7eSjoerg SmallVector<unsigned, 8> ItemLengths; 82206f32e7eSjoerg 82306f32e7eSjoerg /// Precomputed formats that can be used for this list. 82406f32e7eSjoerg SmallVector<ColumnFormat, 4> Formats; 82506f32e7eSjoerg 82606f32e7eSjoerg bool HasNestedBracedList; 82706f32e7eSjoerg }; 82806f32e7eSjoerg 82906f32e7eSjoerg /// Encapsulates keywords that are context sensitive or for languages not 83006f32e7eSjoerg /// properly supported by Clang's lexer. 83106f32e7eSjoerg struct AdditionalKeywords { AdditionalKeywordsAdditionalKeywords83206f32e7eSjoerg AdditionalKeywords(IdentifierTable &IdentTable) { 83306f32e7eSjoerg kw_final = &IdentTable.get("final"); 83406f32e7eSjoerg kw_override = &IdentTable.get("override"); 83506f32e7eSjoerg kw_in = &IdentTable.get("in"); 83606f32e7eSjoerg kw_of = &IdentTable.get("of"); 83706f32e7eSjoerg kw_CF_CLOSED_ENUM = &IdentTable.get("CF_CLOSED_ENUM"); 83806f32e7eSjoerg kw_CF_ENUM = &IdentTable.get("CF_ENUM"); 83906f32e7eSjoerg kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS"); 84006f32e7eSjoerg kw_NS_CLOSED_ENUM = &IdentTable.get("NS_CLOSED_ENUM"); 84106f32e7eSjoerg kw_NS_ENUM = &IdentTable.get("NS_ENUM"); 84206f32e7eSjoerg kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS"); 84306f32e7eSjoerg 84406f32e7eSjoerg kw_as = &IdentTable.get("as"); 84506f32e7eSjoerg kw_async = &IdentTable.get("async"); 84606f32e7eSjoerg kw_await = &IdentTable.get("await"); 84706f32e7eSjoerg kw_declare = &IdentTable.get("declare"); 84806f32e7eSjoerg kw_finally = &IdentTable.get("finally"); 84906f32e7eSjoerg kw_from = &IdentTable.get("from"); 85006f32e7eSjoerg kw_function = &IdentTable.get("function"); 85106f32e7eSjoerg kw_get = &IdentTable.get("get"); 85206f32e7eSjoerg kw_import = &IdentTable.get("import"); 85306f32e7eSjoerg kw_infer = &IdentTable.get("infer"); 85406f32e7eSjoerg kw_is = &IdentTable.get("is"); 85506f32e7eSjoerg kw_let = &IdentTable.get("let"); 85606f32e7eSjoerg kw_module = &IdentTable.get("module"); 85706f32e7eSjoerg kw_readonly = &IdentTable.get("readonly"); 85806f32e7eSjoerg kw_set = &IdentTable.get("set"); 85906f32e7eSjoerg kw_type = &IdentTable.get("type"); 86006f32e7eSjoerg kw_typeof = &IdentTable.get("typeof"); 86106f32e7eSjoerg kw_var = &IdentTable.get("var"); 86206f32e7eSjoerg kw_yield = &IdentTable.get("yield"); 86306f32e7eSjoerg 86406f32e7eSjoerg kw_abstract = &IdentTable.get("abstract"); 86506f32e7eSjoerg kw_assert = &IdentTable.get("assert"); 86606f32e7eSjoerg kw_extends = &IdentTable.get("extends"); 86706f32e7eSjoerg kw_implements = &IdentTable.get("implements"); 86806f32e7eSjoerg kw_instanceof = &IdentTable.get("instanceof"); 86906f32e7eSjoerg kw_interface = &IdentTable.get("interface"); 87006f32e7eSjoerg kw_native = &IdentTable.get("native"); 87106f32e7eSjoerg kw_package = &IdentTable.get("package"); 87206f32e7eSjoerg kw_synchronized = &IdentTable.get("synchronized"); 87306f32e7eSjoerg kw_throws = &IdentTable.get("throws"); 87406f32e7eSjoerg kw___except = &IdentTable.get("__except"); 87506f32e7eSjoerg kw___has_include = &IdentTable.get("__has_include"); 87606f32e7eSjoerg kw___has_include_next = &IdentTable.get("__has_include_next"); 87706f32e7eSjoerg 87806f32e7eSjoerg kw_mark = &IdentTable.get("mark"); 87906f32e7eSjoerg 88006f32e7eSjoerg kw_extend = &IdentTable.get("extend"); 88106f32e7eSjoerg kw_option = &IdentTable.get("option"); 88206f32e7eSjoerg kw_optional = &IdentTable.get("optional"); 88306f32e7eSjoerg kw_repeated = &IdentTable.get("repeated"); 88406f32e7eSjoerg kw_required = &IdentTable.get("required"); 88506f32e7eSjoerg kw_returns = &IdentTable.get("returns"); 88606f32e7eSjoerg 88706f32e7eSjoerg kw_signals = &IdentTable.get("signals"); 88806f32e7eSjoerg kw_qsignals = &IdentTable.get("Q_SIGNALS"); 88906f32e7eSjoerg kw_slots = &IdentTable.get("slots"); 89006f32e7eSjoerg kw_qslots = &IdentTable.get("Q_SLOTS"); 89106f32e7eSjoerg 89206f32e7eSjoerg // C# keywords 89306f32e7eSjoerg kw_dollar = &IdentTable.get("dollar"); 89406f32e7eSjoerg kw_base = &IdentTable.get("base"); 89506f32e7eSjoerg kw_byte = &IdentTable.get("byte"); 89606f32e7eSjoerg kw_checked = &IdentTable.get("checked"); 89706f32e7eSjoerg kw_decimal = &IdentTable.get("decimal"); 89806f32e7eSjoerg kw_delegate = &IdentTable.get("delegate"); 89906f32e7eSjoerg kw_event = &IdentTable.get("event"); 90006f32e7eSjoerg kw_fixed = &IdentTable.get("fixed"); 90106f32e7eSjoerg kw_foreach = &IdentTable.get("foreach"); 90206f32e7eSjoerg kw_implicit = &IdentTable.get("implicit"); 90306f32e7eSjoerg kw_internal = &IdentTable.get("internal"); 90406f32e7eSjoerg kw_lock = &IdentTable.get("lock"); 90506f32e7eSjoerg kw_null = &IdentTable.get("null"); 90606f32e7eSjoerg kw_object = &IdentTable.get("object"); 90706f32e7eSjoerg kw_out = &IdentTable.get("out"); 90806f32e7eSjoerg kw_params = &IdentTable.get("params"); 90906f32e7eSjoerg kw_ref = &IdentTable.get("ref"); 91006f32e7eSjoerg kw_string = &IdentTable.get("string"); 91106f32e7eSjoerg kw_stackalloc = &IdentTable.get("stackalloc"); 91206f32e7eSjoerg kw_sbyte = &IdentTable.get("sbyte"); 91306f32e7eSjoerg kw_sealed = &IdentTable.get("sealed"); 91406f32e7eSjoerg kw_uint = &IdentTable.get("uint"); 91506f32e7eSjoerg kw_ulong = &IdentTable.get("ulong"); 91606f32e7eSjoerg kw_unchecked = &IdentTable.get("unchecked"); 91706f32e7eSjoerg kw_unsafe = &IdentTable.get("unsafe"); 91806f32e7eSjoerg kw_ushort = &IdentTable.get("ushort"); 919*13fbcb42Sjoerg kw_when = &IdentTable.get("when"); 920*13fbcb42Sjoerg kw_where = &IdentTable.get("where"); 92106f32e7eSjoerg 92206f32e7eSjoerg // Keep this at the end of the constructor to make sure everything here 92306f32e7eSjoerg // is 92406f32e7eSjoerg // already initialized. 92506f32e7eSjoerg JsExtraKeywords = std::unordered_set<IdentifierInfo *>( 92606f32e7eSjoerg {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from, 92706f32e7eSjoerg kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly, 92806f32e7eSjoerg kw_set, kw_type, kw_typeof, kw_var, kw_yield, 92906f32e7eSjoerg // Keywords from the Java section. 93006f32e7eSjoerg kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface}); 93106f32e7eSjoerg 93206f32e7eSjoerg CSharpExtraKeywords = std::unordered_set<IdentifierInfo *>( 93306f32e7eSjoerg {kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate, kw_event, 93406f32e7eSjoerg kw_fixed, kw_foreach, kw_implicit, kw_in, kw_interface, kw_internal, 93506f32e7eSjoerg kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override, kw_params, 93606f32e7eSjoerg kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte, kw_sealed, 937*13fbcb42Sjoerg kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort, kw_when, 938*13fbcb42Sjoerg kw_where, 93906f32e7eSjoerg // Keywords from the JavaScript section. 94006f32e7eSjoerg kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from, 94106f32e7eSjoerg kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly, 94206f32e7eSjoerg kw_set, kw_type, kw_typeof, kw_var, kw_yield, 94306f32e7eSjoerg // Keywords from the Java section. 94406f32e7eSjoerg kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface}); 94506f32e7eSjoerg } 94606f32e7eSjoerg 94706f32e7eSjoerg // Context sensitive keywords. 94806f32e7eSjoerg IdentifierInfo *kw_final; 94906f32e7eSjoerg IdentifierInfo *kw_override; 95006f32e7eSjoerg IdentifierInfo *kw_in; 95106f32e7eSjoerg IdentifierInfo *kw_of; 95206f32e7eSjoerg IdentifierInfo *kw_CF_CLOSED_ENUM; 95306f32e7eSjoerg IdentifierInfo *kw_CF_ENUM; 95406f32e7eSjoerg IdentifierInfo *kw_CF_OPTIONS; 95506f32e7eSjoerg IdentifierInfo *kw_NS_CLOSED_ENUM; 95606f32e7eSjoerg IdentifierInfo *kw_NS_ENUM; 95706f32e7eSjoerg IdentifierInfo *kw_NS_OPTIONS; 95806f32e7eSjoerg IdentifierInfo *kw___except; 95906f32e7eSjoerg IdentifierInfo *kw___has_include; 96006f32e7eSjoerg IdentifierInfo *kw___has_include_next; 96106f32e7eSjoerg 96206f32e7eSjoerg // JavaScript keywords. 96306f32e7eSjoerg IdentifierInfo *kw_as; 96406f32e7eSjoerg IdentifierInfo *kw_async; 96506f32e7eSjoerg IdentifierInfo *kw_await; 96606f32e7eSjoerg IdentifierInfo *kw_declare; 96706f32e7eSjoerg IdentifierInfo *kw_finally; 96806f32e7eSjoerg IdentifierInfo *kw_from; 96906f32e7eSjoerg IdentifierInfo *kw_function; 97006f32e7eSjoerg IdentifierInfo *kw_get; 97106f32e7eSjoerg IdentifierInfo *kw_import; 97206f32e7eSjoerg IdentifierInfo *kw_infer; 97306f32e7eSjoerg IdentifierInfo *kw_is; 97406f32e7eSjoerg IdentifierInfo *kw_let; 97506f32e7eSjoerg IdentifierInfo *kw_module; 97606f32e7eSjoerg IdentifierInfo *kw_readonly; 97706f32e7eSjoerg IdentifierInfo *kw_set; 97806f32e7eSjoerg IdentifierInfo *kw_type; 97906f32e7eSjoerg IdentifierInfo *kw_typeof; 98006f32e7eSjoerg IdentifierInfo *kw_var; 98106f32e7eSjoerg IdentifierInfo *kw_yield; 98206f32e7eSjoerg 98306f32e7eSjoerg // Java keywords. 98406f32e7eSjoerg IdentifierInfo *kw_abstract; 98506f32e7eSjoerg IdentifierInfo *kw_assert; 98606f32e7eSjoerg IdentifierInfo *kw_extends; 98706f32e7eSjoerg IdentifierInfo *kw_implements; 98806f32e7eSjoerg IdentifierInfo *kw_instanceof; 98906f32e7eSjoerg IdentifierInfo *kw_interface; 99006f32e7eSjoerg IdentifierInfo *kw_native; 99106f32e7eSjoerg IdentifierInfo *kw_package; 99206f32e7eSjoerg IdentifierInfo *kw_synchronized; 99306f32e7eSjoerg IdentifierInfo *kw_throws; 99406f32e7eSjoerg 99506f32e7eSjoerg // Pragma keywords. 99606f32e7eSjoerg IdentifierInfo *kw_mark; 99706f32e7eSjoerg 99806f32e7eSjoerg // Proto keywords. 99906f32e7eSjoerg IdentifierInfo *kw_extend; 100006f32e7eSjoerg IdentifierInfo *kw_option; 100106f32e7eSjoerg IdentifierInfo *kw_optional; 100206f32e7eSjoerg IdentifierInfo *kw_repeated; 100306f32e7eSjoerg IdentifierInfo *kw_required; 100406f32e7eSjoerg IdentifierInfo *kw_returns; 100506f32e7eSjoerg 100606f32e7eSjoerg // QT keywords. 100706f32e7eSjoerg IdentifierInfo *kw_signals; 100806f32e7eSjoerg IdentifierInfo *kw_qsignals; 100906f32e7eSjoerg IdentifierInfo *kw_slots; 101006f32e7eSjoerg IdentifierInfo *kw_qslots; 101106f32e7eSjoerg 101206f32e7eSjoerg // C# keywords 101306f32e7eSjoerg IdentifierInfo *kw_dollar; 101406f32e7eSjoerg IdentifierInfo *kw_base; 101506f32e7eSjoerg IdentifierInfo *kw_byte; 101606f32e7eSjoerg IdentifierInfo *kw_checked; 101706f32e7eSjoerg IdentifierInfo *kw_decimal; 101806f32e7eSjoerg IdentifierInfo *kw_delegate; 101906f32e7eSjoerg IdentifierInfo *kw_event; 102006f32e7eSjoerg IdentifierInfo *kw_fixed; 102106f32e7eSjoerg IdentifierInfo *kw_foreach; 102206f32e7eSjoerg IdentifierInfo *kw_implicit; 102306f32e7eSjoerg IdentifierInfo *kw_internal; 102406f32e7eSjoerg 102506f32e7eSjoerg IdentifierInfo *kw_lock; 102606f32e7eSjoerg IdentifierInfo *kw_null; 102706f32e7eSjoerg IdentifierInfo *kw_object; 102806f32e7eSjoerg IdentifierInfo *kw_out; 102906f32e7eSjoerg 103006f32e7eSjoerg IdentifierInfo *kw_params; 103106f32e7eSjoerg 103206f32e7eSjoerg IdentifierInfo *kw_ref; 103306f32e7eSjoerg IdentifierInfo *kw_string; 103406f32e7eSjoerg IdentifierInfo *kw_stackalloc; 103506f32e7eSjoerg IdentifierInfo *kw_sbyte; 103606f32e7eSjoerg IdentifierInfo *kw_sealed; 103706f32e7eSjoerg IdentifierInfo *kw_uint; 103806f32e7eSjoerg IdentifierInfo *kw_ulong; 103906f32e7eSjoerg IdentifierInfo *kw_unchecked; 104006f32e7eSjoerg IdentifierInfo *kw_unsafe; 104106f32e7eSjoerg IdentifierInfo *kw_ushort; 1042*13fbcb42Sjoerg IdentifierInfo *kw_when; 1043*13fbcb42Sjoerg IdentifierInfo *kw_where; 104406f32e7eSjoerg 104506f32e7eSjoerg /// Returns \c true if \p Tok is a true JavaScript identifier, returns 104606f32e7eSjoerg /// \c false if it is a keyword or a pseudo keyword. 1047*13fbcb42Sjoerg /// If \c AcceptIdentifierName is true, returns true not only for keywords, 1048*13fbcb42Sjoerg // but also for IdentifierName tokens (aka pseudo-keywords), such as 1049*13fbcb42Sjoerg // ``yield``. 1050*13fbcb42Sjoerg bool IsJavaScriptIdentifier(const FormatToken &Tok, 1051*13fbcb42Sjoerg bool AcceptIdentifierName = true) const { 1052*13fbcb42Sjoerg // Based on the list of JavaScript & TypeScript keywords here: 1053*13fbcb42Sjoerg // https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts#L74 1054*13fbcb42Sjoerg switch (Tok.Tok.getKind()) { 1055*13fbcb42Sjoerg case tok::kw_break: 1056*13fbcb42Sjoerg case tok::kw_case: 1057*13fbcb42Sjoerg case tok::kw_catch: 1058*13fbcb42Sjoerg case tok::kw_class: 1059*13fbcb42Sjoerg case tok::kw_continue: 1060*13fbcb42Sjoerg case tok::kw_const: 1061*13fbcb42Sjoerg case tok::kw_default: 1062*13fbcb42Sjoerg case tok::kw_delete: 1063*13fbcb42Sjoerg case tok::kw_do: 1064*13fbcb42Sjoerg case tok::kw_else: 1065*13fbcb42Sjoerg case tok::kw_enum: 1066*13fbcb42Sjoerg case tok::kw_export: 1067*13fbcb42Sjoerg case tok::kw_false: 1068*13fbcb42Sjoerg case tok::kw_for: 1069*13fbcb42Sjoerg case tok::kw_if: 1070*13fbcb42Sjoerg case tok::kw_import: 1071*13fbcb42Sjoerg case tok::kw_module: 1072*13fbcb42Sjoerg case tok::kw_new: 1073*13fbcb42Sjoerg case tok::kw_private: 1074*13fbcb42Sjoerg case tok::kw_protected: 1075*13fbcb42Sjoerg case tok::kw_public: 1076*13fbcb42Sjoerg case tok::kw_return: 1077*13fbcb42Sjoerg case tok::kw_static: 1078*13fbcb42Sjoerg case tok::kw_switch: 1079*13fbcb42Sjoerg case tok::kw_this: 1080*13fbcb42Sjoerg case tok::kw_throw: 1081*13fbcb42Sjoerg case tok::kw_true: 1082*13fbcb42Sjoerg case tok::kw_try: 1083*13fbcb42Sjoerg case tok::kw_typeof: 1084*13fbcb42Sjoerg case tok::kw_void: 1085*13fbcb42Sjoerg case tok::kw_while: 1086*13fbcb42Sjoerg // These are JS keywords that are lexed by LLVM/clang as keywords. 1087*13fbcb42Sjoerg return false; 1088*13fbcb42Sjoerg case tok::identifier: { 1089*13fbcb42Sjoerg // For identifiers, make sure they are true identifiers, excluding the 1090*13fbcb42Sjoerg // JavaScript pseudo-keywords (not lexed by LLVM/clang as keywords). 1091*13fbcb42Sjoerg bool IsPseudoKeyword = 1092*13fbcb42Sjoerg JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) != 109306f32e7eSjoerg JsExtraKeywords.end(); 1094*13fbcb42Sjoerg return AcceptIdentifierName || !IsPseudoKeyword; 1095*13fbcb42Sjoerg } 1096*13fbcb42Sjoerg default: 1097*13fbcb42Sjoerg // Other keywords are handled in the switch below, to avoid problems due 1098*13fbcb42Sjoerg // to duplicate case labels when using the #include trick. 1099*13fbcb42Sjoerg break; 1100*13fbcb42Sjoerg } 1101*13fbcb42Sjoerg 1102*13fbcb42Sjoerg switch (Tok.Tok.getKind()) { 1103*13fbcb42Sjoerg // Handle C++ keywords not included above: these are all JS identifiers. 1104*13fbcb42Sjoerg #define KEYWORD(X, Y) case tok::kw_##X: 1105*13fbcb42Sjoerg #include "clang/Basic/TokenKinds.def" 1106*13fbcb42Sjoerg // #undef KEYWORD is not needed -- it's #undef-ed at the end of 1107*13fbcb42Sjoerg // TokenKinds.def 1108*13fbcb42Sjoerg return true; 1109*13fbcb42Sjoerg default: 1110*13fbcb42Sjoerg // All other tokens (punctuation etc) are not JS identifiers. 1111*13fbcb42Sjoerg return false; 1112*13fbcb42Sjoerg } 111306f32e7eSjoerg } 111406f32e7eSjoerg 111506f32e7eSjoerg /// Returns \c true if \p Tok is a C# keyword, returns 111606f32e7eSjoerg /// \c false if it is a anything else. isCSharpKeywordAdditionalKeywords111706f32e7eSjoerg bool isCSharpKeyword(const FormatToken &Tok) const { 111806f32e7eSjoerg switch (Tok.Tok.getKind()) { 111906f32e7eSjoerg case tok::kw_bool: 112006f32e7eSjoerg case tok::kw_break: 112106f32e7eSjoerg case tok::kw_case: 112206f32e7eSjoerg case tok::kw_catch: 112306f32e7eSjoerg case tok::kw_char: 112406f32e7eSjoerg case tok::kw_class: 112506f32e7eSjoerg case tok::kw_const: 112606f32e7eSjoerg case tok::kw_continue: 112706f32e7eSjoerg case tok::kw_default: 112806f32e7eSjoerg case tok::kw_do: 112906f32e7eSjoerg case tok::kw_double: 113006f32e7eSjoerg case tok::kw_else: 113106f32e7eSjoerg case tok::kw_enum: 113206f32e7eSjoerg case tok::kw_explicit: 113306f32e7eSjoerg case tok::kw_extern: 113406f32e7eSjoerg case tok::kw_false: 113506f32e7eSjoerg case tok::kw_float: 113606f32e7eSjoerg case tok::kw_for: 113706f32e7eSjoerg case tok::kw_goto: 113806f32e7eSjoerg case tok::kw_if: 113906f32e7eSjoerg case tok::kw_int: 114006f32e7eSjoerg case tok::kw_long: 114106f32e7eSjoerg case tok::kw_namespace: 114206f32e7eSjoerg case tok::kw_new: 114306f32e7eSjoerg case tok::kw_operator: 114406f32e7eSjoerg case tok::kw_private: 114506f32e7eSjoerg case tok::kw_protected: 114606f32e7eSjoerg case tok::kw_public: 114706f32e7eSjoerg case tok::kw_return: 114806f32e7eSjoerg case tok::kw_short: 114906f32e7eSjoerg case tok::kw_sizeof: 115006f32e7eSjoerg case tok::kw_static: 115106f32e7eSjoerg case tok::kw_struct: 115206f32e7eSjoerg case tok::kw_switch: 115306f32e7eSjoerg case tok::kw_this: 115406f32e7eSjoerg case tok::kw_throw: 115506f32e7eSjoerg case tok::kw_true: 115606f32e7eSjoerg case tok::kw_try: 115706f32e7eSjoerg case tok::kw_typeof: 115806f32e7eSjoerg case tok::kw_using: 115906f32e7eSjoerg case tok::kw_virtual: 116006f32e7eSjoerg case tok::kw_void: 116106f32e7eSjoerg case tok::kw_volatile: 116206f32e7eSjoerg case tok::kw_while: 116306f32e7eSjoerg return true; 116406f32e7eSjoerg default: 116506f32e7eSjoerg return Tok.is(tok::identifier) && 116606f32e7eSjoerg CSharpExtraKeywords.find(Tok.Tok.getIdentifierInfo()) == 116706f32e7eSjoerg CSharpExtraKeywords.end(); 116806f32e7eSjoerg } 116906f32e7eSjoerg } 117006f32e7eSjoerg 117106f32e7eSjoerg private: 117206f32e7eSjoerg /// The JavaScript keywords beyond the C++ keyword set. 117306f32e7eSjoerg std::unordered_set<IdentifierInfo *> JsExtraKeywords; 117406f32e7eSjoerg 117506f32e7eSjoerg /// The C# keywords beyond the C++ keyword set 117606f32e7eSjoerg std::unordered_set<IdentifierInfo *> CSharpExtraKeywords; 117706f32e7eSjoerg }; 117806f32e7eSjoerg 117906f32e7eSjoerg } // namespace format 118006f32e7eSjoerg } // namespace clang 118106f32e7eSjoerg 118206f32e7eSjoerg #endif 1183