1 //===--- FormatToken.h - Format C++ code ------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file contains the declaration of the FormatToken, a wrapper
11 /// around Token with additional information related to formatting.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H
16 #define LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H
18 #include "clang/Basic/IdentifierTable.h"
19 #include "clang/Basic/OperatorPrecedence.h"
20 #include "clang/Format/Format.h"
21 #include "clang/Lex/Lexer.h"
23 #include <unordered_set>
28 #define LIST_TOKEN_TYPES \
29 TYPE(ArrayInitializerLSquare) \
30 TYPE(ArraySubscriptLSquare) \
31 TYPE(AttributeColon) \
32 TYPE(AttributeParen) \
33 TYPE(AttributeSquare) \
34 TYPE(BinaryOperator) \
38 TYPE(ConditionalExpr) \
39 TYPE(ConflictAlternative) \
42 TYPE(CtorInitializerColon) \
43 TYPE(CtorInitializerComma) \
44 TYPE(DesignatedInitializerLSquare) \
45 TYPE(DesignatedInitializerPeriod) \
48 TYPE(FunctionAnnotationRParen) \
49 TYPE(FunctionDeclarationName) \
50 TYPE(FunctionLBrace) \
51 TYPE(FunctionTypeLParen) \
52 TYPE(ImplicitStringLiteral) \
53 TYPE(InheritanceColon) \
54 TYPE(InheritanceComma) \
55 TYPE(InlineASMBrace) \
56 TYPE(InlineASMColon) \
57 TYPE(JavaAnnotation) \
58 TYPE(JsComputedPropertyName) \
59 TYPE(JsExponentiation) \
60 TYPE(JsExponentiationEqual) \
62 TYPE(JsNonNullAssertion) \
63 TYPE(JsPrivateIdentifier) \
65 TYPE(JsTypeOperator) \
66 TYPE(JsTypeOptionalQuestion) \
70 TYPE(LeadingJavaAnnotation) \
72 TYPE(MacroBlockBegin) \
74 TYPE(NamespaceMacro) \
75 TYPE(ObjCBlockLBrace) \
76 TYPE(ObjCBlockLParen) \
79 TYPE(ObjCMethodExpr) \
80 TYPE(ObjCMethodSpecifier) \
82 TYPE(ObjCStringLiteral) \
83 TYPE(OverloadedOperator) \
84 TYPE(OverloadedOperatorLParen) \
85 TYPE(PointerOrReference) \
86 TYPE(PureVirtualSpecifier) \
87 TYPE(RangeBasedForLoopColon) \
91 TYPE(StatementMacro) \
92 TYPE(StructuredBindingLSquare) \
93 TYPE(TemplateCloser) \
94 TYPE(TemplateOpener) \
95 TYPE(TemplateString) \
96 TYPE(ProtoExtensionLSquare) \
97 TYPE(TrailingAnnotation) \
98 TYPE(TrailingReturnArrow) \
99 TYPE(TrailingUnaryOperator) \
100 TYPE(TypenameMacro) \
101 TYPE(UnaryOperator) \
102 TYPE(CSharpStringLiteral) \
103 TYPE(CSharpNullCoalescing) \
107 #define TYPE(X) TT_##X,
113 /// Determines the name of a token type.
114 const char *getTokenTypeName(TokenType Type);
116 // Represents what type of block a set of braces open.
117 enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit };
119 // The packing kind of a function's parameters.
120 enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive };
122 enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };
127 /// A wrapper around a \c Token storing information about the
128 /// whitespace characters preceding it.
135 /// The number of newlines immediately before the \c Token.
137 /// This can be used to determine what the user wrote in the original code
138 /// and thereby e.g. leave an empty line between two function definitions.
139 unsigned NewlinesBefore = 0;
141 /// Whether there is at least one unescaped newline before the \c
143 bool HasUnescapedNewline = false;
145 /// The range of the whitespace immediately preceding the \c Token.
146 SourceRange WhitespaceRange;
148 /// The offset just past the last '\n' in this token's leading
149 /// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.
150 unsigned LastNewlineOffset = 0;
152 /// The width of the non-whitespace parts of the token (or its first
153 /// line for multi-line tokens) in columns.
154 /// We need this to correctly measure number of columns a token spans.
155 unsigned ColumnWidth = 0;
157 /// Contains the width in columns of the last line of a multi-line
159 unsigned LastLineColumnWidth = 0;
161 /// Whether the token text contains newlines (escaped or not).
162 bool IsMultiline = false;
164 /// Indicates that this is the first token of the file.
165 bool IsFirst = false;
167 /// Whether there must be a line break before this token.
169 /// This happens for example when a preprocessor directive ended directly
170 /// before the token.
171 bool MustBreakBefore = false;
173 /// The raw text of the token.
175 /// Contains the raw token text without leading whitespace and without leading
176 /// escaped newlines.
179 /// Set to \c true if this token is an unterminated literal.
180 bool IsUnterminatedLiteral = 0;
182 /// Contains the kind of block if this token is a brace.
183 BraceBlockKind BlockKind = BK_Unknown;
185 TokenType Type = TT_Unknown;
187 /// The number of spaces that should be inserted before this token.
188 unsigned SpacesRequiredBefore = 0;
190 /// \c true if it is allowed to break before this token.
191 bool CanBreakBefore = false;
193 /// \c true if this is the ">" of "template<..>".
194 bool ClosesTemplateDeclaration = false;
196 /// Number of parameters, if this is "(", "[" or "<".
197 unsigned ParameterCount = 0;
199 /// Number of parameters that are nested blocks,
200 /// if this is "(", "[" or "<".
201 unsigned BlockParameterCount = 0;
203 /// If this is a bracket ("<", "(", "[" or "{"), contains the kind of
204 /// the surrounding bracket.
205 tok::TokenKind ParentBracket = tok::unknown;
207 /// A token can have a special role that can carry extra information
208 /// about the token's formatting.
209 std::unique_ptr<TokenRole> Role;
211 /// If this is an opening parenthesis, how are the parameters packed?
212 ParameterPackingKind PackingKind = PPK_Inconclusive;
214 /// The total length of the unwrapped line up to and including this
216 unsigned TotalLength = 0;
218 /// The original 0-based column of this token, including expanded tabs.
219 /// The configured TabWidth is used as tab width.
220 unsigned OriginalColumn = 0;
222 /// The length of following tokens until the next natural split point,
223 /// or the next token that can be broken.
224 unsigned UnbreakableTailLength = 0;
226 // FIXME: Come up with a 'cleaner' concept.
227 /// The binding strength of a token. This is a combined value of
228 /// operator precedence, parenthesis nesting, etc.
229 unsigned BindingStrength = 0;
231 /// The nesting level of this token, i.e. the number of surrounding (),
233 unsigned NestingLevel = 0;
235 /// The indent level of this token. Copied from the surrounding line.
236 unsigned IndentLevel = 0;
238 /// Penalty for inserting a line break before this token.
239 unsigned SplitPenalty = 0;
241 /// If this is the first ObjC selector name in an ObjC method
242 /// definition or call, this contains the length of the longest name.
244 /// This being set to 0 means that the selectors should not be colon-aligned,
245 /// e.g. because several of them are block-type.
246 unsigned LongestObjCSelectorName = 0;
248 /// If this is the first ObjC selector name in an ObjC method
249 /// definition or call, this contains the number of parts that the whole
250 /// selector consist of.
251 unsigned ObjCSelectorNameParts = 0;
253 /// The 0-based index of the parameter/argument. For ObjC it is set
254 /// for the selector name token.
255 /// For now calculated only for ObjC.
256 unsigned ParameterIndex = 0;
258 /// Stores the number of required fake parentheses and the
259 /// corresponding operator precedence.
261 /// If multiple fake parentheses start at a token, this vector stores them in
262 /// reverse order, i.e. inner fake parenthesis first.
263 SmallVector<prec::Level, 4> FakeLParens;
264 /// Insert this many fake ) after this token for correct indentation.
265 unsigned FakeRParens = 0;
267 /// \c true if this token starts a binary expression, i.e. has at least
268 /// one fake l_paren with a precedence greater than prec::Unknown.
269 bool StartsBinaryExpression = false;
270 /// \c true if this token ends a binary expression.
271 bool EndsBinaryExpression = false;
273 /// If this is an operator (or "."/"->") in a sequence of operators
274 /// with the same precedence, contains the 0-based operator index.
275 unsigned OperatorIndex = 0;
277 /// If this is an operator (or "."/"->") in a sequence of operators
278 /// with the same precedence, points to the next operator.
279 FormatToken *NextOperator = nullptr;
281 /// Is this token part of a \c DeclStmt defining multiple variables?
283 /// Only set if \c Type == \c TT_StartOfName.
284 bool PartOfMultiVariableDeclStmt = false;
286 /// Does this line comment continue a line comment section?
288 /// Only set to true if \c Type == \c TT_LineComment.
289 bool ContinuesLineCommentSection = false;
291 /// If this is a bracket, this points to the matching one.
292 FormatToken *MatchingParen = nullptr;
294 /// The previous token in the unwrapped line.
295 FormatToken *Previous = nullptr;
297 /// The next token in the unwrapped line.
298 FormatToken *Next = nullptr;
300 /// If this token starts a block, this contains all the unwrapped lines
302 SmallVector<AnnotatedLine *, 1> Children;
304 /// Stores the formatting decision for the token once it was made.
305 FormatDecision Decision = FD_Unformatted;
307 /// If \c true, this token has been fully formatted (indented and
308 /// potentially re-formatted inside), and we do not allow further formatting
310 bool Finalized = false;
312 bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
313 bool is(TokenType TT) const { return Type == TT; }
314 bool is(const IdentifierInfo *II) const {
315 return II && II == Tok.getIdentifierInfo();
317 bool is(tok::PPKeywordKind Kind) const {
318 return Tok.getIdentifierInfo() &&
319 Tok.getIdentifierInfo()->getPPKeywordID() == Kind;
321 template <typename A, typename B> bool isOneOf(A K1, B K2) const {
322 return is(K1) || is(K2);
324 template <typename A, typename B, typename... Ts>
325 bool isOneOf(A K1, B K2, Ts... Ks) const {
326 return is(K1) || isOneOf(K2, Ks...);
328 template <typename T> bool isNot(T Kind) const { return !is(Kind); }
330 bool closesScopeAfterBlock() const {
331 if (BlockKind == BK_Block)
334 return Previous->closesScopeAfterBlock();
338 /// \c true if this token starts a sequence with the given tokens in order,
339 /// following the ``Next`` pointers, ignoring comments.
340 template <typename A, typename... Ts>
341 bool startsSequence(A K1, Ts... Tokens) const {
342 return startsSequenceInternal(K1, Tokens...);
345 /// \c true if this token ends a sequence with the given tokens in order,
346 /// following the ``Previous`` pointers, ignoring comments.
347 template <typename A, typename... Ts>
348 bool endsSequence(A K1, Ts... Tokens) const {
349 return endsSequenceInternal(K1, Tokens...);
352 bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); }
354 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
355 return Tok.isObjCAtKeyword(Kind);
358 bool isAccessSpecifier(bool ColonRequired = true) const {
359 return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) &&
360 (!ColonRequired || (Next && Next->is(tok::colon)));
363 /// Determine whether the token is a simple-type-specifier.
364 bool isSimpleTypeSpecifier() const;
366 bool isObjCAccessSpecifier() const {
367 return is(tok::at) && Next &&
368 (Next->isObjCAtKeyword(tok::objc_public) ||
369 Next->isObjCAtKeyword(tok::objc_protected) ||
370 Next->isObjCAtKeyword(tok::objc_package) ||
371 Next->isObjCAtKeyword(tok::objc_private));
374 /// Returns whether \p Tok is ([{ or an opening < of a template or in
376 bool opensScope() const {
377 if (is(TT_TemplateString) && TokenText.endswith("${"))
379 if (is(TT_DictLiteral) && is(tok::less))
381 return isOneOf(tok::l_paren, tok::l_brace, tok::l_square,
384 /// Returns whether \p Tok is )]} or a closing > of a template or in
386 bool closesScope() const {
387 if (is(TT_TemplateString) && TokenText.startswith("}"))
389 if (is(TT_DictLiteral) && is(tok::greater))
391 return isOneOf(tok::r_paren, tok::r_brace, tok::r_square,
395 /// Returns \c true if this is a "." or "->" accessing a member.
396 bool isMemberAccess() const {
397 return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&
398 !isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow,
402 bool isUnaryOperator() const {
403 switch (Tok.getKind()) {
407 case tok::minusminus:
411 case tok::kw_alignof:
418 bool isBinaryOperator() const {
419 // Comma is a binary operator, but does not behave as such wrt. formatting.
420 return getPrecedence() > prec::Comma;
423 bool isTrailingComment() const {
424 return is(tok::comment) &&
425 (is(TT_LineComment) || !Next || Next->NewlinesBefore > 0);
428 /// Returns \c true if this is a keyword that can be used
429 /// like a function call (e.g. sizeof, typeid, ...).
430 bool isFunctionLikeKeyword() const {
431 switch (Tok.getKind()) {
436 case tok::kw_alignof:
437 case tok::kw_alignas:
438 case tok::kw_decltype:
439 case tok::kw_noexcept:
440 case tok::kw_static_assert:
441 case tok::kw___attribute:
448 /// Returns \c true if this is a string literal that's like a label,
449 /// e.g. ends with "=" or ":".
450 bool isLabelString() const {
451 if (!is(tok::string_literal))
453 StringRef Content = TokenText;
454 if (Content.startswith("\"") || Content.startswith("'"))
455 Content = Content.drop_front(1);
456 if (Content.endswith("\"") || Content.endswith("'"))
457 Content = Content.drop_back(1);
458 Content = Content.trim();
459 return Content.size() > 1 &&
460 (Content.back() == ':' || Content.back() == '=');
463 /// Returns actual token start location without leading escaped
464 /// newlines and whitespace.
466 /// This can be different to Tok.getLocation(), which includes leading escaped
468 SourceLocation getStartOfNonWhitespace() const {
469 return WhitespaceRange.getEnd();
472 prec::Level getPrecedence() const {
473 return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true,
474 /*CPlusPlus11=*/true);
477 /// Returns the previous token ignoring comments.
478 FormatToken *getPreviousNonComment() const {
479 FormatToken *Tok = Previous;
480 while (Tok && Tok->is(tok::comment))
485 /// Returns the next token ignoring comments.
486 const FormatToken *getNextNonComment() const {
487 const FormatToken *Tok = Next;
488 while (Tok && Tok->is(tok::comment))
493 /// Returns \c true if this tokens starts a block-type list, i.e. a
494 /// list that should be indented with a block indent.
495 bool opensBlockOrBlockTypeList(const FormatStyle &Style) const {
496 if (is(TT_TemplateString) && opensScope())
498 return is(TT_ArrayInitializerLSquare) || is(TT_ProtoExtensionLSquare) ||
500 (BlockKind == BK_Block || is(TT_DictLiteral) ||
501 (!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
502 (is(tok::less) && (Style.Language == FormatStyle::LK_Proto ||
503 Style.Language == FormatStyle::LK_TextProto));
506 /// Returns whether the token is the left square bracket of a C++
507 /// structured binding declaration.
508 bool isCppStructuredBinding(const FormatStyle &Style) const {
509 if (!Style.isCpp() || isNot(tok::l_square))
511 const FormatToken *T = this;
513 T = T->getPreviousNonComment();
514 } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp,
516 return T && T->is(tok::kw_auto);
519 /// Same as opensBlockOrBlockTypeList, but for the closing token.
520 bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {
521 if (is(TT_TemplateString) && closesScope())
523 return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);
526 /// Return the actual namespace token, if this token starts a namespace
528 const FormatToken *getNamespaceToken() const {
529 const FormatToken *NamespaceTok = this;
530 if (is(tok::comment))
531 NamespaceTok = NamespaceTok->getNextNonComment();
532 // Detect "(inline|export)? namespace" in the beginning of a line.
533 if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export))
534 NamespaceTok = NamespaceTok->getNextNonComment();
535 return NamespaceTok &&
536 NamespaceTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro)
543 FormatToken(const FormatToken &) = delete;
544 void operator=(const FormatToken &) = delete;
546 template <typename A, typename... Ts>
547 bool startsSequenceInternal(A K1, Ts... Tokens) const {
548 if (is(tok::comment) && Next)
549 return Next->startsSequenceInternal(K1, Tokens...);
550 return is(K1) && Next && Next->startsSequenceInternal(Tokens...);
553 template <typename A> bool startsSequenceInternal(A K1) const {
554 if (is(tok::comment) && Next)
555 return Next->startsSequenceInternal(K1);
559 template <typename A, typename... Ts> bool endsSequenceInternal(A K1) const {
560 if (is(tok::comment) && Previous)
561 return Previous->endsSequenceInternal(K1);
565 template <typename A, typename... Ts>
566 bool endsSequenceInternal(A K1, Ts... Tokens) const {
567 if (is(tok::comment) && Previous)
568 return Previous->endsSequenceInternal(K1, Tokens...);
569 return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...);
573 class ContinuationIndenter;
578 TokenRole(const FormatStyle &Style) : Style(Style) {}
579 virtual ~TokenRole();
581 /// After the \c TokenAnnotator has finished annotating all the tokens,
582 /// this function precomputes required information for formatting.
583 virtual void precomputeFormattingInfos(const FormatToken *Token);
585 /// Apply the special formatting that the given role demands.
587 /// Assumes that the token having this role is already formatted.
589 /// Continues formatting from \p State leaving indentation to \p Indenter and
590 /// returns the total penalty that this formatting incurs.
591 virtual unsigned formatFromToken(LineState &State,
592 ContinuationIndenter *Indenter,
597 /// Same as \c formatFromToken, but assumes that the first token has
598 /// already been set thereby deciding on the first line break.
599 virtual unsigned formatAfterToken(LineState &State,
600 ContinuationIndenter *Indenter,
605 /// Notifies the \c Role that a comma was found.
606 virtual void CommaFound(const FormatToken *Token) {}
608 virtual const FormatToken *lastComma() { return nullptr; }
611 const FormatStyle &Style;
614 class CommaSeparatedList : public TokenRole {
616 CommaSeparatedList(const FormatStyle &Style)
617 : TokenRole(Style), HasNestedBracedList(false) {}
619 void precomputeFormattingInfos(const FormatToken *Token) override;
621 unsigned formatAfterToken(LineState &State, ContinuationIndenter *Indenter,
622 bool DryRun) override;
624 unsigned formatFromToken(LineState &State, ContinuationIndenter *Indenter,
625 bool DryRun) override;
627 /// Adds \p Token as the next comma to the \c CommaSeparated list.
628 void CommaFound(const FormatToken *Token) override {
629 Commas.push_back(Token);
632 const FormatToken *lastComma() override {
635 return Commas.back();
639 /// A struct that holds information on how to format a given list with
640 /// a specific number of columns.
641 struct ColumnFormat {
642 /// The number of columns to use.
645 /// The total width in characters.
648 /// The number of lines required for this format.
651 /// The size of each column in characters.
652 SmallVector<unsigned, 8> ColumnSizes;
655 /// Calculate which \c ColumnFormat fits best into
656 /// \p RemainingCharacters.
657 const ColumnFormat *getColumnFormat(unsigned RemainingCharacters) const;
659 /// The ordered \c FormatTokens making up the commas of this list.
660 SmallVector<const FormatToken *, 8> Commas;
662 /// The length of each of the list's items in characters including the
664 SmallVector<unsigned, 8> ItemLengths;
666 /// Precomputed formats that can be used for this list.
667 SmallVector<ColumnFormat, 4> Formats;
669 bool HasNestedBracedList;
672 /// Encapsulates keywords that are context sensitive or for languages not
673 /// properly supported by Clang's lexer.
674 struct AdditionalKeywords {
675 AdditionalKeywords(IdentifierTable &IdentTable) {
676 kw_final = &IdentTable.get("final");
677 kw_override = &IdentTable.get("override");
678 kw_in = &IdentTable.get("in");
679 kw_of = &IdentTable.get("of");
680 kw_CF_ENUM = &IdentTable.get("CF_ENUM");
681 kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS");
682 kw_NS_ENUM = &IdentTable.get("NS_ENUM");
683 kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS");
685 kw_as = &IdentTable.get("as");
686 kw_async = &IdentTable.get("async");
687 kw_await = &IdentTable.get("await");
688 kw_declare = &IdentTable.get("declare");
689 kw_finally = &IdentTable.get("finally");
690 kw_from = &IdentTable.get("from");
691 kw_function = &IdentTable.get("function");
692 kw_get = &IdentTable.get("get");
693 kw_import = &IdentTable.get("import");
694 kw_infer = &IdentTable.get("infer");
695 kw_is = &IdentTable.get("is");
696 kw_let = &IdentTable.get("let");
697 kw_module = &IdentTable.get("module");
698 kw_readonly = &IdentTable.get("readonly");
699 kw_set = &IdentTable.get("set");
700 kw_type = &IdentTable.get("type");
701 kw_typeof = &IdentTable.get("typeof");
702 kw_var = &IdentTable.get("var");
703 kw_yield = &IdentTable.get("yield");
705 kw_abstract = &IdentTable.get("abstract");
706 kw_assert = &IdentTable.get("assert");
707 kw_extends = &IdentTable.get("extends");
708 kw_implements = &IdentTable.get("implements");
709 kw_instanceof = &IdentTable.get("instanceof");
710 kw_interface = &IdentTable.get("interface");
711 kw_native = &IdentTable.get("native");
712 kw_package = &IdentTable.get("package");
713 kw_synchronized = &IdentTable.get("synchronized");
714 kw_throws = &IdentTable.get("throws");
715 kw___except = &IdentTable.get("__except");
716 kw___has_include = &IdentTable.get("__has_include");
717 kw___has_include_next = &IdentTable.get("__has_include_next");
719 kw_mark = &IdentTable.get("mark");
721 kw_extend = &IdentTable.get("extend");
722 kw_option = &IdentTable.get("option");
723 kw_optional = &IdentTable.get("optional");
724 kw_repeated = &IdentTable.get("repeated");
725 kw_required = &IdentTable.get("required");
726 kw_returns = &IdentTable.get("returns");
728 kw_signals = &IdentTable.get("signals");
729 kw_qsignals = &IdentTable.get("Q_SIGNALS");
730 kw_slots = &IdentTable.get("slots");
731 kw_qslots = &IdentTable.get("Q_SLOTS");
734 kw_dollar = &IdentTable.get("dollar");
735 kw_base = &IdentTable.get("base");
736 kw_byte = &IdentTable.get("byte");
737 kw_checked = &IdentTable.get("checked");
738 kw_decimal = &IdentTable.get("decimal");
739 kw_delegate = &IdentTable.get("delegate");
740 kw_event = &IdentTable.get("event");
741 kw_fixed = &IdentTable.get("fixed");
742 kw_foreach = &IdentTable.get("foreach");
743 kw_implicit = &IdentTable.get("implicit");
744 kw_internal = &IdentTable.get("internal");
745 kw_lock = &IdentTable.get("lock");
746 kw_null = &IdentTable.get("null");
747 kw_object = &IdentTable.get("object");
748 kw_out = &IdentTable.get("out");
749 kw_params = &IdentTable.get("params");
750 kw_ref = &IdentTable.get("ref");
751 kw_string = &IdentTable.get("string");
752 kw_stackalloc = &IdentTable.get("stackalloc");
753 kw_sbyte = &IdentTable.get("sbyte");
754 kw_sealed = &IdentTable.get("sealed");
755 kw_uint = &IdentTable.get("uint");
756 kw_ulong = &IdentTable.get("ulong");
757 kw_unchecked = &IdentTable.get("unchecked");
758 kw_unsafe = &IdentTable.get("unsafe");
759 kw_ushort = &IdentTable.get("ushort");
761 // Keep this at the end of the constructor to make sure everything here
763 // already initialized.
764 JsExtraKeywords = std::unordered_set<IdentifierInfo *>(
765 {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
766 kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,
767 kw_set, kw_type, kw_typeof, kw_var, kw_yield,
768 // Keywords from the Java section.
769 kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
771 CSharpExtraKeywords = std::unordered_set<IdentifierInfo *>(
772 {kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate, kw_event,
773 kw_fixed, kw_foreach, kw_implicit, kw_in, kw_interface, kw_internal,
774 kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override, kw_params,
775 kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte, kw_sealed,
776 kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort,
777 // Keywords from the JavaScript section.
778 kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
779 kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,
780 kw_set, kw_type, kw_typeof, kw_var, kw_yield,
781 // Keywords from the Java section.
782 kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
785 // Context sensitive keywords.
786 IdentifierInfo *kw_final;
787 IdentifierInfo *kw_override;
788 IdentifierInfo *kw_in;
789 IdentifierInfo *kw_of;
790 IdentifierInfo *kw_CF_ENUM;
791 IdentifierInfo *kw_CF_OPTIONS;
792 IdentifierInfo *kw_NS_ENUM;
793 IdentifierInfo *kw_NS_OPTIONS;
794 IdentifierInfo *kw___except;
795 IdentifierInfo *kw___has_include;
796 IdentifierInfo *kw___has_include_next;
798 // JavaScript keywords.
799 IdentifierInfo *kw_as;
800 IdentifierInfo *kw_async;
801 IdentifierInfo *kw_await;
802 IdentifierInfo *kw_declare;
803 IdentifierInfo *kw_finally;
804 IdentifierInfo *kw_from;
805 IdentifierInfo *kw_function;
806 IdentifierInfo *kw_get;
807 IdentifierInfo *kw_import;
808 IdentifierInfo *kw_infer;
809 IdentifierInfo *kw_is;
810 IdentifierInfo *kw_let;
811 IdentifierInfo *kw_module;
812 IdentifierInfo *kw_readonly;
813 IdentifierInfo *kw_set;
814 IdentifierInfo *kw_type;
815 IdentifierInfo *kw_typeof;
816 IdentifierInfo *kw_var;
817 IdentifierInfo *kw_yield;
820 IdentifierInfo *kw_abstract;
821 IdentifierInfo *kw_assert;
822 IdentifierInfo *kw_extends;
823 IdentifierInfo *kw_implements;
824 IdentifierInfo *kw_instanceof;
825 IdentifierInfo *kw_interface;
826 IdentifierInfo *kw_native;
827 IdentifierInfo *kw_package;
828 IdentifierInfo *kw_synchronized;
829 IdentifierInfo *kw_throws;
832 IdentifierInfo *kw_mark;
835 IdentifierInfo *kw_extend;
836 IdentifierInfo *kw_option;
837 IdentifierInfo *kw_optional;
838 IdentifierInfo *kw_repeated;
839 IdentifierInfo *kw_required;
840 IdentifierInfo *kw_returns;
843 IdentifierInfo *kw_signals;
844 IdentifierInfo *kw_qsignals;
845 IdentifierInfo *kw_slots;
846 IdentifierInfo *kw_qslots;
849 IdentifierInfo *kw_dollar;
850 IdentifierInfo *kw_base;
851 IdentifierInfo *kw_byte;
852 IdentifierInfo *kw_checked;
853 IdentifierInfo *kw_decimal;
854 IdentifierInfo *kw_delegate;
855 IdentifierInfo *kw_event;
856 IdentifierInfo *kw_fixed;
857 IdentifierInfo *kw_foreach;
858 IdentifierInfo *kw_implicit;
859 IdentifierInfo *kw_internal;
861 IdentifierInfo *kw_lock;
862 IdentifierInfo *kw_null;
863 IdentifierInfo *kw_object;
864 IdentifierInfo *kw_out;
866 IdentifierInfo *kw_params;
868 IdentifierInfo *kw_ref;
869 IdentifierInfo *kw_string;
870 IdentifierInfo *kw_stackalloc;
871 IdentifierInfo *kw_sbyte;
872 IdentifierInfo *kw_sealed;
873 IdentifierInfo *kw_uint;
874 IdentifierInfo *kw_ulong;
875 IdentifierInfo *kw_unchecked;
876 IdentifierInfo *kw_unsafe;
877 IdentifierInfo *kw_ushort;
879 /// Returns \c true if \p Tok is a true JavaScript identifier, returns
880 /// \c false if it is a keyword or a pseudo keyword.
881 bool IsJavaScriptIdentifier(const FormatToken &Tok) const {
882 return Tok.is(tok::identifier) &&
883 JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
884 JsExtraKeywords.end();
887 /// Returns \c true if \p Tok is a C# keyword, returns
888 /// \c false if it is a anything else.
889 bool isCSharpKeyword(const FormatToken &Tok) const {
890 switch (Tok.Tok.getKind()) {
898 case tok::kw_continue:
899 case tok::kw_default:
904 case tok::kw_explicit:
913 case tok::kw_namespace:
915 case tok::kw_operator:
916 case tok::kw_private:
917 case tok::kw_protected:
931 case tok::kw_virtual:
933 case tok::kw_volatile:
937 return Tok.is(tok::identifier) &&
938 CSharpExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
939 CSharpExtraKeywords.end();
944 /// The JavaScript keywords beyond the C++ keyword set.
945 std::unordered_set<IdentifierInfo *> JsExtraKeywords;
947 /// The C# keywords beyond the C++ keyword set
948 std::unordered_set<IdentifierInfo *> CSharpExtraKeywords;
951 } // namespace format