2086 lines · c
1//===--- FormatToken.h - Format C++ code ------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the declaration of the FormatToken, a wrapper11/// around Token with additional information related to formatting.12///13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H16#define LLVM_CLANG_LIB_FORMAT_FORMATTOKEN_H17 18#include "clang/Basic/IdentifierTable.h"19#include "clang/Basic/OperatorPrecedence.h"20#include "clang/Format/Format.h"21#include "clang/Lex/Lexer.h"22#include <unordered_set>23 24namespace clang {25namespace format {26 27#define LIST_TOKEN_TYPES \28 TYPE(AfterPPDirective) \29 TYPE(ArrayInitializerLSquare) \30 TYPE(ArraySubscriptLSquare) \31 TYPE(AttributeColon) \32 TYPE(AttributeLParen) \33 TYPE(AttributeLSquare) \34 TYPE(AttributeMacro) \35 TYPE(AttributeRParen) \36 TYPE(AttributeRSquare) \37 TYPE(BinaryOperator) \38 TYPE(BitFieldColon) \39 TYPE(BlockComment) \40 /* l_brace of a block that is not the body of a (e.g. loop) statement. */ \41 TYPE(BlockLBrace) \42 TYPE(BracedListLBrace) \43 TYPE(CaseLabelArrow) \44 /* The colon at the end of a case label. */ \45 TYPE(CaseLabelColon) \46 TYPE(CastRParen) \47 TYPE(ClassLBrace) \48 /* Name of class/struct/union/interface definition. */ \49 TYPE(ClassHeadName) \50 TYPE(ClassRBrace) \51 TYPE(CompoundRequirementLBrace) \52 /* ternary ?: expression */ \53 TYPE(ConditionalExpr) \54 /* the condition in an if statement */ \55 TYPE(ConditionLParen) \56 TYPE(ConflictAlternative) \57 TYPE(ConflictEnd) \58 TYPE(ConflictStart) \59 /* l_brace of if/for/while/switch/catch */ \60 TYPE(ControlStatementLBrace) \61 TYPE(ControlStatementRBrace) \62 TYPE(CppCastLParen) \63 TYPE(CSharpGenericTypeConstraint) \64 TYPE(CSharpGenericTypeConstraintColon) \65 TYPE(CSharpGenericTypeConstraintComma) \66 TYPE(CSharpNamedArgumentColon) \67 TYPE(CSharpNullable) \68 TYPE(CSharpNullConditionalLSquare) \69 TYPE(CSharpStringLiteral) \70 TYPE(CtorInitializerColon) \71 TYPE(CtorInitializerComma) \72 TYPE(CtorDtorDeclName) \73 TYPE(DesignatedInitializerLSquare) \74 TYPE(DesignatedInitializerPeriod) \75 TYPE(DictLiteral) \76 TYPE(DoWhile) \77 TYPE(ElseLBrace) \78 TYPE(ElseRBrace) \79 TYPE(EnumLBrace) \80 TYPE(EnumRBrace) \81 TYPE(FatArrow) \82 TYPE(ForEachMacro) \83 TYPE(FunctionAnnotationRParen) \84 TYPE(FunctionDeclarationName) \85 TYPE(FunctionDeclarationLParen) \86 TYPE(FunctionLBrace) \87 TYPE(FunctionLikeMacro) \88 TYPE(FunctionLikeOrFreestandingMacro) \89 TYPE(FunctionTypeLParen) \90 /* The colons as part of a C11 _Generic selection */ \91 TYPE(GenericSelectionColon) \92 /* The colon at the end of a goto label. */ \93 TYPE(GotoLabelColon) \94 TYPE(IfMacro) \95 TYPE(ImplicitStringLiteral) \96 TYPE(InheritanceColon) \97 TYPE(InheritanceComma) \98 TYPE(InlineASMBrace) \99 TYPE(InlineASMColon) \100 TYPE(InlineASMSymbolicNameLSquare) \101 TYPE(JavaAnnotation) \102 TYPE(JsAndAndEqual) \103 TYPE(JsComputedPropertyName) \104 TYPE(JsExponentiation) \105 TYPE(JsExponentiationEqual) \106 TYPE(JsPipePipeEqual) \107 TYPE(JsPrivateIdentifier) \108 TYPE(JsTypeColon) \109 TYPE(JsTypeOperator) \110 TYPE(JsTypeOptionalQuestion) \111 TYPE(LambdaArrow) \112 TYPE(LambdaDefinitionLParen) \113 TYPE(LambdaLBrace) \114 TYPE(LambdaLSquare) \115 TYPE(LeadingJavaAnnotation) \116 TYPE(LineComment) \117 TYPE(MacroBlockBegin) \118 TYPE(MacroBlockEnd) \119 TYPE(ModulePartitionColon) \120 TYPE(NamespaceLBrace) \121 TYPE(NamespaceMacro) \122 TYPE(NamespaceRBrace) \123 TYPE(NonNullAssertion) \124 TYPE(NullCoalescingEqual) \125 TYPE(NullCoalescingOperator) \126 TYPE(NullPropagatingOperator) \127 TYPE(ObjCBlockLBrace) \128 TYPE(ObjCBlockLParen) \129 TYPE(ObjCDecl) \130 TYPE(ObjCForIn) \131 /* The square brackets surrounding a method call, the colon separating the \132 * method or parameter name and the argument inside the square brackets, and \133 * the colon separating the method or parameter name and the type inside the \134 * method declaration. */ \135 TYPE(ObjCMethodExpr) \136 /* The '+' or '-' at the start of the line. */ \137 TYPE(ObjCMethodSpecifier) \138 TYPE(ObjCProperty) \139 /* The parentheses following '@selector' and the colon following the method \140 * or parameter name inside the parentheses. */ \141 TYPE(ObjCSelector) \142 TYPE(ObjCStringLiteral) \143 TYPE(OverloadedOperator) \144 TYPE(OverloadedOperatorLParen) \145 TYPE(PointerOrReference) \146 TYPE(ProtoExtensionLSquare) \147 TYPE(PureVirtualSpecifier) \148 TYPE(QtProperty) \149 TYPE(RangeBasedForLoopColon) \150 TYPE(RecordLBrace) \151 TYPE(RecordRBrace) \152 TYPE(RegexLiteral) \153 TYPE(RequiresClause) \154 TYPE(RequiresClauseInARequiresExpression) \155 TYPE(RequiresExpression) \156 TYPE(RequiresExpressionLBrace) \157 TYPE(RequiresExpressionLParen) \158 /* The hash key in languages that have hash literals, not including the \159 * field name in the C++ struct literal. Also the method or parameter name \160 * in the Objective-C method declaration or call. */ \161 TYPE(SelectorName) \162 TYPE(StartOfName) \163 TYPE(StatementAttributeLikeMacro) \164 TYPE(StatementMacro) \165 /* A string that is part of a string concatenation. For C#, JavaScript, and \166 * Java, it is used for marking whether a string needs parentheses around it \167 * if it is to be split into parts joined by `+`. For Verilog, whether \168 * braces need to be added to split it. Not used for other languages. */ \169 TYPE(StringInConcatenation) \170 TYPE(StructLBrace) \171 TYPE(StructRBrace) \172 TYPE(StructuredBindingLSquare) \173 TYPE(SwitchExpressionLabel) \174 TYPE(SwitchExpressionLBrace) \175 TYPE(TableGenBangOperator) \176 TYPE(TableGenCondOperator) \177 TYPE(TableGenCondOperatorColon) \178 TYPE(TableGenCondOperatorComma) \179 TYPE(TableGenDAGArgCloser) \180 TYPE(TableGenDAGArgListColon) \181 TYPE(TableGenDAGArgListColonToAlign) \182 TYPE(TableGenDAGArgListComma) \183 TYPE(TableGenDAGArgListCommaToBreak) \184 TYPE(TableGenDAGArgOpener) \185 TYPE(TableGenDAGArgOpenerToBreak) \186 TYPE(TableGenDAGArgOperatorID) \187 TYPE(TableGenDAGArgOperatorToBreak) \188 TYPE(TableGenListCloser) \189 TYPE(TableGenListOpener) \190 TYPE(TableGenMultiLineString) \191 TYPE(TableGenTrailingPasteOperator) \192 TYPE(TableGenValueSuffix) \193 TYPE(TemplateCloser) \194 TYPE(TemplateOpener) \195 TYPE(TemplateString) \196 TYPE(TrailingAnnotation) \197 TYPE(TrailingReturnArrow) \198 TYPE(TrailingUnaryOperator) \199 TYPE(TypeDeclarationParen) \200 TYPE(TemplateName) \201 TYPE(TypeName) \202 TYPE(TypenameMacro) \203 TYPE(UnaryOperator) \204 TYPE(UnionLBrace) \205 TYPE(UnionRBrace) \206 TYPE(UntouchableMacroFunc) \207 TYPE(VariableTemplate) \208 /* Like in 'assign x = 0, y = 1;' . */ \209 TYPE(VerilogAssignComma) \210 /* like in begin : block */ \211 TYPE(VerilogBlockLabelColon) \212 /* The square bracket for the dimension part of the type name. \213 * In 'logic [1:0] x[1:0]', only the first '['. This way we can have space \214 * before the first bracket but not the second. */ \215 TYPE(VerilogDimensionedTypeName) \216 /* list of port connections or parameters in a module instantiation */ \217 TYPE(VerilogInstancePortComma) \218 TYPE(VerilogInstancePortLParen) \219 /* A parenthesized list within which line breaks are inserted by the \220 * formatter, for example the list of ports in a module header. */ \221 TYPE(VerilogMultiLineListLParen) \222 /* for the base in a number literal, not including the quote */ \223 TYPE(VerilogNumberBase) \224 /* like `(strong1, pull0)` */ \225 TYPE(VerilogStrength) \226 /* Things inside the table in user-defined primitives. */ \227 TYPE(VerilogTableItem) \228 /* those that separate ports of different types */ \229 TYPE(VerilogTypeComma) \230 TYPE(Unknown)231 232/// Determines the semantic type of a syntactic token, e.g. whether "<" is a233/// template opener or binary operator.234enum TokenType : uint8_t {235#define TYPE(X) TT_##X,236 LIST_TOKEN_TYPES237#undef TYPE238 NUM_TOKEN_TYPES239};240 241/// Determines the name of a token type.242const char *getTokenTypeName(TokenType Type);243 244// Represents what type of block a set of braces open.245enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit };246 247// The packing kind of a function's parameters.248enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive };249 250enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };251 252/// Roles a token can take in a configured macro expansion.253enum MacroRole {254 /// The token was expanded from a macro argument when formatting the expanded255 /// token sequence.256 MR_ExpandedArg,257 /// The token is part of a macro argument that was previously formatted as258 /// expansion when formatting the unexpanded macro call.259 MR_UnexpandedArg,260 /// The token was expanded from a macro definition, and is not visible as part261 /// of the macro call.262 MR_Hidden,263};264 265struct FormatToken;266 267/// Contains information on the token's role in a macro expansion.268///269/// Given the following definitions:270/// A(X) = [ X ]271/// B(X) = < X >272/// C(X) = X273///274/// Consider the macro call:275/// A({B(C(C(x)))}) -> [{<x>}]276///277/// In this case, the tokens of the unexpanded macro call will have the278/// following relevant entries in their macro context (note that formatting279/// the unexpanded macro call happens *after* formatting the expanded macro280/// call):281/// A( { B( C( C(x) ) ) } )282/// Role: NN U NN NN NNUN N N U N (N=None, U=UnexpandedArg)283///284/// [ { < x > } ]285/// Role: H E H E H E H (H=Hidden, E=ExpandedArg)286/// ExpandedFrom[0]: A A A A A A A287/// ExpandedFrom[1]: B B B288/// ExpandedFrom[2]: C289/// ExpandedFrom[3]: C290/// StartOfExpansion: 1 0 1 2 0 0 0291/// EndOfExpansion: 0 0 0 2 1 0 1292struct MacroExpansion {293 MacroExpansion(MacroRole Role) : Role(Role) {}294 295 /// The token's role in the macro expansion.296 /// When formatting an expanded macro, all tokens that are part of macro297 /// arguments will be MR_ExpandedArg, while all tokens that are not visible in298 /// the macro call will be MR_Hidden.299 /// When formatting an unexpanded macro call, all tokens that are part of300 /// macro arguments will be MR_UnexpandedArg.301 MacroRole Role;302 303 /// The stack of macro call identifier tokens this token was expanded from.304 llvm::SmallVector<FormatToken *, 1> ExpandedFrom;305 306 /// The number of expansions of which this macro is the first entry.307 unsigned StartOfExpansion = 0;308 309 /// The number of currently open expansions in \c ExpandedFrom this macro is310 /// the last token in.311 unsigned EndOfExpansion = 0;312};313 314class TokenRole;315class AnnotatedLine;316 317/// A wrapper around a \c Token storing information about the318/// whitespace characters preceding it.319struct FormatToken {320 FormatToken()321 : HasUnescapedNewline(false), IsMultiline(false), IsFirst(false),322 MustBreakBefore(false), MustBreakBeforeFinalized(false),323 IsUnterminatedLiteral(false), CanBreakBefore(false),324 ClosesTemplateDeclaration(false), StartsBinaryExpression(false),325 EndsBinaryExpression(false), PartOfMultiVariableDeclStmt(false),326 ContinuesLineCommentSection(false), Finalized(false),327 ClosesRequiresClause(false), EndsCppAttributeGroup(false),328 BlockKind(BK_Unknown), Decision(FD_Unformatted),329 PackingKind(PPK_Inconclusive), TypeIsFinalized(false),330 Type(TT_Unknown) {}331 332 /// The \c Token.333 Token Tok;334 335 /// The raw text of the token.336 ///337 /// Contains the raw token text without leading whitespace and without leading338 /// escaped newlines.339 StringRef TokenText;340 341 /// A token can have a special role that can carry extra information342 /// about the token's formatting.343 /// FIXME: Make FormatToken for parsing and AnnotatedToken two different344 /// classes and make this a unique_ptr in the AnnotatedToken class.345 std::shared_ptr<TokenRole> Role;346 347 /// The range of the whitespace immediately preceding the \c Token.348 SourceRange WhitespaceRange;349 350 /// Whether there is at least one unescaped newline before the \c351 /// Token.352 unsigned HasUnescapedNewline : 1;353 354 /// Whether the token text contains newlines (escaped or not).355 unsigned IsMultiline : 1;356 357 /// Indicates that this is the first token of the file.358 unsigned IsFirst : 1;359 360 /// Whether there must be a line break before this token.361 ///362 /// This happens for example when a preprocessor directive ended directly363 /// before the token.364 unsigned MustBreakBefore : 1;365 366 /// Whether MustBreakBefore is finalized during parsing and must not367 /// be reset between runs.368 unsigned MustBreakBeforeFinalized : 1;369 370 /// Set to \c true if this token is an unterminated literal.371 unsigned IsUnterminatedLiteral : 1;372 373 /// \c true if it is allowed to break before this token.374 unsigned CanBreakBefore : 1;375 376 /// \c true if this is the ">" of "template<..>".377 unsigned ClosesTemplateDeclaration : 1;378 379 /// \c true if this token starts a binary expression, i.e. has at least380 /// one fake l_paren with a precedence greater than prec::Unknown.381 unsigned StartsBinaryExpression : 1;382 /// \c true if this token ends a binary expression.383 unsigned EndsBinaryExpression : 1;384 385 /// Is this token part of a \c DeclStmt defining multiple variables?386 ///387 /// Only set if \c Type == \c TT_StartOfName.388 unsigned PartOfMultiVariableDeclStmt : 1;389 390 /// Does this line comment continue a line comment section?391 ///392 /// Only set to true if \c Type == \c TT_LineComment.393 unsigned ContinuesLineCommentSection : 1;394 395 /// If \c true, this token has been fully formatted (indented and396 /// potentially re-formatted inside), and we do not allow further formatting397 /// changes.398 unsigned Finalized : 1;399 400 /// \c true if this is the last token within requires clause.401 unsigned ClosesRequiresClause : 1;402 403 /// \c true if this token ends a group of C++ attributes.404 unsigned EndsCppAttributeGroup : 1;405 406private:407 /// Contains the kind of block if this token is a brace.408 unsigned BlockKind : 2;409 410public:411 BraceBlockKind getBlockKind() const {412 return static_cast<BraceBlockKind>(BlockKind);413 }414 void setBlockKind(BraceBlockKind BBK) {415 BlockKind = BBK;416 assert(getBlockKind() == BBK && "BraceBlockKind overflow!");417 }418 419private:420 /// Stores the formatting decision for the token once it was made.421 unsigned Decision : 2;422 423public:424 FormatDecision getDecision() const {425 return static_cast<FormatDecision>(Decision);426 }427 void setDecision(FormatDecision D) {428 Decision = D;429 assert(getDecision() == D && "FormatDecision overflow!");430 }431 432private:433 /// If this is an opening parenthesis, how are the parameters packed?434 unsigned PackingKind : 2;435 436public:437 ParameterPackingKind getPackingKind() const {438 return static_cast<ParameterPackingKind>(PackingKind);439 }440 void setPackingKind(ParameterPackingKind K) {441 PackingKind = K;442 assert(getPackingKind() == K && "ParameterPackingKind overflow!");443 }444 445private:446 unsigned TypeIsFinalized : 1;447 TokenType Type;448 449public:450 /// Returns the token's type, e.g. whether "<" is a template opener or451 /// binary operator.452 TokenType getType() const { return Type; }453 void setType(TokenType T) {454 // If this token is a macro argument while formatting an unexpanded macro455 // call, we do not change its type any more - the type was deduced from456 // formatting the expanded macro stream already.457 if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)458 return;459 assert((!TypeIsFinalized || T == Type) &&460 "Please use overwriteFixedType to change a fixed type.");461 Type = T;462 }463 /// Sets the type and also the finalized flag. This prevents the type to be464 /// reset in TokenAnnotator::resetTokenMetadata(). If the type needs to be set465 /// to another one please use overwriteFixedType, or even better remove the466 /// need to reassign the type.467 void setFinalizedType(TokenType T) {468 if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)469 return;470 Type = T;471 TypeIsFinalized = true;472 }473 void overwriteFixedType(TokenType T) {474 if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)475 return;476 TypeIsFinalized = false;477 setType(T);478 }479 bool isTypeFinalized() const { return TypeIsFinalized; }480 481 /// Used to set an operator precedence explicitly.482 prec::Level ForcedPrecedence = prec::Unknown;483 484 /// The number of newlines immediately before the \c Token.485 ///486 /// This can be used to determine what the user wrote in the original code487 /// and thereby e.g. leave an empty line between two function definitions.488 unsigned NewlinesBefore = 0;489 490 /// The number of newlines immediately before the \c Token after formatting.491 ///492 /// This is used to avoid overlapping whitespace replacements when \c Newlines493 /// is recomputed for a finalized preprocessor branching directive.494 int Newlines = -1;495 496 /// The offset just past the last '\n' in this token's leading497 /// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.498 unsigned LastNewlineOffset = 0;499 500 /// The width of the non-whitespace parts of the token (or its first501 /// line for multi-line tokens) in columns.502 /// We need this to correctly measure number of columns a token spans.503 unsigned ColumnWidth = 0;504 505 /// Contains the width in columns of the last line of a multi-line506 /// token.507 unsigned LastLineColumnWidth = 0;508 509 /// The number of spaces that should be inserted before this token.510 unsigned SpacesRequiredBefore = 0;511 512 /// Number of parameters, if this is "(", "[" or "<".513 unsigned ParameterCount = 0;514 515 /// Number of parameters that are nested blocks,516 /// if this is "(", "[" or "<".517 unsigned BlockParameterCount = 0;518 519 /// If this is a bracket ("<", "(", "[" or "{"), contains the kind of520 /// the surrounding bracket.521 tok::TokenKind ParentBracket = tok::unknown;522 523 /// The total length of the unwrapped line up to and including this524 /// token.525 unsigned TotalLength = 0;526 527 /// The original 0-based column of this token, including expanded tabs.528 /// The configured TabWidth is used as tab width.529 unsigned OriginalColumn = 0;530 531 /// The length of following tokens until the next natural split point,532 /// or the next token that can be broken.533 unsigned UnbreakableTailLength = 0;534 535 // FIXME: Come up with a 'cleaner' concept.536 /// The binding strength of a token. This is a combined value of537 /// operator precedence, parenthesis nesting, etc.538 unsigned BindingStrength = 0;539 540 /// The nesting level of this token, i.e. the number of surrounding (),541 /// [], {} or <>.542 unsigned NestingLevel = 0;543 544 /// The indent level of this token. Copied from the surrounding line.545 unsigned IndentLevel = 0;546 547 /// Penalty for inserting a line break before this token.548 unsigned SplitPenalty = 0;549 550 /// If this is the first ObjC selector name in an ObjC method551 /// definition or call, this contains the length of the longest name.552 ///553 /// This being set to 0 means that the selectors should not be colon-aligned,554 /// e.g. because several of them are block-type.555 unsigned LongestObjCSelectorName = 0;556 557 /// If this is the first ObjC selector name in an ObjC method558 /// definition or call, this contains the number of parts that the whole559 /// selector consist of.560 unsigned ObjCSelectorNameParts = 0;561 562 /// The 0-based index of the parameter/argument. For ObjC it is set563 /// for the selector name token.564 /// For now calculated only for ObjC.565 unsigned ParameterIndex = 0;566 567 /// Stores the number of required fake parentheses and the568 /// corresponding operator precedence.569 ///570 /// If multiple fake parentheses start at a token, this vector stores them in571 /// reverse order, i.e. inner fake parenthesis first.572 SmallVector<prec::Level, 4> FakeLParens;573 /// Insert this many fake ) after this token for correct indentation.574 unsigned FakeRParens = 0;575 576 /// If this is an operator (or "."/"->") in a sequence of operators577 /// with the same precedence, contains the 0-based operator index.578 unsigned OperatorIndex = 0;579 580 /// If this is an operator (or "."/"->") in a sequence of operators581 /// with the same precedence, points to the next operator.582 FormatToken *NextOperator = nullptr;583 584 /// If this is a bracket, this points to the matching one.585 FormatToken *MatchingParen = nullptr;586 587 /// The previous token in the unwrapped line.588 FormatToken *Previous = nullptr;589 590 /// The next token in the unwrapped line.591 FormatToken *Next = nullptr;592 593 /// The first token in set of column elements.594 bool StartsColumn = false;595 596 /// This notes the start of the line of an array initializer.597 bool ArrayInitializerLineStart = false;598 599 /// This starts an array initializer.600 bool IsArrayInitializer = false;601 602 /// Is optional and can be removed.603 bool Optional = false;604 605 /// Might be function declaration open/closing paren.606 bool MightBeFunctionDeclParen = false;607 608 /// Has "\n\f\n" or "\n\f\r\n" before TokenText.609 bool HasFormFeedBefore = false;610 611 /// Is the first token after a preprocessor line.612 bool FirstAfterPPLine = false;613 614 /// Number of optional braces to be inserted after this token:615 /// -1: a single left brace616 /// 0: no braces617 /// >0: number of right braces618 int8_t BraceCount = 0;619 620 /// If this token starts a block, this contains all the unwrapped lines621 /// in it.622 SmallVector<AnnotatedLine *, 1> Children;623 624 // Contains all attributes related to how this token takes part625 // in a configured macro expansion.626 std::optional<MacroExpansion> MacroCtx;627 628 /// When macro expansion introduces nodes with children, those are marked as629 /// \c MacroParent.630 /// FIXME: The formatting code currently hard-codes the assumption that631 /// child nodes are introduced by blocks following an opening brace.632 /// This is deeply baked into the code and disentangling this will require633 /// signficant refactorings. \c MacroParent allows us to special-case the634 /// cases in which we treat parents as block-openers for now.635 bool MacroParent = false;636 637 bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }638 bool is(tok::ObjCKeywordKind Kind) const {639 return Tok.getObjCKeywordID() == Kind;640 }641 bool is(TokenType TT) const { return getType() == TT; }642 bool is(const IdentifierInfo *II) const {643 return II && II == Tok.getIdentifierInfo();644 }645 bool is(tok::PPKeywordKind Kind) const {646 return Tok.getIdentifierInfo() &&647 Tok.getIdentifierInfo()->getPPKeywordID() == Kind;648 }649 bool is(BraceBlockKind BBK) const { return getBlockKind() == BBK; }650 bool is(ParameterPackingKind PPK) const { return getPackingKind() == PPK; }651 652 template <typename A, typename B> bool isOneOf(A K1, B K2) const {653 return is(K1) || is(K2);654 }655 template <typename A, typename B, typename... Ts>656 bool isOneOf(A K1, B K2, Ts... Ks) const {657 return is(K1) || isOneOf(K2, Ks...);658 }659 template <typename T> bool isNot(T Kind) const { return !is(Kind); }660 template <typename... Ts> bool isNoneOf(Ts... Ks) const {661 return !isOneOf(Ks...);662 }663 664 bool isIf(bool AllowConstexprMacro = true) const {665 return is(tok::kw_if) || endsSequence(tok::kw_constexpr, tok::kw_if) ||666 (endsSequence(tok::identifier, tok::kw_if) && AllowConstexprMacro);667 }668 669 bool isLoop(const FormatStyle &Style) const {670 return isOneOf(tok::kw_for, tok::kw_while) ||671 (Style.isJavaScript() && isNot(tok::l_paren) && Previous &&672 Previous->is(tok::kw_for));673 }674 675 bool closesScopeAfterBlock() const {676 if (getBlockKind() == BK_Block)677 return true;678 if (closesScope())679 return Previous->closesScopeAfterBlock();680 return false;681 }682 683 /// \c true if this token starts a sequence with the given tokens in order,684 /// following the ``Next`` pointers, ignoring comments.685 template <typename A, typename... Ts>686 bool startsSequence(A K1, Ts... Tokens) const {687 return startsSequenceInternal(K1, Tokens...);688 }689 690 /// \c true if this token ends a sequence with the given tokens in order,691 /// following the ``Previous`` pointers, ignoring comments.692 /// For example, given tokens [T1, T2, T3], the function returns true if693 /// 3 tokens ending at this (ignoring comments) are [T3, T2, T1]. In other694 /// words, the tokens passed to this function need to the reverse of the695 /// order the tokens appear in code.696 template <typename A, typename... Ts>697 bool endsSequence(A K1, Ts... Tokens) const {698 return endsSequenceInternal(K1, Tokens...);699 }700 701 bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); }702 703 bool isAttribute() const {704 return isOneOf(tok::kw___attribute, tok::kw___declspec, TT_AttributeMacro);705 }706 707 bool isAccessSpecifierKeyword() const {708 return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private);709 }710 711 bool isAccessSpecifier(bool ColonRequired = true) const {712 if (!isAccessSpecifierKeyword())713 return false;714 if (!ColonRequired)715 return true;716 const auto *NextNonComment = getNextNonComment();717 return NextNonComment && NextNonComment->is(tok::colon);718 }719 720 bool canBePointerOrReferenceQualifier() const {721 return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile,722 tok::kw__Nonnull, tok::kw__Nullable,723 tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64,724 tok::kw___funcref) ||725 isAttribute();726 }727 728 [[nodiscard]] bool isQtProperty() const;729 [[nodiscard]] bool isTypeName(const LangOptions &LangOpts) const;730 [[nodiscard]] bool isTypeOrIdentifier(const LangOptions &LangOpts) const;731 732 bool isObjCAccessSpecifier() const {733 return is(tok::at) && Next &&734 Next->isOneOf(tok::objc_public, tok::objc_protected,735 tok::objc_package, tok::objc_private);736 }737 738 bool isObjCLifetimeQualifier(const FormatStyle &Style) const {739 if (Style.Language != FormatStyle::LK_ObjC || isNot(tok::identifier) ||740 !TokenText.starts_with("__")) {741 return false;742 }743 const auto Qualifier = TokenText.substr(2);744 return Qualifier == "autoreleasing" || Qualifier == "strong" ||745 Qualifier == "weak" || Qualifier == "unsafe_unretained";746 }747 748 /// Returns whether \p Tok is ([{ or an opening < of a template or in749 /// protos.750 bool opensScope() const {751 if (is(TT_TemplateString) && TokenText.ends_with("${"))752 return true;753 if (is(TT_DictLiteral) && is(tok::less))754 return true;755 return isOneOf(tok::l_paren, tok::l_brace, tok::l_square,756 TT_TemplateOpener);757 }758 /// Returns whether \p Tok is )]} or a closing > of a template or in759 /// protos.760 bool closesScope() const {761 if (is(TT_TemplateString) && TokenText.starts_with("}"))762 return true;763 if (is(TT_DictLiteral) && is(tok::greater))764 return true;765 return isOneOf(tok::r_paren, tok::r_brace, tok::r_square,766 TT_TemplateCloser);767 }768 769 /// Returns \c true if this is a "." or "->" accessing a member.770 bool isMemberAccess() const {771 return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&772 isNoneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow,773 TT_LambdaArrow, TT_LeadingJavaAnnotation);774 }775 776 bool isPointerOrReference() const {777 return isOneOf(tok::star, tok::amp, tok::ampamp);778 }779 780 bool isPlacementOperator() const {781 return isOneOf(tok::kw_new, tok::kw_delete);782 }783 784 bool isUnaryOperator() const {785 switch (Tok.getKind()) {786 case tok::plus:787 case tok::plusplus:788 case tok::minus:789 case tok::minusminus:790 case tok::exclaim:791 case tok::tilde:792 case tok::kw_sizeof:793 case tok::kw_alignof:794 return true;795 default:796 return false;797 }798 }799 800 bool isBinaryOperator() const {801 // Comma is a binary operator, but does not behave as such wrt. formatting.802 return getPrecedence() > prec::Comma;803 }804 805 bool isTrailingComment() const {806 return is(tok::comment) &&807 (is(TT_LineComment) || !Next || Next->NewlinesBefore > 0);808 }809 810 /// Returns \c true if this is a keyword that can be used811 /// like a function call (e.g. sizeof, typeid, ...).812 bool isFunctionLikeKeyword() const {813 if (isAttribute())814 return true;815 816 return isOneOf(tok::kw_throw, tok::kw_typeid, tok::kw_return,817 tok::kw_sizeof, tok::kw_alignof, tok::kw_alignas,818 tok::kw_decltype, tok::kw_noexcept, tok::kw_static_assert,819 tok::kw__Atomic,820#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,821#include "clang/Basic/TransformTypeTraits.def"822 tok::kw_requires);823 }824 825 /// Returns \c true if this is a string literal that's like a label,826 /// e.g. ends with "=" or ":".827 bool isLabelString() const {828 if (isNot(tok::string_literal))829 return false;830 StringRef Content = TokenText;831 if (Content.starts_with("\"") || Content.starts_with("'"))832 Content = Content.drop_front(1);833 if (Content.ends_with("\"") || Content.ends_with("'"))834 Content = Content.drop_back(1);835 Content = Content.trim();836 return Content.size() > 1 &&837 (Content.back() == ':' || Content.back() == '=');838 }839 840 /// Returns actual token start location without leading escaped841 /// newlines and whitespace.842 ///843 /// This can be different to Tok.getLocation(), which includes leading escaped844 /// newlines.845 SourceLocation getStartOfNonWhitespace() const {846 return WhitespaceRange.getEnd();847 }848 849 /// Returns \c true if the range of whitespace immediately preceding the \c850 /// Token is not empty.851 bool hasWhitespaceBefore() const {852 return WhitespaceRange.getBegin() != WhitespaceRange.getEnd();853 }854 855 prec::Level getPrecedence() const {856 if (ForcedPrecedence != prec::Unknown)857 return ForcedPrecedence;858 return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true,859 /*CPlusPlus11=*/true);860 }861 862 /// Returns the previous token ignoring comments.863 [[nodiscard]] FormatToken *getPreviousNonComment() const {864 FormatToken *Tok = Previous;865 while (Tok && Tok->is(tok::comment))866 Tok = Tok->Previous;867 return Tok;868 }869 870 /// Returns the next token ignoring comments.871 [[nodiscard]] FormatToken *getNextNonComment() const {872 FormatToken *Tok = Next;873 while (Tok && Tok->is(tok::comment))874 Tok = Tok->Next;875 return Tok;876 }877 878 /// Returns \c true if this token ends a block indented initializer list.879 [[nodiscard]] bool isBlockIndentedInitRBrace(const FormatStyle &Style) const;880 881 /// Returns \c true if this tokens starts a block-type list, i.e. a882 /// list that should be indented with a block indent.883 [[nodiscard]] bool opensBlockOrBlockTypeList(const FormatStyle &Style) const;884 885 /// Returns whether the token is the left square bracket of a C++886 /// structured binding declaration.887 bool isCppStructuredBinding(bool IsCpp) const {888 if (!IsCpp || isNot(tok::l_square))889 return false;890 const FormatToken *T = this;891 do {892 T = T->getPreviousNonComment();893 } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp,894 tok::ampamp));895 return T && T->is(tok::kw_auto);896 }897 898 /// Same as opensBlockOrBlockTypeList, but for the closing token.899 bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {900 if (is(TT_TemplateString) && closesScope())901 return true;902 return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);903 }904 905 /// Return the actual namespace token, if this token starts a namespace906 /// block.907 const FormatToken *getNamespaceToken() const {908 const FormatToken *NamespaceTok = this;909 if (is(tok::comment))910 NamespaceTok = NamespaceTok->getNextNonComment();911 // Detect "(inline|export)? namespace" in the beginning of a line.912 if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export))913 NamespaceTok = NamespaceTok->getNextNonComment();914 return NamespaceTok &&915 NamespaceTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro)916 ? NamespaceTok917 : nullptr;918 }919 920 void copyFrom(const FormatToken &Tok) { *this = Tok; }921 922private:923 // Only allow copying via the explicit copyFrom method.924 FormatToken(const FormatToken &) = delete;925 FormatToken &operator=(const FormatToken &) = default;926 927 template <typename A, typename... Ts>928 bool startsSequenceInternal(A K1, Ts... Tokens) const {929 if (is(tok::comment) && Next)930 return Next->startsSequenceInternal(K1, Tokens...);931 return is(K1) && Next && Next->startsSequenceInternal(Tokens...);932 }933 934 template <typename A> bool startsSequenceInternal(A K1) const {935 if (is(tok::comment) && Next)936 return Next->startsSequenceInternal(K1);937 return is(K1);938 }939 940 template <typename A, typename... Ts> bool endsSequenceInternal(A K1) const {941 if (is(tok::comment) && Previous)942 return Previous->endsSequenceInternal(K1);943 return is(K1);944 }945 946 template <typename A, typename... Ts>947 bool endsSequenceInternal(A K1, Ts... Tokens) const {948 if (is(tok::comment) && Previous)949 return Previous->endsSequenceInternal(K1, Tokens...);950 return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...);951 }952};953 954class ContinuationIndenter;955struct LineState;956 957class TokenRole {958public:959 TokenRole(const FormatStyle &Style) : Style(Style) {}960 virtual ~TokenRole();961 962 /// After the \c TokenAnnotator has finished annotating all the tokens,963 /// this function precomputes required information for formatting.964 virtual void precomputeFormattingInfos(const FormatToken *Token);965 966 /// Apply the special formatting that the given role demands.967 ///968 /// Assumes that the token having this role is already formatted.969 ///970 /// Continues formatting from \p State leaving indentation to \p Indenter and971 /// returns the total penalty that this formatting incurs.972 virtual unsigned formatFromToken(LineState &State,973 ContinuationIndenter *Indenter,974 bool DryRun) {975 return 0;976 }977 978 /// Same as \c formatFromToken, but assumes that the first token has979 /// already been set thereby deciding on the first line break.980 virtual unsigned formatAfterToken(LineState &State,981 ContinuationIndenter *Indenter,982 bool DryRun) {983 return 0;984 }985 986 /// Notifies the \c Role that a comma was found.987 virtual void CommaFound(const FormatToken *Token) {}988 989 virtual const FormatToken *lastComma() { return nullptr; }990 991protected:992 const FormatStyle &Style;993};994 995class CommaSeparatedList : public TokenRole {996public:997 CommaSeparatedList(const FormatStyle &Style)998 : TokenRole(Style), HasNestedBracedList(false) {}999 1000 void precomputeFormattingInfos(const FormatToken *Token) override;1001 1002 unsigned formatAfterToken(LineState &State, ContinuationIndenter *Indenter,1003 bool DryRun) override;1004 1005 unsigned formatFromToken(LineState &State, ContinuationIndenter *Indenter,1006 bool DryRun) override;1007 1008 /// Adds \p Token as the next comma to the \c CommaSeparated list.1009 void CommaFound(const FormatToken *Token) override {1010 Commas.push_back(Token);1011 }1012 1013 const FormatToken *lastComma() override {1014 if (Commas.empty())1015 return nullptr;1016 return Commas.back();1017 }1018 1019private:1020 /// A struct that holds information on how to format a given list with1021 /// a specific number of columns.1022 struct ColumnFormat {1023 /// The number of columns to use.1024 unsigned Columns;1025 1026 /// The total width in characters.1027 unsigned TotalWidth;1028 1029 /// The number of lines required for this format.1030 unsigned LineCount;1031 1032 /// The size of each column in characters.1033 SmallVector<unsigned, 8> ColumnSizes;1034 };1035 1036 /// Calculate which \c ColumnFormat fits best into1037 /// \p RemainingCharacters.1038 const ColumnFormat *getColumnFormat(unsigned RemainingCharacters) const;1039 1040 /// The ordered \c FormatTokens making up the commas of this list.1041 SmallVector<const FormatToken *, 8> Commas;1042 1043 /// The length of each of the list's items in characters including the1044 /// trailing comma.1045 SmallVector<unsigned, 8> ItemLengths;1046 1047 /// Precomputed formats that can be used for this list.1048 SmallVector<ColumnFormat, 4> Formats;1049 1050 bool HasNestedBracedList;1051};1052 1053/// Encapsulates keywords that are context sensitive or for languages not1054/// properly supported by Clang's lexer.1055struct AdditionalKeywords {1056 AdditionalKeywords(IdentifierTable &IdentTable) {1057 kw_final = &IdentTable.get("final");1058 kw_override = &IdentTable.get("override");1059 kw_in = &IdentTable.get("in");1060 kw_of = &IdentTable.get("of");1061 kw_CF_CLOSED_ENUM = &IdentTable.get("CF_CLOSED_ENUM");1062 kw_CF_ENUM = &IdentTable.get("CF_ENUM");1063 kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS");1064 kw_NS_CLOSED_ENUM = &IdentTable.get("NS_CLOSED_ENUM");1065 kw_NS_ENUM = &IdentTable.get("NS_ENUM");1066 kw_NS_ERROR_ENUM = &IdentTable.get("NS_ERROR_ENUM");1067 kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS");1068 1069 kw_as = &IdentTable.get("as");1070 kw_async = &IdentTable.get("async");1071 kw_await = &IdentTable.get("await");1072 kw_declare = &IdentTable.get("declare");1073 kw_finally = &IdentTable.get("finally");1074 kw_from = &IdentTable.get("from");1075 kw_function = &IdentTable.get("function");1076 kw_get = &IdentTable.get("get");1077 kw_import = &IdentTable.get("import");1078 kw_infer = &IdentTable.get("infer");1079 kw_is = &IdentTable.get("is");1080 kw_let = &IdentTable.get("let");1081 kw_module = &IdentTable.get("module");1082 kw_readonly = &IdentTable.get("readonly");1083 kw_set = &IdentTable.get("set");1084 kw_type = &IdentTable.get("type");1085 kw_typeof = &IdentTable.get("typeof");1086 kw_var = &IdentTable.get("var");1087 kw_yield = &IdentTable.get("yield");1088 1089 kw_abstract = &IdentTable.get("abstract");1090 kw_assert = &IdentTable.get("assert");1091 kw_extends = &IdentTable.get("extends");1092 kw_implements = &IdentTable.get("implements");1093 kw_instanceof = &IdentTable.get("instanceof");1094 kw_interface = &IdentTable.get("interface");1095 kw_native = &IdentTable.get("native");1096 kw_package = &IdentTable.get("package");1097 kw_record = &IdentTable.get("record");1098 kw_synchronized = &IdentTable.get("synchronized");1099 kw_throws = &IdentTable.get("throws");1100 kw___except = &IdentTable.get("__except");1101 kw___has_include = &IdentTable.get("__has_include");1102 kw___has_include_next = &IdentTable.get("__has_include_next");1103 1104 kw_mark = &IdentTable.get("mark");1105 kw_region = &IdentTable.get("region");1106 1107 kw_extend = &IdentTable.get("extend");1108 kw_option = &IdentTable.get("option");1109 kw_optional = &IdentTable.get("optional");1110 kw_repeated = &IdentTable.get("repeated");1111 kw_required = &IdentTable.get("required");1112 kw_returns = &IdentTable.get("returns");1113 1114 kw_signals = &IdentTable.get("signals");1115 kw_qsignals = &IdentTable.get("Q_SIGNALS");1116 kw_slots = &IdentTable.get("slots");1117 kw_qslots = &IdentTable.get("Q_SLOTS");1118 1119 // For internal clang-format use.1120 kw_internal_ident_after_define =1121 &IdentTable.get("__CLANG_FORMAT_INTERNAL_IDENT_AFTER_DEFINE__");1122 1123 // C# keywords1124 kw_dollar = &IdentTable.get("dollar");1125 kw_base = &IdentTable.get("base");1126 kw_byte = &IdentTable.get("byte");1127 kw_checked = &IdentTable.get("checked");1128 kw_decimal = &IdentTable.get("decimal");1129 kw_delegate = &IdentTable.get("delegate");1130 kw_event = &IdentTable.get("event");1131 kw_fixed = &IdentTable.get("fixed");1132 kw_foreach = &IdentTable.get("foreach");1133 kw_init = &IdentTable.get("init");1134 kw_implicit = &IdentTable.get("implicit");1135 kw_internal = &IdentTable.get("internal");1136 kw_lock = &IdentTable.get("lock");1137 kw_null = &IdentTable.get("null");1138 kw_object = &IdentTable.get("object");1139 kw_out = &IdentTable.get("out");1140 kw_params = &IdentTable.get("params");1141 kw_ref = &IdentTable.get("ref");1142 kw_string = &IdentTable.get("string");1143 kw_stackalloc = &IdentTable.get("stackalloc");1144 kw_sbyte = &IdentTable.get("sbyte");1145 kw_sealed = &IdentTable.get("sealed");1146 kw_uint = &IdentTable.get("uint");1147 kw_ulong = &IdentTable.get("ulong");1148 kw_unchecked = &IdentTable.get("unchecked");1149 kw_unsafe = &IdentTable.get("unsafe");1150 kw_ushort = &IdentTable.get("ushort");1151 kw_when = &IdentTable.get("when");1152 kw_where = &IdentTable.get("where");1153 1154 // Verilog keywords1155 kw_always = &IdentTable.get("always");1156 kw_always_comb = &IdentTable.get("always_comb");1157 kw_always_ff = &IdentTable.get("always_ff");1158 kw_always_latch = &IdentTable.get("always_latch");1159 kw_assign = &IdentTable.get("assign");1160 kw_assume = &IdentTable.get("assume");1161 kw_automatic = &IdentTable.get("automatic");1162 kw_before = &IdentTable.get("before");1163 kw_begin = &IdentTable.get("begin");1164 kw_begin_keywords = &IdentTable.get("begin_keywords");1165 kw_bins = &IdentTable.get("bins");1166 kw_binsof = &IdentTable.get("binsof");1167 kw_casex = &IdentTable.get("casex");1168 kw_casez = &IdentTable.get("casez");1169 kw_celldefine = &IdentTable.get("celldefine");1170 kw_checker = &IdentTable.get("checker");1171 kw_clocking = &IdentTable.get("clocking");1172 kw_constraint = &IdentTable.get("constraint");1173 kw_context = &IdentTable.get("context");1174 kw_cover = &IdentTable.get("cover");1175 kw_covergroup = &IdentTable.get("covergroup");1176 kw_coverpoint = &IdentTable.get("coverpoint");1177 kw_default_decay_time = &IdentTable.get("default_decay_time");1178 kw_default_nettype = &IdentTable.get("default_nettype");1179 kw_default_trireg_strength = &IdentTable.get("default_trireg_strength");1180 kw_delay_mode_distributed = &IdentTable.get("delay_mode_distributed");1181 kw_delay_mode_path = &IdentTable.get("delay_mode_path");1182 kw_delay_mode_unit = &IdentTable.get("delay_mode_unit");1183 kw_delay_mode_zero = &IdentTable.get("delay_mode_zero");1184 kw_disable = &IdentTable.get("disable");1185 kw_dist = &IdentTable.get("dist");1186 kw_edge = &IdentTable.get("edge");1187 kw_elsif = &IdentTable.get("elsif");1188 kw_end = &IdentTable.get("end");1189 kw_end_keywords = &IdentTable.get("end_keywords");1190 kw_endcase = &IdentTable.get("endcase");1191 kw_endcelldefine = &IdentTable.get("endcelldefine");1192 kw_endchecker = &IdentTable.get("endchecker");1193 kw_endclass = &IdentTable.get("endclass");1194 kw_endclocking = &IdentTable.get("endclocking");1195 kw_endfunction = &IdentTable.get("endfunction");1196 kw_endgenerate = &IdentTable.get("endgenerate");1197 kw_endgroup = &IdentTable.get("endgroup");1198 kw_endinterface = &IdentTable.get("endinterface");1199 kw_endmodule = &IdentTable.get("endmodule");1200 kw_endpackage = &IdentTable.get("endpackage");1201 kw_endprimitive = &IdentTable.get("endprimitive");1202 kw_endprogram = &IdentTable.get("endprogram");1203 kw_endproperty = &IdentTable.get("endproperty");1204 kw_endsequence = &IdentTable.get("endsequence");1205 kw_endspecify = &IdentTable.get("endspecify");1206 kw_endtable = &IdentTable.get("endtable");1207 kw_endtask = &IdentTable.get("endtask");1208 kw_forever = &IdentTable.get("forever");1209 kw_fork = &IdentTable.get("fork");1210 kw_generate = &IdentTable.get("generate");1211 kw_highz0 = &IdentTable.get("highz0");1212 kw_highz1 = &IdentTable.get("highz1");1213 kw_iff = &IdentTable.get("iff");1214 kw_ifnone = &IdentTable.get("ifnone");1215 kw_ignore_bins = &IdentTable.get("ignore_bins");1216 kw_illegal_bins = &IdentTable.get("illegal_bins");1217 kw_initial = &IdentTable.get("initial");1218 kw_inout = &IdentTable.get("inout");1219 kw_input = &IdentTable.get("input");1220 kw_inside = &IdentTable.get("inside");1221 kw_interconnect = &IdentTable.get("interconnect");1222 kw_intersect = &IdentTable.get("intersect");1223 kw_join = &IdentTable.get("join");1224 kw_join_any = &IdentTable.get("join_any");1225 kw_join_none = &IdentTable.get("join_none");1226 kw_large = &IdentTable.get("large");1227 kw_local = &IdentTable.get("local");1228 kw_localparam = &IdentTable.get("localparam");1229 kw_macromodule = &IdentTable.get("macromodule");1230 kw_matches = &IdentTable.get("matches");1231 kw_medium = &IdentTable.get("medium");1232 kw_negedge = &IdentTable.get("negedge");1233 kw_nounconnected_drive = &IdentTable.get("nounconnected_drive");1234 kw_output = &IdentTable.get("output");1235 kw_packed = &IdentTable.get("packed");1236 kw_parameter = &IdentTable.get("parameter");1237 kw_posedge = &IdentTable.get("posedge");1238 kw_primitive = &IdentTable.get("primitive");1239 kw_priority = &IdentTable.get("priority");1240 kw_program = &IdentTable.get("program");1241 kw_property = &IdentTable.get("property");1242 kw_pull0 = &IdentTable.get("pull0");1243 kw_pull1 = &IdentTable.get("pull1");1244 kw_pure = &IdentTable.get("pure");1245 kw_rand = &IdentTable.get("rand");1246 kw_randc = &IdentTable.get("randc");1247 kw_randcase = &IdentTable.get("randcase");1248 kw_randsequence = &IdentTable.get("randsequence");1249 kw_repeat = &IdentTable.get("repeat");1250 kw_resetall = &IdentTable.get("resetall");1251 kw_sample = &IdentTable.get("sample");1252 kw_scalared = &IdentTable.get("scalared");1253 kw_sequence = &IdentTable.get("sequence");1254 kw_small = &IdentTable.get("small");1255 kw_soft = &IdentTable.get("soft");1256 kw_solve = &IdentTable.get("solve");1257 kw_specify = &IdentTable.get("specify");1258 kw_specparam = &IdentTable.get("specparam");1259 kw_strong0 = &IdentTable.get("strong0");1260 kw_strong1 = &IdentTable.get("strong1");1261 kw_supply0 = &IdentTable.get("supply0");1262 kw_supply1 = &IdentTable.get("supply1");1263 kw_table = &IdentTable.get("table");1264 kw_tagged = &IdentTable.get("tagged");1265 kw_task = &IdentTable.get("task");1266 kw_timescale = &IdentTable.get("timescale");1267 kw_tri = &IdentTable.get("tri");1268 kw_tri0 = &IdentTable.get("tri0");1269 kw_tri1 = &IdentTable.get("tri1");1270 kw_triand = &IdentTable.get("triand");1271 kw_trior = &IdentTable.get("trior");1272 kw_trireg = &IdentTable.get("trireg");1273 kw_unconnected_drive = &IdentTable.get("unconnected_drive");1274 kw_undefineall = &IdentTable.get("undefineall");1275 kw_unique = &IdentTable.get("unique");1276 kw_unique0 = &IdentTable.get("unique0");1277 kw_uwire = &IdentTable.get("uwire");1278 kw_vectored = &IdentTable.get("vectored");1279 kw_wait = &IdentTable.get("wait");1280 kw_wand = &IdentTable.get("wand");1281 kw_weak0 = &IdentTable.get("weak0");1282 kw_weak1 = &IdentTable.get("weak1");1283 kw_wildcard = &IdentTable.get("wildcard");1284 kw_wire = &IdentTable.get("wire");1285 kw_with = &IdentTable.get("with");1286 kw_wor = &IdentTable.get("wor");1287 1288 // Symbols that are treated as keywords.1289 kw_verilogHash = &IdentTable.get("#");1290 kw_verilogHashHash = &IdentTable.get("##");1291 kw_apostrophe = &IdentTable.get("\'");1292 1293 // TableGen keywords.1294 kw_bit = &IdentTable.get("bit");1295 kw_bits = &IdentTable.get("bits");1296 kw_code = &IdentTable.get("code");1297 kw_dag = &IdentTable.get("dag");1298 kw_def = &IdentTable.get("def");1299 kw_defm = &IdentTable.get("defm");1300 kw_defset = &IdentTable.get("defset");1301 kw_defvar = &IdentTable.get("defvar");1302 kw_dump = &IdentTable.get("dump");1303 kw_include = &IdentTable.get("include");1304 kw_list = &IdentTable.get("list");1305 kw_multiclass = &IdentTable.get("multiclass");1306 kw_then = &IdentTable.get("then");1307 1308 // Keep this at the end of the constructor to make sure everything here is1309 // already initialized.1310 JsExtraKeywords = std::unordered_set<IdentifierInfo *>(1311 {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,1312 kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_override,1313 kw_readonly, kw_set, kw_type, kw_typeof, kw_var, kw_yield,1314 // Keywords from the Java section.1315 kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});1316 1317 CSharpExtraKeywords = JsExtraKeywords;1318 CSharpExtraKeywords.insert(1319 {kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate,1320 kw_event, kw_fixed, kw_foreach, kw_implicit, kw_in,1321 kw_init, kw_internal, kw_lock, kw_null, kw_object,1322 kw_out, kw_params, kw_ref, kw_string, kw_stackalloc,1323 kw_sbyte, kw_sealed, kw_uint, kw_ulong, kw_unchecked,1324 kw_unsafe, kw_ushort, kw_when, kw_where});1325 1326 // Some keywords are not included here because they don't need special1327 // treatment like `showcancelled` or they should be treated as identifiers1328 // like `int` and `logic`.1329 VerilogExtraKeywords =1330 std::unordered_set<IdentifierInfo *>({kw_always,1331 kw_always_comb,1332 kw_always_ff,1333 kw_always_latch,1334 kw_assert,1335 kw_assign,1336 kw_assume,1337 kw_automatic,1338 kw_before,1339 kw_begin,1340 kw_bins,1341 kw_binsof,1342 kw_casex,1343 kw_casez,1344 kw_celldefine,1345 kw_checker,1346 kw_clocking,1347 kw_constraint,1348 kw_context,1349 kw_cover,1350 kw_covergroup,1351 kw_coverpoint,1352 kw_disable,1353 kw_dist,1354 kw_edge,1355 kw_end,1356 kw_endcase,1357 kw_endchecker,1358 kw_endclass,1359 kw_endclocking,1360 kw_endfunction,1361 kw_endgenerate,1362 kw_endgroup,1363 kw_endinterface,1364 kw_endmodule,1365 kw_endpackage,1366 kw_endprimitive,1367 kw_endprogram,1368 kw_endproperty,1369 kw_endsequence,1370 kw_endspecify,1371 kw_endtable,1372 kw_endtask,1373 kw_extends,1374 kw_final,1375 kw_foreach,1376 kw_forever,1377 kw_fork,1378 kw_function,1379 kw_generate,1380 kw_highz0,1381 kw_highz1,1382 kw_iff,1383 kw_ifnone,1384 kw_ignore_bins,1385 kw_illegal_bins,1386 kw_implements,1387 kw_import,1388 kw_initial,1389 kw_inout,1390 kw_input,1391 kw_inside,1392 kw_interconnect,1393 kw_interface,1394 kw_intersect,1395 kw_join,1396 kw_join_any,1397 kw_join_none,1398 kw_large,1399 kw_let,1400 kw_local,1401 kw_localparam,1402 kw_macromodule,1403 kw_matches,1404 kw_medium,1405 kw_module,1406 kw_negedge,1407 kw_output,1408 kw_package,1409 kw_packed,1410 kw_parameter,1411 kw_posedge,1412 kw_primitive,1413 kw_priority,1414 kw_program,1415 kw_property,1416 kw_pull0,1417 kw_pull1,1418 kw_pure,1419 kw_rand,1420 kw_randc,1421 kw_randcase,1422 kw_randsequence,1423 kw_ref,1424 kw_repeat,1425 kw_sample,1426 kw_scalared,1427 kw_sequence,1428 kw_small,1429 kw_soft,1430 kw_solve,1431 kw_specify,1432 kw_specparam,1433 kw_strong0,1434 kw_strong1,1435 kw_supply0,1436 kw_supply1,1437 kw_table,1438 kw_tagged,1439 kw_task,1440 kw_tri,1441 kw_tri0,1442 kw_tri1,1443 kw_triand,1444 kw_trior,1445 kw_trireg,1446 kw_unique,1447 kw_unique0,1448 kw_uwire,1449 kw_var,1450 kw_vectored,1451 kw_wait,1452 kw_wand,1453 kw_weak0,1454 kw_weak1,1455 kw_wildcard,1456 kw_wire,1457 kw_with,1458 kw_wor,1459 kw_verilogHash,1460 kw_verilogHashHash});1461 1462 TableGenExtraKeywords = std::unordered_set<IdentifierInfo *>({1463 kw_assert,1464 kw_bit,1465 kw_bits,1466 kw_code,1467 kw_dag,1468 kw_def,1469 kw_defm,1470 kw_defset,1471 kw_defvar,1472 kw_dump,1473 kw_foreach,1474 kw_in,1475 kw_include,1476 kw_let,1477 kw_list,1478 kw_multiclass,1479 kw_string,1480 kw_then,1481 });1482 }1483 1484 // Context sensitive keywords.1485 IdentifierInfo *kw_final;1486 IdentifierInfo *kw_override;1487 IdentifierInfo *kw_in;1488 IdentifierInfo *kw_of;1489 IdentifierInfo *kw_CF_CLOSED_ENUM;1490 IdentifierInfo *kw_CF_ENUM;1491 IdentifierInfo *kw_CF_OPTIONS;1492 IdentifierInfo *kw_NS_CLOSED_ENUM;1493 IdentifierInfo *kw_NS_ENUM;1494 IdentifierInfo *kw_NS_ERROR_ENUM;1495 IdentifierInfo *kw_NS_OPTIONS;1496 IdentifierInfo *kw___except;1497 IdentifierInfo *kw___has_include;1498 IdentifierInfo *kw___has_include_next;1499 1500 // JavaScript keywords.1501 IdentifierInfo *kw_as;1502 IdentifierInfo *kw_async;1503 IdentifierInfo *kw_await;1504 IdentifierInfo *kw_declare;1505 IdentifierInfo *kw_finally;1506 IdentifierInfo *kw_from;1507 IdentifierInfo *kw_function;1508 IdentifierInfo *kw_get;1509 IdentifierInfo *kw_import;1510 IdentifierInfo *kw_infer;1511 IdentifierInfo *kw_is;1512 IdentifierInfo *kw_let;1513 IdentifierInfo *kw_module;1514 IdentifierInfo *kw_readonly;1515 IdentifierInfo *kw_set;1516 IdentifierInfo *kw_type;1517 IdentifierInfo *kw_typeof;1518 IdentifierInfo *kw_var;1519 IdentifierInfo *kw_yield;1520 1521 // Java keywords.1522 IdentifierInfo *kw_abstract;1523 IdentifierInfo *kw_assert;1524 IdentifierInfo *kw_extends;1525 IdentifierInfo *kw_implements;1526 IdentifierInfo *kw_instanceof;1527 IdentifierInfo *kw_interface;1528 IdentifierInfo *kw_native;1529 IdentifierInfo *kw_package;1530 IdentifierInfo *kw_record;1531 IdentifierInfo *kw_synchronized;1532 IdentifierInfo *kw_throws;1533 1534 // Pragma keywords.1535 IdentifierInfo *kw_mark;1536 IdentifierInfo *kw_region;1537 1538 // Proto keywords.1539 IdentifierInfo *kw_extend;1540 IdentifierInfo *kw_option;1541 IdentifierInfo *kw_optional;1542 IdentifierInfo *kw_repeated;1543 IdentifierInfo *kw_required;1544 IdentifierInfo *kw_returns;1545 1546 // QT keywords.1547 IdentifierInfo *kw_signals;1548 IdentifierInfo *kw_qsignals;1549 IdentifierInfo *kw_slots;1550 IdentifierInfo *kw_qslots;1551 1552 // For internal use by clang-format.1553 IdentifierInfo *kw_internal_ident_after_define;1554 1555 // C# keywords1556 IdentifierInfo *kw_dollar;1557 IdentifierInfo *kw_base;1558 IdentifierInfo *kw_byte;1559 IdentifierInfo *kw_checked;1560 IdentifierInfo *kw_decimal;1561 IdentifierInfo *kw_delegate;1562 IdentifierInfo *kw_event;1563 IdentifierInfo *kw_fixed;1564 IdentifierInfo *kw_foreach;1565 IdentifierInfo *kw_implicit;1566 IdentifierInfo *kw_init;1567 IdentifierInfo *kw_internal;1568 1569 IdentifierInfo *kw_lock;1570 IdentifierInfo *kw_null;1571 IdentifierInfo *kw_object;1572 IdentifierInfo *kw_out;1573 1574 IdentifierInfo *kw_params;1575 1576 IdentifierInfo *kw_ref;1577 IdentifierInfo *kw_string;1578 IdentifierInfo *kw_stackalloc;1579 IdentifierInfo *kw_sbyte;1580 IdentifierInfo *kw_sealed;1581 IdentifierInfo *kw_uint;1582 IdentifierInfo *kw_ulong;1583 IdentifierInfo *kw_unchecked;1584 IdentifierInfo *kw_unsafe;1585 IdentifierInfo *kw_ushort;1586 IdentifierInfo *kw_when;1587 IdentifierInfo *kw_where;1588 1589 // Verilog keywords1590 IdentifierInfo *kw_always;1591 IdentifierInfo *kw_always_comb;1592 IdentifierInfo *kw_always_ff;1593 IdentifierInfo *kw_always_latch;1594 IdentifierInfo *kw_assign;1595 IdentifierInfo *kw_assume;1596 IdentifierInfo *kw_automatic;1597 IdentifierInfo *kw_before;1598 IdentifierInfo *kw_begin;1599 IdentifierInfo *kw_begin_keywords;1600 IdentifierInfo *kw_bins;1601 IdentifierInfo *kw_binsof;1602 IdentifierInfo *kw_casex;1603 IdentifierInfo *kw_casez;1604 IdentifierInfo *kw_celldefine;1605 IdentifierInfo *kw_checker;1606 IdentifierInfo *kw_clocking;1607 IdentifierInfo *kw_constraint;1608 IdentifierInfo *kw_context;1609 IdentifierInfo *kw_cover;1610 IdentifierInfo *kw_covergroup;1611 IdentifierInfo *kw_coverpoint;1612 IdentifierInfo *kw_default_decay_time;1613 IdentifierInfo *kw_default_nettype;1614 IdentifierInfo *kw_default_trireg_strength;1615 IdentifierInfo *kw_delay_mode_distributed;1616 IdentifierInfo *kw_delay_mode_path;1617 IdentifierInfo *kw_delay_mode_unit;1618 IdentifierInfo *kw_delay_mode_zero;1619 IdentifierInfo *kw_disable;1620 IdentifierInfo *kw_dist;1621 IdentifierInfo *kw_elsif;1622 IdentifierInfo *kw_edge;1623 IdentifierInfo *kw_end;1624 IdentifierInfo *kw_end_keywords;1625 IdentifierInfo *kw_endcase;1626 IdentifierInfo *kw_endcelldefine;1627 IdentifierInfo *kw_endchecker;1628 IdentifierInfo *kw_endclass;1629 IdentifierInfo *kw_endclocking;1630 IdentifierInfo *kw_endfunction;1631 IdentifierInfo *kw_endgenerate;1632 IdentifierInfo *kw_endgroup;1633 IdentifierInfo *kw_endinterface;1634 IdentifierInfo *kw_endmodule;1635 IdentifierInfo *kw_endpackage;1636 IdentifierInfo *kw_endprimitive;1637 IdentifierInfo *kw_endprogram;1638 IdentifierInfo *kw_endproperty;1639 IdentifierInfo *kw_endsequence;1640 IdentifierInfo *kw_endspecify;1641 IdentifierInfo *kw_endtable;1642 IdentifierInfo *kw_endtask;1643 IdentifierInfo *kw_forever;1644 IdentifierInfo *kw_fork;1645 IdentifierInfo *kw_generate;1646 IdentifierInfo *kw_highz0;1647 IdentifierInfo *kw_highz1;1648 IdentifierInfo *kw_iff;1649 IdentifierInfo *kw_ifnone;1650 IdentifierInfo *kw_ignore_bins;1651 IdentifierInfo *kw_illegal_bins;1652 IdentifierInfo *kw_initial;1653 IdentifierInfo *kw_inout;1654 IdentifierInfo *kw_input;1655 IdentifierInfo *kw_inside;1656 IdentifierInfo *kw_interconnect;1657 IdentifierInfo *kw_intersect;1658 IdentifierInfo *kw_join;1659 IdentifierInfo *kw_join_any;1660 IdentifierInfo *kw_join_none;1661 IdentifierInfo *kw_large;1662 IdentifierInfo *kw_local;1663 IdentifierInfo *kw_localparam;1664 IdentifierInfo *kw_macromodule;1665 IdentifierInfo *kw_matches;1666 IdentifierInfo *kw_medium;1667 IdentifierInfo *kw_negedge;1668 IdentifierInfo *kw_nounconnected_drive;1669 IdentifierInfo *kw_output;1670 IdentifierInfo *kw_packed;1671 IdentifierInfo *kw_parameter;1672 IdentifierInfo *kw_posedge;1673 IdentifierInfo *kw_primitive;1674 IdentifierInfo *kw_priority;1675 IdentifierInfo *kw_program;1676 IdentifierInfo *kw_property;1677 IdentifierInfo *kw_pull0;1678 IdentifierInfo *kw_pull1;1679 IdentifierInfo *kw_pure;1680 IdentifierInfo *kw_rand;1681 IdentifierInfo *kw_randc;1682 IdentifierInfo *kw_randcase;1683 IdentifierInfo *kw_randsequence;1684 IdentifierInfo *kw_repeat;1685 IdentifierInfo *kw_resetall;1686 IdentifierInfo *kw_sample;1687 IdentifierInfo *kw_scalared;1688 IdentifierInfo *kw_sequence;1689 IdentifierInfo *kw_small;1690 IdentifierInfo *kw_soft;1691 IdentifierInfo *kw_solve;1692 IdentifierInfo *kw_specify;1693 IdentifierInfo *kw_specparam;1694 IdentifierInfo *kw_strong0;1695 IdentifierInfo *kw_strong1;1696 IdentifierInfo *kw_supply0;1697 IdentifierInfo *kw_supply1;1698 IdentifierInfo *kw_table;1699 IdentifierInfo *kw_tagged;1700 IdentifierInfo *kw_task;1701 IdentifierInfo *kw_timescale;1702 IdentifierInfo *kw_tri0;1703 IdentifierInfo *kw_tri1;1704 IdentifierInfo *kw_tri;1705 IdentifierInfo *kw_triand;1706 IdentifierInfo *kw_trior;1707 IdentifierInfo *kw_trireg;1708 IdentifierInfo *kw_unconnected_drive;1709 IdentifierInfo *kw_undefineall;1710 IdentifierInfo *kw_unique;1711 IdentifierInfo *kw_unique0;1712 IdentifierInfo *kw_uwire;1713 IdentifierInfo *kw_vectored;1714 IdentifierInfo *kw_wait;1715 IdentifierInfo *kw_wand;1716 IdentifierInfo *kw_weak0;1717 IdentifierInfo *kw_weak1;1718 IdentifierInfo *kw_wildcard;1719 IdentifierInfo *kw_wire;1720 IdentifierInfo *kw_with;1721 IdentifierInfo *kw_wor;1722 1723 // Workaround for hashes and backticks in Verilog.1724 IdentifierInfo *kw_verilogHash;1725 IdentifierInfo *kw_verilogHashHash;1726 1727 // Symbols in Verilog that don't exist in C++.1728 IdentifierInfo *kw_apostrophe;1729 1730 // TableGen keywords1731 IdentifierInfo *kw_bit;1732 IdentifierInfo *kw_bits;1733 IdentifierInfo *kw_code;1734 IdentifierInfo *kw_dag;1735 IdentifierInfo *kw_def;1736 IdentifierInfo *kw_defm;1737 IdentifierInfo *kw_defset;1738 IdentifierInfo *kw_defvar;1739 IdentifierInfo *kw_dump;1740 IdentifierInfo *kw_include;1741 IdentifierInfo *kw_list;1742 IdentifierInfo *kw_multiclass;1743 IdentifierInfo *kw_then;1744 1745 /// Returns \c true if \p Tok is a keyword or an identifier.1746 bool isWordLike(const FormatToken &Tok, bool IsVerilog = true) const {1747 // getIdentifierinfo returns non-null for keywords as well as identifiers.1748 return Tok.Tok.getIdentifierInfo() &&1749 (!IsVerilog || !isVerilogKeywordSymbol(Tok));1750 }1751 1752 /// Returns \c true if \p Tok is a true JavaScript identifier, returns1753 /// \c false if it is a keyword or a pseudo keyword.1754 /// If \c AcceptIdentifierName is true, returns true not only for keywords,1755 // but also for IdentifierName tokens (aka pseudo-keywords), such as1756 // ``yield``.1757 bool isJavaScriptIdentifier(const FormatToken &Tok,1758 bool AcceptIdentifierName = true) const {1759 // Based on the list of JavaScript & TypeScript keywords here:1760 // https://github.com/microsoft/TypeScript/blob/main/src/compiler/scanner.ts#L741761 if (Tok.isAccessSpecifierKeyword())1762 return false;1763 switch (Tok.Tok.getKind()) {1764 case tok::kw_break:1765 case tok::kw_case:1766 case tok::kw_catch:1767 case tok::kw_class:1768 case tok::kw_continue:1769 case tok::kw_const:1770 case tok::kw_default:1771 case tok::kw_delete:1772 case tok::kw_do:1773 case tok::kw_else:1774 case tok::kw_enum:1775 case tok::kw_export:1776 case tok::kw_false:1777 case tok::kw_for:1778 case tok::kw_if:1779 case tok::kw_import:1780 case tok::kw_module:1781 case tok::kw_new:1782 case tok::kw_return:1783 case tok::kw_static:1784 case tok::kw_switch:1785 case tok::kw_this:1786 case tok::kw_throw:1787 case tok::kw_true:1788 case tok::kw_try:1789 case tok::kw_typeof:1790 case tok::kw_void:1791 case tok::kw_while:1792 // These are JS keywords that are lexed by LLVM/clang as keywords.1793 return false;1794 case tok::identifier: {1795 // For identifiers, make sure they are true identifiers, excluding the1796 // JavaScript pseudo-keywords (not lexed by LLVM/clang as keywords).1797 bool IsPseudoKeyword =1798 JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=1799 JsExtraKeywords.end();1800 return AcceptIdentifierName || !IsPseudoKeyword;1801 }1802 default:1803 // Other keywords are handled in the switch below, to avoid problems due1804 // to duplicate case labels when using the #include trick.1805 break;1806 }1807 1808 switch (Tok.Tok.getKind()) {1809 // Handle C++ keywords not included above: these are all JS identifiers.1810#define KEYWORD(X, Y) case tok::kw_##X:1811#include "clang/Basic/TokenKinds.def"1812 // #undef KEYWORD is not needed -- it's #undef-ed at the end of1813 // TokenKinds.def1814 return true;1815 default:1816 // All other tokens (punctuation etc) are not JS identifiers.1817 return false;1818 }1819 }1820 1821 /// Returns \c true if \p Tok is a C# keyword, returns \c false if it is1822 /// anything else.1823 bool isCSharpKeyword(const FormatToken &Tok) const {1824 if (Tok.isAccessSpecifierKeyword())1825 return true;1826 switch (Tok.Tok.getKind()) {1827 case tok::kw_bool:1828 case tok::kw_break:1829 case tok::kw_case:1830 case tok::kw_catch:1831 case tok::kw_char:1832 case tok::kw_class:1833 case tok::kw_const:1834 case tok::kw_continue:1835 case tok::kw_default:1836 case tok::kw_do:1837 case tok::kw_double:1838 case tok::kw_else:1839 case tok::kw_enum:1840 case tok::kw_explicit:1841 case tok::kw_extern:1842 case tok::kw_false:1843 case tok::kw_float:1844 case tok::kw_for:1845 case tok::kw_goto:1846 case tok::kw_if:1847 case tok::kw_int:1848 case tok::kw_long:1849 case tok::kw_namespace:1850 case tok::kw_new:1851 case tok::kw_operator:1852 case tok::kw_return:1853 case tok::kw_short:1854 case tok::kw_sizeof:1855 case tok::kw_static:1856 case tok::kw_struct:1857 case tok::kw_switch:1858 case tok::kw_this:1859 case tok::kw_throw:1860 case tok::kw_true:1861 case tok::kw_try:1862 case tok::kw_typeof:1863 case tok::kw_using:1864 case tok::kw_virtual:1865 case tok::kw_void:1866 case tok::kw_volatile:1867 case tok::kw_while:1868 return true;1869 default:1870 return Tok.is(tok::identifier) &&1871 CSharpExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==1872 CSharpExtraKeywords.end();1873 }1874 }1875 1876 bool isVerilogKeywordSymbol(const FormatToken &Tok) const {1877 return Tok.isOneOf(kw_verilogHash, kw_verilogHashHash, kw_apostrophe);1878 }1879 1880 bool isVerilogWordOperator(const FormatToken &Tok) const {1881 return Tok.isOneOf(kw_before, kw_intersect, kw_dist, kw_iff, kw_inside,1882 kw_with);1883 }1884 1885 bool isVerilogIdentifier(const FormatToken &Tok) const {1886 switch (Tok.Tok.getKind()) {1887 case tok::kw_case:1888 case tok::kw_class:1889 case tok::kw_const:1890 case tok::kw_continue:1891 case tok::kw_default:1892 case tok::kw_do:1893 case tok::kw_else:1894 case tok::kw_enum:1895 case tok::kw_export:1896 case tok::kw_extern:1897 case tok::kw_for:1898 case tok::kw_if:1899 case tok::kw_import:1900 case tok::kw_restrict:1901 case tok::kw_signed:1902 case tok::kw_static:1903 case tok::kw_struct:1904 case tok::kw_typedef:1905 case tok::kw_union:1906 case tok::kw_unsigned:1907 case tok::kw_virtual:1908 case tok::kw_while:1909 return false;1910 case tok::identifier:1911 return isWordLike(Tok) &&1912 VerilogExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==1913 VerilogExtraKeywords.end();1914 default:1915 // getIdentifierInfo returns non-null for both identifiers and keywords.1916 return Tok.Tok.getIdentifierInfo();1917 }1918 }1919 1920 /// Returns whether \p Tok is a Verilog preprocessor directive. This is1921 /// needed because macro expansions start with a backtick as well and they1922 /// need to be treated differently.1923 bool isVerilogPPDirective(const FormatToken &Tok) const {1924 auto Info = Tok.Tok.getIdentifierInfo();1925 if (!Info)1926 return false;1927 switch (Info->getPPKeywordID()) {1928 case tok::pp_define:1929 case tok::pp_else:1930 case tok::pp_endif:1931 case tok::pp_ifdef:1932 case tok::pp_ifndef:1933 case tok::pp_include:1934 case tok::pp_line:1935 case tok::pp_pragma:1936 case tok::pp_undef:1937 return true;1938 default:1939 return Tok.isOneOf(kw_begin_keywords, kw_celldefine,1940 kw_default_decay_time, kw_default_nettype,1941 kw_default_trireg_strength, kw_delay_mode_distributed,1942 kw_delay_mode_path, kw_delay_mode_unit,1943 kw_delay_mode_zero, kw_elsif, kw_end_keywords,1944 kw_endcelldefine, kw_nounconnected_drive, kw_resetall,1945 kw_timescale, kw_unconnected_drive, kw_undefineall);1946 }1947 }1948 1949 /// Returns whether \p Tok is a Verilog keyword that opens a block.1950 bool isVerilogBegin(const FormatToken &Tok) const {1951 // `table` is not included since it needs to be treated specially.1952 if (Tok.isOneOf(kw_begin, kw_generate, kw_specify))1953 return true;1954 if (Tok.isNot(kw_fork))1955 return false;1956 const auto *Prev = Tok.getPreviousNonComment();1957 return !(Prev && Prev->isOneOf(kw_disable, kw_wait));1958 }1959 1960 /// Returns whether \p Tok is a Verilog keyword that closes a block.1961 bool isVerilogEnd(const FormatToken &Tok) const {1962 return !Tok.endsSequence(kw_join, kw_rand) &&1963 Tok.isOneOf(TT_MacroBlockEnd, kw_end, kw_endcase, kw_endclass,1964 kw_endclocking, kw_endchecker, kw_endfunction,1965 kw_endgenerate, kw_endgroup, kw_endinterface,1966 kw_endmodule, kw_endpackage, kw_endprimitive,1967 kw_endprogram, kw_endproperty, kw_endsequence,1968 kw_endspecify, kw_endtable, kw_endtask, kw_join,1969 kw_join_any, kw_join_none);1970 }1971 1972 /// Returns whether \p Tok is a Verilog keyword that opens a module, etc.1973 bool isVerilogHierarchy(const FormatToken &Tok) const {1974 if (Tok.endsSequence(kw_function, kw_with))1975 return false;1976 if (Tok.is(kw_property)) {1977 const FormatToken *Prev = Tok.getPreviousNonComment();1978 return !(Prev &&1979 Prev->isOneOf(tok::kw_restrict, kw_assert, kw_assume, kw_cover));1980 }1981 return Tok.isOneOf(tok::kw_case, tok::kw_class, kw_function, kw_module,1982 kw_interface, kw_package, kw_casex, kw_casez, kw_checker,1983 kw_clocking, kw_covergroup, kw_macromodule, kw_primitive,1984 kw_program, kw_property, kw_randcase, kw_randsequence,1985 kw_task);1986 }1987 1988 bool isVerilogEndOfLabel(const FormatToken &Tok) const {1989 const FormatToken *Next = Tok.getNextNonComment();1990 // In Verilog the colon in a default label is optional.1991 return Tok.is(TT_CaseLabelColon) ||1992 (Tok.is(tok::kw_default) &&1993 !(Next && Next->isOneOf(tok::colon, tok::semi, kw_clocking, kw_iff,1994 kw_input, kw_output, kw_sequence)));1995 }1996 1997 /// Returns whether \p Tok is a Verilog keyword that starts a1998 /// structured procedure like 'always'.1999 bool isVerilogStructuredProcedure(const FormatToken &Tok) const {2000 return Tok.isOneOf(kw_always, kw_always_comb, kw_always_ff, kw_always_latch,2001 kw_final, kw_forever, kw_initial);2002 }2003 2004 bool isVerilogQualifier(const FormatToken &Tok) const {2005 switch (Tok.Tok.getKind()) {2006 case tok::kw_extern:2007 case tok::kw_signed:2008 case tok::kw_static:2009 case tok::kw_unsigned:2010 case tok::kw_virtual:2011 return true;2012 case tok::identifier:2013 return Tok.isOneOf(2014 kw_let, kw_var, kw_ref, kw_automatic, kw_bins, kw_coverpoint,2015 kw_ignore_bins, kw_illegal_bins, kw_inout, kw_input, kw_interconnect,2016 kw_local, kw_localparam, kw_output, kw_parameter, kw_pure, kw_rand,2017 kw_randc, kw_scalared, kw_specparam, kw_tri, kw_tri0, kw_tri1,2018 kw_triand, kw_trior, kw_trireg, kw_uwire, kw_vectored, kw_wand,2019 kw_wildcard, kw_wire, kw_wor);2020 default:2021 return false;2022 }2023 }2024 2025 bool isTableGenDefinition(const FormatToken &Tok) const {2026 return Tok.isOneOf(kw_def, kw_defm, kw_defset, kw_defvar, kw_multiclass,2027 kw_let, tok::kw_class);2028 }2029 2030 bool isTableGenKeyword(const FormatToken &Tok) const {2031 switch (Tok.Tok.getKind()) {2032 case tok::kw_class:2033 case tok::kw_else:2034 case tok::kw_false:2035 case tok::kw_if:2036 case tok::kw_int:2037 case tok::kw_true:2038 return true;2039 default:2040 return Tok.is(tok::identifier) &&2041 TableGenExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=2042 TableGenExtraKeywords.end();2043 }2044 }2045 2046private:2047 /// The JavaScript keywords beyond the C++ keyword set.2048 std::unordered_set<IdentifierInfo *> JsExtraKeywords;2049 2050 /// The C# keywords beyond the C++ keyword set.2051 std::unordered_set<IdentifierInfo *> CSharpExtraKeywords;2052 2053 /// The Verilog keywords beyond the C++ keyword set.2054 std::unordered_set<IdentifierInfo *> VerilogExtraKeywords;2055 2056 /// The TableGen keywords beyond the C++ keyword set.2057 std::unordered_set<IdentifierInfo *> TableGenExtraKeywords;2058};2059 2060inline bool isLineComment(const FormatToken &FormatTok) {2061 return FormatTok.is(tok::comment) && !FormatTok.TokenText.starts_with("/*");2062}2063 2064// Checks if \p FormatTok is a line comment that continues the line comment2065// \p Previous. The original column of \p MinColumnToken is used to determine2066// whether \p FormatTok is indented enough to the right to continue \p Previous.2067inline bool continuesLineComment(const FormatToken &FormatTok,2068 const FormatToken *Previous,2069 const FormatToken *MinColumnToken) {2070 if (!Previous || !MinColumnToken)2071 return false;2072 unsigned MinContinueColumn =2073 MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);2074 return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&2075 isLineComment(*Previous) &&2076 FormatTok.OriginalColumn >= MinContinueColumn;2077}2078 2079// Returns \c true if \c Current starts a new parameter.2080bool startsNextParameter(const FormatToken &Current, const FormatStyle &Style);2081 2082} // namespace format2083} // namespace clang2084 2085#endif2086