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