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