Path: blob/main/contrib/llvm-project/clang/lib/Format/FormatToken.h
35233 views
//===--- FormatToken.h - Format C++ code ------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file contains the declaration of the FormatToken, a wrapper10/// around Token with additional information related to formatting.11///12//===----------------------------------------------------------------------===//1314#ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H15#define LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H1617#include "clang/Basic/IdentifierTable.h"18#include "clang/Basic/OperatorPrecedence.h"19#include "clang/Format/Format.h"20#include "clang/Lex/Lexer.h"21#include <unordered_set>2223namespace clang {24namespace format {2526#define LIST_TOKEN_TYPES \27TYPE(ArrayInitializerLSquare) \28TYPE(ArraySubscriptLSquare) \29TYPE(AttributeColon) \30TYPE(AttributeLParen) \31TYPE(AttributeMacro) \32TYPE(AttributeRParen) \33TYPE(AttributeSquare) \34TYPE(BinaryOperator) \35TYPE(BitFieldColon) \36TYPE(BlockComment) \37/* l_brace of a block that is not the body of a (e.g. loop) statement. */ \38TYPE(BlockLBrace) \39TYPE(BracedListLBrace) \40TYPE(CaseLabelArrow) \41/* The colon at the end of a case label. */ \42TYPE(CaseLabelColon) \43TYPE(CastRParen) \44TYPE(ClassLBrace) \45TYPE(ClassRBrace) \46/* ternary ?: expression */ \47TYPE(ConditionalExpr) \48/* the condition in an if statement */ \49TYPE(ConditionLParen) \50TYPE(ConflictAlternative) \51TYPE(ConflictEnd) \52TYPE(ConflictStart) \53/* l_brace of if/for/while */ \54TYPE(ControlStatementLBrace) \55TYPE(ControlStatementRBrace) \56TYPE(CppCastLParen) \57TYPE(CSharpGenericTypeConstraint) \58TYPE(CSharpGenericTypeConstraintColon) \59TYPE(CSharpGenericTypeConstraintComma) \60TYPE(CSharpNamedArgumentColon) \61TYPE(CSharpNullable) \62TYPE(CSharpNullConditionalLSquare) \63TYPE(CSharpStringLiteral) \64TYPE(CtorInitializerColon) \65TYPE(CtorInitializerComma) \66TYPE(CtorDtorDeclName) \67TYPE(DesignatedInitializerLSquare) \68TYPE(DesignatedInitializerPeriod) \69TYPE(DictLiteral) \70TYPE(DoWhile) \71TYPE(ElseLBrace) \72TYPE(ElseRBrace) \73TYPE(EnumLBrace) \74TYPE(EnumRBrace) \75TYPE(FatArrow) \76TYPE(ForEachMacro) \77TYPE(FunctionAnnotationRParen) \78TYPE(FunctionDeclarationName) \79TYPE(FunctionDeclarationLParen) \80TYPE(FunctionLBrace) \81TYPE(FunctionLikeOrFreestandingMacro) \82TYPE(FunctionTypeLParen) \83/* The colons as part of a C11 _Generic selection */ \84TYPE(GenericSelectionColon) \85/* The colon at the end of a goto label. */ \86TYPE(GotoLabelColon) \87TYPE(IfMacro) \88TYPE(ImplicitStringLiteral) \89TYPE(InheritanceColon) \90TYPE(InheritanceComma) \91TYPE(InlineASMBrace) \92TYPE(InlineASMColon) \93TYPE(InlineASMSymbolicNameLSquare) \94TYPE(JavaAnnotation) \95TYPE(JsAndAndEqual) \96TYPE(JsComputedPropertyName) \97TYPE(JsExponentiation) \98TYPE(JsExponentiationEqual) \99TYPE(JsPipePipeEqual) \100TYPE(JsPrivateIdentifier) \101TYPE(JsTypeColon) \102TYPE(JsTypeOperator) \103TYPE(JsTypeOptionalQuestion) \104TYPE(LambdaArrow) \105TYPE(LambdaLBrace) \106TYPE(LambdaLSquare) \107TYPE(LeadingJavaAnnotation) \108TYPE(LineComment) \109TYPE(MacroBlockBegin) \110TYPE(MacroBlockEnd) \111TYPE(ModulePartitionColon) \112TYPE(NamespaceLBrace) \113TYPE(NamespaceMacro) \114TYPE(NamespaceRBrace) \115TYPE(NonNullAssertion) \116TYPE(NullCoalescingEqual) \117TYPE(NullCoalescingOperator) \118TYPE(NullPropagatingOperator) \119TYPE(ObjCBlockLBrace) \120TYPE(ObjCBlockLParen) \121TYPE(ObjCDecl) \122TYPE(ObjCForIn) \123TYPE(ObjCMethodExpr) \124TYPE(ObjCMethodSpecifier) \125TYPE(ObjCProperty) \126TYPE(ObjCStringLiteral) \127TYPE(OverloadedOperator) \128TYPE(OverloadedOperatorLParen) \129TYPE(PointerOrReference) \130TYPE(ProtoExtensionLSquare) \131TYPE(PureVirtualSpecifier) \132TYPE(RangeBasedForLoopColon) \133TYPE(RecordLBrace) \134TYPE(RecordRBrace) \135TYPE(RegexLiteral) \136TYPE(RequiresClause) \137TYPE(RequiresClauseInARequiresExpression) \138TYPE(RequiresExpression) \139TYPE(RequiresExpressionLBrace) \140TYPE(RequiresExpressionLParen) \141TYPE(SelectorName) \142TYPE(StartOfName) \143TYPE(StatementAttributeLikeMacro) \144TYPE(StatementMacro) \145/* A string that is part of a string concatenation. For C#, JavaScript, and \146* Java, it is used for marking whether a string needs parentheses around it \147* if it is to be split into parts joined by `+`. For Verilog, whether \148* braces need to be added to split it. Not used for other languages. */ \149TYPE(StringInConcatenation) \150TYPE(StructLBrace) \151TYPE(StructRBrace) \152TYPE(StructuredBindingLSquare) \153TYPE(SwitchExpressionLabel) \154TYPE(SwitchExpressionLBrace) \155TYPE(TableGenBangOperator) \156TYPE(TableGenCondOperator) \157TYPE(TableGenCondOperatorColon) \158TYPE(TableGenCondOperatorComma) \159TYPE(TableGenDAGArgCloser) \160TYPE(TableGenDAGArgListColon) \161TYPE(TableGenDAGArgListColonToAlign) \162TYPE(TableGenDAGArgListComma) \163TYPE(TableGenDAGArgListCommaToBreak) \164TYPE(TableGenDAGArgOpener) \165TYPE(TableGenDAGArgOpenerToBreak) \166TYPE(TableGenDAGArgOperatorID) \167TYPE(TableGenDAGArgOperatorToBreak) \168TYPE(TableGenListCloser) \169TYPE(TableGenListOpener) \170TYPE(TableGenMultiLineString) \171TYPE(TableGenTrailingPasteOperator) \172TYPE(TableGenValueSuffix) \173TYPE(TemplateCloser) \174TYPE(TemplateOpener) \175TYPE(TemplateString) \176TYPE(TrailingAnnotation) \177TYPE(TrailingReturnArrow) \178TYPE(TrailingUnaryOperator) \179TYPE(TypeDeclarationParen) \180TYPE(TypeName) \181TYPE(TypenameMacro) \182TYPE(UnaryOperator) \183TYPE(UnionLBrace) \184TYPE(UnionRBrace) \185TYPE(UntouchableMacroFunc) \186/* Like in 'assign x = 0, y = 1;' . */ \187TYPE(VerilogAssignComma) \188/* like in begin : block */ \189TYPE(VerilogBlockLabelColon) \190/* The square bracket for the dimension part of the type name. \191* In 'logic [1:0] x[1:0]', only the first '['. This way we can have space \192* before the first bracket but not the second. */ \193TYPE(VerilogDimensionedTypeName) \194/* list of port connections or parameters in a module instantiation */ \195TYPE(VerilogInstancePortComma) \196TYPE(VerilogInstancePortLParen) \197/* A parenthesized list within which line breaks are inserted by the \198* formatter, for example the list of ports in a module header. */ \199TYPE(VerilogMultiLineListLParen) \200/* for the base in a number literal, not including the quote */ \201TYPE(VerilogNumberBase) \202/* like `(strong1, pull0)` */ \203TYPE(VerilogStrength) \204/* Things inside the table in user-defined primitives. */ \205TYPE(VerilogTableItem) \206/* those that separate ports of different types */ \207TYPE(VerilogTypeComma) \208TYPE(Unknown)209210/// Determines the semantic type of a syntactic token, e.g. whether "<" is a211/// template opener or binary operator.212enum TokenType : uint8_t {213#define TYPE(X) TT_##X,214LIST_TOKEN_TYPES215#undef TYPE216NUM_TOKEN_TYPES217};218219/// Determines the name of a token type.220const char *getTokenTypeName(TokenType Type);221222// Represents what type of block a set of braces open.223enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit };224225// The packing kind of a function's parameters.226enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive };227228enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };229230/// Roles a token can take in a configured macro expansion.231enum MacroRole {232/// The token was expanded from a macro argument when formatting the expanded233/// token sequence.234MR_ExpandedArg,235/// The token is part of a macro argument that was previously formatted as236/// expansion when formatting the unexpanded macro call.237MR_UnexpandedArg,238/// The token was expanded from a macro definition, and is not visible as part239/// of the macro call.240MR_Hidden,241};242243struct FormatToken;244245/// Contains information on the token's role in a macro expansion.246///247/// Given the following definitions:248/// A(X) = [ X ]249/// B(X) = < X >250/// C(X) = X251///252/// Consider the macro call:253/// A({B(C(C(x)))}) -> [{<x>}]254///255/// In this case, the tokens of the unexpanded macro call will have the256/// following relevant entries in their macro context (note that formatting257/// the unexpanded macro call happens *after* formatting the expanded macro258/// call):259/// A( { B( C( C(x) ) ) } )260/// Role: NN U NN NN NNUN N N U N (N=None, U=UnexpandedArg)261///262/// [ { < x > } ]263/// Role: H E H E H E H (H=Hidden, E=ExpandedArg)264/// ExpandedFrom[0]: A A A A A A A265/// ExpandedFrom[1]: B B B266/// ExpandedFrom[2]: C267/// ExpandedFrom[3]: C268/// StartOfExpansion: 1 0 1 2 0 0 0269/// EndOfExpansion: 0 0 0 2 1 0 1270struct MacroExpansion {271MacroExpansion(MacroRole Role) : Role(Role) {}272273/// The token's role in the macro expansion.274/// When formatting an expanded macro, all tokens that are part of macro275/// arguments will be MR_ExpandedArg, while all tokens that are not visible in276/// the macro call will be MR_Hidden.277/// When formatting an unexpanded macro call, all tokens that are part of278/// macro arguments will be MR_UnexpandedArg.279MacroRole Role;280281/// The stack of macro call identifier tokens this token was expanded from.282llvm::SmallVector<FormatToken *, 1> ExpandedFrom;283284/// The number of expansions of which this macro is the first entry.285unsigned StartOfExpansion = 0;286287/// The number of currently open expansions in \c ExpandedFrom this macro is288/// the last token in.289unsigned EndOfExpansion = 0;290};291292class TokenRole;293class AnnotatedLine;294295/// A wrapper around a \c Token storing information about the296/// whitespace characters preceding it.297struct FormatToken {298FormatToken()299: HasUnescapedNewline(false), IsMultiline(false), IsFirst(false),300MustBreakBefore(false), MustBreakBeforeFinalized(false),301IsUnterminatedLiteral(false), CanBreakBefore(false),302ClosesTemplateDeclaration(false), StartsBinaryExpression(false),303EndsBinaryExpression(false), PartOfMultiVariableDeclStmt(false),304ContinuesLineCommentSection(false), Finalized(false),305ClosesRequiresClause(false), EndsCppAttributeGroup(false),306BlockKind(BK_Unknown), Decision(FD_Unformatted),307PackingKind(PPK_Inconclusive), TypeIsFinalized(false),308Type(TT_Unknown) {}309310/// The \c Token.311Token Tok;312313/// The raw text of the token.314///315/// Contains the raw token text without leading whitespace and without leading316/// escaped newlines.317StringRef TokenText;318319/// A token can have a special role that can carry extra information320/// about the token's formatting.321/// FIXME: Make FormatToken for parsing and AnnotatedToken two different322/// classes and make this a unique_ptr in the AnnotatedToken class.323std::shared_ptr<TokenRole> Role;324325/// The range of the whitespace immediately preceding the \c Token.326SourceRange WhitespaceRange;327328/// Whether there is at least one unescaped newline before the \c329/// Token.330unsigned HasUnescapedNewline : 1;331332/// Whether the token text contains newlines (escaped or not).333unsigned IsMultiline : 1;334335/// Indicates that this is the first token of the file.336unsigned IsFirst : 1;337338/// Whether there must be a line break before this token.339///340/// This happens for example when a preprocessor directive ended directly341/// before the token.342unsigned MustBreakBefore : 1;343344/// Whether MustBreakBefore is finalized during parsing and must not345/// be reset between runs.346unsigned MustBreakBeforeFinalized : 1;347348/// Set to \c true if this token is an unterminated literal.349unsigned IsUnterminatedLiteral : 1;350351/// \c true if it is allowed to break before this token.352unsigned CanBreakBefore : 1;353354/// \c true if this is the ">" of "template<..>".355unsigned ClosesTemplateDeclaration : 1;356357/// \c true if this token starts a binary expression, i.e. has at least358/// one fake l_paren with a precedence greater than prec::Unknown.359unsigned StartsBinaryExpression : 1;360/// \c true if this token ends a binary expression.361unsigned EndsBinaryExpression : 1;362363/// Is this token part of a \c DeclStmt defining multiple variables?364///365/// Only set if \c Type == \c TT_StartOfName.366unsigned PartOfMultiVariableDeclStmt : 1;367368/// Does this line comment continue a line comment section?369///370/// Only set to true if \c Type == \c TT_LineComment.371unsigned ContinuesLineCommentSection : 1;372373/// If \c true, this token has been fully formatted (indented and374/// potentially re-formatted inside), and we do not allow further formatting375/// changes.376unsigned Finalized : 1;377378/// \c true if this is the last token within requires clause.379unsigned ClosesRequiresClause : 1;380381/// \c true if this token ends a group of C++ attributes.382unsigned EndsCppAttributeGroup : 1;383384private:385/// Contains the kind of block if this token is a brace.386unsigned BlockKind : 2;387388public:389BraceBlockKind getBlockKind() const {390return static_cast<BraceBlockKind>(BlockKind);391}392void setBlockKind(BraceBlockKind BBK) {393BlockKind = BBK;394assert(getBlockKind() == BBK && "BraceBlockKind overflow!");395}396397private:398/// Stores the formatting decision for the token once it was made.399unsigned Decision : 2;400401public:402FormatDecision getDecision() const {403return static_cast<FormatDecision>(Decision);404}405void setDecision(FormatDecision D) {406Decision = D;407assert(getDecision() == D && "FormatDecision overflow!");408}409410private:411/// If this is an opening parenthesis, how are the parameters packed?412unsigned PackingKind : 2;413414public:415ParameterPackingKind getPackingKind() const {416return static_cast<ParameterPackingKind>(PackingKind);417}418void setPackingKind(ParameterPackingKind K) {419PackingKind = K;420assert(getPackingKind() == K && "ParameterPackingKind overflow!");421}422423private:424unsigned TypeIsFinalized : 1;425TokenType Type;426427public:428/// Returns the token's type, e.g. whether "<" is a template opener or429/// binary operator.430TokenType getType() const { return Type; }431void setType(TokenType T) {432// If this token is a macro argument while formatting an unexpanded macro433// call, we do not change its type any more - the type was deduced from434// formatting the expanded macro stream already.435if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)436return;437assert((!TypeIsFinalized || T == Type) &&438"Please use overwriteFixedType to change a fixed type.");439Type = T;440}441/// Sets the type and also the finalized flag. This prevents the type to be442/// reset in TokenAnnotator::resetTokenMetadata(). If the type needs to be set443/// to another one please use overwriteFixedType, or even better remove the444/// need to reassign the type.445void setFinalizedType(TokenType T) {446if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)447return;448Type = T;449TypeIsFinalized = true;450}451void overwriteFixedType(TokenType T) {452if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)453return;454TypeIsFinalized = false;455setType(T);456}457bool isTypeFinalized() const { return TypeIsFinalized; }458459/// Used to set an operator precedence explicitly.460prec::Level ForcedPrecedence = prec::Unknown;461462/// The number of newlines immediately before the \c Token.463///464/// This can be used to determine what the user wrote in the original code465/// and thereby e.g. leave an empty line between two function definitions.466unsigned NewlinesBefore = 0;467468/// The number of newlines immediately before the \c Token after formatting.469///470/// This is used to avoid overlapping whitespace replacements when \c Newlines471/// is recomputed for a finalized preprocessor branching directive.472int Newlines = -1;473474/// The offset just past the last '\n' in this token's leading475/// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.476unsigned LastNewlineOffset = 0;477478/// The width of the non-whitespace parts of the token (or its first479/// line for multi-line tokens) in columns.480/// We need this to correctly measure number of columns a token spans.481unsigned ColumnWidth = 0;482483/// Contains the width in columns of the last line of a multi-line484/// token.485unsigned LastLineColumnWidth = 0;486487/// The number of spaces that should be inserted before this token.488unsigned SpacesRequiredBefore = 0;489490/// Number of parameters, if this is "(", "[" or "<".491unsigned ParameterCount = 0;492493/// Number of parameters that are nested blocks,494/// if this is "(", "[" or "<".495unsigned BlockParameterCount = 0;496497/// If this is a bracket ("<", "(", "[" or "{"), contains the kind of498/// the surrounding bracket.499tok::TokenKind ParentBracket = tok::unknown;500501/// The total length of the unwrapped line up to and including this502/// token.503unsigned TotalLength = 0;504505/// The original 0-based column of this token, including expanded tabs.506/// The configured TabWidth is used as tab width.507unsigned OriginalColumn = 0;508509/// The length of following tokens until the next natural split point,510/// or the next token that can be broken.511unsigned UnbreakableTailLength = 0;512513// FIXME: Come up with a 'cleaner' concept.514/// The binding strength of a token. This is a combined value of515/// operator precedence, parenthesis nesting, etc.516unsigned BindingStrength = 0;517518/// The nesting level of this token, i.e. the number of surrounding (),519/// [], {} or <>.520unsigned NestingLevel = 0;521522/// The indent level of this token. Copied from the surrounding line.523unsigned IndentLevel = 0;524525/// Penalty for inserting a line break before this token.526unsigned SplitPenalty = 0;527528/// If this is the first ObjC selector name in an ObjC method529/// definition or call, this contains the length of the longest name.530///531/// This being set to 0 means that the selectors should not be colon-aligned,532/// e.g. because several of them are block-type.533unsigned LongestObjCSelectorName = 0;534535/// If this is the first ObjC selector name in an ObjC method536/// definition or call, this contains the number of parts that the whole537/// selector consist of.538unsigned ObjCSelectorNameParts = 0;539540/// The 0-based index of the parameter/argument. For ObjC it is set541/// for the selector name token.542/// For now calculated only for ObjC.543unsigned ParameterIndex = 0;544545/// Stores the number of required fake parentheses and the546/// corresponding operator precedence.547///548/// If multiple fake parentheses start at a token, this vector stores them in549/// reverse order, i.e. inner fake parenthesis first.550SmallVector<prec::Level, 4> FakeLParens;551/// Insert this many fake ) after this token for correct indentation.552unsigned FakeRParens = 0;553554/// If this is an operator (or "."/"->") in a sequence of operators555/// with the same precedence, contains the 0-based operator index.556unsigned OperatorIndex = 0;557558/// If this is an operator (or "."/"->") in a sequence of operators559/// with the same precedence, points to the next operator.560FormatToken *NextOperator = nullptr;561562/// If this is a bracket, this points to the matching one.563FormatToken *MatchingParen = nullptr;564565/// The previous token in the unwrapped line.566FormatToken *Previous = nullptr;567568/// The next token in the unwrapped line.569FormatToken *Next = nullptr;570571/// The first token in set of column elements.572bool StartsColumn = false;573574/// This notes the start of the line of an array initializer.575bool ArrayInitializerLineStart = false;576577/// This starts an array initializer.578bool IsArrayInitializer = false;579580/// Is optional and can be removed.581bool Optional = false;582583/// Might be function declaration open/closing paren.584bool MightBeFunctionDeclParen = false;585586/// Number of optional braces to be inserted after this token:587/// -1: a single left brace588/// 0: no braces589/// >0: number of right braces590int8_t BraceCount = 0;591592/// If this token starts a block, this contains all the unwrapped lines593/// in it.594SmallVector<AnnotatedLine *, 1> Children;595596// Contains all attributes related to how this token takes part597// in a configured macro expansion.598std::optional<MacroExpansion> MacroCtx;599600/// When macro expansion introduces nodes with children, those are marked as601/// \c MacroParent.602/// FIXME: The formatting code currently hard-codes the assumption that603/// child nodes are introduced by blocks following an opening brace.604/// This is deeply baked into the code and disentangling this will require605/// signficant refactorings. \c MacroParent allows us to special-case the606/// cases in which we treat parents as block-openers for now.607bool MacroParent = false;608609bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }610bool is(TokenType TT) const { return getType() == TT; }611bool is(const IdentifierInfo *II) const {612return II && II == Tok.getIdentifierInfo();613}614bool is(tok::PPKeywordKind Kind) const {615return Tok.getIdentifierInfo() &&616Tok.getIdentifierInfo()->getPPKeywordID() == Kind;617}618bool is(BraceBlockKind BBK) const { return getBlockKind() == BBK; }619bool is(ParameterPackingKind PPK) const { return getPackingKind() == PPK; }620621template <typename A, typename B> bool isOneOf(A K1, B K2) const {622return is(K1) || is(K2);623}624template <typename A, typename B, typename... Ts>625bool isOneOf(A K1, B K2, Ts... Ks) const {626return is(K1) || isOneOf(K2, Ks...);627}628template <typename T> bool isNot(T Kind) const { return !is(Kind); }629630bool isIf(bool AllowConstexprMacro = true) const {631return is(tok::kw_if) || endsSequence(tok::kw_constexpr, tok::kw_if) ||632(endsSequence(tok::identifier, tok::kw_if) && AllowConstexprMacro);633}634635bool closesScopeAfterBlock() const {636if (getBlockKind() == BK_Block)637return true;638if (closesScope())639return Previous->closesScopeAfterBlock();640return false;641}642643/// \c true if this token starts a sequence with the given tokens in order,644/// following the ``Next`` pointers, ignoring comments.645template <typename A, typename... Ts>646bool startsSequence(A K1, Ts... Tokens) const {647return startsSequenceInternal(K1, Tokens...);648}649650/// \c true if this token ends a sequence with the given tokens in order,651/// following the ``Previous`` pointers, ignoring comments.652/// For example, given tokens [T1, T2, T3], the function returns true if653/// 3 tokens ending at this (ignoring comments) are [T3, T2, T1]. In other654/// words, the tokens passed to this function need to the reverse of the655/// order the tokens appear in code.656template <typename A, typename... Ts>657bool endsSequence(A K1, Ts... Tokens) const {658return endsSequenceInternal(K1, Tokens...);659}660661bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); }662663bool isAttribute() const {664return isOneOf(tok::kw___attribute, tok::kw___declspec, TT_AttributeMacro);665}666667bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {668return Tok.isObjCAtKeyword(Kind);669}670671bool isAccessSpecifierKeyword() const {672return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private);673}674675bool isAccessSpecifier(bool ColonRequired = true) const {676if (!isAccessSpecifierKeyword())677return false;678if (!ColonRequired)679return true;680const auto *NextNonComment = getNextNonComment();681return NextNonComment && NextNonComment->is(tok::colon);682}683684bool canBePointerOrReferenceQualifier() const {685return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile,686tok::kw__Nonnull, tok::kw__Nullable,687tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64,688tok::kw___funcref) ||689isAttribute();690}691692[[nodiscard]] bool isTypeName(const LangOptions &LangOpts) const;693[[nodiscard]] bool isTypeOrIdentifier(const LangOptions &LangOpts) const;694695bool isObjCAccessSpecifier() const {696return is(tok::at) && Next &&697(Next->isObjCAtKeyword(tok::objc_public) ||698Next->isObjCAtKeyword(tok::objc_protected) ||699Next->isObjCAtKeyword(tok::objc_package) ||700Next->isObjCAtKeyword(tok::objc_private));701}702703/// Returns whether \p Tok is ([{ or an opening < of a template or in704/// protos.705bool opensScope() const {706if (is(TT_TemplateString) && TokenText.ends_with("${"))707return true;708if (is(TT_DictLiteral) && is(tok::less))709return true;710return isOneOf(tok::l_paren, tok::l_brace, tok::l_square,711TT_TemplateOpener);712}713/// Returns whether \p Tok is )]} or a closing > of a template or in714/// protos.715bool closesScope() const {716if (is(TT_TemplateString) && TokenText.starts_with("}"))717return true;718if (is(TT_DictLiteral) && is(tok::greater))719return true;720return isOneOf(tok::r_paren, tok::r_brace, tok::r_square,721TT_TemplateCloser);722}723724/// Returns \c true if this is a "." or "->" accessing a member.725bool isMemberAccess() const {726return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&727!isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow,728TT_LambdaArrow, TT_LeadingJavaAnnotation);729}730731bool isPointerOrReference() const {732return isOneOf(tok::star, tok::amp, tok::ampamp);733}734735bool isCppAlternativeOperatorKeyword() const {736assert(!TokenText.empty());737if (!isalpha(TokenText[0]))738return false;739740switch (Tok.getKind()) {741case tok::ampamp:742case tok::ampequal:743case tok::amp:744case tok::pipe:745case tok::tilde:746case tok::exclaim:747case tok::exclaimequal:748case tok::pipepipe:749case tok::pipeequal:750case tok::caret:751case tok::caretequal:752return true;753default:754return false;755}756}757758bool isUnaryOperator() const {759switch (Tok.getKind()) {760case tok::plus:761case tok::plusplus:762case tok::minus:763case tok::minusminus:764case tok::exclaim:765case tok::tilde:766case tok::kw_sizeof:767case tok::kw_alignof:768return true;769default:770return false;771}772}773774bool isBinaryOperator() const {775// Comma is a binary operator, but does not behave as such wrt. formatting.776return getPrecedence() > prec::Comma;777}778779bool isTrailingComment() const {780return is(tok::comment) &&781(is(TT_LineComment) || !Next || Next->NewlinesBefore > 0);782}783784/// Returns \c true if this is a keyword that can be used785/// like a function call (e.g. sizeof, typeid, ...).786bool isFunctionLikeKeyword() const {787if (isAttribute())788return true;789790return isOneOf(tok::kw_throw, tok::kw_typeid, tok::kw_return,791tok::kw_sizeof, tok::kw_alignof, tok::kw_alignas,792tok::kw_decltype, tok::kw_noexcept, tok::kw_static_assert,793tok::kw__Atomic,794#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,795#include "clang/Basic/TransformTypeTraits.def"796tok::kw_requires);797}798799/// Returns \c true if this is a string literal that's like a label,800/// e.g. ends with "=" or ":".801bool isLabelString() const {802if (isNot(tok::string_literal))803return false;804StringRef Content = TokenText;805if (Content.starts_with("\"") || Content.starts_with("'"))806Content = Content.drop_front(1);807if (Content.ends_with("\"") || Content.ends_with("'"))808Content = Content.drop_back(1);809Content = Content.trim();810return Content.size() > 1 &&811(Content.back() == ':' || Content.back() == '=');812}813814/// Returns actual token start location without leading escaped815/// newlines and whitespace.816///817/// This can be different to Tok.getLocation(), which includes leading escaped818/// newlines.819SourceLocation getStartOfNonWhitespace() const {820return WhitespaceRange.getEnd();821}822823/// Returns \c true if the range of whitespace immediately preceding the \c824/// Token is not empty.825bool hasWhitespaceBefore() const {826return WhitespaceRange.getBegin() != WhitespaceRange.getEnd();827}828829prec::Level getPrecedence() const {830if (ForcedPrecedence != prec::Unknown)831return ForcedPrecedence;832return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true,833/*CPlusPlus11=*/true);834}835836/// Returns the previous token ignoring comments.837[[nodiscard]] FormatToken *getPreviousNonComment() const {838FormatToken *Tok = Previous;839while (Tok && Tok->is(tok::comment))840Tok = Tok->Previous;841return Tok;842}843844/// Returns the next token ignoring comments.845[[nodiscard]] FormatToken *getNextNonComment() const {846FormatToken *Tok = Next;847while (Tok && Tok->is(tok::comment))848Tok = Tok->Next;849return Tok;850}851852/// Returns \c true if this token ends a block indented initializer list.853[[nodiscard]] bool isBlockIndentedInitRBrace(const FormatStyle &Style) const;854855/// Returns \c true if this tokens starts a block-type list, i.e. a856/// list that should be indented with a block indent.857[[nodiscard]] bool opensBlockOrBlockTypeList(const FormatStyle &Style) const;858859/// Returns whether the token is the left square bracket of a C++860/// structured binding declaration.861bool isCppStructuredBinding(bool IsCpp) const {862if (!IsCpp || isNot(tok::l_square))863return false;864const FormatToken *T = this;865do {866T = T->getPreviousNonComment();867} while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp,868tok::ampamp));869return T && T->is(tok::kw_auto);870}871872/// Same as opensBlockOrBlockTypeList, but for the closing token.873bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {874if (is(TT_TemplateString) && closesScope())875return true;876return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);877}878879/// Return the actual namespace token, if this token starts a namespace880/// block.881const FormatToken *getNamespaceToken() const {882const FormatToken *NamespaceTok = this;883if (is(tok::comment))884NamespaceTok = NamespaceTok->getNextNonComment();885// Detect "(inline|export)? namespace" in the beginning of a line.886if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export))887NamespaceTok = NamespaceTok->getNextNonComment();888return NamespaceTok &&889NamespaceTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro)890? NamespaceTok891: nullptr;892}893894void copyFrom(const FormatToken &Tok) { *this = Tok; }895896private:897// Only allow copying via the explicit copyFrom method.898FormatToken(const FormatToken &) = delete;899FormatToken &operator=(const FormatToken &) = default;900901template <typename A, typename... Ts>902bool startsSequenceInternal(A K1, Ts... Tokens) const {903if (is(tok::comment) && Next)904return Next->startsSequenceInternal(K1, Tokens...);905return is(K1) && Next && Next->startsSequenceInternal(Tokens...);906}907908template <typename A> bool startsSequenceInternal(A K1) const {909if (is(tok::comment) && Next)910return Next->startsSequenceInternal(K1);911return is(K1);912}913914template <typename A, typename... Ts> bool endsSequenceInternal(A K1) const {915if (is(tok::comment) && Previous)916return Previous->endsSequenceInternal(K1);917return is(K1);918}919920template <typename A, typename... Ts>921bool endsSequenceInternal(A K1, Ts... Tokens) const {922if (is(tok::comment) && Previous)923return Previous->endsSequenceInternal(K1, Tokens...);924return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...);925}926};927928class ContinuationIndenter;929struct LineState;930931class TokenRole {932public:933TokenRole(const FormatStyle &Style) : Style(Style) {}934virtual ~TokenRole();935936/// After the \c TokenAnnotator has finished annotating all the tokens,937/// this function precomputes required information for formatting.938virtual void precomputeFormattingInfos(const FormatToken *Token);939940/// Apply the special formatting that the given role demands.941///942/// Assumes that the token having this role is already formatted.943///944/// Continues formatting from \p State leaving indentation to \p Indenter and945/// returns the total penalty that this formatting incurs.946virtual unsigned formatFromToken(LineState &State,947ContinuationIndenter *Indenter,948bool DryRun) {949return 0;950}951952/// Same as \c formatFromToken, but assumes that the first token has953/// already been set thereby deciding on the first line break.954virtual unsigned formatAfterToken(LineState &State,955ContinuationIndenter *Indenter,956bool DryRun) {957return 0;958}959960/// Notifies the \c Role that a comma was found.961virtual void CommaFound(const FormatToken *Token) {}962963virtual const FormatToken *lastComma() { return nullptr; }964965protected:966const FormatStyle &Style;967};968969class CommaSeparatedList : public TokenRole {970public:971CommaSeparatedList(const FormatStyle &Style)972: TokenRole(Style), HasNestedBracedList(false) {}973974void precomputeFormattingInfos(const FormatToken *Token) override;975976unsigned formatAfterToken(LineState &State, ContinuationIndenter *Indenter,977bool DryRun) override;978979unsigned formatFromToken(LineState &State, ContinuationIndenter *Indenter,980bool DryRun) override;981982/// Adds \p Token as the next comma to the \c CommaSeparated list.983void CommaFound(const FormatToken *Token) override {984Commas.push_back(Token);985}986987const FormatToken *lastComma() override {988if (Commas.empty())989return nullptr;990return Commas.back();991}992993private:994/// A struct that holds information on how to format a given list with995/// a specific number of columns.996struct ColumnFormat {997/// The number of columns to use.998unsigned Columns;9991000/// The total width in characters.1001unsigned TotalWidth;10021003/// The number of lines required for this format.1004unsigned LineCount;10051006/// The size of each column in characters.1007SmallVector<unsigned, 8> ColumnSizes;1008};10091010/// Calculate which \c ColumnFormat fits best into1011/// \p RemainingCharacters.1012const ColumnFormat *getColumnFormat(unsigned RemainingCharacters) const;10131014/// The ordered \c FormatTokens making up the commas of this list.1015SmallVector<const FormatToken *, 8> Commas;10161017/// The length of each of the list's items in characters including the1018/// trailing comma.1019SmallVector<unsigned, 8> ItemLengths;10201021/// Precomputed formats that can be used for this list.1022SmallVector<ColumnFormat, 4> Formats;10231024bool HasNestedBracedList;1025};10261027/// Encapsulates keywords that are context sensitive or for languages not1028/// properly supported by Clang's lexer.1029struct AdditionalKeywords {1030AdditionalKeywords(IdentifierTable &IdentTable) {1031kw_final = &IdentTable.get("final");1032kw_override = &IdentTable.get("override");1033kw_in = &IdentTable.get("in");1034kw_of = &IdentTable.get("of");1035kw_CF_CLOSED_ENUM = &IdentTable.get("CF_CLOSED_ENUM");1036kw_CF_ENUM = &IdentTable.get("CF_ENUM");1037kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS");1038kw_NS_CLOSED_ENUM = &IdentTable.get("NS_CLOSED_ENUM");1039kw_NS_ENUM = &IdentTable.get("NS_ENUM");1040kw_NS_ERROR_ENUM = &IdentTable.get("NS_ERROR_ENUM");1041kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS");10421043kw_as = &IdentTable.get("as");1044kw_async = &IdentTable.get("async");1045kw_await = &IdentTable.get("await");1046kw_declare = &IdentTable.get("declare");1047kw_finally = &IdentTable.get("finally");1048kw_from = &IdentTable.get("from");1049kw_function = &IdentTable.get("function");1050kw_get = &IdentTable.get("get");1051kw_import = &IdentTable.get("import");1052kw_infer = &IdentTable.get("infer");1053kw_is = &IdentTable.get("is");1054kw_let = &IdentTable.get("let");1055kw_module = &IdentTable.get("module");1056kw_readonly = &IdentTable.get("readonly");1057kw_set = &IdentTable.get("set");1058kw_type = &IdentTable.get("type");1059kw_typeof = &IdentTable.get("typeof");1060kw_var = &IdentTable.get("var");1061kw_yield = &IdentTable.get("yield");10621063kw_abstract = &IdentTable.get("abstract");1064kw_assert = &IdentTable.get("assert");1065kw_extends = &IdentTable.get("extends");1066kw_implements = &IdentTable.get("implements");1067kw_instanceof = &IdentTable.get("instanceof");1068kw_interface = &IdentTable.get("interface");1069kw_native = &IdentTable.get("native");1070kw_package = &IdentTable.get("package");1071kw_synchronized = &IdentTable.get("synchronized");1072kw_throws = &IdentTable.get("throws");1073kw___except = &IdentTable.get("__except");1074kw___has_include = &IdentTable.get("__has_include");1075kw___has_include_next = &IdentTable.get("__has_include_next");10761077kw_mark = &IdentTable.get("mark");1078kw_region = &IdentTable.get("region");10791080kw_extend = &IdentTable.get("extend");1081kw_option = &IdentTable.get("option");1082kw_optional = &IdentTable.get("optional");1083kw_repeated = &IdentTable.get("repeated");1084kw_required = &IdentTable.get("required");1085kw_returns = &IdentTable.get("returns");10861087kw_signals = &IdentTable.get("signals");1088kw_qsignals = &IdentTable.get("Q_SIGNALS");1089kw_slots = &IdentTable.get("slots");1090kw_qslots = &IdentTable.get("Q_SLOTS");10911092// For internal clang-format use.1093kw_internal_ident_after_define =1094&IdentTable.get("__CLANG_FORMAT_INTERNAL_IDENT_AFTER_DEFINE__");10951096// C# keywords1097kw_dollar = &IdentTable.get("dollar");1098kw_base = &IdentTable.get("base");1099kw_byte = &IdentTable.get("byte");1100kw_checked = &IdentTable.get("checked");1101kw_decimal = &IdentTable.get("decimal");1102kw_delegate = &IdentTable.get("delegate");1103kw_event = &IdentTable.get("event");1104kw_fixed = &IdentTable.get("fixed");1105kw_foreach = &IdentTable.get("foreach");1106kw_init = &IdentTable.get("init");1107kw_implicit = &IdentTable.get("implicit");1108kw_internal = &IdentTable.get("internal");1109kw_lock = &IdentTable.get("lock");1110kw_null = &IdentTable.get("null");1111kw_object = &IdentTable.get("object");1112kw_out = &IdentTable.get("out");1113kw_params = &IdentTable.get("params");1114kw_ref = &IdentTable.get("ref");1115kw_string = &IdentTable.get("string");1116kw_stackalloc = &IdentTable.get("stackalloc");1117kw_sbyte = &IdentTable.get("sbyte");1118kw_sealed = &IdentTable.get("sealed");1119kw_uint = &IdentTable.get("uint");1120kw_ulong = &IdentTable.get("ulong");1121kw_unchecked = &IdentTable.get("unchecked");1122kw_unsafe = &IdentTable.get("unsafe");1123kw_ushort = &IdentTable.get("ushort");1124kw_when = &IdentTable.get("when");1125kw_where = &IdentTable.get("where");11261127// Verilog keywords1128kw_always = &IdentTable.get("always");1129kw_always_comb = &IdentTable.get("always_comb");1130kw_always_ff = &IdentTable.get("always_ff");1131kw_always_latch = &IdentTable.get("always_latch");1132kw_assign = &IdentTable.get("assign");1133kw_assume = &IdentTable.get("assume");1134kw_automatic = &IdentTable.get("automatic");1135kw_before = &IdentTable.get("before");1136kw_begin = &IdentTable.get("begin");1137kw_begin_keywords = &IdentTable.get("begin_keywords");1138kw_bins = &IdentTable.get("bins");1139kw_binsof = &IdentTable.get("binsof");1140kw_casex = &IdentTable.get("casex");1141kw_casez = &IdentTable.get("casez");1142kw_celldefine = &IdentTable.get("celldefine");1143kw_checker = &IdentTable.get("checker");1144kw_clocking = &IdentTable.get("clocking");1145kw_constraint = &IdentTable.get("constraint");1146kw_cover = &IdentTable.get("cover");1147kw_covergroup = &IdentTable.get("covergroup");1148kw_coverpoint = &IdentTable.get("coverpoint");1149kw_default_decay_time = &IdentTable.get("default_decay_time");1150kw_default_nettype = &IdentTable.get("default_nettype");1151kw_default_trireg_strength = &IdentTable.get("default_trireg_strength");1152kw_delay_mode_distributed = &IdentTable.get("delay_mode_distributed");1153kw_delay_mode_path = &IdentTable.get("delay_mode_path");1154kw_delay_mode_unit = &IdentTable.get("delay_mode_unit");1155kw_delay_mode_zero = &IdentTable.get("delay_mode_zero");1156kw_disable = &IdentTable.get("disable");1157kw_dist = &IdentTable.get("dist");1158kw_edge = &IdentTable.get("edge");1159kw_elsif = &IdentTable.get("elsif");1160kw_end = &IdentTable.get("end");1161kw_end_keywords = &IdentTable.get("end_keywords");1162kw_endcase = &IdentTable.get("endcase");1163kw_endcelldefine = &IdentTable.get("endcelldefine");1164kw_endchecker = &IdentTable.get("endchecker");1165kw_endclass = &IdentTable.get("endclass");1166kw_endclocking = &IdentTable.get("endclocking");1167kw_endfunction = &IdentTable.get("endfunction");1168kw_endgenerate = &IdentTable.get("endgenerate");1169kw_endgroup = &IdentTable.get("endgroup");1170kw_endinterface = &IdentTable.get("endinterface");1171kw_endmodule = &IdentTable.get("endmodule");1172kw_endpackage = &IdentTable.get("endpackage");1173kw_endprimitive = &IdentTable.get("endprimitive");1174kw_endprogram = &IdentTable.get("endprogram");1175kw_endproperty = &IdentTable.get("endproperty");1176kw_endsequence = &IdentTable.get("endsequence");1177kw_endspecify = &IdentTable.get("endspecify");1178kw_endtable = &IdentTable.get("endtable");1179kw_endtask = &IdentTable.get("endtask");1180kw_forever = &IdentTable.get("forever");1181kw_fork = &IdentTable.get("fork");1182kw_generate = &IdentTable.get("generate");1183kw_highz0 = &IdentTable.get("highz0");1184kw_highz1 = &IdentTable.get("highz1");1185kw_iff = &IdentTable.get("iff");1186kw_ifnone = &IdentTable.get("ifnone");1187kw_ignore_bins = &IdentTable.get("ignore_bins");1188kw_illegal_bins = &IdentTable.get("illegal_bins");1189kw_initial = &IdentTable.get("initial");1190kw_inout = &IdentTable.get("inout");1191kw_input = &IdentTable.get("input");1192kw_inside = &IdentTable.get("inside");1193kw_interconnect = &IdentTable.get("interconnect");1194kw_intersect = &IdentTable.get("intersect");1195kw_join = &IdentTable.get("join");1196kw_join_any = &IdentTable.get("join_any");1197kw_join_none = &IdentTable.get("join_none");1198kw_large = &IdentTable.get("large");1199kw_local = &IdentTable.get("local");1200kw_localparam = &IdentTable.get("localparam");1201kw_macromodule = &IdentTable.get("macromodule");1202kw_matches = &IdentTable.get("matches");1203kw_medium = &IdentTable.get("medium");1204kw_negedge = &IdentTable.get("negedge");1205kw_nounconnected_drive = &IdentTable.get("nounconnected_drive");1206kw_output = &IdentTable.get("output");1207kw_packed = &IdentTable.get("packed");1208kw_parameter = &IdentTable.get("parameter");1209kw_posedge = &IdentTable.get("posedge");1210kw_primitive = &IdentTable.get("primitive");1211kw_priority = &IdentTable.get("priority");1212kw_program = &IdentTable.get("program");1213kw_property = &IdentTable.get("property");1214kw_pull0 = &IdentTable.get("pull0");1215kw_pull1 = &IdentTable.get("pull1");1216kw_pure = &IdentTable.get("pure");1217kw_rand = &IdentTable.get("rand");1218kw_randc = &IdentTable.get("randc");1219kw_randcase = &IdentTable.get("randcase");1220kw_randsequence = &IdentTable.get("randsequence");1221kw_repeat = &IdentTable.get("repeat");1222kw_resetall = &IdentTable.get("resetall");1223kw_sample = &IdentTable.get("sample");1224kw_scalared = &IdentTable.get("scalared");1225kw_sequence = &IdentTable.get("sequence");1226kw_small = &IdentTable.get("small");1227kw_soft = &IdentTable.get("soft");1228kw_solve = &IdentTable.get("solve");1229kw_specify = &IdentTable.get("specify");1230kw_specparam = &IdentTable.get("specparam");1231kw_strong0 = &IdentTable.get("strong0");1232kw_strong1 = &IdentTable.get("strong1");1233kw_supply0 = &IdentTable.get("supply0");1234kw_supply1 = &IdentTable.get("supply1");1235kw_table = &IdentTable.get("table");1236kw_tagged = &IdentTable.get("tagged");1237kw_task = &IdentTable.get("task");1238kw_timescale = &IdentTable.get("timescale");1239kw_tri = &IdentTable.get("tri");1240kw_tri0 = &IdentTable.get("tri0");1241kw_tri1 = &IdentTable.get("tri1");1242kw_triand = &IdentTable.get("triand");1243kw_trior = &IdentTable.get("trior");1244kw_trireg = &IdentTable.get("trireg");1245kw_unconnected_drive = &IdentTable.get("unconnected_drive");1246kw_undefineall = &IdentTable.get("undefineall");1247kw_unique = &IdentTable.get("unique");1248kw_unique0 = &IdentTable.get("unique0");1249kw_uwire = &IdentTable.get("uwire");1250kw_vectored = &IdentTable.get("vectored");1251kw_wand = &IdentTable.get("wand");1252kw_weak0 = &IdentTable.get("weak0");1253kw_weak1 = &IdentTable.get("weak1");1254kw_wildcard = &IdentTable.get("wildcard");1255kw_wire = &IdentTable.get("wire");1256kw_with = &IdentTable.get("with");1257kw_wor = &IdentTable.get("wor");12581259// Symbols that are treated as keywords.1260kw_verilogHash = &IdentTable.get("#");1261kw_verilogHashHash = &IdentTable.get("##");1262kw_apostrophe = &IdentTable.get("\'");12631264// TableGen keywords1265kw_bit = &IdentTable.get("bit");1266kw_bits = &IdentTable.get("bits");1267kw_code = &IdentTable.get("code");1268kw_dag = &IdentTable.get("dag");1269kw_def = &IdentTable.get("def");1270kw_defm = &IdentTable.get("defm");1271kw_defset = &IdentTable.get("defset");1272kw_defvar = &IdentTable.get("defvar");1273kw_dump = &IdentTable.get("dump");1274kw_include = &IdentTable.get("include");1275kw_list = &IdentTable.get("list");1276kw_multiclass = &IdentTable.get("multiclass");1277kw_then = &IdentTable.get("then");12781279// Keep this at the end of the constructor to make sure everything here1280// is1281// already initialized.1282JsExtraKeywords = std::unordered_set<IdentifierInfo *>(1283{kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,1284kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_override,1285kw_readonly, kw_set, kw_type, kw_typeof, kw_var, kw_yield,1286// Keywords from the Java section.1287kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});12881289CSharpExtraKeywords = std::unordered_set<IdentifierInfo *>(1290{kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate, kw_event,1291kw_fixed, kw_foreach, kw_implicit, kw_in, kw_init, kw_interface,1292kw_internal, kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override,1293kw_params, kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte,1294kw_sealed, kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort,1295kw_when, kw_where,1296// Keywords from the JavaScript section.1297kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,1298kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,1299kw_set, kw_type, kw_typeof, kw_var, kw_yield,1300// Keywords from the Java section.1301kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});13021303// Some keywords are not included here because they don't need special1304// treatment like `showcancelled` or they should be treated as identifiers1305// like `int` and `logic`.1306VerilogExtraKeywords = std::unordered_set<IdentifierInfo *>(1307{kw_always, kw_always_comb,1308kw_always_ff, kw_always_latch,1309kw_assert, kw_assign,1310kw_assume, kw_automatic,1311kw_before, kw_begin,1312kw_bins, kw_binsof,1313kw_casex, kw_casez,1314kw_celldefine, kw_checker,1315kw_clocking, kw_constraint,1316kw_cover, kw_covergroup,1317kw_coverpoint, kw_disable,1318kw_dist, kw_edge,1319kw_end, kw_endcase,1320kw_endchecker, kw_endclass,1321kw_endclocking, kw_endfunction,1322kw_endgenerate, kw_endgroup,1323kw_endinterface, kw_endmodule,1324kw_endpackage, kw_endprimitive,1325kw_endprogram, kw_endproperty,1326kw_endsequence, kw_endspecify,1327kw_endtable, kw_endtask,1328kw_extends, kw_final,1329kw_foreach, kw_forever,1330kw_fork, kw_function,1331kw_generate, kw_highz0,1332kw_highz1, kw_iff,1333kw_ifnone, kw_ignore_bins,1334kw_illegal_bins, kw_implements,1335kw_import, kw_initial,1336kw_inout, kw_input,1337kw_inside, kw_interconnect,1338kw_interface, kw_intersect,1339kw_join, kw_join_any,1340kw_join_none, kw_large,1341kw_let, kw_local,1342kw_localparam, kw_macromodule,1343kw_matches, kw_medium,1344kw_negedge, kw_output,1345kw_package, kw_packed,1346kw_parameter, kw_posedge,1347kw_primitive, kw_priority,1348kw_program, kw_property,1349kw_pull0, kw_pull1,1350kw_pure, kw_rand,1351kw_randc, kw_randcase,1352kw_randsequence, kw_ref,1353kw_repeat, kw_sample,1354kw_scalared, kw_sequence,1355kw_small, kw_soft,1356kw_solve, kw_specify,1357kw_specparam, kw_strong0,1358kw_strong1, kw_supply0,1359kw_supply1, kw_table,1360kw_tagged, kw_task,1361kw_tri, kw_tri0,1362kw_tri1, kw_triand,1363kw_trior, kw_trireg,1364kw_unique, kw_unique0,1365kw_uwire, kw_var,1366kw_vectored, kw_wand,1367kw_weak0, kw_weak1,1368kw_wildcard, kw_wire,1369kw_with, kw_wor,1370kw_verilogHash, kw_verilogHashHash});13711372TableGenExtraKeywords = std::unordered_set<IdentifierInfo *>({1373kw_assert,1374kw_bit,1375kw_bits,1376kw_code,1377kw_dag,1378kw_def,1379kw_defm,1380kw_defset,1381kw_defvar,1382kw_dump,1383kw_foreach,1384kw_in,1385kw_include,1386kw_let,1387kw_list,1388kw_multiclass,1389kw_string,1390kw_then,1391});1392}13931394// Context sensitive keywords.1395IdentifierInfo *kw_final;1396IdentifierInfo *kw_override;1397IdentifierInfo *kw_in;1398IdentifierInfo *kw_of;1399IdentifierInfo *kw_CF_CLOSED_ENUM;1400IdentifierInfo *kw_CF_ENUM;1401IdentifierInfo *kw_CF_OPTIONS;1402IdentifierInfo *kw_NS_CLOSED_ENUM;1403IdentifierInfo *kw_NS_ENUM;1404IdentifierInfo *kw_NS_ERROR_ENUM;1405IdentifierInfo *kw_NS_OPTIONS;1406IdentifierInfo *kw___except;1407IdentifierInfo *kw___has_include;1408IdentifierInfo *kw___has_include_next;14091410// JavaScript keywords.1411IdentifierInfo *kw_as;1412IdentifierInfo *kw_async;1413IdentifierInfo *kw_await;1414IdentifierInfo *kw_declare;1415IdentifierInfo *kw_finally;1416IdentifierInfo *kw_from;1417IdentifierInfo *kw_function;1418IdentifierInfo *kw_get;1419IdentifierInfo *kw_import;1420IdentifierInfo *kw_infer;1421IdentifierInfo *kw_is;1422IdentifierInfo *kw_let;1423IdentifierInfo *kw_module;1424IdentifierInfo *kw_readonly;1425IdentifierInfo *kw_set;1426IdentifierInfo *kw_type;1427IdentifierInfo *kw_typeof;1428IdentifierInfo *kw_var;1429IdentifierInfo *kw_yield;14301431// Java keywords.1432IdentifierInfo *kw_abstract;1433IdentifierInfo *kw_assert;1434IdentifierInfo *kw_extends;1435IdentifierInfo *kw_implements;1436IdentifierInfo *kw_instanceof;1437IdentifierInfo *kw_interface;1438IdentifierInfo *kw_native;1439IdentifierInfo *kw_package;1440IdentifierInfo *kw_synchronized;1441IdentifierInfo *kw_throws;14421443// Pragma keywords.1444IdentifierInfo *kw_mark;1445IdentifierInfo *kw_region;14461447// Proto keywords.1448IdentifierInfo *kw_extend;1449IdentifierInfo *kw_option;1450IdentifierInfo *kw_optional;1451IdentifierInfo *kw_repeated;1452IdentifierInfo *kw_required;1453IdentifierInfo *kw_returns;14541455// QT keywords.1456IdentifierInfo *kw_signals;1457IdentifierInfo *kw_qsignals;1458IdentifierInfo *kw_slots;1459IdentifierInfo *kw_qslots;14601461// For internal use by clang-format.1462IdentifierInfo *kw_internal_ident_after_define;14631464// C# keywords1465IdentifierInfo *kw_dollar;1466IdentifierInfo *kw_base;1467IdentifierInfo *kw_byte;1468IdentifierInfo *kw_checked;1469IdentifierInfo *kw_decimal;1470IdentifierInfo *kw_delegate;1471IdentifierInfo *kw_event;1472IdentifierInfo *kw_fixed;1473IdentifierInfo *kw_foreach;1474IdentifierInfo *kw_implicit;1475IdentifierInfo *kw_init;1476IdentifierInfo *kw_internal;14771478IdentifierInfo *kw_lock;1479IdentifierInfo *kw_null;1480IdentifierInfo *kw_object;1481IdentifierInfo *kw_out;14821483IdentifierInfo *kw_params;14841485IdentifierInfo *kw_ref;1486IdentifierInfo *kw_string;1487IdentifierInfo *kw_stackalloc;1488IdentifierInfo *kw_sbyte;1489IdentifierInfo *kw_sealed;1490IdentifierInfo *kw_uint;1491IdentifierInfo *kw_ulong;1492IdentifierInfo *kw_unchecked;1493IdentifierInfo *kw_unsafe;1494IdentifierInfo *kw_ushort;1495IdentifierInfo *kw_when;1496IdentifierInfo *kw_where;14971498// Verilog keywords1499IdentifierInfo *kw_always;1500IdentifierInfo *kw_always_comb;1501IdentifierInfo *kw_always_ff;1502IdentifierInfo *kw_always_latch;1503IdentifierInfo *kw_assign;1504IdentifierInfo *kw_assume;1505IdentifierInfo *kw_automatic;1506IdentifierInfo *kw_before;1507IdentifierInfo *kw_begin;1508IdentifierInfo *kw_begin_keywords;1509IdentifierInfo *kw_bins;1510IdentifierInfo *kw_binsof;1511IdentifierInfo *kw_casex;1512IdentifierInfo *kw_casez;1513IdentifierInfo *kw_celldefine;1514IdentifierInfo *kw_checker;1515IdentifierInfo *kw_clocking;1516IdentifierInfo *kw_constraint;1517IdentifierInfo *kw_cover;1518IdentifierInfo *kw_covergroup;1519IdentifierInfo *kw_coverpoint;1520IdentifierInfo *kw_default_decay_time;1521IdentifierInfo *kw_default_nettype;1522IdentifierInfo *kw_default_trireg_strength;1523IdentifierInfo *kw_delay_mode_distributed;1524IdentifierInfo *kw_delay_mode_path;1525IdentifierInfo *kw_delay_mode_unit;1526IdentifierInfo *kw_delay_mode_zero;1527IdentifierInfo *kw_disable;1528IdentifierInfo *kw_dist;1529IdentifierInfo *kw_elsif;1530IdentifierInfo *kw_edge;1531IdentifierInfo *kw_end;1532IdentifierInfo *kw_end_keywords;1533IdentifierInfo *kw_endcase;1534IdentifierInfo *kw_endcelldefine;1535IdentifierInfo *kw_endchecker;1536IdentifierInfo *kw_endclass;1537IdentifierInfo *kw_endclocking;1538IdentifierInfo *kw_endfunction;1539IdentifierInfo *kw_endgenerate;1540IdentifierInfo *kw_endgroup;1541IdentifierInfo *kw_endinterface;1542IdentifierInfo *kw_endmodule;1543IdentifierInfo *kw_endpackage;1544IdentifierInfo *kw_endprimitive;1545IdentifierInfo *kw_endprogram;1546IdentifierInfo *kw_endproperty;1547IdentifierInfo *kw_endsequence;1548IdentifierInfo *kw_endspecify;1549IdentifierInfo *kw_endtable;1550IdentifierInfo *kw_endtask;1551IdentifierInfo *kw_forever;1552IdentifierInfo *kw_fork;1553IdentifierInfo *kw_generate;1554IdentifierInfo *kw_highz0;1555IdentifierInfo *kw_highz1;1556IdentifierInfo *kw_iff;1557IdentifierInfo *kw_ifnone;1558IdentifierInfo *kw_ignore_bins;1559IdentifierInfo *kw_illegal_bins;1560IdentifierInfo *kw_initial;1561IdentifierInfo *kw_inout;1562IdentifierInfo *kw_input;1563IdentifierInfo *kw_inside;1564IdentifierInfo *kw_interconnect;1565IdentifierInfo *kw_intersect;1566IdentifierInfo *kw_join;1567IdentifierInfo *kw_join_any;1568IdentifierInfo *kw_join_none;1569IdentifierInfo *kw_large;1570IdentifierInfo *kw_local;1571IdentifierInfo *kw_localparam;1572IdentifierInfo *kw_macromodule;1573IdentifierInfo *kw_matches;1574IdentifierInfo *kw_medium;1575IdentifierInfo *kw_negedge;1576IdentifierInfo *kw_nounconnected_drive;1577IdentifierInfo *kw_output;1578IdentifierInfo *kw_packed;1579IdentifierInfo *kw_parameter;1580IdentifierInfo *kw_posedge;1581IdentifierInfo *kw_primitive;1582IdentifierInfo *kw_priority;1583IdentifierInfo *kw_program;1584IdentifierInfo *kw_property;1585IdentifierInfo *kw_pull0;1586IdentifierInfo *kw_pull1;1587IdentifierInfo *kw_pure;1588IdentifierInfo *kw_rand;1589IdentifierInfo *kw_randc;1590IdentifierInfo *kw_randcase;1591IdentifierInfo *kw_randsequence;1592IdentifierInfo *kw_repeat;1593IdentifierInfo *kw_resetall;1594IdentifierInfo *kw_sample;1595IdentifierInfo *kw_scalared;1596IdentifierInfo *kw_sequence;1597IdentifierInfo *kw_small;1598IdentifierInfo *kw_soft;1599IdentifierInfo *kw_solve;1600IdentifierInfo *kw_specify;1601IdentifierInfo *kw_specparam;1602IdentifierInfo *kw_strong0;1603IdentifierInfo *kw_strong1;1604IdentifierInfo *kw_supply0;1605IdentifierInfo *kw_supply1;1606IdentifierInfo *kw_table;1607IdentifierInfo *kw_tagged;1608IdentifierInfo *kw_task;1609IdentifierInfo *kw_timescale;1610IdentifierInfo *kw_tri0;1611IdentifierInfo *kw_tri1;1612IdentifierInfo *kw_tri;1613IdentifierInfo *kw_triand;1614IdentifierInfo *kw_trior;1615IdentifierInfo *kw_trireg;1616IdentifierInfo *kw_unconnected_drive;1617IdentifierInfo *kw_undefineall;1618IdentifierInfo *kw_unique;1619IdentifierInfo *kw_unique0;1620IdentifierInfo *kw_uwire;1621IdentifierInfo *kw_vectored;1622IdentifierInfo *kw_wand;1623IdentifierInfo *kw_weak0;1624IdentifierInfo *kw_weak1;1625IdentifierInfo *kw_wildcard;1626IdentifierInfo *kw_wire;1627IdentifierInfo *kw_with;1628IdentifierInfo *kw_wor;16291630// Workaround for hashes and backticks in Verilog.1631IdentifierInfo *kw_verilogHash;1632IdentifierInfo *kw_verilogHashHash;16331634// Symbols in Verilog that don't exist in C++.1635IdentifierInfo *kw_apostrophe;16361637// TableGen keywords1638IdentifierInfo *kw_bit;1639IdentifierInfo *kw_bits;1640IdentifierInfo *kw_code;1641IdentifierInfo *kw_dag;1642IdentifierInfo *kw_def;1643IdentifierInfo *kw_defm;1644IdentifierInfo *kw_defset;1645IdentifierInfo *kw_defvar;1646IdentifierInfo *kw_dump;1647IdentifierInfo *kw_include;1648IdentifierInfo *kw_list;1649IdentifierInfo *kw_multiclass;1650IdentifierInfo *kw_then;16511652/// Returns \c true if \p Tok is a keyword or an identifier.1653bool isWordLike(const FormatToken &Tok, bool IsVerilog = true) const {1654// getIdentifierinfo returns non-null for keywords as well as identifiers.1655return Tok.Tok.getIdentifierInfo() &&1656(!IsVerilog || !isVerilogKeywordSymbol(Tok));1657}16581659/// Returns \c true if \p Tok is a true JavaScript identifier, returns1660/// \c false if it is a keyword or a pseudo keyword.1661/// If \c AcceptIdentifierName is true, returns true not only for keywords,1662// but also for IdentifierName tokens (aka pseudo-keywords), such as1663// ``yield``.1664bool isJavaScriptIdentifier(const FormatToken &Tok,1665bool AcceptIdentifierName = true) const {1666// Based on the list of JavaScript & TypeScript keywords here:1667// https://github.com/microsoft/TypeScript/blob/main/src/compiler/scanner.ts#L741668if (Tok.isAccessSpecifierKeyword())1669return false;1670switch (Tok.Tok.getKind()) {1671case tok::kw_break:1672case tok::kw_case:1673case tok::kw_catch:1674case tok::kw_class:1675case tok::kw_continue:1676case tok::kw_const:1677case tok::kw_default:1678case tok::kw_delete:1679case tok::kw_do:1680case tok::kw_else:1681case tok::kw_enum:1682case tok::kw_export:1683case tok::kw_false:1684case tok::kw_for:1685case tok::kw_if:1686case tok::kw_import:1687case tok::kw_module:1688case tok::kw_new:1689case tok::kw_return:1690case tok::kw_static:1691case tok::kw_switch:1692case tok::kw_this:1693case tok::kw_throw:1694case tok::kw_true:1695case tok::kw_try:1696case tok::kw_typeof:1697case tok::kw_void:1698case tok::kw_while:1699// These are JS keywords that are lexed by LLVM/clang as keywords.1700return false;1701case tok::identifier: {1702// For identifiers, make sure they are true identifiers, excluding the1703// JavaScript pseudo-keywords (not lexed by LLVM/clang as keywords).1704bool IsPseudoKeyword =1705JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=1706JsExtraKeywords.end();1707return AcceptIdentifierName || !IsPseudoKeyword;1708}1709default:1710// Other keywords are handled in the switch below, to avoid problems due1711// to duplicate case labels when using the #include trick.1712break;1713}17141715switch (Tok.Tok.getKind()) {1716// Handle C++ keywords not included above: these are all JS identifiers.1717#define KEYWORD(X, Y) case tok::kw_##X:1718#include "clang/Basic/TokenKinds.def"1719// #undef KEYWORD is not needed -- it's #undef-ed at the end of1720// TokenKinds.def1721return true;1722default:1723// All other tokens (punctuation etc) are not JS identifiers.1724return false;1725}1726}17271728/// Returns \c true if \p Tok is a C# keyword, returns1729/// \c false if it is a anything else.1730bool isCSharpKeyword(const FormatToken &Tok) const {1731if (Tok.isAccessSpecifierKeyword())1732return true;1733switch (Tok.Tok.getKind()) {1734case tok::kw_bool:1735case tok::kw_break:1736case tok::kw_case:1737case tok::kw_catch:1738case tok::kw_char:1739case tok::kw_class:1740case tok::kw_const:1741case tok::kw_continue:1742case tok::kw_default:1743case tok::kw_do:1744case tok::kw_double:1745case tok::kw_else:1746case tok::kw_enum:1747case tok::kw_explicit:1748case tok::kw_extern:1749case tok::kw_false:1750case tok::kw_float:1751case tok::kw_for:1752case tok::kw_goto:1753case tok::kw_if:1754case tok::kw_int:1755case tok::kw_long:1756case tok::kw_namespace:1757case tok::kw_new:1758case tok::kw_operator:1759case tok::kw_return:1760case tok::kw_short:1761case tok::kw_sizeof:1762case tok::kw_static:1763case tok::kw_struct:1764case tok::kw_switch:1765case tok::kw_this:1766case tok::kw_throw:1767case tok::kw_true:1768case tok::kw_try:1769case tok::kw_typeof:1770case tok::kw_using:1771case tok::kw_virtual:1772case tok::kw_void:1773case tok::kw_volatile:1774case tok::kw_while:1775return true;1776default:1777return Tok.is(tok::identifier) &&1778CSharpExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==1779CSharpExtraKeywords.end();1780}1781}17821783bool isVerilogKeywordSymbol(const FormatToken &Tok) const {1784return Tok.isOneOf(kw_verilogHash, kw_verilogHashHash, kw_apostrophe);1785}17861787bool isVerilogWordOperator(const FormatToken &Tok) const {1788return Tok.isOneOf(kw_before, kw_intersect, kw_dist, kw_iff, kw_inside,1789kw_with);1790}17911792bool isVerilogIdentifier(const FormatToken &Tok) const {1793switch (Tok.Tok.getKind()) {1794case tok::kw_case:1795case tok::kw_class:1796case tok::kw_const:1797case tok::kw_continue:1798case tok::kw_default:1799case tok::kw_do:1800case tok::kw_extern:1801case tok::kw_else:1802case tok::kw_enum:1803case tok::kw_for:1804case tok::kw_if:1805case tok::kw_restrict:1806case tok::kw_signed:1807case tok::kw_static:1808case tok::kw_struct:1809case tok::kw_typedef:1810case tok::kw_union:1811case tok::kw_unsigned:1812case tok::kw_virtual:1813case tok::kw_while:1814return false;1815case tok::identifier:1816return isWordLike(Tok) &&1817VerilogExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==1818VerilogExtraKeywords.end();1819default:1820// getIdentifierInfo returns non-null for both identifiers and keywords.1821return Tok.Tok.getIdentifierInfo();1822}1823}18241825/// Returns whether \p Tok is a Verilog preprocessor directive. This is1826/// needed because macro expansions start with a backtick as well and they1827/// need to be treated differently.1828bool isVerilogPPDirective(const FormatToken &Tok) const {1829auto Info = Tok.Tok.getIdentifierInfo();1830if (!Info)1831return false;1832switch (Info->getPPKeywordID()) {1833case tok::pp_define:1834case tok::pp_else:1835case tok::pp_endif:1836case tok::pp_ifdef:1837case tok::pp_ifndef:1838case tok::pp_include:1839case tok::pp_line:1840case tok::pp_pragma:1841case tok::pp_undef:1842return true;1843default:1844return Tok.isOneOf(kw_begin_keywords, kw_celldefine,1845kw_default_decay_time, kw_default_nettype,1846kw_default_trireg_strength, kw_delay_mode_distributed,1847kw_delay_mode_path, kw_delay_mode_unit,1848kw_delay_mode_zero, kw_elsif, kw_end_keywords,1849kw_endcelldefine, kw_nounconnected_drive, kw_resetall,1850kw_timescale, kw_unconnected_drive, kw_undefineall);1851}1852}18531854/// Returns whether \p Tok is a Verilog keyword that opens a block.1855bool isVerilogBegin(const FormatToken &Tok) const {1856// `table` is not included since it needs to be treated specially.1857return !Tok.endsSequence(kw_fork, kw_disable) &&1858Tok.isOneOf(kw_begin, kw_fork, kw_generate, kw_specify);1859}18601861/// Returns whether \p Tok is a Verilog keyword that closes a block.1862bool isVerilogEnd(const FormatToken &Tok) const {1863return !Tok.endsSequence(kw_join, kw_rand) &&1864Tok.isOneOf(TT_MacroBlockEnd, kw_end, kw_endcase, kw_endclass,1865kw_endclocking, kw_endchecker, kw_endfunction,1866kw_endgenerate, kw_endgroup, kw_endinterface,1867kw_endmodule, kw_endpackage, kw_endprimitive,1868kw_endprogram, kw_endproperty, kw_endsequence,1869kw_endspecify, kw_endtable, kw_endtask, kw_join,1870kw_join_any, kw_join_none);1871}18721873/// Returns whether \p Tok is a Verilog keyword that opens a module, etc.1874bool isVerilogHierarchy(const FormatToken &Tok) const {1875if (Tok.endsSequence(kw_function, kw_with))1876return false;1877if (Tok.is(kw_property)) {1878const FormatToken *Prev = Tok.getPreviousNonComment();1879return !(Prev &&1880Prev->isOneOf(tok::kw_restrict, kw_assert, kw_assume, kw_cover));1881}1882return Tok.isOneOf(tok::kw_case, tok::kw_class, kw_function, kw_module,1883kw_interface, kw_package, kw_casex, kw_casez, kw_checker,1884kw_clocking, kw_covergroup, kw_macromodule, kw_primitive,1885kw_program, kw_property, kw_randcase, kw_randsequence,1886kw_task);1887}18881889bool isVerilogEndOfLabel(const FormatToken &Tok) const {1890const FormatToken *Next = Tok.getNextNonComment();1891// In Verilog the colon in a default label is optional.1892return Tok.is(TT_CaseLabelColon) ||1893(Tok.is(tok::kw_default) &&1894!(Next && Next->isOneOf(tok::colon, tok::semi, kw_clocking, kw_iff,1895kw_input, kw_output, kw_sequence)));1896}18971898/// Returns whether \p Tok is a Verilog keyword that starts a1899/// structured procedure like 'always'.1900bool isVerilogStructuredProcedure(const FormatToken &Tok) const {1901return Tok.isOneOf(kw_always, kw_always_comb, kw_always_ff, kw_always_latch,1902kw_final, kw_forever, kw_initial);1903}19041905bool isVerilogQualifier(const FormatToken &Tok) const {1906switch (Tok.Tok.getKind()) {1907case tok::kw_extern:1908case tok::kw_signed:1909case tok::kw_static:1910case tok::kw_unsigned:1911case tok::kw_virtual:1912return true;1913case tok::identifier:1914return Tok.isOneOf(1915kw_let, kw_var, kw_ref, kw_automatic, kw_bins, kw_coverpoint,1916kw_ignore_bins, kw_illegal_bins, kw_inout, kw_input, kw_interconnect,1917kw_local, kw_localparam, kw_output, kw_parameter, kw_pure, kw_rand,1918kw_randc, kw_scalared, kw_specparam, kw_tri, kw_tri0, kw_tri1,1919kw_triand, kw_trior, kw_trireg, kw_uwire, kw_vectored, kw_wand,1920kw_wildcard, kw_wire, kw_wor);1921default:1922return false;1923}1924}19251926bool isTableGenDefinition(const FormatToken &Tok) const {1927return Tok.isOneOf(kw_def, kw_defm, kw_defset, kw_defvar, kw_multiclass,1928kw_let, tok::kw_class);1929}19301931bool isTableGenKeyword(const FormatToken &Tok) const {1932switch (Tok.Tok.getKind()) {1933case tok::kw_class:1934case tok::kw_else:1935case tok::kw_false:1936case tok::kw_if:1937case tok::kw_int:1938case tok::kw_true:1939return true;1940default:1941return Tok.is(tok::identifier) &&1942TableGenExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=1943TableGenExtraKeywords.end();1944}1945}19461947private:1948/// The JavaScript keywords beyond the C++ keyword set.1949std::unordered_set<IdentifierInfo *> JsExtraKeywords;19501951/// The C# keywords beyond the C++ keyword set1952std::unordered_set<IdentifierInfo *> CSharpExtraKeywords;19531954/// The Verilog keywords beyond the C++ keyword set.1955std::unordered_set<IdentifierInfo *> VerilogExtraKeywords;19561957/// The TableGen keywords beyond the C++ keyword set.1958std::unordered_set<IdentifierInfo *> TableGenExtraKeywords;1959};19601961inline bool isLineComment(const FormatToken &FormatTok) {1962return FormatTok.is(tok::comment) && !FormatTok.TokenText.starts_with("/*");1963}19641965// Checks if \p FormatTok is a line comment that continues the line comment1966// \p Previous. The original column of \p MinColumnToken is used to determine1967// whether \p FormatTok is indented enough to the right to continue \p Previous.1968inline bool continuesLineComment(const FormatToken &FormatTok,1969const FormatToken *Previous,1970const FormatToken *MinColumnToken) {1971if (!Previous || !MinColumnToken)1972return false;1973unsigned MinContinueColumn =1974MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);1975return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&1976isLineComment(*Previous) &&1977FormatTok.OriginalColumn >= MinContinueColumn;1978}19791980} // namespace format1981} // namespace clang19821983#endif198419851986