| //===--- SwiftLangSupport.cpp ---------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "SwiftLangSupport.h" |
| #include "SwiftASTManager.h" |
| #include "SourceKit/Core/Context.h" |
| #include "SourceKit/SwiftLang/Factory.h" |
| #include "SourceKit/Support/FileSystemProvider.h" |
| #include "SourceKit/Support/UIdent.h" |
| |
| #include "swift/AST/ASTVisitor.h" |
| #include "swift/AST/ClangModuleLoader.h" |
| #include "swift/AST/ParameterList.h" |
| #include "swift/AST/SILOptions.h" |
| #include "swift/AST/USRGeneration.h" |
| #include "swift/Config.h" |
| #include "swift/IDE/CodeCompletion.h" |
| #include "swift/IDE/CodeCompletionCache.h" |
| #include "swift/IDE/SyntaxModel.h" |
| #include "swift/IDE/Utils.h" |
| |
| #include "clang/Lex/HeaderSearch.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include "llvm/ADT/APInt.h" |
| #include "llvm/ADT/Hashing.h" |
| #include "llvm/Support/ConvertUTF.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| #if !defined(_WIN32) |
| #include <sys/param.h> |
| #else |
| #define WIN32_MEAN_AND_LEAN |
| #define NOMINMAX |
| #include <windows.h> |
| #endif |
| |
| using namespace SourceKit; |
| using namespace swift; |
| using namespace swift::ide; |
| using swift::index::SymbolKind; |
| using swift::index::SymbolSubKind; |
| using swift::index::SymbolProperty; |
| using swift::index::SymbolPropertySet; |
| using swift::index::SymbolInfo; |
| using swift::index::SymbolRole; |
| using swift::index::SymbolRoleSet; |
| |
| #define KIND(NAME, CONTENT) static UIdent Kind##NAME(CONTENT); |
| #include "SourceKit/Core/ProtocolUIDs.def" |
| |
| #define REFACTORING(KIND, NAME, ID) static UIdent Kind##Refactoring##KIND("source.refactoring.kind."#ID); |
| #include "swift/IDE/RefactoringKinds.def" |
| |
| static UIdent Attr_IBAction("source.decl.attribute.ibaction"); |
| static UIdent Attr_IBOutlet("source.decl.attribute.iboutlet"); |
| static UIdent Attr_IBDesignable("source.decl.attribute.ibdesignable"); |
| static UIdent Attr_IBInspectable("source.decl.attribute.ibinspectable"); |
| static UIdent Attr_GKInspectable("source.decl.attribute.gkinspectable"); |
| static UIdent Attr_Objc("source.decl.attribute.objc"); |
| static UIdent Attr_ObjcNamed("source.decl.attribute.objc.name"); |
| static UIdent Attr_Private("source.decl.attribute.private"); |
| static UIdent Attr_FilePrivate("source.decl.attribute.fileprivate"); |
| static UIdent Attr_Internal("source.decl.attribute.internal"); |
| static UIdent Attr_Public("source.decl.attribute.public"); |
| static UIdent Attr_Open("source.decl.attribute.open"); |
| static UIdent Attr_Setter_Private("source.decl.attribute.setter_access.private"); |
| static UIdent Attr_Setter_FilePrivate("source.decl.attribute.setter_access.fileprivate"); |
| static UIdent Attr_Setter_Internal("source.decl.attribute.setter_access.internal"); |
| static UIdent Attr_Setter_Public("source.decl.attribute.setter_access.public"); |
| static UIdent Attr_Setter_Open("source.decl.attribute.setter_access.open"); |
| |
| std::unique_ptr<LangSupport> |
| SourceKit::createSwiftLangSupport(SourceKit::Context &SKCtx) { |
| return std::unique_ptr<LangSupport>(new SwiftLangSupport(SKCtx)); |
| } |
| |
| const std::string LangSupport::SynthesizedUSRSeparator = "::SYNTHESIZED::"; |
| |
| namespace { |
| |
| class UIdentVisitor : public ASTVisitor<UIdentVisitor, |
| UIdent, UIdent, UIdent, UIdent > { |
| const bool IsRef; |
| |
| public: |
| explicit UIdentVisitor(bool IsRef) : IsRef(IsRef) { } |
| |
| /// TODO: reconsider whether having a default case is a good idea. |
| UIdent visitDecl(const Decl *D) { return UIdent(); } |
| |
| UIdent visitFuncDecl(const FuncDecl *D); |
| UIdent visitVarDecl(const VarDecl *D); |
| UIdent visitParamDecl(const ParamDecl *D); |
| UIdent visitExtensionDecl(const ExtensionDecl *D); |
| |
| #define UID_FOR(CLASS) \ |
| UIdent visit##CLASS##Decl(const CLASS##Decl *) { \ |
| return IsRef ? KindRef##CLASS : KindDecl##CLASS; \ |
| } |
| UID_FOR(Class) |
| UID_FOR(Struct) |
| UID_FOR(Enum) |
| UID_FOR(EnumElement) |
| UID_FOR(Protocol) |
| UID_FOR(TypeAlias) |
| UID_FOR(AssociatedType) |
| UID_FOR(GenericTypeParam) |
| UID_FOR(Constructor) |
| UID_FOR(Destructor) |
| UID_FOR(Subscript) |
| UID_FOR(OpaqueType) |
| #undef UID_FOR |
| }; |
| |
| } // anonymous namespace |
| |
| UIdent UIdentVisitor::visitFuncDecl(const FuncDecl *D) { |
| if (auto AD = dyn_cast<AccessorDecl>(D)) { |
| return SwiftLangSupport::getUIDForAccessor(AD->getStorage(), |
| AD->getAccessorKind(), |
| IsRef); |
| } |
| |
| if (auto *Op = D->getOperatorDecl()) { |
| switch (Op->getKind()) { |
| case DeclKind::PrefixOperator: |
| return IsRef ? KindRefFunctionPrefixOperator : KindDeclFunctionPrefixOperator; |
| case DeclKind::PostfixOperator: |
| return IsRef ? KindRefFunctionPostfixOperator : KindDeclFunctionPostfixOperator; |
| case DeclKind::InfixOperator: |
| return IsRef ? KindRefFunctionInfixOperator : KindDeclFunctionInfixOperator; |
| default: |
| llvm_unreachable("unexpected operator kind"); |
| } |
| } |
| |
| const DeclContext *DC = D->getDeclContext(); |
| if (DC->isTypeContext()) { |
| if (D->isStatic()) { |
| if (D->getCorrectStaticSpelling() == StaticSpellingKind::KeywordClass) |
| return IsRef ? KindRefMethodClass : KindDeclMethodClass; |
| else |
| return IsRef ? KindRefMethodStatic : KindDeclMethodStatic; |
| } |
| return IsRef ? KindRefMethodInstance : KindDeclMethodInstance; |
| } |
| return IsRef ? KindRefFunctionFree : KindDeclFunctionFree; |
| } |
| |
| UIdent UIdentVisitor::visitVarDecl(const VarDecl *D) { |
| const DeclContext *DC = D->getDeclContext(); |
| if (DC->isTypeContext()) { |
| if (D->isStatic()) { |
| if (D->getCorrectStaticSpelling() == StaticSpellingKind::KeywordClass) |
| return IsRef ? KindRefVarClass : KindDeclVarClass; |
| else |
| return IsRef ? KindRefVarStatic : KindDeclVarStatic; |
| } |
| return IsRef ? KindRefVarInstance : KindDeclVarInstance; |
| } |
| if (DC->isLocalContext()) |
| return IsRef ? KindRefVarLocal : KindDeclVarLocal; |
| return IsRef ? KindRefVarGlobal : KindDeclVarGlobal; |
| } |
| |
| UIdent UIdentVisitor::visitParamDecl(const ParamDecl *D) { |
| // There is no KindRefVarParam. It's not usually an interesting difference. |
| return IsRef ? KindRefVarLocal : KindDeclVarParam; |
| } |
| |
| UIdent UIdentVisitor::visitExtensionDecl(const ExtensionDecl *D) { |
| assert(!IsRef && "reference to an extension ?"); |
| if (NominalTypeDecl *NTD = D->getExtendedNominal()) { |
| if (isa<StructDecl>(NTD)) |
| return KindDeclExtensionStruct; |
| if (isa<ClassDecl>(NTD)) |
| return KindDeclExtensionClass; |
| if (isa<EnumDecl>(NTD)) |
| return KindDeclExtensionEnum; |
| if (isa<ProtocolDecl>(NTD)) |
| return KindDeclExtensionProtocol; |
| } |
| return UIdent(); |
| } |
| |
| namespace { |
| /// A simple FileSystemProvider that creates an InMemoryFileSystem for a given |
| /// dictionary of file contents and overlays that on top of the real filesystem. |
| class InMemoryFileSystemProvider: public SourceKit::FileSystemProvider { |
| /// Provides the real filesystem, overlayed with an InMemoryFileSystem that |
| /// contains specified files at specified locations. |
| llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> |
| getFileSystem(OptionsDictionary &options, std::string &error) override { |
| auto InMemoryFS = llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>( |
| new llvm::vfs::InMemoryFileSystem()); |
| |
| static UIdent KeyFiles("key.files"); |
| static UIdent KeyName("key.name"); |
| static UIdent KeySourceFile("key.sourcefile"); |
| static UIdent KeySourceText("key.sourcetext"); |
| bool failed = options.forEach(KeyFiles, [&](OptionsDictionary &file) { |
| StringRef name; |
| if (!file.valueForOption(KeyName, name)) { |
| error = "missing 'key.name'"; |
| return true; |
| } |
| |
| StringRef content; |
| if (file.valueForOption(KeySourceText, content)) { |
| auto buffer = llvm::MemoryBuffer::getMemBufferCopy(content, name); |
| InMemoryFS->addFile(name, 0, std::move(buffer)); |
| return false; |
| } |
| |
| StringRef mappedPath; |
| if (!file.valueForOption(KeySourceFile, mappedPath)) { |
| error = "missing 'key.sourcefile' or 'key.sourcetext'"; |
| return true; |
| } |
| |
| auto bufferOrErr = llvm::MemoryBuffer::getFile(mappedPath); |
| if (auto err = bufferOrErr.getError()) { |
| llvm::raw_string_ostream errStream(error); |
| errStream << "error reading target file '" << mappedPath |
| << "': " << err.message() << "\n"; |
| return true; |
| } |
| |
| auto renamedBuffer = llvm::MemoryBuffer::getMemBufferCopy( |
| bufferOrErr.get()->getBuffer(), name); |
| InMemoryFS->addFile(name, 0, std::move(renamedBuffer)); |
| return false; |
| }); |
| |
| if (failed) |
| return nullptr; |
| |
| auto OverlayFS = llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>( |
| new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); |
| OverlayFS->pushOverlay(std::move(InMemoryFS)); |
| return OverlayFS; |
| } |
| }; |
| |
| class DirectlyPassedFileSystemProvider : public SourceKit::FileSystemProvider { |
| public: |
| struct Options : public OptionsDictionary { |
| const unsigned FSID; |
| |
| Options(unsigned FSID) : FSID(FSID) {} |
| |
| bool valueForOption(UIdent Key, unsigned &Val) override { |
| static UIdent KeyFSID("key.fsid"); |
| if (Key != KeyFSID) |
| return false; |
| Val = FSID; |
| return true; |
| } |
| bool valueForOption(UIdent Key, bool &Val) override { return true; } |
| bool valueForOption(UIdent Key, StringRef &Val) override { return false; } |
| bool |
| forEach(UIdent key, |
| llvm::function_ref<bool(OptionsDictionary &)> applier) override { |
| return false; |
| } |
| }; |
| |
| llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> |
| getFileSystem(OptionsDictionary &options, std::string &error) override { |
| llvm::sys::ScopedLock L(mtx); |
| static UIdent KeyFSID("key.fsid"); |
| unsigned FSID; |
| if (!options.valueForOption(KeyFSID, FSID)) { |
| error = "'key.fsid' not specified"; |
| return nullptr; |
| } |
| |
| auto result = FileSystems.find(FSID); |
| if (result == FileSystems.end()) { |
| error = "filesystem not found"; |
| return nullptr; |
| } |
| |
| return result->second; |
| } |
| |
| Options addFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs) { |
| llvm::sys::ScopedLock L(mtx); |
| auto result = FileSystems.try_emplace(NextFSID, std::move(fs)); |
| assert(result.second && "duplicate key"); |
| Options ret(NextFSID); |
| ++NextFSID; |
| return ret; |
| } |
| |
| void removeFileSystem(Options &options) { |
| llvm::sys::ScopedLock L(mtx); |
| FileSystems.erase(options.FSID); |
| } |
| |
| private: |
| llvm::sys::Mutex mtx; |
| unsigned NextFSID = 0; |
| llvm::DenseMap<unsigned, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>> |
| FileSystems; |
| }; |
| } |
| |
| SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) |
| : NotificationCtr(SKCtx.getNotificationCenter()), |
| CCCache(new SwiftCompletionCache) { |
| llvm::SmallString<128> LibPath(SKCtx.getRuntimeLibPath()); |
| llvm::sys::path::append(LibPath, "swift"); |
| RuntimeResourcePath = LibPath.str(); |
| |
| Stats = std::make_shared<SwiftStatistics>(); |
| EditorDocuments = std::make_shared<SwiftEditorDocumentFileMap>(); |
| ASTMgr = std::make_shared<SwiftASTManager>(EditorDocuments, Stats, |
| RuntimeResourcePath); |
| // By default, just use the in-memory cache. |
| CCCache->inMemory = llvm::make_unique<ide::CodeCompletionCache>(); |
| |
| // Provide a default file system provider. |
| setFileSystemProvider("in-memory-vfs", llvm::make_unique<InMemoryFileSystemProvider>()); |
| |
| // SWIFT_ENABLE_TENSORFLOW |
| setFileSystemProvider("directly-passed-vfs", |
| llvm::make_unique<DirectlyPassedFileSystemProvider>()); |
| } |
| |
| SwiftLangSupport::~SwiftLangSupport() { |
| } |
| |
| // SWIFT_ENABLE_TENSORFLOW |
| void SwiftLangSupport::setInMemoryOutputFileSystem( |
| llvm::IntrusiveRefCntPtr<clang::InMemoryOutputFileSystem> FS) { |
| ASTMgr->setInMemoryOutputFileSystem(std::move(FS)); |
| } |
| |
| std::unique_ptr<llvm::MemoryBuffer> |
| SwiftLangSupport::makeCodeCompletionMemoryBuffer( |
| const llvm::MemoryBuffer *origBuf, unsigned &Offset, |
| const std::string bufferIdentifier) { |
| |
| auto origBuffSize = origBuf->getBufferSize(); |
| if (Offset > origBuffSize) |
| Offset = origBuffSize; |
| |
| auto newBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer( |
| origBuffSize + 1, bufferIdentifier); |
| auto *pos = origBuf->getBufferStart() + Offset; |
| auto *newPos = |
| std::copy(origBuf->getBufferStart(), pos, newBuffer->getBufferStart()); |
| *newPos = '\0'; |
| std::copy(pos, origBuf->getBufferEnd(), newPos + 1); |
| |
| return std::unique_ptr<llvm::MemoryBuffer>(newBuffer.release()); |
| } |
| |
| UIdent SwiftLangSupport::getUIDForDecl(const Decl *D, bool IsRef) { |
| return UIdentVisitor(IsRef).visit(const_cast<Decl*>(D)); |
| } |
| |
| UIdent SwiftLangSupport::getUIDForExtensionOfDecl(const Decl *D) { |
| switch (D->getKind()) { |
| case swift::DeclKind::Struct: |
| return KindDeclExtensionStruct; |
| case swift::DeclKind::Enum: |
| return KindDeclExtensionEnum; |
| case swift::DeclKind::Class: |
| return KindDeclExtensionClass; |
| case swift::DeclKind::Protocol: |
| return KindDeclExtensionProtocol; |
| default: |
| llvm_unreachable("cannot have extension."); |
| } |
| } |
| |
| UIdent SwiftLangSupport::getUIDForLocalVar(bool IsRef) { |
| return IsRef ? KindRefVarLocal : KindDeclVarLocal; |
| } |
| |
| UIdent SwiftLangSupport::getUIDForAccessor(const ValueDecl *D, |
| AccessorKind AccKind, |
| bool IsRef) { |
| switch (AccKind) { |
| case AccessorKind::Get: |
| return IsRef ? KindRefAccessorGetter : KindDeclAccessorGetter; |
| case AccessorKind::Set: |
| return IsRef ? KindRefAccessorSetter : KindDeclAccessorSetter; |
| case AccessorKind::WillSet: |
| return IsRef ? KindRefAccessorWillSet : KindDeclAccessorWillSet; |
| case AccessorKind::DidSet: |
| return IsRef ? KindRefAccessorDidSet : KindDeclAccessorDidSet; |
| case AccessorKind::Address: |
| return IsRef ? KindRefAccessorAddress : KindDeclAccessorAddress; |
| case AccessorKind::MutableAddress: |
| return IsRef ? KindRefAccessorMutableAddress |
| : KindDeclAccessorMutableAddress; |
| case AccessorKind::Read: |
| return IsRef ? KindRefAccessorRead : KindDeclAccessorRead; |
| case AccessorKind::Modify: |
| return IsRef ? KindRefAccessorModify : KindDeclAccessorModify; |
| } |
| |
| llvm_unreachable("Unhandled AccessorKind in switch."); |
| } |
| |
| SourceKit::UIdent SwiftLangSupport::getUIDForModuleRef() { |
| return KindRefModule; |
| } |
| |
| SourceKit::UIdent SwiftLangSupport::getUIDForObjCAttr() { |
| return Attr_Objc; |
| } |
| |
| UIdent SwiftLangSupport::getUIDForRefactoringKind(ide::RefactoringKind Kind){ |
| switch(Kind) { |
| case ide::RefactoringKind::None: llvm_unreachable("cannot end up here."); |
| #define REFACTORING(KIND, NAME, ID) \ |
| case ide::RefactoringKind::KIND: return KindRefactoring##KIND; |
| #include "swift/IDE/RefactoringKinds.def" |
| } |
| } |
| |
| UIdent SwiftLangSupport::getUIDForCodeCompletionDeclKind( |
| ide::CodeCompletionDeclKind Kind, bool IsRef) { |
| if (IsRef) { |
| // FIXME: The code-completion kind is also used for semantic annotations. |
| // We should either create a new kind or rename the code-completion kind to |
| // something more general. |
| switch (Kind) { |
| case CodeCompletionDeclKind::Module: return KindRefModule; |
| case CodeCompletionDeclKind::Class: return KindRefClass; |
| case CodeCompletionDeclKind::Struct: return KindRefStruct; |
| case CodeCompletionDeclKind::Enum: return KindRefEnum; |
| case CodeCompletionDeclKind::EnumElement: return KindRefEnumElement; |
| case CodeCompletionDeclKind::Protocol: return KindRefProtocol; |
| case CodeCompletionDeclKind::AssociatedType: return KindRefAssociatedType; |
| case CodeCompletionDeclKind::TypeAlias: return KindRefTypeAlias; |
| case CodeCompletionDeclKind::GenericTypeParam: return KindRefGenericTypeParam; |
| case CodeCompletionDeclKind::Constructor: return KindRefConstructor; |
| case CodeCompletionDeclKind::Destructor: return KindRefDestructor; |
| case CodeCompletionDeclKind::Subscript: return KindRefSubscript; |
| case CodeCompletionDeclKind::StaticMethod: return KindRefMethodClass; |
| case CodeCompletionDeclKind::InstanceMethod: return KindRefMethodInstance; |
| case CodeCompletionDeclKind::PrefixOperatorFunction: return KindRefFunctionPrefixOperator; |
| case CodeCompletionDeclKind::PostfixOperatorFunction: return KindRefFunctionPostfixOperator; |
| case CodeCompletionDeclKind::InfixOperatorFunction: return KindRefFunctionInfixOperator; |
| case CodeCompletionDeclKind::PrecedenceGroup: return KindRefPrecedenceGroup; |
| case CodeCompletionDeclKind::FreeFunction: return KindRefFunctionFree; |
| case CodeCompletionDeclKind::StaticVar: return KindRefVarClass; |
| case CodeCompletionDeclKind::InstanceVar: return KindRefVarInstance; |
| case CodeCompletionDeclKind::LocalVar: return KindRefVarLocal; |
| case CodeCompletionDeclKind::GlobalVar: return KindRefVarGlobal; |
| } |
| } |
| |
| switch (Kind) { |
| case CodeCompletionDeclKind::Module: return KindDeclModule; |
| case CodeCompletionDeclKind::Class: return KindDeclClass; |
| case CodeCompletionDeclKind::Struct: return KindDeclStruct; |
| case CodeCompletionDeclKind::Enum: return KindDeclEnum; |
| case CodeCompletionDeclKind::EnumElement: return KindDeclEnumElement; |
| case CodeCompletionDeclKind::Protocol: return KindDeclProtocol; |
| case CodeCompletionDeclKind::AssociatedType: return KindDeclAssociatedType; |
| case CodeCompletionDeclKind::TypeAlias: return KindDeclTypeAlias; |
| case CodeCompletionDeclKind::GenericTypeParam: return KindDeclGenericTypeParam; |
| case CodeCompletionDeclKind::Constructor: return KindDeclConstructor; |
| case CodeCompletionDeclKind::Destructor: return KindDeclDestructor; |
| case CodeCompletionDeclKind::Subscript: return KindDeclSubscript; |
| case CodeCompletionDeclKind::StaticMethod: return KindDeclMethodClass; |
| case CodeCompletionDeclKind::InstanceMethod: return KindDeclMethodInstance; |
| case CodeCompletionDeclKind::PrefixOperatorFunction: return KindDeclFunctionPrefixOperator; |
| case CodeCompletionDeclKind::PostfixOperatorFunction: return KindDeclFunctionPostfixOperator; |
| case CodeCompletionDeclKind::InfixOperatorFunction: return KindDeclFunctionInfixOperator; |
| case CodeCompletionDeclKind::PrecedenceGroup: return KindDeclPrecedenceGroup; |
| case CodeCompletionDeclKind::FreeFunction: return KindDeclFunctionFree; |
| case CodeCompletionDeclKind::StaticVar: return KindDeclVarClass; |
| case CodeCompletionDeclKind::InstanceVar: return KindDeclVarInstance; |
| case CodeCompletionDeclKind::LocalVar: return KindDeclVarLocal; |
| case CodeCompletionDeclKind::GlobalVar: return KindDeclVarGlobal; |
| } |
| |
| llvm_unreachable("Unhandled CodeCompletionDeclKind in switch."); |
| } |
| |
| UIdent SwiftLangSupport::getUIDForSyntaxNodeKind(SyntaxNodeKind SC) { |
| switch (SC) { |
| case SyntaxNodeKind::Keyword: |
| return KindKeyword; |
| case SyntaxNodeKind::Identifier: |
| case SyntaxNodeKind::DollarIdent: |
| return KindIdentifier; |
| case SyntaxNodeKind::Integer: |
| case SyntaxNodeKind::Floating: |
| return KindNumber; |
| case SyntaxNodeKind::String: |
| return KindString; |
| case SyntaxNodeKind::StringInterpolationAnchor: |
| return KindStringInterpolation; |
| case SyntaxNodeKind::CommentLine: |
| case SyntaxNodeKind::CommentBlock: |
| return KindComment; |
| case SyntaxNodeKind::CommentMarker: |
| return KindCommentMarker; |
| case SyntaxNodeKind::CommentURL: |
| return KindCommentURL; |
| case SyntaxNodeKind::DocCommentLine: |
| case SyntaxNodeKind::DocCommentBlock: |
| return KindDocComment; |
| case SyntaxNodeKind::DocCommentField: |
| return KindDocCommentField; |
| case SyntaxNodeKind::TypeId: |
| return KindTypeIdentifier; |
| case SyntaxNodeKind::BuildConfigKeyword: |
| return KindBuildConfigKeyword; |
| case SyntaxNodeKind::BuildConfigId: |
| return KindBuildConfigId; |
| case SyntaxNodeKind::PoundDirectiveKeyword: |
| return KindPoundDirectiveKeyword; |
| case SyntaxNodeKind::AttributeId: |
| return KindAttributeId; |
| case SyntaxNodeKind::AttributeBuiltin: |
| return KindAttributeBuiltin; |
| case SyntaxNodeKind::EditorPlaceholder: |
| return KindPlaceholder; |
| case SyntaxNodeKind::ObjectLiteral: |
| return KindObjectLiteral; |
| } |
| |
| // Default to a known kind to prevent crashing in non-asserts builds |
| assert(0 && "Unhandled SyntaxNodeKind in switch."); |
| return KindIdentifier; |
| } |
| |
| UIdent SwiftLangSupport::getUIDForSyntaxStructureKind( |
| SyntaxStructureKind Kind) { |
| switch (Kind) { |
| case SyntaxStructureKind::Class: |
| return KindDeclClass; |
| case SyntaxStructureKind::Struct: |
| return KindDeclStruct; |
| case SyntaxStructureKind::Protocol: |
| return KindDeclProtocol; |
| case SyntaxStructureKind::Enum: |
| return KindDeclEnum; |
| case SyntaxStructureKind::Extension: |
| return KindDeclExtension; |
| case SyntaxStructureKind::FreeFunction: |
| return KindDeclFunctionFree; |
| case SyntaxStructureKind::InstanceFunction: |
| return KindDeclMethodInstance; |
| case SyntaxStructureKind::StaticFunction: |
| return KindDeclMethodStatic; |
| case SyntaxStructureKind::ClassFunction: |
| return KindDeclMethodClass; |
| case SyntaxStructureKind::GlobalVariable: |
| return KindDeclVarGlobal; |
| case SyntaxStructureKind::InstanceVariable: |
| return KindDeclVarInstance; |
| case SyntaxStructureKind::StaticVariable: |
| return KindDeclVarStatic; |
| case SyntaxStructureKind::ClassVariable: |
| return KindDeclVarClass; |
| case SyntaxStructureKind::LocalVariable: |
| return KindDeclVarLocal; |
| case SyntaxStructureKind::EnumCase: |
| return KindDeclEnumCase; |
| case SyntaxStructureKind::EnumElement: |
| return KindDeclEnumElement; |
| case SyntaxStructureKind::TypeAlias: |
| return KindDeclTypeAlias; |
| case SyntaxStructureKind::Subscript: |
| return KindDeclSubscript; |
| case SyntaxStructureKind::AssociatedType: |
| return KindDeclAssociatedType; |
| case SyntaxStructureKind::GenericTypeParam: |
| return KindDeclGenericTypeParam; |
| case SyntaxStructureKind::Parameter: |
| return KindDeclVarParam; |
| case SyntaxStructureKind::ForEachStatement: |
| return KindStmtForEach; |
| case SyntaxStructureKind::WhileStatement: |
| return KindStmtWhile; |
| case SyntaxStructureKind::RepeatWhileStatement: |
| return KindStmtRepeatWhile; |
| case SyntaxStructureKind::IfStatement: |
| return KindStmtIf; |
| case SyntaxStructureKind::GuardStatement: |
| return KindStmtGuard; |
| case SyntaxStructureKind::SwitchStatement: |
| return KindStmtSwitch; |
| case SyntaxStructureKind::CaseStatement: |
| return KindStmtCase; |
| case SyntaxStructureKind::BraceStatement: |
| return KindStmtBrace; |
| case SyntaxStructureKind::CallExpression: |
| return KindExprCall; |
| case SyntaxStructureKind::ArrayExpression: |
| return KindExprArray; |
| case SyntaxStructureKind::DictionaryExpression: |
| return KindExprDictionary; |
| case SyntaxStructureKind::ObjectLiteralExpression: |
| return KindExprObjectLiteral; |
| case SyntaxStructureKind::TupleExpression: |
| return KindExprTuple; |
| case SyntaxStructureKind::ClosureExpression: |
| return KindExprClosure; |
| case SyntaxStructureKind::Argument: |
| return KindExprArg; |
| } |
| |
| llvm_unreachable("Unhandled SyntaxStructureKind in switch."); |
| } |
| |
| UIdent SwiftLangSupport::getUIDForSyntaxStructureElementKind( |
| SyntaxStructureElementKind Kind) { |
| switch (Kind) { |
| case SyntaxStructureElementKind::Id: return KindStructureElemId; |
| case SyntaxStructureElementKind::Expr: return KindStructureElemExpr; |
| case SyntaxStructureElementKind::InitExpr: return KindStructureElemInitExpr; |
| case SyntaxStructureElementKind::ConditionExpr: return KindStructureElemCondExpr; |
| case SyntaxStructureElementKind::Pattern: return KindStructureElemPattern; |
| case SyntaxStructureElementKind::TypeRef: return KindStructureElemTypeRef; |
| } |
| |
| llvm_unreachable("Unhandled SyntaxStructureElementKind in switch."); |
| } |
| |
| SourceKit::UIdent SwiftLangSupport:: |
| getUIDForRangeKind(swift::ide::RangeKind Kind) { |
| switch (Kind) { |
| case swift::ide::RangeKind::SingleExpression: return KindRangeSingleExpression; |
| case swift::ide::RangeKind::SingleStatement: return KindRangeSingleStatement; |
| case swift::ide::RangeKind::SingleDecl: return KindRangeSingleDeclaration; |
| case swift::ide::RangeKind::MultiStatement: return KindRangeMultiStatement; |
| case swift::ide::RangeKind::MultiTypeMemberDecl: |
| return KindRangeMultiTypeMemberDeclaration; |
| case swift::ide::RangeKind::PartOfExpression: return KindRangeInvalid; |
| case swift::ide::RangeKind::Invalid: return KindRangeInvalid; |
| } |
| |
| llvm_unreachable("Unhandled RangeKind in switch."); |
| } |
| |
| SourceKit::UIdent SwiftLangSupport:: |
| getUIDForRegionType(swift::ide::RegionType Type) { |
| switch (Type) { |
| case swift::ide::RegionType::ActiveCode: return KindEditActive; |
| case swift::ide::RegionType::InactiveCode: return KindEditInactive; |
| case swift::ide::RegionType::Selector: return KindEditSelector; |
| case swift::ide::RegionType::String: return KindEditString; |
| case swift::ide::RegionType::Comment: return KindEditComment; |
| case swift::ide::RegionType::Mismatch: return KindEditMismatch; |
| case swift::ide::RegionType::Unmatched: return KindEditUnknown; |
| } |
| } |
| |
| SourceKit::UIdent SwiftLangSupport:: |
| getUIDForRefactoringRangeKind(ide::RefactoringRangeKind Kind) { |
| switch (Kind) { |
| case ide::RefactoringRangeKind::BaseName: |
| return KindRenameRangeBase; |
| case ide::RefactoringRangeKind::KeywordBaseName: |
| return KindRenameRangeKeywordBase; |
| case ide::RefactoringRangeKind::ParameterName: |
| return KindRenameRangeParam; |
| case ide::RefactoringRangeKind::NoncollapsibleParameterName: |
| return KindRenameRangeNoncollapsibleParam; |
| case ide::RefactoringRangeKind::DeclArgumentLabel: |
| return KindRenameRangeDeclArgLabel; |
| case ide::RefactoringRangeKind::CallArgumentLabel: |
| return KindRenameRangeCallArgLabel; |
| case ide::RefactoringRangeKind::CallArgumentColon: |
| return KindRenameRangeCallArgColon; |
| case ide::RefactoringRangeKind::CallArgumentCombined: |
| return KindRenameRangeCallArgCombined; |
| case ide::RefactoringRangeKind::SelectorArgumentLabel: |
| return KindRenameRangeSelectorArgLabel; |
| } |
| } |
| |
| UIdent SwiftLangSupport::getUIDForSymbol(SymbolInfo sym, bool isRef) { |
| |
| #define UID_FOR(CLASS) isRef ? KindRef##CLASS : KindDecl##CLASS; |
| |
| switch (sym.SubKind) { |
| default: break; |
| case SymbolSubKind::AccessorGetter: return UID_FOR(AccessorGetter); |
| case SymbolSubKind::AccessorSetter: return UID_FOR(AccessorSetter); |
| case SymbolSubKind::SwiftAccessorWillSet: return UID_FOR(AccessorWillSet); |
| case SymbolSubKind::SwiftAccessorDidSet: return UID_FOR(AccessorDidSet); |
| case SymbolSubKind::SwiftAccessorAddressor: return UID_FOR(AccessorAddress); |
| case SymbolSubKind::SwiftAccessorMutableAddressor: return UID_FOR(AccessorMutableAddress); |
| } |
| |
| #define SIMPLE_CASE(KIND) \ |
| case SymbolKind::KIND: \ |
| return UID_FOR(KIND); |
| |
| switch (sym.Kind) { |
| SIMPLE_CASE(Enum) |
| SIMPLE_CASE(Struct) |
| SIMPLE_CASE(Class) |
| SIMPLE_CASE(Protocol) |
| SIMPLE_CASE(Constructor) |
| SIMPLE_CASE(Destructor) |
| |
| case SymbolKind::EnumConstant: |
| return UID_FOR(EnumElement); |
| |
| case SymbolKind::TypeAlias: |
| if (sym.SubKind == SymbolSubKind::SwiftAssociatedType) |
| return UID_FOR(AssociatedType); |
| if (sym.SubKind == SymbolSubKind::SwiftGenericTypeParam) |
| return UID_FOR(GenericTypeParam); |
| return UID_FOR(TypeAlias); |
| |
| case SymbolKind::Function: |
| case SymbolKind::StaticMethod: |
| if (sym.SubKind == SymbolSubKind::SwiftPrefixOperator) |
| return UID_FOR(FunctionPrefixOperator); |
| if (sym.SubKind == SymbolSubKind::SwiftPostfixOperator) |
| return UID_FOR(FunctionPostfixOperator); |
| if (sym.SubKind == SymbolSubKind::SwiftInfixOperator) |
| return UID_FOR(FunctionInfixOperator); |
| if (sym.Kind == SymbolKind::StaticMethod) { |
| return UID_FOR(MethodStatic); |
| } else { |
| return UID_FOR(FunctionFree); |
| } |
| case SymbolKind::Variable: |
| return UID_FOR(VarGlobal); |
| case SymbolKind::InstanceMethod: |
| return UID_FOR(MethodInstance); |
| case SymbolKind::ClassMethod: |
| return UID_FOR(MethodClass); |
| case SymbolKind::InstanceProperty: |
| if (sym.SubKind == SymbolSubKind::SwiftSubscript) |
| return UID_FOR(Subscript); |
| return UID_FOR(VarInstance); |
| case SymbolKind::ClassProperty: |
| return UID_FOR(VarClass); |
| case SymbolKind::StaticProperty: |
| return UID_FOR(VarStatic); |
| |
| case SymbolKind::Extension: |
| assert(!isRef && "reference to extension decl?"); |
| if (sym.SubKind == SymbolSubKind::SwiftExtensionOfStruct) { |
| return KindDeclExtensionStruct; |
| } else if (sym.SubKind == SymbolSubKind::SwiftExtensionOfClass) { |
| return KindDeclExtensionClass; |
| } else if (sym.SubKind == SymbolSubKind::SwiftExtensionOfEnum) { |
| return KindDeclExtensionEnum; |
| } else if (sym.SubKind == SymbolSubKind::SwiftExtensionOfProtocol) { |
| return KindDeclExtensionProtocol; |
| } else { |
| llvm_unreachable("missing extension sub kind"); |
| } |
| |
| case SymbolKind::Module: |
| return KindRefModule; |
| |
| default: |
| // TODO: reconsider whether having a default case is a good idea. |
| return UIdent(); |
| } |
| |
| #undef SIMPLE_CASE |
| #undef UID_FOR |
| } |
| |
| SourceKit::UIdent SwiftLangSupport::getUIDForNameKind(swift::ide::NameKind Kind) { |
| switch(Kind) { |
| case swift::ide::NameKind::ObjC: return KindNameObjc; |
| case swift::ide::NameKind::Swift: return KindNameSwift; |
| } |
| |
| llvm_unreachable("Unhandled NameKind in switch."); |
| } |
| |
| swift::ide::NameKind SwiftLangSupport::getNameKindForUID(SourceKit::UIdent Id) { |
| if (Id == KindNameObjc) |
| return swift::ide::NameKind::ObjC; |
| assert(Id == KindNameSwift); |
| return swift::ide::NameKind::Swift; |
| } |
| |
| Optional<UIdent> SwiftLangSupport::getUIDForDeclAttribute(const swift::DeclAttribute *Attr) { |
| // Check special-case names first. |
| switch (Attr->getKind()) { |
| case DAK_IBAction: { |
| return Attr_IBAction; |
| } |
| case DAK_IBSegueAction: { |
| static UIdent Attr_IBSegueAction("source.decl.attribute.ibsegueaction"); |
| return Attr_IBSegueAction; |
| } |
| case DAK_IBOutlet: { |
| return Attr_IBOutlet; |
| } |
| case DAK_IBDesignable: { |
| return Attr_IBDesignable; |
| } |
| case DAK_IBInspectable: { |
| return Attr_IBInspectable; |
| } |
| case DAK_GKInspectable: { |
| return Attr_GKInspectable; |
| } |
| case DAK_ObjC: { |
| if (cast<ObjCAttr>(Attr)->hasName()) { |
| return Attr_ObjcNamed; |
| } else { |
| return Attr_Objc; |
| } |
| } |
| case DAK_AccessControl: { |
| switch (cast<AbstractAccessControlAttr>(Attr)->getAccess()) { |
| case AccessLevel::Private: |
| return Attr_Private; |
| case AccessLevel::FilePrivate: |
| return Attr_FilePrivate; |
| case AccessLevel::Internal: |
| return Attr_Internal; |
| case AccessLevel::Public: |
| return Attr_Public; |
| case AccessLevel::Open: |
| return Attr_Open; |
| } |
| } |
| case DAK_SetterAccess: { |
| switch (cast<AbstractAccessControlAttr>(Attr)->getAccess()) { |
| case AccessLevel::Private: |
| return Attr_Setter_Private; |
| case AccessLevel::FilePrivate: |
| return Attr_Setter_FilePrivate; |
| case AccessLevel::Internal: |
| return Attr_Setter_Internal; |
| case AccessLevel::Public: |
| return Attr_Setter_Public; |
| case AccessLevel::Open: |
| return Attr_Setter_Open; |
| } |
| } |
| |
| // Ignore these. |
| case DAK_ShowInInterface: |
| case DAK_RawDocComment: |
| case DAK_HasInitialValue: |
| case DAK_HasStorage: |
| return None; |
| default: |
| break; |
| } |
| |
| switch (Attr->getKind()) { |
| case DAK_Count: |
| break; |
| #define DECL_ATTR(X, CLASS, ...)\ |
| case DAK_##CLASS: {\ |
| static UIdent Attr_##X("source.decl.attribute."#X); \ |
| return Attr_##X; \ |
| } |
| #include "swift/AST/Attr.def" |
| } |
| |
| return None; |
| } |
| |
| std::vector<UIdent> SwiftLangSupport::UIDsFromDeclAttributes(const DeclAttributes &Attrs) { |
| std::vector<UIdent> AttrUIDs; |
| |
| for (auto Attr : Attrs) { |
| if (auto AttrUID = getUIDForDeclAttribute(Attr)) { |
| AttrUIDs.push_back(AttrUID.getValue()); |
| } |
| } |
| |
| return AttrUIDs; |
| } |
| |
| bool SwiftLangSupport::printDisplayName(const swift::ValueDecl *D, |
| llvm::raw_ostream &OS) { |
| if (!D->hasName()) |
| return true; |
| |
| OS << D->getFullName(); |
| return false; |
| } |
| |
| bool SwiftLangSupport::printUSR(const ValueDecl *D, llvm::raw_ostream &OS) { |
| return ide::printDeclUSR(D, OS); |
| } |
| |
| bool SwiftLangSupport::printDeclTypeUSR(const ValueDecl *D, llvm::raw_ostream &OS) { |
| return ide::printDeclTypeUSR(D, OS); |
| } |
| |
| bool SwiftLangSupport::printTypeUSR(Type Ty, llvm::raw_ostream &OS) { |
| return ide::printTypeUSR(Ty, OS); |
| } |
| |
| bool SwiftLangSupport::printAccessorUSR(const AbstractStorageDecl *D, |
| AccessorKind AccKind, |
| llvm::raw_ostream &OS) { |
| return ide::printAccessorUSR(D, AccKind, OS); |
| } |
| |
| void SwiftLangSupport::printMemberDeclDescription(const swift::ValueDecl *VD, |
| swift::Type baseTy, |
| bool usePlaceholder, |
| llvm::raw_ostream &OS) { |
| // Base name. |
| OS << VD->getBaseName().userFacingName(); |
| |
| // Parameters. |
| auto *M = VD->getModuleContext(); |
| auto substMap = baseTy->getMemberSubstitutionMap(M, VD); |
| auto printSingleParam = [&](ParamDecl *param) { |
| auto paramTy = param->getInterfaceType(); |
| |
| // Label. |
| if (!param->getArgumentName().empty()) |
| OS << param->getArgumentName() << ": "; |
| |
| // InOut. |
| if (param->isInOut()) { |
| OS << "&"; |
| paramTy = paramTy->getInOutObjectType(); |
| } |
| |
| // Type. |
| if (usePlaceholder) |
| OS << "<#T##"; |
| |
| paramTy = paramTy.subst(substMap); |
| if (paramTy->hasError() && param->getTypeLoc().hasLocation()) { |
| // Fallback to 'TypeRepr' printing. |
| param->getTypeLoc().getTypeRepr()->print(OS); |
| } else { |
| paramTy.print(OS); |
| } |
| |
| if (usePlaceholder) |
| OS << "#>"; |
| }; |
| auto printParams = [&](const ParameterList *params) { |
| OS << '('; |
| bool isFirst = true; |
| for (auto param : params->getArray()) { |
| if (isFirst) |
| isFirst = false; |
| else |
| OS << ", "; |
| printSingleParam(param); |
| } |
| OS << ')'; |
| }; |
| if (auto EED = dyn_cast<EnumElementDecl>(VD)) { |
| if (auto params = EED->getParameterList()) |
| printParams(params); |
| } else if (auto *FD = dyn_cast<FuncDecl>(VD)) { |
| if (auto params = FD->getParameters()) |
| printParams(params); |
| } else if (isa<VarDecl>(VD)) { |
| // Var decl doesn't have parameters. |
| } else { |
| llvm_unreachable("Unsupported Decl kind for printMemberDeclDescription()"); |
| } |
| } |
| |
| std::string SwiftLangSupport::resolvePathSymlinks(StringRef FilePath) { |
| std::string InputPath = FilePath; |
| #if !defined(_WIN32) |
| char full_path[MAXPATHLEN]; |
| if (const char *path = realpath(InputPath.c_str(), full_path)) |
| return path; |
| |
| return InputPath; |
| #else |
| wchar_t full_path[MAX_PATH] = {0}; |
| llvm::SmallVector<llvm::UTF16, 50> utf16Path; |
| llvm::convertUTF8ToUTF16String(InputPath.c_str(), utf16Path); |
| |
| HANDLE fileHandle = CreateFileW( |
| (LPCWSTR)utf16Path.data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, |
| OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); |
| |
| if (fileHandle == INVALID_HANDLE_VALUE) |
| return InputPath; |
| |
| DWORD numChars = GetFinalPathNameByHandleW(fileHandle, full_path, MAX_PATH, |
| FILE_NAME_NORMALIZED); |
| CloseHandle(fileHandle); |
| std::string utf8Path; |
| if (numChars > 0 && numChars <= MAX_PATH) { |
| llvm::ArrayRef<char> pathRef((const char *)full_path, |
| (const char *)(full_path + numChars)); |
| return llvm::convertUTF16ToUTF8String(pathRef, utf8Path) ? utf8Path |
| : InputPath; |
| } |
| return InputPath; |
| #endif |
| } |
| |
| void SwiftLangSupport::getStatistics(StatisticsReceiver receiver) { |
| std::vector<Statistic *> stats = { |
| #define SWIFT_STATISTIC(VAR, UID, DESC) &Stats->VAR, |
| #include "SwiftStatistics.def" |
| }; |
| receiver(stats); |
| } |
| |
| // SWIFT_ENABLE_TENSORFLOW |
| void SwiftLangSupport::codeComplete( |
| llvm::MemoryBuffer *InputBuf, unsigned Offset, |
| CodeCompletionConsumer &Consumer, ArrayRef<const char *> Args, |
| llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { |
| VFSOptions vfsOptions; |
| vfsOptions.name = "directly-passed-vfs"; |
| auto *provider = static_cast<DirectlyPassedFileSystemProvider *>( |
| getFileSystemProvider(vfsOptions.name)); |
| assert(provider); |
| auto options = provider->addFileSystem(FS); |
| vfsOptions.options = |
| llvm::make_unique<DirectlyPassedFileSystemProvider::Options>(options); |
| codeComplete(InputBuf, Offset, Consumer, Args, std::move(vfsOptions)); |
| provider->removeFileSystem(options); |
| } |
| |
| void SwiftLangSupport::editorOpen( |
| StringRef Name, llvm::MemoryBuffer *Buf, EditorConsumer &Consumer, |
| ArrayRef<const char *> Args, |
| llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { |
| VFSOptions vfsOptions; |
| vfsOptions.name = "directly-passed-vfs"; |
| auto *provider = static_cast<DirectlyPassedFileSystemProvider *>( |
| getFileSystemProvider(vfsOptions.name)); |
| assert(provider); |
| auto options = provider->addFileSystem(FS); |
| vfsOptions.options = |
| llvm::make_unique<DirectlyPassedFileSystemProvider::Options>(options); |
| editorOpen(Name, Buf, Consumer, Args, std::move(vfsOptions)); |
| provider->removeFileSystem(options); |
| } |
| |
| |
| FileSystemProvider *SwiftLangSupport::getFileSystemProvider(StringRef Name) { |
| auto It = FileSystemProviders.find(Name); |
| if (It == FileSystemProviders.end()) |
| return nullptr; |
| return It->second.get(); |
| } |
| |
| void SwiftLangSupport::setFileSystemProvider( |
| StringRef Name, std::unique_ptr<FileSystemProvider> FileSystemProvider) { |
| assert(FileSystemProvider); |
| auto Result = FileSystemProviders.try_emplace(Name, std::move(FileSystemProvider)); |
| assert(Result.second && "tried to set existing FileSystemProvider"); |
| } |
| |
| llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> |
| SwiftLangSupport::getFileSystem(const Optional<VFSOptions> &vfsOptions, |
| Optional<StringRef> primaryFile, |
| std::string &error) { |
| // First, try the specified vfsOptions. |
| if (vfsOptions) { |
| auto provider = getFileSystemProvider(vfsOptions->name); |
| if (!provider) { |
| error = "unknown virtual filesystem '" + vfsOptions->name + "'"; |
| return nullptr; |
| } |
| |
| return provider->getFileSystem(*vfsOptions->options, error); |
| } |
| |
| // Otherwise, try to find an open document with a filesystem. |
| if (primaryFile) { |
| if (auto doc = EditorDocuments->getByUnresolvedName(*primaryFile)) { |
| return doc->getFileSystem(); |
| } |
| } |
| |
| // Fallback to the real filesystem. |
| return llvm::vfs::getRealFileSystem(); |
| } |
| |
| CloseClangModuleFiles::~CloseClangModuleFiles() { |
| clang::Preprocessor &PP = loader.getClangPreprocessor(); |
| clang::ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); |
| for (auto I = ModMap.module_begin(), E = ModMap.module_end(); I != E; ++I) { |
| clang::Module *M = I->second; |
| if (!M->isSubModule() && M->getASTFile()) |
| M->getASTFile()->closeFile(); |
| } |
| } |
| |
| void SourceKit::disableExpensiveSILOptions(SILOptions &Opts) { |
| // Disable the sanitizers. |
| Opts.Sanitizers = {}; |
| |
| // Disable PGO and code coverage. |
| Opts.GenerateProfile = false; |
| Opts.EmitProfileCoverageMapping = false; |
| Opts.UseProfile = ""; |
| } |