//===--- CodeCompletionResult.h -------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2022 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_IDE_CODECOMPLETION_RESULT_H #define SWIFT_IDE_CODECOMPLETION_RESULT_H #include "swift/Basic/StringExtras.h" #include "swift/IDE/CodeCompletionResultType.h" #include "swift/IDE/CodeCompletionString.h" #include "swift/IDE/CommentConversion.h" namespace swift { namespace ide { struct CodeCompletionResultSink; /// Describes the origin of the code completion result. /// /// This enum is ordered from the contexts that are "nearest" to the code /// completion point to "outside" contexts. enum class SemanticContextKind : uint8_t { /// Used in cases when the concept of semantic context is not applicable. None, /// A declaration from the same function. Local, /// A declaration found in the immediately enclosing nominal decl. CurrentNominal, /// A declaration found in the superclass of the immediately enclosing /// nominal decl. Super, /// A declaration found in the non-immediately enclosing nominal decl. /// /// For example, 'Foo' is visible at (1) because of this. /// \code /// struct A { /// typealias Foo = Int /// struct B { /// func foo() { /// // (1) /// } /// } /// } /// \endcode OutsideNominal, /// A declaration from the current module. CurrentModule, /// A declaration imported from other module. OtherModule, MAX_VALUE = OtherModule }; enum class CodeCompletionFlairBit : uint8_t { /// **Deprecated**. Old style catch-all prioritization. ExpressionSpecific = 1 << 0, /// E.g. override func foo() { super.foo() ... SuperChain = 1 << 1, /// Argument label and type. i.e. 'label: <#Ty#>'. ArgumentLabels = 1 << 2, /// E.g. decl introducer or modifiers ('enum', 'protocol', 'public', etc.) at /// top-level. CommonKeywordAtCurrentPosition = 1 << 3, /// E.g. type decl introducer ('enum', 'class', etc.) in a function body. RareKeywordAtCurrentPosition = 1 << 4, /// E.g. protocol names at an expression position. RareTypeAtCurrentPosition = 1 << 5, /// E.g. referencing a type, function, etc… at top level position in a non /// script/main.swift file ExpressionAtNonScriptOrMainFileScope = 1 << 6, }; using CodeCompletionFlair = OptionSet; /// The declaration kind of a code completion result, if it is a declaration. enum class CodeCompletionDeclKind : uint8_t { Module, Class, Actor, Struct, Enum, EnumElement, Protocol, AssociatedType, TypeAlias, GenericTypeParam, Constructor, Destructor, Subscript, StaticMethod, InstanceMethod, PrefixOperatorFunction, PostfixOperatorFunction, InfixOperatorFunction, FreeFunction, StaticVar, InstanceVar, LocalVar, GlobalVar, PrecedenceGroup, Macro, }; enum class CodeCompletionLiteralKind : uint8_t { ArrayLiteral, BooleanLiteral, ColorLiteral, DictionaryLiteral, IntegerLiteral, ImageLiteral, NilLiteral, StringLiteral, Tuple, }; enum class CodeCompletionOperatorKind : uint8_t { None, Unknown, Bang, // ! NotEq, // != NotEqEq, // !== Modulo, // % ModuloEq, // %= Amp, // & AmpAmp, // && AmpStar, // &* AmpPlus, // &+ AmpMinus, // &- AmpEq, // &= LParen, // ( -- not really an operator, but treated as one in some cases. Star, // * StarEq, // *= Plus, // + PlusEq, // += Minus, // - MinusEq, // -= Dot, // . DotDotDot, // ... DotDotLess, // ..< Slash, // / SlashEq, // /= Less, // < LessLess, // << LessLessEq, // <<= LessEq, // <= Eq, // = EqEq, // == EqEqEq, // === Greater, // > GreaterEq, // >= GreaterGreater, // >> GreaterGreaterEq, // >>= QuestionDot, // ?. Caret, // ^ CaretEq, // ^= Pipe, // | PipeEq, // |= PipePipe, // || TildeEq, // ~= MAX_VALUE = TildeEq }; enum class CodeCompletionKeywordKind : uint8_t { None, #define KEYWORD(X) kw_##X, #define POUND_KEYWORD(X) pound_##X, #include "swift/AST/TokenKinds.def" }; enum class CompletionKind : uint8_t { None, Import, Using, UnresolvedMember, DotExpr, StmtOrExpr, PostfixExprBeginning, PostfixExpr, KeyPathExprObjC, KeyPathExprSwift, TypePossibleFunctionParamBeginning, TypeDeclResultBeginning, TypeBeginning, TypeSimpleOrComposition, TypeSimpleBeginning, TypeSimpleWithDot, TypeSimpleWithoutDot, TypeSimpleInverted, CaseStmtKeyword, CaseStmtBeginning, NominalMemberBeginning, AccessorBeginning, AttributeBegin, AttributeDeclParen, EffectsSpecifier, PoundAvailablePlatform, CallArg, ReturnStmtExpr, ThenStmtExpr, YieldStmtExpr, ForEachSequence, /// The \c in keyword in a for-each loop. ForEachInKw, AfterPoundExpr, AfterPoundDirective, PlatformConditon, AfterIfStmtElse, GenericRequirement, PrecedenceGroup, StmtLabel, ForEachPatternBeginning, TypeAttrBeginning, TypeAttrInheritanceBeginning, OptionalBinding, }; enum class CodeCompletionDiagnosticSeverity : uint8_t { None, Error, Warning, Remark, Note, MAX_VALUE = Note }; /// Reasons why a code completion item might not be recommended in a certain /// context. /// This enum is split into two subsets: \c ContextFreeNotRecommendedReason and /// \c ContextualNotRecommendedReason. When adding a case to this enum also add /// it to either of those. /// Context-free diagnostics are independent of the context they are used in. /// The not-recommended reason can thus be cached as part of a context free /// code completion result. /// Contextual not recommended reasons depend on the context they are used in. /// E.g. \c InvalidAsyncContext depends on whether the usage context is async or /// not. enum class NotRecommendedReason : uint8_t { None = 0, // both contextual and context-free RedundantImport, // contextual RedundantImportIndirect, // contextual Deprecated, // context-free SoftDeprecated, // context-free VariableUsedInOwnDefinition, // contextual NonAsyncAlternativeUsedInAsyncContext, // contextual MAX_VALUE = NonAsyncAlternativeUsedInAsyncContext }; /// TODO: We consider deprecation warnings as context free although they don't /// produce deprecation warnings insdide context that have the same or a /// stronger deprecation attribute. /// E.g. /// In SDK: /// \code /// @available(iOS, deprecated: 12.0) /// func deprecatedFunc() /// \endcode /// /// User code: /// \code /// @available(iOS, deprecated: 12.0) /// func insiderUserDeprecatedContext() { /// #^COMPLETE^# /// } /// \endcode /// suggests \c deprecatedFunc as deprecated although it doesn't produce a /// diagnostic during compilation. But this allows us to show deprecation /// warnings for cached results. enum class ContextFreeNotRecommendedReason : uint8_t { None = 0, Deprecated, SoftDeprecated, MAX_VALUE = SoftDeprecated }; enum class ContextualNotRecommendedReason : uint8_t { None = 0, RedundantImport, RedundantImportIndirect, VariableUsedInOwnDefinition, /// A method that is sync and has an async alternative is used in an async /// context. NonAsyncAlternativeUsedInAsyncContext, MAX_VALUE = NonAsyncAlternativeUsedInAsyncContext }; enum class CodeCompletionResultKind : uint8_t { Declaration, Keyword, Pattern, Literal, BuiltinOperator, MAX_VALUE = BuiltinOperator }; enum class CodeCompletionMacroRole : uint8_t { Expression = 1 << 0, Declaration = 1 << 1, CodeItem = 1 << 2, AttachedVar = 1 << 3, AttachedContext = 1 << 4, AttachedDecl = 1 << 5, AttachedFunction = 1 << 6, }; using CodeCompletionMacroRoles = OptionSet; enum class CodeCompletionFilterFlag : uint16_t { Expr = 1 << 0, Type = 1 << 1, PrecedenceGroup = 1 << 2, Module = 1 << 3, ExpressionMacro = 1 << 4, DeclarationMacro = 1 << 5, CodeItemMacro = 1 << 6, AttachedVarMacro = 1 << 7, AttachedContextMacro = 1 << 8, AttachedDeclMacro = 1 << 9, AttachedFunctionMacro = 1 << 10, }; using CodeCompletionFilter = OptionSet; CodeCompletionMacroRoles getCompletionMacroRoles(const Decl *D); CodeCompletionMacroRoles getCompletionMacroRoles(OptionSet kinds); CodeCompletionMacroRoles getCompletionMacroRoles(CodeCompletionFilter filter); CodeCompletionFilter getCompletionFilter(CodeCompletionMacroRoles roles); /// The parts of a \c CodeCompletionResult that are not dependent on the context /// it appears in and can thus be cached. class ContextFreeCodeCompletionResult { CodeCompletionResultKind Kind : 3; static_assert(int(CodeCompletionResultKind::MAX_VALUE) < 1 << 3, ""); union { CodeCompletionDeclKind Decl; CodeCompletionLiteralKind Literal; CodeCompletionKeywordKind Keyword; uint8_t Opaque; } AssociatedKind; static_assert(sizeof(AssociatedKind) == sizeof(AssociatedKind.Opaque), "Opaque should cover all bits"); CodeCompletionOperatorKind KnownOperatorKind : 6; static_assert(int(CodeCompletionOperatorKind::MAX_VALUE) < 1 << 6, ""); CodeCompletionMacroRoles MacroRoles; bool IsSystem : 1; /// Whether the result has been annotated as having an async alternative that /// should be preferred in async contexts. bool HasAsyncAlternative : 1; CodeCompletionString *CompletionString; NullTerminatedStringRef ModuleName; NullTerminatedStringRef BriefDocComment; ArrayRef AssociatedUSRs; /// The Swift USR for a declaration (including for Clang declarations) used /// for looking up the \c Decl instance for cached results. NullTerminatedStringRef SwiftUSR; CodeCompletionResultType ResultType; ContextFreeNotRecommendedReason NotRecommended : 3; static_assert(int(ContextFreeNotRecommendedReason::MAX_VALUE) < 1 << 3, ""); CodeCompletionDiagnosticSeverity DiagnosticSeverity : 3; static_assert(int(CodeCompletionDiagnosticSeverity::MAX_VALUE) < 1 << 3, ""); NullTerminatedStringRef DiagnosticMessage; NullTerminatedStringRef FilterName; /// If the result represents a \c ValueDecl the name by which this decl should /// be referred to in diagnostics. NullTerminatedStringRef NameForDiagnostics; public: /// Memberwise initializer. \p AssociatedKind is opaque and will be /// interpreted based on \p Kind. If \p KnownOperatorKind is \c None and the /// completion item is an operator, it will be determined based on the /// completion string. /// /// \note The caller must ensure that the \p CompletionString and all the /// \c Ref types outlive this result, typically by storing them in the same /// \c CodeCompletionResultSink as the result itself. ContextFreeCodeCompletionResult( CodeCompletionResultKind Kind, uint8_t AssociatedKind, CodeCompletionOperatorKind KnownOperatorKind, CodeCompletionMacroRoles MacroRoles, bool IsSystem, bool HasAsyncAlternative, CodeCompletionString *CompletionString, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, NullTerminatedStringRef DiagnosticMessage, NullTerminatedStringRef FilterName, NullTerminatedStringRef NameForDiagnostics) : Kind(Kind), KnownOperatorKind(KnownOperatorKind), MacroRoles(MacroRoles), IsSystem(IsSystem), HasAsyncAlternative(HasAsyncAlternative), CompletionString(CompletionString), ModuleName(ModuleName), BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs), SwiftUSR(SwiftUSR), ResultType(ResultType), NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity), DiagnosticMessage(DiagnosticMessage), FilterName(FilterName), NameForDiagnostics(NameForDiagnostics) { this->AssociatedKind.Opaque = AssociatedKind; assert((NotRecommended == ContextFreeNotRecommendedReason::None) == (DiagnosticSeverity == CodeCompletionDiagnosticSeverity::None) && "Result should be not recommended iff it has a diagnostic"); assert((DiagnosticSeverity == CodeCompletionDiagnosticSeverity::None) == DiagnosticMessage.empty() && "Completion item should have diagnostic message iff the diagnostics " "severity is not none"); assert(CompletionString && "Result should have a completion string"); if (isOperator() && KnownOperatorKind == CodeCompletionOperatorKind::None) { this->KnownOperatorKind = getCodeCompletionOperatorKind(CompletionString); } assert(!isOperator() || getKnownOperatorKind() != CodeCompletionOperatorKind::None && "isOperator implies operator kind != None"); } /// Constructs a \c Pattern or \c BuiltinOperator result. /// /// \note The caller must ensure that the \p CompletionString and \c /// StringRefs outlive this result, typically by storing them in the same /// \c CodeCompletionResultSink as the result itself. static ContextFreeCodeCompletionResult *createPatternOrBuiltInOperatorResult( CodeCompletionResultSink &Sink, CodeCompletionResultKind Kind, CodeCompletionString *CompletionString, CodeCompletionOperatorKind KnownOperatorKin, NullTerminatedStringRef BriefDocComment, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, NullTerminatedStringRef DiagnosticMessage); /// Constructs a \c Keyword result. /// /// \note The caller must ensure that the \p CompletionString and /// \p BriefDocComment outlive this result, typically by storing them in /// the same \c CodeCompletionResultSink as the result itself. static ContextFreeCodeCompletionResult * createKeywordResult(CodeCompletionResultSink &Sink, CodeCompletionKeywordKind Kind, CodeCompletionString *CompletionString, NullTerminatedStringRef BriefDocComment, CodeCompletionResultType ResultType); /// Constructs a \c Literal result. /// /// \note The caller must ensure that the \p CompletionString outlives this /// result, typically by storing them in the same \c CodeCompletionResultSink /// as the result itself. static ContextFreeCodeCompletionResult * createLiteralResult(CodeCompletionResultSink &Sink, CodeCompletionLiteralKind LiteralKind, CodeCompletionString *CompletionString, CodeCompletionResultType ResultType); /// Constructs a \c Declaration result. /// /// \note The caller must ensure that the \p CompletionString and all /// \c StringRefs outlive this result, typically by storing them in the same /// \c CodeCompletionResultSink as the result itself. static ContextFreeCodeCompletionResult *createDeclResult( CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString, const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, NullTerminatedStringRef DiagnosticMessage); CodeCompletionResultKind getKind() const { return Kind; } /// Returns the raw associated kind which will be interpreted differently /// depending on the completion item's kind. uint8_t getOpaqueAssociatedKind() const { return AssociatedKind.Opaque; } CodeCompletionDeclKind getAssociatedDeclKind() const { assert(getKind() == CodeCompletionResultKind::Declaration); return AssociatedKind.Decl; } CodeCompletionLiteralKind getLiteralKind() const { assert(getKind() == CodeCompletionResultKind::Literal); return AssociatedKind.Literal; } CodeCompletionKeywordKind getKeywordKind() const { assert(getKind() == CodeCompletionResultKind::Keyword); return AssociatedKind.Keyword; } CodeCompletionOperatorKind getKnownOperatorKind() const { assert(isOperator()); return KnownOperatorKind; } CodeCompletionMacroRoles getMacroRoles() const { return MacroRoles; } bool isSystem() const { return IsSystem; }; bool hasAsyncAlternative() const { return HasAsyncAlternative; }; CodeCompletionString *getCompletionString() const { return CompletionString; } NullTerminatedStringRef getModuleName() const { return ModuleName; } NullTerminatedStringRef getBriefDocComment() const { return BriefDocComment; } ArrayRef getAssociatedUSRs() const { return AssociatedUSRs; } NullTerminatedStringRef getSwiftUSR() const { return SwiftUSR; } const CodeCompletionResultType &getResultType() const { return ResultType; } ContextFreeNotRecommendedReason getNotRecommendedReason() const { return NotRecommended; } ContextualNotRecommendedReason calculateContextualNotRecommendedReason( ContextualNotRecommendedReason explicitReason, bool canCurrDeclContextHandleAsync) const; CodeCompletionResultTypeRelation calculateContextualTypeRelation( const DeclContext *dc, const ExpectedTypeContext *typeContext, const USRBasedTypeContext *usrTypeContext) const; CodeCompletionDiagnosticSeverity getDiagnosticSeverity() const { return DiagnosticSeverity; } NullTerminatedStringRef getDiagnosticMessage() const { return DiagnosticMessage; } NullTerminatedStringRef getFilterName() const { return FilterName; } NullTerminatedStringRef getNameForDiagnostics() const { return NameForDiagnostics; } bool isOperator() const { if (getKind() == CodeCompletionResultKind::Declaration) { switch (getAssociatedDeclKind()) { case CodeCompletionDeclKind::PrefixOperatorFunction: case CodeCompletionDeclKind::PostfixOperatorFunction: case CodeCompletionDeclKind::InfixOperatorFunction: return true; default: return false; } } else { return getKind() == CodeCompletionResultKind::BuiltinOperator; } } /// Helper methods used during initialization of /// \c ContextFreeCodeCompletionResult. static CodeCompletionOperatorKind getCodeCompletionOperatorKind(const CodeCompletionString *str); static CodeCompletionDeclKind getCodeCompletionDeclKind(const Decl *D); static bool getDeclIsSystem(const Decl *D); }; /// A single code completion result enriched with information that depend on /// the completion's usage context. class CodeCompletionResult { const ContextFreeCodeCompletionResult &ContextFree; /// Contains the associated declaration if fetched; if not, stores the /// ASTContext to use for finding the associated declaration through the Swift /// USR. mutable llvm::PointerUnion DeclOrCtx; SemanticContextKind SemanticContext : 3; static_assert(int(SemanticContextKind::MAX_VALUE) < 1 << 3, ""); unsigned char Flair : 8; /// Contextual diagnostics. If the contextual not recommended reason is /// \c None, then the context free diagnostic will be shown to the user. ContextualNotRecommendedReason NotRecommended : 4; static_assert(int(ContextualNotRecommendedReason::MAX_VALUE) < 1 << 4, ""); /// The number of bytes to the left of the code completion point that /// should be erased first if this completion string is inserted in the /// editor buffer. unsigned NumBytesToErase : 7; public: static const unsigned MaxNumBytesToErase = 127; private: CodeCompletionResultTypeRelation TypeDistance : 3; static_assert(int(CodeCompletionResultTypeRelation::MAX_VALUE) < 1 << 3, ""); public: /// Memberwise initializer /// The \c ContextFree result must outlive this result. Typically, this is /// done by allocating the two in the same sink or adopting the context free /// sink in the sink that allocates this result. CodeCompletionResult(const ContextFreeCodeCompletionResult &ContextFree, llvm::PointerUnion DeclOrCtx, SemanticContextKind SemanticContext, CodeCompletionFlair Flair, uint8_t NumBytesToErase, CodeCompletionResultTypeRelation TypeDistance, ContextualNotRecommendedReason NotRecommended) : ContextFree(ContextFree), DeclOrCtx(DeclOrCtx), SemanticContext(SemanticContext), Flair(Flair.toRaw()), NotRecommended(NotRecommended), NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {} const ContextFreeCodeCompletionResult &getContextFreeResult() const { return ContextFree; } /// Return a pointer to the data structure storing the context free /// properties. /// The pointer is valid as long as this result is alive. const ContextFreeCodeCompletionResult *getContextFreeResultPtr() { return &ContextFree; } /// Copy this result to \p Sink with \p newFlair . Note that this does NOT /// copy the context free result. Thus the caller needs to ensure that the /// context free result outlives the result the result returned by this /// method. CodeCompletionResult *withFlair(CodeCompletionFlair newFlair, CodeCompletionResultSink &Sink) const; /// Copy this result to \p Sink with \p newFlair . Note that this does NOT /// copy the context free result. Thus the caller needs to ensure that the /// context free result outlives the result the result returned by this /// method. CodeCompletionResult *withContextFreeResultSemanticContextAndFlair( const ContextFreeCodeCompletionResult &NewContextFree, SemanticContextKind NewSemanticContext, CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const; CodeCompletionResultKind getKind() const { return getContextFreeResult().getKind(); } CodeCompletionDeclKind getAssociatedDeclKind() const { return getContextFreeResult().getAssociatedDeclKind(); } CodeCompletionLiteralKind getLiteralKind() const { return getContextFreeResult().getLiteralKind(); } CodeCompletionKeywordKind getKeywordKind() const { return getContextFreeResult().getKeywordKind(); } bool isOperator() const { return getContextFreeResult().isOperator(); } CodeCompletionOperatorKind getOperatorKind() const { return getContextFreeResult().getKnownOperatorKind(); } bool isSystem() const { return getContextFreeResult().isSystem(); } CodeCompletionResultTypeRelation getExpectedTypeRelation() const { return TypeDistance; } /// Get the contextual not-recommended reason. This disregards context-free /// not recommended reasons. ContextualNotRecommendedReason getContextualNotRecommendedReason() const { return NotRecommended; } /// Return the contextual not recommended reason if there is one. If there is /// no contextual not recommended reason, return the context-free not /// recommended reason. NotRecommendedReason getNotRecommendedReason() const { switch (NotRecommended) { case ContextualNotRecommendedReason::None: switch (getContextFreeResult().getNotRecommendedReason()) { case ContextFreeNotRecommendedReason::None: return NotRecommendedReason::None; case ContextFreeNotRecommendedReason::Deprecated: return NotRecommendedReason::Deprecated; case ContextFreeNotRecommendedReason::SoftDeprecated: return NotRecommendedReason::SoftDeprecated; } case ContextualNotRecommendedReason::RedundantImport: return NotRecommendedReason::RedundantImport; case ContextualNotRecommendedReason::RedundantImportIndirect: return NotRecommendedReason::RedundantImportIndirect; case ContextualNotRecommendedReason::NonAsyncAlternativeUsedInAsyncContext: return NotRecommendedReason::NonAsyncAlternativeUsedInAsyncContext; case ContextualNotRecommendedReason::VariableUsedInOwnDefinition: return NotRecommendedReason::VariableUsedInOwnDefinition; } } /// Finds the associated declaration on-demand and caches it. const Decl *getAssociatedDecl() const; SemanticContextKind getSemanticContext() const { return SemanticContext; } CodeCompletionFlair getFlair() const { return CodeCompletionFlair(Flair); } /// Modify "flair" of this result *in place*. void setFlair(CodeCompletionFlair flair) { Flair = flair.toRaw(); } bool isNotRecommended() const { return getNotRecommendedReason() != NotRecommendedReason::None; } unsigned getNumBytesToErase() const { return NumBytesToErase; } CodeCompletionString *getCompletionString() const { return getContextFreeResult().getCompletionString(); } NullTerminatedStringRef getModuleName() const { return getContextFreeResult().getModuleName(); } NullTerminatedStringRef getBriefDocComment() const { return getContextFreeResult().getBriefDocComment(); } /// Prints the full documentation comment as XML to the provided \p OS stream. /// /// \returns true if the result has a documentation comment. bool printFullDocCommentAsXML(raw_ostream &OS) const { if (auto *D = getAssociatedDecl()) return ide::getDocumentationCommentAsXML(D, OS); return false; } /// Prints the raw documentation comment to the provided \p OS stream. /// /// \returns true if the result has a documentation comment. bool printRawDocComment(raw_ostream &OS) const { if (auto *D = getAssociatedDecl()) return ide::getRawDocumentationComment(D, OS); return false; } ArrayRef getAssociatedUSRs() const { return getContextFreeResult().getAssociatedUSRs(); } /// Get the contextual diagnostic severity and message. This disregards /// context-free diagnostics. std::pair getContextualDiagnosticSeverityAndMessage(SmallVectorImpl &Scratch, const ASTContext &Ctx) const; /// Return the contextual diagnostic severity and message if there was a /// contextual diagnostic. If there is no contextual diagnostic, return the /// context-free diagnostic severity and message. std::pair getDiagnosticSeverityAndMessage(SmallVectorImpl &Scratch, const ASTContext &Ctx) const { if (NotRecommended != ContextualNotRecommendedReason::None) { return getContextualDiagnosticSeverityAndMessage(Scratch, Ctx); } else { return std::make_pair(getContextFreeResult().getDiagnosticSeverity(), getContextFreeResult().getDiagnosticMessage()); } } NullTerminatedStringRef getFilterName() const { return getContextFreeResult().getFilterName(); } /// Print a debug representation of the code completion result to \p OS. void printPrefix(raw_ostream &OS) const; SWIFT_DEBUG_DUMP; }; } // end namespace ide } // end namespace swift namespace llvm { template <> struct DenseMapInfo { using Kind = swift::ide::CodeCompletionKeywordKind; static Kind getEmptyKey() { return Kind(~0u); } static Kind getTombstoneKey() { return Kind(~1u); } static unsigned getHashValue(const Kind &Val) { return unsigned(Val); } static bool isEqual(const Kind &LHS, const Kind &RHS) { return LHS == RHS; } }; template <> struct DenseMapInfo { using Kind = swift::ide::CodeCompletionLiteralKind; static Kind getEmptyKey() { return Kind(~0u); } static Kind getTombstoneKey() { return Kind(~1u); } static unsigned getHashValue(const Kind &Val) { return unsigned(Val); } static bool isEqual(const Kind &LHS, const Kind &RHS) { return LHS == RHS; } }; template <> struct DenseMapInfo { using Kind = swift::ide::CodeCompletionDeclKind; static Kind getEmptyKey() { return Kind(~0u); } static Kind getTombstoneKey() { return Kind(~1u); } static unsigned getHashValue(const Kind &Val) { return unsigned(Val); } static bool isEqual(const Kind &LHS, const Kind &RHS) { return LHS == RHS; } }; } #endif // SWIFT_IDE_CODECOMPLETION_RESULT_H