diff --git a/include/swift/Basic/LoadDynamicLibrary.h b/include/swift/Basic/LoadDynamicLibrary.h new file mode 100644 index 0000000000000..55969f803b611 --- /dev/null +++ b/include/swift/Basic/LoadDynamicLibrary.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 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_BASIC_LOADDYNAMICLIBRARY_H +#define SWIFT_BASIC_LOADDYNAMICLIBRARY_H + +#include + +namespace swift { +void *loadLibrary(const char *path, std::string *err); +void *getAddressOfSymbol(void *handle, const char *symbol); +} // end namespace swift + +#endif // SWIFT_BASIC_LOADDYNAMICLIBRARY_H diff --git a/lib/AST/PluginRegistry.cpp b/lib/AST/PluginRegistry.cpp index 7231e691c56f3..bbfffe9ef319b 100644 --- a/lib/AST/PluginRegistry.cpp +++ b/lib/AST/PluginRegistry.cpp @@ -14,6 +14,7 @@ #include "swift/Basic/Assertions.h" #include "swift/Basic/Defer.h" +#include "swift/Basic/LoadDynamicLibrary.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/Program.h" #include "swift/Basic/Sandbox.h" @@ -25,16 +26,6 @@ #include -#if defined(_WIN32) -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Windows/WindowsSupport.h" -#include -#else -#include -#endif - #if HAVE_UNISTD_H #include #elif defined(_WIN32) @@ -43,46 +34,6 @@ using namespace swift; -namespace { -void *loadLibrary(const char *path, std::string *err); -void *getAddressOfSymbol(void *handle, const char *symbol); - -#if defined(_WIN32) -void *loadLibrary(const char *path, std::string *err) { - SmallVector pathUnicode; - if (std::error_code ec = llvm::sys::windows::UTF8ToUTF16(path, pathUnicode)) { - SetLastError(ec.value()); - llvm::MakeErrMsg(err, std::string(path) + ": Can't convert to UTF-16"); - return nullptr; - } - - HMODULE handle = LoadLibraryW(pathUnicode.data()); - if (handle == NULL) { - llvm::MakeErrMsg(err, std::string(path) + ": Can't open"); - return nullptr; - } - return (void *)handle; -} - -void *getAddressOfSymbol(void *handle, const char *symbol) { - return (void *)uintptr_t(GetProcAddress((HMODULE)handle, symbol)); -} - -#else -void *loadLibrary(const char *path, std::string *err) { - void *handle = ::dlopen(path, RTLD_LAZY | RTLD_LOCAL); - if (!handle) - *err = ::dlerror(); - return handle; -} - -void *getAddressOfSymbol(void *handle, const char *symbol) { - return ::dlsym(handle, symbol); -} - -#endif -} // namespace - PluginRegistry::PluginRegistry() { dumpMessaging = ::getenv("SWIFT_DUMP_PLUGIN_MESSAGING") != nullptr; } diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt index 32da9a1a860ac..8047cbec21ad1 100644 --- a/lib/Basic/CMakeLists.txt +++ b/lib/Basic/CMakeLists.txt @@ -58,6 +58,7 @@ add_swift_host_library(swiftBasic STATIC ParseableOutput.cpp JSONSerialization.cpp LangOptions.cpp + LoadDynamicLibrary.cpp Located.cpp Mangler.cpp OutputFileMap.cpp diff --git a/lib/Basic/LoadDynamicLibrary.cpp b/lib/Basic/LoadDynamicLibrary.cpp new file mode 100644 index 0000000000000..4e14d4f36a1b9 --- /dev/null +++ b/lib/Basic/LoadDynamicLibrary.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 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 "swift/Basic/LoadDynamicLibrary.h" + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Windows/WindowsSupport.h" +#include "swift/Basic/LLVM.h" +#include +#else +#include +#endif + +#if defined(_WIN32) +void *swift::loadLibrary(const char *path, std::string *err) { + SmallVector pathUnicode; + if (std::error_code ec = llvm::sys::windows::UTF8ToUTF16(path, pathUnicode)) { + SetLastError(ec.value()); + llvm::MakeErrMsg(err, std::string(path) + ": Can't convert to UTF-16"); + return nullptr; + } + + HMODULE handle = LoadLibraryW(pathUnicode.data()); + if (handle == NULL) { + llvm::MakeErrMsg(err, std::string(path) + ": Can't open"); + return nullptr; + } + return (void *)handle; +} + +void *swift::getAddressOfSymbol(void *handle, const char *symbol) { + return (void *)uintptr_t(GetProcAddress((HMODULE)handle, symbol)); +} + +#else +void *swift::loadLibrary(const char *path, std::string *err) { + void *handle = ::dlopen(path, RTLD_LAZY | RTLD_LOCAL); + if (!handle) + *err = ::dlerror(); + return handle; +} + +void *swift::getAddressOfSymbol(void *handle, const char *symbol) { + return ::dlsym(handle, symbol); +} +#endif \ No newline at end of file diff --git a/tools/SourceKit/include/SourceKit/Core/Context.h b/tools/SourceKit/include/SourceKit/Core/Context.h index a269ba486abc2..5e7118a47025f 100644 --- a/tools/SourceKit/include/SourceKit/Core/Context.h +++ b/tools/SourceKit/include/SourceKit/Core/Context.h @@ -31,28 +31,30 @@ namespace llvm { namespace SourceKit { class LangSupport; class NotificationCenter; - -class GlobalConfig { -public: - struct Settings { - struct IDEInspectionOptions { - - /// Max count of reusing ASTContext for cached IDE inspection. - unsigned MaxASTContextReuseCount = 100; - - /// Interval second for checking dependencies in cached IDE inspection. - unsigned CheckDependencyInterval = 5; - } IDEInspectionOpts; - }; - -private: - Settings State; - mutable llvm::sys::Mutex Mtx; - -public: - Settings update(std::optional IDEInspectionMaxASTContextReuseCount, - std::optional IDEInspectionCheckDependencyInterval); - Settings::IDEInspectionOptions getIDEInspectionOpts() const; + class PluginSupport; + + class GlobalConfig { + public: + struct Settings { + struct IDEInspectionOptions { + + /// Max count of reusing ASTContext for cached IDE inspection. + unsigned MaxASTContextReuseCount = 100; + + /// Interval second for checking dependencies in cached IDE inspection. + unsigned CheckDependencyInterval = 5; + } IDEInspectionOpts; + }; + + private: + Settings State; + mutable llvm::sys::Mutex Mtx; + + public: + Settings + update(std::optional IDEInspectionMaxASTContextReuseCount, + std::optional IDEInspectionCheckDependencyInterval); + Settings::IDEInspectionOptions getIDEInspectionOpts() const; }; /// Keeps track of all requests that are currently in progress and coordinates @@ -169,6 +171,7 @@ class Context { std::shared_ptr NotificationCtr; std::shared_ptr Config; std::shared_ptr ReqTracker; + std::shared_ptr Plugins; std::shared_ptr SlowRequestSim; public: @@ -176,6 +179,8 @@ class Context { StringRef DiagnosticDocumentationPath, llvm::function_ref(Context &)> LangSupportFactoryFn, + llvm::function_ref(Context &)> + PluginSupportFactoryFn, bool shouldDispatchNotificationsOnMain = true); ~Context(); @@ -192,6 +197,8 @@ class Context { std::shared_ptr getGlobalConfiguration() { return Config; } + std::shared_ptr getPlugins() { return Plugins; } + std::shared_ptr getSlowRequestSimulator() { return SlowRequestSim; } diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h index 2fc820fb178e6..4b143b0f8ea8c 100644 --- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h +++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h @@ -1024,6 +1024,8 @@ class LangSupport { virtual ~LangSupport() { } + virtual void *getOpaqueSwiftIDEInspectionInstance() { return nullptr; } + virtual void globalConfigurationUpdated(std::shared_ptr Config) {}; virtual void dependencyUpdated() {} diff --git a/tools/SourceKit/lib/Core/Context.cpp b/tools/SourceKit/lib/Core/Context.cpp index 609b65779b95a..6f8bba5667289 100644 --- a/tools/SourceKit/lib/Core/Context.cpp +++ b/tools/SourceKit/lib/Core/Context.cpp @@ -40,6 +40,8 @@ SourceKit::Context::Context( StringRef DiagnosticDocumentationPath, llvm::function_ref(Context &)> LangSupportFactoryFn, + llvm::function_ref(Context &)> + PluginSupportFactoryFn, bool shouldDispatchNotificationsOnMain) : SwiftExecutablePath(SwiftExecutablePath), RuntimeLibPath(RuntimeLibPath), DiagnosticDocumentationPath(DiagnosticDocumentationPath), @@ -49,6 +51,7 @@ SourceKit::Context::Context( SlowRequestSim(new SlowRequestSimulator(ReqTracker)) { // Should be called last after everything is initialized. SwiftLang = LangSupportFactoryFn(*this); + Plugins = PluginSupportFactoryFn(*this); } SourceKit::Context::~Context() { diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h index 716299b19c9c3..aced4a4059c47 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h @@ -534,6 +534,10 @@ class SwiftLangSupport : public LangSupport { // LangSupport Interface //==========================================================================// + void *getOpaqueSwiftIDEInspectionInstance() override { + return IDEInspectionInst.get(); + } + void globalConfigurationUpdated(std::shared_ptr Config) override; void dependencyUpdated() override; diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CMakeLists.txt b/tools/SourceKit/tools/sourcekitd/bin/InProc/CMakeLists.txt index a7d239a7e435c..6d70803a2b025 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CMakeLists.txt +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CMakeLists.txt @@ -11,6 +11,7 @@ swift_is_installing_component(sourcekit-inproc SOURCEKIT_INSTALLING_INPROC) set(sourcekitdInProc_args sourcekitdInProc.cpp + CodeCompletionSwiftInterop.cpp LLVM_LINK_COMPONENTS support coverage ) @@ -18,6 +19,8 @@ if (SOURCEKIT_INSTALLING_INPROC) if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") add_sourcekit_framework(sourcekitdInProc ${SOURCEKITD_SOURCE_DIR}/include/sourcekitd/sourcekitd.h + ${SOURCEKITD_SOURCE_DIR}/include/sourcekitd/plugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/CodeCompletionSwiftInterop.h ${sourcekitdInProc_args} MODULEMAP module.modulemap INSTALL_IN_COMPONENT sourcekit-inproc diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp new file mode 100644 index 0000000000000..106361e973ac6 --- /dev/null +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -0,0 +1,905 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 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 "CodeCompletionSwiftInterop.h" +#include "SourceKit/Core/Context.h" +#include "sourcekitd/sourcekitdInProc-Internal.h" +#include "swift/AST/ASTPrinter.h" +#include "swift/AST/USRGeneration.h" +#include "swift/Basic/StringExtras.h" +#include "swift/Driver/FrontendUtil.h" +#include "swift/Frontend/PrintingDiagnosticConsumer.h" +#include "swift/IDE/CodeCompletion.h" +#include "swift/IDE/CodeCompletionCache.h" +#include "swift/IDE/CodeCompletionResultPrinter.h" +#include "swift/IDE/FuzzyStringMatcher.h" +#include "swift/IDE/Utils.h" +#include "swift/IDETool/CompilerInvocation.h" +#include "swift/IDETool/IDEInspectionInstance.h" +#include "llvm/Support/Signals.h" +#include + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#else +#include +#endif + +using namespace swift; +using namespace swift::ide; +using namespace sourcekitdInProc; + +static std::string getRuntimeResourcesPath(); + +using FileSystemRef = llvm::IntrusiveRefCntPtr; + +namespace { +struct CompletionResult; + +class SharedStringInMemoryFS : public llvm::vfs::InMemoryFileSystem { + SmallVector, 8> strings; + +public: + SharedStringInMemoryFS( + const llvm::StringMap> &files) { + strings.reserve(files.size()); + for (auto &pair : files) { + strings.push_back(pair.getValue()); + auto buffer = + llvm::MemoryBuffer::getMemBuffer(*pair.getValue(), pair.getKey()); + if (!addFile(pair.getKey(), /*ModTime=*/0, std::move(buffer))) { + // FIXME: report error! + } + } + } +}; + +class Connection { + IDEInspectionInstance *ideInspectionInstance; + /// If the connection was not passed an `IDEInspectionInstance` it creates + /// its own. This unique_ptr scopes the lifetime of 'ideInspectionInstance' + /// to the lifetime of 'Connection'. + std::unique_ptr ownedIDEInspectionInstance; + llvm::StringMap> modifiedFiles; + std::shared_ptr completionCache; + std::string swiftExecutablePath; + std::string runtimeResourcePath; + std::string diagnosticsDocumentationPath; + std::shared_ptr requestTracker; + +public: + std::unique_ptr currentResponse; + const time_t sessionTimestamp; + + Connection(IDEInspectionInstance *ideInspectionInstance) + : ideInspectionInstance(ideInspectionInstance), + completionCache(std::make_shared()), + swiftExecutablePath(getSwiftExecutablePath()), + runtimeResourcePath(getRuntimeResourcesPath()), + diagnosticsDocumentationPath(getDiagnosticDocumentationPath()), + requestTracker(new SourceKit::RequestTracker()), + sessionTimestamp(llvm::sys::toTimeT(std::chrono::system_clock::now())) { + if (ideInspectionInstance == nullptr) { + this->ownedIDEInspectionInstance.reset(new IDEInspectionInstance()); + this->ideInspectionInstance = this->ownedIDEInspectionInstance.get(); + } + } + + void setFileContents(StringRef path, const char *contents) { + if (contents) { + modifiedFiles[path] = std::make_shared(contents); + } else { + modifiedFiles.erase(path); + } + } + + std::shared_ptr getCompletionCache() const { + return completionCache; + } + + FileSystemRef createFileSystem() { + auto *overlayFS = + new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()); + overlayFS->pushOverlay(new SharedStringInMemoryFS(modifiedFiles)); + return overlayFS; + } + + void cancelRequest(SourceKit::SourceKitCancellationToken cancellationToken) { + requestTracker->cancel(cancellationToken); + } + + void codeComplete( + StringRef path, unsigned offset, ArrayRef args, + FileSystemRef fileSystem, ide::CodeCompletionContext &completionContext, + SourceKit::SourceKitCancellationToken cancellationToken, + llvm::function_ref)> callback); + + void markCachedCompilerInstanceShouldBeInvalidated() { + ideInspectionInstance->markCachedCompilerInstanceShouldBeInvalidated(); + } +}; + +} // anonymous namespace + +swiftide_connection_t swiftide_connection_create(void) { + return swiftide_connection_create_with_inspection_instance(nullptr); +} + +swiftide_connection_t swiftide_connection_create_with_inspection_instance( + void *opaqueIDESwiftInspectionInstance) { + static std::once_flag once; + std::call_once( + once, [] { llvm::sys::PrintStackTraceOnErrorSignal("IDESwiftInterop"); }); + IDEInspectionInstance *inspectInstance = + static_cast(opaqueIDESwiftInspectionInstance); + + return static_cast(new Connection(inspectInstance)); +} + +void swiftide_connection_dispose(swiftide_connection_t conn) { + assert(conn); + delete static_cast(conn); +} + +void swiftide_connection_mark_cached_compiler_instance_should_be_invalidated( + swiftide_connection_t _conn, swiftide_cache_invalidation_options_t _opts) { + auto *conn = static_cast(_conn); + // '_opts' is not used at this point. + assert(conn); + conn->markCachedCompilerInstanceShouldBeInvalidated(); +} + +void swiftide_set_file_contents(swiftide_connection_t _conn, const char *path, + const char *contents) { + auto *conn = static_cast(_conn); + assert(conn); + conn->setFileContents(path, contents); +} + +namespace { +struct CompletionResult { + Connection &conn; + CodeCompletionContext context; + ImportDepth importDepth; + std::string error; + bool isCancelled = false; + SmallString<0> scratch; + CodeCompletionResultSink resultSink; + /// The compiler instance that produced the results. Used to lazily compute + /// diagnostics for results. + std::shared_ptr compilerInstance; + + CompletionResult(Connection &conn) + : conn(conn), context(*conn.getCompletionCache()) { + // Pre-allocate a whole page. Empirically, this is enough to cover the vast + // majority of cases. + scratch.reserve(4096); + } + + bool hasError() const { return !error.empty(); } + + ArrayRef getCompletions() { + return resultSink.Results; + } +}; + +struct SwiftInteropCodeCompletionConsumer : public ide::CodeCompletionConsumer { + CompletionResult &result; + + SwiftInteropCodeCompletionConsumer(CompletionResult &result) + : result(result) {} + + void handleResults(CodeCompletionContext &context) override { + assert(&context == &(result.context)); + } +}; + +struct CompletionRequest { + llvm::BumpPtrAllocator allocator; + StringRef path; + unsigned offset; + std::vector compilerArguments; + bool annotateResult = false; + bool includeObjectLiterals = true; + bool addInitsToTopLevel = false; + bool addCallWithNoDefaultArgs = true; + + CompletionRequest(const char *path, unsigned offset, + ArrayRef args) { + this->path = StringRef(path).copy(allocator); + this->offset = offset; + compilerArguments.reserve(args.size()); + for (const char *arg : args) { + compilerArguments.push_back(copyCString(arg, allocator)); + } + } +}; + +} // namespace + +void swiftide_cancel_request(swiftide_connection_t _conn, + swiftide_request_handle_t handle) { + assert(_conn); + auto *conn = static_cast(_conn); + conn->cancelRequest(handle); +} + +swiftide_completion_request_t +swiftide_completion_request_create(const char *path, uint32_t offset, + char *const *const compiler_args, + uint32_t num_compiler_args) { + + return new CompletionRequest( + path, offset, llvm::ArrayRef(compiler_args, num_compiler_args)); +} + +void swiftide_completion_request_dispose(swiftide_completion_request_t _req) { + delete static_cast(_req); +} + +void swiftide_completion_request_set_annotate_result( + swiftide_completion_request_t _req, bool annotate) { + auto &req = *static_cast(_req); + req.annotateResult = annotate; +} + +void swiftide_completion_request_set_include_objectliterals( + swiftide_completion_request_t _req, bool flag) { + auto &req = *static_cast(_req); + req.includeObjectLiterals = flag; +} + +void swiftide_completion_request_set_add_inits_to_top_level( + swiftide_completion_request_t _req, bool flag) { + auto &req = *static_cast(_req); + req.addInitsToTopLevel = flag; +} + +void swiftide_completion_request_set_add_call_with_no_default_args( + swiftide_completion_request_t _req, bool flag) { + auto &req = *static_cast(_req); + req.addCallWithNoDefaultArgs = flag; +} + +swiftide_completion_response_t +swiftide_complete_cancellable(swiftide_connection_t _conn, + swiftide_completion_request_t _req, + swiftide_request_handle_t handle) { + assert(_conn && _req); + auto *conn = static_cast(_conn); + auto &req = *static_cast(_req); + + if (conn->currentResponse) { + llvm::report_fatal_error( + "must dispose of previous response before completing again"); + } + + conn->currentResponse = std::make_unique(*conn); + auto result = conn->currentResponse.get(); + + SwiftInteropCodeCompletionConsumer consumer(*result); + + auto fileSystem = conn->createFileSystem(); + + result->context.setAnnotateResult(req.annotateResult); + result->context.setIncludeObjectLiterals(req.includeObjectLiterals); + result->context.setAddInitsToTopLevel(req.addInitsToTopLevel); + result->context.setAddCallWithNoDefaultArgs(req.addCallWithNoDefaultArgs); + + conn->codeComplete( + req.path, req.offset, req.compilerArguments, fileSystem, result->context, + handle, [&result](CancellableResult completeResult) { + switch (completeResult.getKind()) { + case CancellableResultKind::Success: + result->importDepth = completeResult->ImportDep; + result->resultSink = completeResult->ResultSink; + result->compilerInstance = completeResult->Info.compilerInstance; + break; + case CancellableResultKind::Failure: + result->error = completeResult.getError(); + break; + case CancellableResultKind::Cancelled: + result->isCancelled = true; + break; + } + }); + + return static_cast(result); +} + +swiftide_completion_response_t +swiftide_complete(swiftide_connection_t _conn, + swiftide_completion_request_t _req) { + // handle = nullptr indicates that the request can't be cancelled. + return swiftide_complete_cancellable(_conn, _req, /*handle=*/nullptr); +} + +void Connection::codeComplete( + StringRef path, unsigned offset, ArrayRef args, + FileSystemRef fileSystem, ide::CodeCompletionContext &completionContext, + SourceKit::SourceKitCancellationToken cancellationToken, + llvm::function_ref)> callback) { + using ResultType = CancellableResult; + // Resolve symlinks for the input file; we resolve them for the input files + // in the arguments as well. + // FIXME: We need the Swift equivalent of Clang's FileEntry. + llvm::SmallString<128> bufferIdentifier; + if (auto err = fileSystem->getRealPath(path, bufferIdentifier)) + bufferIdentifier = path; + + auto inputFile = fileSystem->openFileForRead(path); + if (auto err = inputFile.getError()) { + std::string error; + llvm::raw_string_ostream OS(error); + OS << "failed to open '" << path << "': " << err.message(); + callback(ResultType::failure(error)); + return; + } + + auto inputBuffer = inputFile->get()->getBuffer(bufferIdentifier); + if (auto err = inputBuffer.getError()) { + std::string error; + llvm::raw_string_ostream OS(error); + OS << "failed to read '" << path << "': " << err.message(); + callback(ResultType::failure(error)); + return; + } + + // Create a buffer for code completion. This contains '\0' at 'Offset' + // position of 'UnresolvedInputFile' buffer. + auto newBuffer = ide::makeCodeCompletionMemoryBuffer( + inputBuffer.get().get(), offset, bufferIdentifier); + + CompilerInvocation invocation; + SourceManager SM; + DiagnosticEngine diags(SM); + ForwardingDiagnosticConsumer ciDiags(diags); + PrintingDiagnosticConsumer printDiags; + diags.addConsumer(printDiags); + + std::string compilerInvocationError; + bool creatingInvocationFailed = initCompilerInvocation( + invocation, args, FrontendOptions::ActionType::Typecheck, diags, path, + fileSystem, swiftExecutablePath, runtimeResourcePath, + diagnosticsDocumentationPath, sessionTimestamp, compilerInvocationError); + if (creatingInvocationFailed) { + callback(ResultType::failure(compilerInvocationError)); + return; + } else if (!invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) { + callback(ResultType::failure("no input filenames specified")); + return; + } + auto cancellationFlag = std::make_shared>(false); + requestTracker->setCancellationHandler( + cancellationToken, [cancellationFlag]() { + cancellationFlag->store(true, std::memory_order_relaxed); + }); + + ideInspectionInstance->codeComplete( + invocation, args, fileSystem, newBuffer.get(), offset, &ciDiags, + completionContext, cancellationFlag, callback); +} + +void swiftide_completion_result_dispose(swiftide_completion_response_t result) { + auto *response = static_cast(result); + auto &conn = response->conn; + assert(conn.currentResponse.get() == response); + conn.currentResponse = nullptr; +} + +bool swiftide_completion_result_is_error( + swiftide_completion_response_t _result) { + auto &result = *static_cast(_result); + return result.hasError(); +} + +const char *swiftide_completion_result_get_error_description( + swiftide_completion_response_t _result) { + auto &result = *static_cast(_result); + return result.error.c_str(); +} + +bool swiftide_completion_result_is_cancelled( + swiftide_completion_response_t _result) { + auto result = static_cast(_result); + return result->isCancelled; +} + +/// Copies a string representation of the completion result. This string should +/// be disposed of with \c free when done. +const char *swiftide_completion_result_description_copy( + swiftide_completion_response_t _result) { + auto &result = *static_cast(_result); + std::string desc; + do { + llvm::raw_string_ostream OS(desc); + if (result.hasError()) { + OS << "error: " << result.error; + break; + } + + /// FXIME: this code copied from PrintingCodeCompletionConsumer + OS << "Begin completions, " << result.getCompletions().size() << " items\n"; + for (auto *item : result.getCompletions()) { + item->printPrefix(OS); + if (result.context.getAnnotateResult()) { + printCodeCompletionResultDescriptionAnnotated( + *item, OS, /*leadingPunctuation=*/false); + OS << "; typename="; + printCodeCompletionResultTypeNameAnnotated(*item, OS); + } else { + item->getCompletionString()->print(OS); + } + + OS << "; name=" << item->getFilterName(); + OS << "\n"; + } + OS << "End completions\n"; + } while (0); + return strdup(desc.c_str()); +} + +void swiftide_completion_result_get_completions( + swiftide_completion_response_t _result, + void (^completions_handler)(const swiftide_completion_item_t *completions, + const char **filter_names, + uint64_t num_completions)) { + auto &result = *static_cast(_result); + if (result.hasError() || result.getCompletions().empty()) { + completions_handler(nullptr, nullptr, 0); + return; + } + + std::vector filterNames; + filterNames.reserve(result.getCompletions().size()); + for (auto *item : result.getCompletions()) { + filterNames.push_back(item->getFilterName().data()); + } + + assert(filterNames.size() == result.getCompletions().size()); + + completions_handler( + (const swiftide_completion_item_t *)result.getCompletions().data(), + filterNames.data(), result.getCompletions().size()); +} + +swiftide_completion_item_t swiftide_completion_result_get_completion_at_index( + swiftide_completion_response_t _response, uint64_t index) { + auto &response = *static_cast(_response); + if (response.hasError() || response.getCompletions().size() < index) { + return nullptr; + } + return response.getCompletions()[index]; +} + +swiftide_completion_kind_t +swiftide_completion_result_get_kind(swiftide_completion_response_t _response) { + auto &response = *static_cast(_response); + switch (response.context.CodeCompletionKind) { + case CompletionKind::None: + return SWIFTIDE_COMPLETION_KIND_NONE; + case CompletionKind::Import: + return SWIFTIDE_COMPLETION_KIND_IMPORT; + case CompletionKind::UnresolvedMember: + return SWIFTIDE_COMPLETION_KIND_UNRESOLVEDMEMBER; + case CompletionKind::DotExpr: + return SWIFTIDE_COMPLETION_KIND_DOTEXPR; + case CompletionKind::StmtOrExpr: + return SWIFTIDE_COMPLETION_KIND_STMTOREXPR; + case CompletionKind::PostfixExprBeginning: + return SWIFTIDE_COMPLETION_KIND_POSTFIXEXPRBEGINNING; + case CompletionKind::PostfixExpr: + return SWIFTIDE_COMPLETION_KIND_POSTFIXEXPR; + case CompletionKind::KeyPathExprObjC: + return SWIFTIDE_COMPLETION_KIND_KEYPATHEXPROBJC; + case CompletionKind::KeyPathExprSwift: + return SWIFTIDE_COMPLETION_KIND_KEYPATHEXPRSWIFT; + case CompletionKind::TypePossibleFunctionParamBeginning: + return SWIFTIDE_COMPLETION_KIND_TYPEPOSSIBLEFUNCTIONPARAMBEGINNING; + case CompletionKind::TypeDeclResultBeginning: + return SWIFTIDE_COMPLETION_KIND_TYPEDECLRESULTBEGINNING; + case CompletionKind::TypeBeginning: + return SWIFTIDE_COMPLETION_KIND_TYPEBEGINNING; + case CompletionKind::TypeSimpleOrComposition: + return SWIFTIDE_COMPLETION_KIND_TYPESIMPLEORCOMPOSITION; + case CompletionKind::TypeSimpleBeginning: + return SWIFTIDE_COMPLETION_KIND_TYPESIMPLEBEGINNING; + case CompletionKind::TypeSimpleWithDot: + // TODO: check if this is still correct + return SWIFTIDE_COMPLETION_KIND_TYPEIDENTIFIERWITHDOT; + case CompletionKind::TypeSimpleWithoutDot: + // TODO: check if this is still correct + return SWIFTIDE_COMPLETION_KIND_TYPEIDENTIFIERWITHOUTDOT; + case CompletionKind::CaseStmtKeyword: + return SWIFTIDE_COMPLETION_KIND_CASESTMTKEYWORD; + case CompletionKind::CaseStmtBeginning: + return SWIFTIDE_COMPLETION_KIND_CASESTMTBEGINNING; + case CompletionKind::NominalMemberBeginning: + return SWIFTIDE_COMPLETION_KIND_NOMINALMEMBERBEGINNING; + case CompletionKind::AccessorBeginning: + return SWIFTIDE_COMPLETION_KIND_ACCESSORBEGINNING; + case CompletionKind::AttributeBegin: + return SWIFTIDE_COMPLETION_KIND_ATTRIBUTEBEGIN; + case CompletionKind::AttributeDeclParen: + return SWIFTIDE_COMPLETION_KIND_ATTRIBUTEDECLPAREN; + case CompletionKind::EffectsSpecifier: + return SWIFTIDE_COMPLETION_KIND_EFFECTSSPECIFIER; + case CompletionKind::PoundAvailablePlatform: + return SWIFTIDE_COMPLETION_KIND_POUNDAVAILABLEPLATFORM; + case CompletionKind::CallArg: + return SWIFTIDE_COMPLETION_KIND_CALLARG; + case CompletionKind::ReturnStmtExpr: + return SWIFTIDE_COMPLETION_KIND_RETURNSTMTEXPR; + case CompletionKind::YieldStmtExpr: + return SWIFTIDE_COMPLETION_KIND_YIELDSTMTEXPR; + case CompletionKind::ForEachSequence: + return SWIFTIDE_COMPLETION_KIND_FOREACHSEQUENCE; + case CompletionKind::ForEachInKw: + return SWIFTIDE_COMPLETION_KIND_FOREACHKWIN; + case CompletionKind::AfterPoundExpr: + return SWIFTIDE_COMPLETION_KIND_AFTERPOUNDEXPR; + case CompletionKind::AfterPoundDirective: + return SWIFTIDE_COMPLETION_KIND_AFTERPOUNDDIRECTIVE; + case CompletionKind::PlatformConditon: + return SWIFTIDE_COMPLETION_KIND_PLATFORMCONDITON; + case CompletionKind::AfterIfStmtElse: + return SWIFTIDE_COMPLETION_KIND_AFTERIFSTMTELSE; + case CompletionKind::GenericRequirement: + return SWIFTIDE_COMPLETION_KIND_GENERICREQUIREMENT; + case CompletionKind::PrecedenceGroup: + return SWIFTIDE_COMPLETION_KIND_PRECEDENCEGROUP; + case CompletionKind::StmtLabel: + return SWIFTIDE_COMPLETION_KIND_STMTLABEL; + case CompletionKind::ForEachPatternBeginning: + return SWIFTIDE_COMPLETION_KIND_FOREACHPATTERNBEGINNING; + case CompletionKind::TypeAttrBeginning: + return SWIFTIDE_COMPLETION_KIND_TYPEATTRBEGINNING; + case CompletionKind::TypeAttrInheritanceBeginning: + return SWIFTIDE_COMPLETION_KIND_TYPEATTRINHERITANCEBEGINNING; + case CompletionKind::OptionalBinding: + return SWIFTIDE_COMPLETION_KIND_OPTIONALBINDING; + case CompletionKind::TypeSimpleInverted: + return SWIFTIDE_COMPLETION_KIND_TYPESIMPLEINVERTED; + case CompletionKind::ThenStmtExpr: + return SWIFTIDE_COMPLETION_KIND_THENSTMTEXPR; + } +} + +void swiftide_completion_result_foreach_baseexpr_typename( + swiftide_completion_response_t _response, bool (^handler)(const char *)) { + auto &response = *static_cast(_response); + for (const auto typeName : response.context.LookedupNominalTypeNames) { + if (/*shouldStop=*/handler(typeName.data())) { + return; + } + } +} + +bool swiftide_completion_result_is_reusing_astcontext( + swiftide_completion_response_t _response) { + auto &response = *static_cast(_response); + return response.context.ReusingASTContext; +} + +const char * +swiftide_completion_item_description_copy(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + llvm::SmallString<256> buffer; + { + llvm::raw_svector_ostream OS(buffer); + item.printPrefix(OS); + item.getCompletionString()->print(OS); + } + return strdup(buffer.c_str()); +} + +void swiftide_completion_item_get_label( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + bool annotate, void (^handler)(const char *)) { + auto &response = *static_cast(_response); + auto &item = *static_cast(_item); + response.scratch.clear(); + { + llvm::raw_svector_ostream OS(response.scratch); + if (annotate) { + printCodeCompletionResultDescriptionAnnotated(item, OS, false); + } else { + printCodeCompletionResultDescription(item, OS, false); + } + } + handler(response.scratch.c_str()); +} + +void swiftide_completion_item_get_source_text( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char *)) { + auto &response = *static_cast(_response); + auto &item = *static_cast(_item); + response.scratch.clear(); + { + llvm::raw_svector_ostream OS(response.scratch); + printCodeCompletionResultSourceText(item, OS); + } + handler(response.scratch.c_str()); +} + +void swiftide_completion_item_get_type_name( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + bool annotate, void (^handler)(const char *)) { + auto &response = *static_cast(_response); + auto &item = *static_cast(_item); + response.scratch.clear(); + { + llvm::raw_svector_ostream OS(response.scratch); + if (annotate) { + printCodeCompletionResultTypeNameAnnotated(item, OS); + } else { + printCodeCompletionResultTypeName(item, OS); + } + } + handler(response.scratch.empty() ? nullptr : response.scratch.c_str()); +} + +void swiftide_completion_item_get_doc_brief( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char *)) { + auto &item = *static_cast(_item); + if (item.getBriefDocComment().empty()) { + return handler(nullptr); + } + handler(item.getBriefDocComment().data()); +} + +void swiftide_completion_item_get_associated_usrs( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char **, uint64_t)) { + auto &item = *static_cast(_item); + llvm::SmallVector usrs; + for (auto usr : item.getAssociatedUSRs()) { + usrs.push_back(usr.data()); + } + handler(usrs.data(), usrs.size()); +} + +uint32_t swiftide_completion_item_get_kind(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + // FIXME: keep this in sync with ide::CodeCompletionResult + return static_cast(item.getKind()); +} + +uint32_t +swiftide_completion_item_get_associated_kind(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + // FIXME: keep this in sync with ide::CodeCompletionResult + switch (item.getKind()) { + case CodeCompletionResultKind::Declaration: + switch (item.getAssociatedDeclKind()) { +#define CASE(KIND, VAL) \ + case swift::ide::CodeCompletionDeclKind::KIND: \ + return SWIFTIDE_COMPLETION_ITEM_DECL_KIND_##VAL; + + CASE(Module, MODULE) + CASE(Class, CLASS) + CASE(Actor, ACTOR) + CASE(Struct, STRUCT) + CASE(Enum, ENUM) + CASE(EnumElement, ENUMELEMENT) + CASE(Protocol, PROTOCOL) + CASE(AssociatedType, ASSOCIATEDTYPE) + CASE(TypeAlias, TYPEALIAS) + CASE(GenericTypeParam, GENERICTYPEPARAM) + CASE(Constructor, CONSTRUCTOR) + CASE(Destructor, DESTRUCTOR) + CASE(Subscript, SUBSCRIPT) + CASE(StaticMethod, STATICMETHOD) + CASE(InstanceMethod, INSTANCEMETHOD) + CASE(PrefixOperatorFunction, PREFIXOPERATORFUNCTION) + CASE(PostfixOperatorFunction, POSTFIXOPERATORFUNCTION) + CASE(InfixOperatorFunction, INFIXOPERATORFUNCTION) + CASE(FreeFunction, FREEFUNCTION) + CASE(StaticVar, STATICVAR) + CASE(InstanceVar, INSTANCEVAR) + CASE(LocalVar, LOCALVAR) + CASE(GlobalVar, GLOBALVAR) + CASE(PrecedenceGroup, PRECEDENCEGROUP) + CASE(Macro, MACRO) +#undef CASE + } + llvm_unreachable("unhandled enum value"); + case CodeCompletionResultKind::Literal: + return static_cast(item.getLiteralKind()); + case CodeCompletionResultKind::Keyword: + return static_cast(item.getKeywordKind()); + default: + return 0; + } +} + +uint32_t swiftide_completion_item_get_semantic_context( + swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + switch (item.getSemanticContext()) { + case swift::ide::SemanticContextKind::None: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_NONE; + case swift::ide::SemanticContextKind::Local: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_LOCAL; + case swift::ide::SemanticContextKind::CurrentNominal: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_CURRENTNOMINAL; + case swift::ide::SemanticContextKind::Super: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_SUPER; + case swift::ide::SemanticContextKind::OutsideNominal: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_OUTSIDENOMINAL; + case swift::ide::SemanticContextKind::CurrentModule: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_CURRENTMODULE; + case swift::ide::SemanticContextKind::OtherModule: + return SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_OTHERMODULE; + } +} + +uint32_t swiftide_completion_item_get_flair(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + uint32_t result = 0; + auto flair = item.getFlair(); + if (flair.contains(CodeCompletionFlairBit::ExpressionSpecific)) + result |= SWIFTIDE_COMPLETION_FLAIR_EXPRESSIONSPECIFIC; + if (flair.contains(CodeCompletionFlairBit::SuperChain)) + result |= SWIFTIDE_COMPLETION_FLAIR_SUPERCHAIN; + if (flair.contains(CodeCompletionFlairBit::ArgumentLabels)) + result |= SWIFTIDE_COMPLETION_FLAIR_ARGUMENTLABELS; + if (flair.contains(CodeCompletionFlairBit::CommonKeywordAtCurrentPosition)) + result |= SWIFTIDE_COMPLETION_FLAIR_COMMONKEYWORDATCURRENTPOSITION; + if (flair.contains(CodeCompletionFlairBit::RareKeywordAtCurrentPosition)) + result |= SWIFTIDE_COMPLETION_FLAIR_RAREKEYWORDATCURRENTPOSITION; + if (flair.contains(CodeCompletionFlairBit::RareTypeAtCurrentPosition)) + result |= SWIFTIDE_COMPLETION_FLAIR_RARETYPEATCURRENTPOSITION; + if (flair.contains( + CodeCompletionFlairBit::ExpressionAtNonScriptOrMainFileScope)) + result |= SWIFTIDE_COMPLETION_FLAIR_EXPRESSIONATNONSCRIPTORMAINFILESCOPE; + return result; +} + +bool swiftide_completion_item_is_not_recommended( + swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + return item.isNotRecommended(); +} + +uint32_t swiftide_completion_item_not_recommended_reason( + swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + switch (item.getNotRecommendedReason()) { + case NotRecommendedReason::None: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_NONE; + case NotRecommendedReason::RedundantImport: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_REDUNDANT_IMPORT; + case NotRecommendedReason::RedundantImportIndirect: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_REDUNDANT_IMPORT_INDIRECT; + case NotRecommendedReason::Deprecated: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_DEPRECATED; + case NotRecommendedReason::SoftDeprecated: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_SOFTDEPRECATED; + case NotRecommendedReason::VariableUsedInOwnDefinition: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_VARIABLE_USED_IN_OWN_DEFINITION; + case NotRecommendedReason::NonAsyncAlternativeUsedInAsyncContext: + return SWIFTIDE_COMPLETION_NOT_RECOMMENDED_NON_ASYNC_ALTERNATIVE_USED_IN_ASYNC_CONTEXT; + } +} + +bool swiftide_completion_item_has_diagnostic(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + return (item.getNotRecommendedReason() != NotRecommendedReason::None); +} + +void swiftide_completion_item_get_diagnostic( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(swiftide_completion_diagnostic_severity_t, const char *)) { + auto &response = *static_cast(_response); + auto &item = *static_cast(_item); + swiftide_completion_diagnostic_severity_t severity; + llvm::SmallString<64> scratch; + auto severityAndMessage = item.getDiagnosticSeverityAndMessage( + scratch, response.compilerInstance->getASTContext()); + switch (severityAndMessage.first) { + case CodeCompletionDiagnosticSeverity::None: + handler(SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_NONE, nullptr); + return; + case CodeCompletionDiagnosticSeverity::Error: + severity = SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_ERROR; + break; + case CodeCompletionDiagnosticSeverity::Warning: + severity = SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_WARNING; + break; + case CodeCompletionDiagnosticSeverity::Remark: + severity = SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_REMARK; + break; + case CodeCompletionDiagnosticSeverity::Note: + severity = SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_NOTE; + break; + } + + handler(severity, severityAndMessage.second.data()); +} + +bool swiftide_completion_item_is_system(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + return item.isSystem(); +} + +void swiftide_completion_item_get_module_name( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char *)) { + auto &item = *static_cast(_item); + handler(item.getContextFreeResult().getModuleName().data()); +} + +uint32_t swiftide_completion_item_get_num_bytes_to_erase( + swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + return item.getNumBytesToErase(); +} + +uint32_t +swiftide_completion_item_get_type_relation(swiftide_completion_item_t _item) { + auto &item = *static_cast(_item); + // FIXME: keep this in sync with ide::CodeCompletionResult + return static_cast( + item.getExpectedTypeRelation()); +} + +uint32_t +swiftide_completion_item_import_depth(swiftide_completion_response_t _response, + swiftide_completion_item_t _item) { + auto &response = *static_cast(_response); + auto &item = *static_cast(_item); + if (item.getSemanticContext() == SemanticContextKind::OtherModule) { + if (auto depth = response.importDepth.lookup(item.getModuleName())) { + return *depth; + } else { + return ~0u; + } + } else { + return 0; + } +} + +swiftide_fuzzy_match_pattern_t +swiftide_fuzzy_match_pattern_create(const char *pattern) { + return static_cast( + new FuzzyStringMatcher(pattern)); +} + +bool swiftide_fuzzy_match_pattern_matches_candidate( + swiftide_fuzzy_match_pattern_t _pattern, const char *_candidate, + double *outScore) { + auto &matcher = *static_cast(_pattern); + StringRef candidate = _candidate; + if (matcher.matchesCandidate(candidate)) { + if (outScore) + *outScore = matcher.scoreCandidate(candidate); + return true; + } + return false; +} + +void swiftide_fuzzy_match_pattern_dispose( + swiftide_fuzzy_match_pattern_t _pattern) { + delete static_cast(_pattern); +} + +static std::string getRuntimeResourcesPath() { + auto libPath = getRuntimeLibPath(); + llvm::SmallString<128> libPathTmp(libPath); + llvm::sys::path::append(libPathTmp, "swift"); + return libPathTmp.str().str(); +} diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h new file mode 100644 index 0000000000000..591bb18e67fff --- /dev/null +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h @@ -0,0 +1,408 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 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_C_CODE_COMPLETION_H +#define SWIFT_C_CODE_COMPLETION_H + +#include +#include +#include + +/// The version constants for the SwiftCodeCompletion C API. +/// SWIFTIDE_VERSION_MINOR should increase when there are API additions. +/// SWIFTIDE_VERSION_MAJOR is intended for "major" source/ABI breaking changes. +#define SWIFTIDE_VERSION_MAJOR 0 +#define SWIFTIDE_VERSION_MINOR 1 + +#define SWIFTIDE_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1)) + +#define SWIFTIDE_VERSION \ + SWIFTIDE_VERSION_ENCODE(SWIFTIDE_VERSION_MAJOR, SWIFTIDE_VERSION_MINOR) + +#define SWIFTIDE_VERSION_STRINGIZE_(major, minor) #major "." #minor +#define SWIFTIDE_VERSION_STRINGIZE(major, minor) \ + SWIFTIDE_VERSION_STRINGIZE_(major, minor) + +#define SWIFTIDE_VERSION_STRING \ + SWIFTIDE_VERSION_STRINGIZE(SWIFTIDE_VERSION_MAJOR, SWIFTIDE_VERSION_MINOR) + +#ifdef __cplusplus +#define SWIFTIDE_BEGIN_DECLS extern "C" { +#define SWIFTIDE_END_DECLS } +#else +#define SWIFTIDE_BEGIN_DECLS +#define SWIFTIDE_END_DECLS +#endif + +#ifndef SWIFTIDE_PUBLIC +#if defined(_MSC_VER) +#define SWIFTIDE_PUBLIC __declspec(dllimport) +#else +#define SWIFTIDE_PUBLIC +#endif +#endif + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#if !__has_feature(blocks) +#error -fblocks is a requirement to use this library +#endif + +#if defined(__clang__) || defined(__GNUC__) +#define SWIFTIDE_DEPRECATED(m) __attribute__((deprecated(m))) +#endif + +SWIFTIDE_BEGIN_DECLS + +//=== Types ---------------------------------------------------------------===// + +/// Global state across completions including compiler instance caching. +typedef void *swiftide_connection_t; + +/// Opaque completion item handle, used to retrieve additional information that +/// may be more expensive to compute. +typedef void *swiftide_completion_item_t; + +typedef enum { + SWIFTIDE_COMPLETION_KIND_NONE = 0, + SWIFTIDE_COMPLETION_KIND_IMPORT = 1, + SWIFTIDE_COMPLETION_KIND_UNRESOLVEDMEMBER = 2, + SWIFTIDE_COMPLETION_KIND_DOTEXPR = 3, + SWIFTIDE_COMPLETION_KIND_STMTOREXPR = 4, + SWIFTIDE_COMPLETION_KIND_POSTFIXEXPRBEGINNING = 5, + SWIFTIDE_COMPLETION_KIND_POSTFIXEXPR = 6, + /* obsoleted */ SWIFTIDE_COMPLETION_KIND_POSTFIXEXPRPAREN = 7, + SWIFTIDE_COMPLETION_KIND_KEYPATHEXPROBJC = 8, + SWIFTIDE_COMPLETION_KIND_KEYPATHEXPRSWIFT = 9, + SWIFTIDE_COMPLETION_KIND_TYPEDECLRESULTBEGINNING = 10, + SWIFTIDE_COMPLETION_KIND_TYPESIMPLEBEGINNING = 11, + SWIFTIDE_COMPLETION_KIND_TYPEIDENTIFIERWITHDOT = 12, + SWIFTIDE_COMPLETION_KIND_TYPEIDENTIFIERWITHOUTDOT = 13, + SWIFTIDE_COMPLETION_KIND_CASESTMTKEYWORD = 14, + SWIFTIDE_COMPLETION_KIND_CASESTMTBEGINNING = 15, + SWIFTIDE_COMPLETION_KIND_NOMINALMEMBERBEGINNING = 16, + SWIFTIDE_COMPLETION_KIND_ACCESSORBEGINNING = 17, + SWIFTIDE_COMPLETION_KIND_ATTRIBUTEBEGIN = 18, + SWIFTIDE_COMPLETION_KIND_ATTRIBUTEDECLPAREN = 19, + SWIFTIDE_COMPLETION_KIND_POUNDAVAILABLEPLATFORM = 20, + SWIFTIDE_COMPLETION_KIND_CALLARG = 21, + SWIFTIDE_COMPLETION_KIND_LABELEDTRAILINGCLOSURE = 22, + SWIFTIDE_COMPLETION_KIND_RETURNSTMTEXPR = 23, + SWIFTIDE_COMPLETION_KIND_YIELDSTMTEXPR = 24, + SWIFTIDE_COMPLETION_KIND_FOREACHSEQUENCE = 25, + SWIFTIDE_COMPLETION_KIND_AFTERPOUNDEXPR = 26, + SWIFTIDE_COMPLETION_KIND_AFTERPOUNDDIRECTIVE = 27, + SWIFTIDE_COMPLETION_KIND_PLATFORMCONDITON = 28, + SWIFTIDE_COMPLETION_KIND_AFTERIFSTMTELSE = 29, + SWIFTIDE_COMPLETION_KIND_GENERICREQUIREMENT = 30, + SWIFTIDE_COMPLETION_KIND_PRECEDENCEGROUP = 31, + SWIFTIDE_COMPLETION_KIND_STMTLABEL = 32, + SWIFTIDE_COMPLETION_KIND_EFFECTSSPECIFIER = 33, + SWIFTIDE_COMPLETION_KIND_FOREACHPATTERNBEGINNING = 34, + SWIFTIDE_COMPLETION_KIND_TYPEATTRBEGINNING = 35, + SWIFTIDE_COMPLETION_KIND_OPTIONALBINDING = 36, + SWIFTIDE_COMPLETION_KIND_FOREACHKWIN = 37, + /*obsoleted*/ SWIFTIDE_COMPLETION_KIND_WITHOUTCONSTRAINTTYPE = 38, + SWIFTIDE_COMPLETION_KIND_THENSTMTEXPR = 39, + SWIFTIDE_COMPLETION_KIND_TYPEBEGINNING = 40, + SWIFTIDE_COMPLETION_KIND_TYPESIMPLEORCOMPOSITION = 41, + SWIFTIDE_COMPLETION_KIND_TYPEPOSSIBLEFUNCTIONPARAMBEGINNING = 42, + SWIFTIDE_COMPLETION_KIND_TYPEATTRINHERITANCEBEGINNING = 43, + SWIFTIDE_COMPLETION_KIND_TYPESIMPLEINVERTED = 44, +} swiftide_completion_kind_t; + +typedef enum { + SWIFTIDE_COMPLETION_ITEM_KIND_DECLARATION = 0, + SWIFTIDE_COMPLETION_ITEM_KIND_KEYWORD = 1, + SWIFTIDE_COMPLETION_ITEM_KIND_PATTERN = 2, + SWIFTIDE_COMPLETION_ITEM_KIND_LITERAL = 3, + SWIFTIDE_COMPLETION_ITEM_KIND_BUILTINOPERATOR = 4, +} swiftide_completion_item_kind_t; + +typedef enum { + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_MODULE = 0, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_CLASS = 1, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_STRUCT = 2, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_ENUM = 3, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_ENUMELEMENT = 4, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_PROTOCOL = 5, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_ASSOCIATEDTYPE = 6, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_TYPEALIAS = 7, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_GENERICTYPEPARAM = 8, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_CONSTRUCTOR = 9, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_DESTRUCTOR = 10, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_SUBSCRIPT = 11, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_STATICMETHOD = 12, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_INSTANCEMETHOD = 13, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_PREFIXOPERATORFUNCTION = 14, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_POSTFIXOPERATORFUNCTION = 15, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_INFIXOPERATORFUNCTION = 16, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_FREEFUNCTION = 17, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_STATICVAR = 18, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_INSTANCEVAR = 19, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_LOCALVAR = 20, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_GLOBALVAR = 21, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_PRECEDENCEGROUP = 22, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_ACTOR = 23, + SWIFTIDE_COMPLETION_ITEM_DECL_KIND_MACRO = 24, +} swiftide_completion_item_decl_kind_t; + +typedef enum { + SWIFTIDE_COMPLETION_TYPE_RELATION_NOTAPPLICABLE = 0, + SWIFTIDE_COMPLETION_TYPE_RELATION_UNKNOWN = 1, + SWIFTIDE_COMPLETION_TYPE_RELATION_UNRELATED = 2, + SWIFTIDE_COMPLETION_TYPE_RELATION_INVALID = 3, + SWIFTIDE_COMPLETION_TYPE_RELATION_CONVERTIBLE = 4, + SWIFTIDE_COMPLETION_TYPE_RELATION_IDENTICAL = 5, +} swiftide_completion_type_relation_t; + +typedef enum { + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_NONE = 0, + /* obsoleted */ SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_EXPRESSIONSPECIFIC = 1, + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_LOCAL = 2, + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_CURRENTNOMINAL = 3, + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_SUPER = 4, + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_OUTSIDENOMINAL = 5, + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_CURRENTMODULE = 6, + SWIFTIDE_COMPLETION_SEMANTIC_CONTEXT_OTHERMODULE = 7, +} swiftide_completion_semantic_context_t; + +typedef enum { + SWIFTIDE_COMPLETION_FLAIR_EXPRESSIONSPECIFIC = 1 << 0, + SWIFTIDE_COMPLETION_FLAIR_SUPERCHAIN = 1 << 1, + SWIFTIDE_COMPLETION_FLAIR_ARGUMENTLABELS = 1 << 2, + SWIFTIDE_COMPLETION_FLAIR_COMMONKEYWORDATCURRENTPOSITION = 1 << 3, + SWIFTIDE_COMPLETION_FLAIR_RAREKEYWORDATCURRENTPOSITION = 1 << 4, + SWIFTIDE_COMPLETION_FLAIR_RARETYPEATCURRENTPOSITION = 1 << 5, + SWIFTIDE_COMPLETION_FLAIR_EXPRESSIONATNONSCRIPTORMAINFILESCOPE = 1 << 6, +} swiftide_completion_flair_t; + +typedef enum { + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_NONE = 0, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_REDUNDANT_IMPORT = 1, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_DEPRECATED = 2, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_INVALID_ASYNC_CONTEXT = 3, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_CROSS_ACTOR_REFERENCE = 4, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_VARIABLE_USED_IN_OWN_DEFINITION = 5, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_REDUNDANT_IMPORT_INDIRECT = 6, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_SOFTDEPRECATED = 7, + SWIFTIDE_COMPLETION_NOT_RECOMMENDED_NON_ASYNC_ALTERNATIVE_USED_IN_ASYNC_CONTEXT = + 8, +} swiftide_completion_not_recommended_reason_t; + +typedef enum { + SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_NONE = 0, + SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_ERROR = 1, + SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_WARNING = 2, + SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_REMARK = 3, + SWIFTIDE_COMPLETION_DIAGNOSTIC_SEVERITY_NOTE = 4, +} swiftide_completion_diagnostic_severity_t; + +typedef void *swiftide_completion_request_t; + +typedef void *swiftide_completion_response_t; + +typedef void *swiftide_fuzzy_match_pattern_t; + +typedef void *swiftide_cache_invalidation_options_t; + +/// swiftide equivalent of sourcekitd_request_handle_t +typedef const void *swiftide_request_handle_t; + +//=== Functions -----------------------------------------------------------===// + +SWIFTIDE_DEPRECATED( + "Use swiftide_connection_create_with_inspection_instance instead") +SWIFTIDE_PUBLIC swiftide_connection_t swiftide_connection_create(void); + +SWIFTIDE_PUBLIC swiftide_connection_t +swiftide_connection_create_with_inspection_instance( + void *opqueSwiftIDEInspectionInstance); + +SWIFTIDE_PUBLIC void swiftide_connection_dispose(swiftide_connection_t); + +SWIFTIDE_PUBLIC void + swiftide_connection_mark_cached_compiler_instance_should_be_invalidated( + swiftide_connection_t, swiftide_cache_invalidation_options_t); + +/// Override the contents of the file \p path with \p contents. If \p contents +/// is NULL, go back to using the real the file system. +SWIFTIDE_PUBLIC void +swiftide_set_file_contents(swiftide_connection_t connection, const char *path, + const char *contents); + +/// Cancel the request with \p handle. +SWIFTIDE_PUBLIC void swiftide_cancel_request(swiftide_connection_t _conn, + swiftide_request_handle_t handle); + +SWIFTIDE_PUBLIC swiftide_completion_request_t +swiftide_completion_request_create(const char *path, uint32_t offset, + char *const *const compiler_args, + uint32_t num_compiler_args); + +SWIFTIDE_PUBLIC void + swiftide_completion_request_dispose(swiftide_completion_request_t); + +SWIFTIDE_PUBLIC void +swiftide_completion_request_set_annotate_result(swiftide_completion_request_t, + bool); + +SWIFTIDE_PUBLIC void swiftide_completion_request_set_include_objectliterals( + swiftide_completion_request_t, bool); + +SWIFTIDE_PUBLIC void swiftide_completion_request_set_add_inits_to_top_level( + swiftide_completion_request_t, bool); + +SWIFTIDE_PUBLIC void +swiftide_completion_request_set_add_call_with_no_default_args( + swiftide_completion_request_t, bool); + +/// Same as swiftide_complete but supports cancellation. +/// This request is identified by \p handle. Calling swiftide_cancel_request +/// with that handle cancels the request. +/// Note that the caller is responsible for creating a unique request handle. +/// This differs from the sourcekitd functions in which SourceKit creates a +/// unique handle and passes it to the client via an out parameter. +SWIFTIDE_PUBLIC swiftide_completion_response_t swiftide_complete_cancellable( + swiftide_connection_t _conn, swiftide_completion_request_t _req, + swiftide_request_handle_t handle); + +SWIFTIDE_DEPRECATED("Use swiftide_complete_cancellable instead") +SWIFTIDE_PUBLIC swiftide_completion_response_t swiftide_complete( + swiftide_connection_t provider, swiftide_completion_request_t); + +SWIFTIDE_PUBLIC void + swiftide_completion_result_dispose(swiftide_completion_response_t); + +SWIFTIDE_PUBLIC bool + swiftide_completion_result_is_error(swiftide_completion_response_t); + +/// Result has the same lifetime as the result. +SWIFTIDE_PUBLIC const char *swiftide_completion_result_get_error_description( + swiftide_completion_response_t); + +SWIFTIDE_PUBLIC bool + swiftide_completion_result_is_cancelled(swiftide_completion_response_t); + +/// Copies a string representation of the completion result. This string should +/// be disposed of with \c free when done. +SWIFTIDE_PUBLIC const char * + swiftide_completion_result_description_copy(swiftide_completion_response_t); + +SWIFTIDE_PUBLIC void swiftide_completion_result_get_completions( + swiftide_completion_response_t, + void (^completions_handler)(const swiftide_completion_item_t *completions, + const char **filter_names, + uint64_t num_completions)); + +SWIFTIDE_PUBLIC swiftide_completion_item_t +swiftide_completion_result_get_completion_at_index( + swiftide_completion_response_t, uint64_t index); + +SWIFTIDE_PUBLIC swiftide_completion_kind_t + swiftide_completion_result_get_kind(swiftide_completion_response_t); + +SWIFTIDE_PUBLIC void swiftide_completion_result_foreach_baseexpr_typename( + swiftide_completion_response_t, bool (^handler)(const char *)); + +SWIFTIDE_PUBLIC bool swiftide_completion_result_is_reusing_astcontext( + swiftide_completion_response_t); + +/// Copies a string representation of the completion item. This string should +/// be disposed of with \c free when done. +SWIFTIDE_PUBLIC const char * + swiftide_completion_item_description_copy(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC void +swiftide_completion_item_get_label(swiftide_completion_response_t, + swiftide_completion_item_t, bool annotate, + void (^handler)(const char *)); + +SWIFTIDE_PUBLIC void +swiftide_completion_item_get_source_text(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); + +SWIFTIDE_PUBLIC void swiftide_completion_item_get_type_name( + swiftide_completion_response_t, swiftide_completion_item_t, bool annotate, + void (^handler)(const char *)); + +SWIFTIDE_PUBLIC void +swiftide_completion_item_get_doc_brief(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); + +SWIFTIDE_PUBLIC void swiftide_completion_item_get_associated_usrs( + swiftide_completion_response_t, swiftide_completion_item_t, + void (^handler)(const char **, uint64_t)); + +SWIFTIDE_PUBLIC + uint32_t swiftide_completion_item_get_kind(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC uint32_t + swiftide_completion_item_get_associated_kind(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC uint32_t + swiftide_completion_item_get_semantic_context(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC + uint32_t swiftide_completion_item_get_flair(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC bool + swiftide_completion_item_is_not_recommended(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC uint32_t + swiftide_completion_item_not_recommended_reason(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC bool +swiftide_completion_item_has_diagnostic(swiftide_completion_item_t _item); + +SWIFTIDE_PUBLIC void swiftide_completion_item_get_diagnostic( + swiftide_completion_response_t, swiftide_completion_item_t, + void (^handler)(swiftide_completion_diagnostic_severity_t, const char *)); + +SWIFTIDE_PUBLIC bool + swiftide_completion_item_is_system(swiftide_completion_item_t); + +/// Call \p handler with the name of the module the code completion item +/// \p _item is defined in. The module may be \c nullptr for e.g. keywords. +SWIFTIDE_PUBLIC +void swiftide_completion_item_get_module_name( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char *)); + +SWIFTIDE_PUBLIC uint32_t + swiftide_completion_item_get_num_bytes_to_erase(swiftide_completion_item_t); + +SWIFTIDE_PUBLIC uint32_t + swiftide_completion_item_get_type_relation(swiftide_completion_item_t); + +/// Returns 0 for items not in an external module, and ~0u if the other module +/// is not imported or the depth is otherwise unknown. +SWIFTIDE_PUBLIC uint32_t swiftide_completion_item_import_depth( + swiftide_completion_response_t, swiftide_completion_item_t); + +SWIFTIDE_PUBLIC swiftide_fuzzy_match_pattern_t +swiftide_fuzzy_match_pattern_create(const char *pattern); + +SWIFTIDE_PUBLIC bool swiftide_fuzzy_match_pattern_matches_candidate( + swiftide_fuzzy_match_pattern_t pattern, const char *candidate, + double *outScore); + +SWIFTIDE_PUBLIC void + swiftide_fuzzy_match_pattern_dispose(swiftide_fuzzy_match_pattern_t); + +SWIFTIDE_END_DECLS + +#endif diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/module.modulemap b/tools/SourceKit/tools/sourcekitd/bin/InProc/module.modulemap index 9ba45b6d9b86e..97e9413f3f96b 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/module.modulemap +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/module.modulemap @@ -1,5 +1,7 @@ framework module sourcekitdInProc { umbrella header "sourcekitd.h" + header "plugin.h" + header "CodeCompletionSwiftInterop.h" export * module * { export * } } diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports index fa724cc440c3e..f84b2d1304579 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports @@ -2,33 +2,68 @@ sourcekitd_cancel_request sourcekitd_request_handle_dispose sourcekitd_initialize sourcekitd_request_array_create +sourcekitd_request_array_get_bool +sourcekitd_request_array_get_count +sourcekitd_request_array_get_int64 +sourcekitd_request_array_get_string +sourcekitd_request_array_get_uid +sourcekitd_request_array_get_value sourcekitd_request_array_set_int64 sourcekitd_request_array_set_string sourcekitd_request_array_set_stringbuf sourcekitd_request_array_set_uid sourcekitd_request_array_set_value +sourcekitd_request_bool_get_value sourcekitd_request_create_from_yaml sourcekitd_request_description_copy sourcekitd_request_description_dump sourcekitd_request_dictionary_create +sourcekitd_request_dictionary_get_bool +sourcekitd_request_dictionary_get_int64 +sourcekitd_request_dictionary_get_string +sourcekitd_request_dictionary_get_uid +sourcekitd_request_dictionary_get_value sourcekitd_request_dictionary_set_int64 sourcekitd_request_dictionary_set_string sourcekitd_request_dictionary_set_stringbuf sourcekitd_request_dictionary_set_uid sourcekitd_request_dictionary_set_value +sourcekitd_request_get_type sourcekitd_request_int64_create -sourcekitd_request_retain +sourcekitd_request_int64_get_value sourcekitd_request_release +sourcekitd_request_retain sourcekitd_request_string_create +sourcekitd_request_string_get_length +sourcekitd_request_string_get_ptr sourcekitd_request_uid_create +sourcekitd_request_uid_get_value +sourcekitd_response_array_create +sourcekitd_response_array_set_int64 +sourcekitd_response_array_set_double +sourcekitd_response_array_set_string +sourcekitd_response_array_set_stringbuf +sourcekitd_response_array_set_uid +sourcekitd_response_array_set_value sourcekitd_response_description_copy sourcekitd_response_description_dump sourcekitd_response_description_dump_filedesc +sourcekitd_response_dictionary_create +sourcekitd_response_dictionary_set_bool +sourcekitd_response_dictionary_set_double +sourcekitd_response_dictionary_set_custom_buffer +sourcekitd_response_dictionary_set_int64 +sourcekitd_response_dictionary_set_string +sourcekitd_response_dictionary_set_stringbuf +sourcekitd_response_dictionary_set_uid +sourcekitd_response_dictionary_set_value sourcekitd_response_dispose +sourcekitd_response_error_create sourcekitd_response_error_get_description sourcekitd_response_error_get_kind sourcekitd_response_get_value sourcekitd_response_is_error +sourcekitd_response_retain sourcekitd_send_request sourcekitd_send_request_sync sourcekitd_set_interrupted_connection_handler @@ -43,30 +78,115 @@ sourcekitd_uid_get_string_ptr sourcekitd_variant_array_apply sourcekitd_variant_array_apply_f sourcekitd_variant_array_get_bool +sourcekitd_variant_array_get_double sourcekitd_variant_array_get_count sourcekitd_variant_array_get_int64 sourcekitd_variant_array_get_string sourcekitd_variant_array_get_uid sourcekitd_variant_array_get_value sourcekitd_variant_bool_get_value +sourcekitd_variant_double_get_value sourcekitd_variant_description_copy sourcekitd_variant_description_dump sourcekitd_variant_description_dump_filedesc sourcekitd_variant_dictionary_apply sourcekitd_variant_dictionary_apply_f sourcekitd_variant_dictionary_get_bool +sourcekitd_variant_dictionary_get_double sourcekitd_variant_dictionary_get_int64 sourcekitd_variant_dictionary_get_string -sourcekitd_variant_dictionary_get_value sourcekitd_variant_dictionary_get_uid +sourcekitd_variant_dictionary_get_value sourcekitd_variant_get_type sourcekitd_variant_json_description_copy sourcekitd_variant_string_get_length sourcekitd_variant_string_get_ptr -sourcekitd_variant_data_get_size sourcekitd_variant_data_get_ptr +sourcekitd_variant_data_get_size sourcekitd_variant_int64_get_value sourcekitd_variant_uid_get_value +sourcekitd_variant_functions_create +sourcekitd_variant_functions_set_get_type +sourcekitd_variant_functions_set_array_apply +sourcekitd_variant_functions_set_array_get_bool +sourcekitd_variant_functions_set_array_get_double +sourcekitd_variant_functions_set_array_get_count +sourcekitd_variant_functions_set_array_get_int64 +sourcekitd_variant_functions_set_array_get_string +sourcekitd_variant_functions_set_array_get_uid +sourcekitd_variant_functions_set_array_get_value +sourcekitd_variant_functions_set_bool_get_value +sourcekitd_variant_functions_set_double_get_value +sourcekitd_variant_functions_set_dictionary_apply +sourcekitd_variant_functions_set_dictionary_get_bool +sourcekitd_variant_functions_set_dictionary_get_double +sourcekitd_variant_functions_set_dictionary_get_int64 +sourcekitd_variant_functions_set_dictionary_get_string +sourcekitd_variant_functions_set_dictionary_get_value +sourcekitd_variant_functions_set_dictionary_get_uid +sourcekitd_variant_functions_set_string_get_length +sourcekitd_variant_functions_set_string_get_ptr +sourcekitd_variant_functions_set_int64_get_value +sourcekitd_variant_functions_set_uid_get_value +sourcekitd_variant_functions_set_data_get_size +sourcekitd_variant_functions_set_data_get_ptr +sourcekitd_plugin_initialize_is_client_only +sourcekitd_plugin_initialize_custom_buffer_start +sourcekitd_plugin_initialize_uid_get_from_cstr +sourcekitd_plugin_initialize_uid_get_string_ptr +sourcekitd_plugin_initialize_register_request_handler +sourcekitd_plugin_initialize_register_cancellable_request_handler +sourcekitd_plugin_initialize_register_cancellation_handler +sourcekitd_plugin_initialize_register_custom_buffer +sourcekitd_plugin_initialize_get_swift_ide_inspection_instance +sourcekitd_register_plugin_path +sourcekitd_load_client_plugins +swiftide_cancel_request +swiftide_complete +swiftide_complete_cancellable +swiftide_completion_item_description_copy +swiftide_completion_item_get_associated_kind +swiftide_completion_item_get_associated_usrs +swiftide_completion_item_get_diagnostic +swiftide_completion_item_get_doc_brief +swiftide_completion_item_get_flair +swiftide_completion_item_get_kind +swiftide_completion_item_get_label +swiftide_completion_item_get_module_name +swiftide_completion_item_get_num_bytes_to_erase +swiftide_completion_item_get_semantic_context +swiftide_completion_item_get_source_text +swiftide_completion_item_get_type_name +swiftide_completion_item_get_type_relation +swiftide_completion_item_has_diagnostic +swiftide_completion_item_import_depth +swiftide_completion_item_is_not_recommended +swiftide_completion_item_is_system +swiftide_completion_item_not_recommended_reason +swiftide_completion_request_create +swiftide_completion_request_dispose +swiftide_completion_request_set_add_call_with_no_default_args +swiftide_completion_request_set_add_inits_to_top_level +swiftide_completion_request_set_annotate_result +swiftide_completion_request_set_include_objectliterals +swiftide_completion_result_description_copy +swiftide_completion_result_dispose +swiftide_completion_result_foreach_baseexpr_typename +swiftide_completion_result_get_completion_at_index +swiftide_completion_result_get_completions +swiftide_completion_result_get_error_description +swiftide_completion_result_get_kind +swiftide_completion_result_is_cancelled +swiftide_completion_result_is_error +swiftide_completion_result_is_reusing_astcontext +swiftide_connection_create +swiftide_connection_create_with_inspection_instance +swiftide_connection_dispose +swiftide_connection_mark_cached_compiler_instance_should_be_invalidated +swiftide_fuzzy_match_pattern_create +swiftide_fuzzy_match_pattern_dispose +swiftide_fuzzy_match_pattern_matches_candidate +swiftide_set_file_contents _ZN10sourcekitd13cancelRequestEPKv _ZN10sourcekitd13enableLoggingEN4llvm9StringRefE _ZN10sourcekitd13handleRequestEPvPKvNSt3__18functionIFvS0_EEE @@ -76,6 +196,11 @@ _ZN10sourcekitd27sendBarriersEnabledResponseENSt3__18functionIFvPvEEE _ZN10sourcekitd17initializeServiceEN4llvm9StringRefES1_S1_NSt3__18functionIFvPvEEE _ZN10sourcekitd24createErrorRequestFailedEN4llvm9StringRefE _ZN10sourcekitd24disposeCancellationTokenEPKv +_ZN10sourcekitd11loadPluginsEN4llvm8ArrayRefINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEERNS_16PluginInitParamsE +_ZN10sourcekitd41pluginGetOpaqueSwiftIDEInspectionInstanceEv +_ZN10sourcekitd28pluginRegisterRequestHandlerEU13block_pointerFbPvPKvU13block_pointerFvS0_EE +_ZN10sourcekitd33pluginRegisterCancellationHandlerEU13block_pointerFvPKvE +_ZN10sourcekitd16PluginInitParamsC1EbNSt3__18functionIFvU13block_pointerFbPvPKvU13block_pointerFvS3_EEEEENS2_IFvU13block_pointerFvS5_EEEES3_ _ZN9SourceKit6Logger12LoggingLevelE _ZN9SourceKit6LoggerD1Ev _ZN9SourceKit6UIdent6setTagEPv diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp index 879fb56e3689c..3b6a6fa0a1655 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp @@ -12,6 +12,7 @@ #include "sourcekitd/Internal.h" #include "sourcekitd/Service.h" +#include "sourcekitd/sourcekitdInProc-Internal.h" #include "SourceKit/Support/Concurrency.h" #include "SourceKit/Support/Logging.h" @@ -83,36 +84,51 @@ static void getToolchainPrefixPath(llvm::SmallVectorImpl &Path) { llvm::sys::path::remove_filename(Path); } -static std::string getRuntimeLibPath() { +std::string sourcekitdInProc::getRuntimeLibPath() { llvm::SmallString<128> libPath; getToolchainPrefixPath(libPath); llvm::sys::path::append(libPath, "lib"); return libPath.str().str(); } -static std::string getSwiftExecutablePath() { +std::string sourcekitdInProc::getSwiftExecutablePath() { llvm::SmallString<128> path; getToolchainPrefixPath(path); llvm::sys::path::append(path, "bin", "swift-frontend"); return path.str().str(); } -static std::string getDiagnosticDocumentationPath() { +std::string sourcekitdInProc::getDiagnosticDocumentationPath() { llvm::SmallString<128> docPath; getToolchainPrefixPath(docPath); llvm::sys::path::append(docPath, "share", "doc", "swift", "diagnostics"); return docPath.str().str(); } +static std::vector registeredPlugins; + +void sourcekitd_load_client_plugins(void) { + // There should be no independent client. +} + void sourcekitd_initialize(void) { assert(msgHandlingQueue == nullptr && "Cannot initialize service twice"); msgHandlingQueue = new WorkQueue(WorkQueue::Dequeuing::Concurrent, "sourcekitdInProc.msgHandlingQueue"); if (sourcekitd::initializeClient()) { LOG_INFO_FUNC(High, "initializing"); - sourcekitd::initializeService(getSwiftExecutablePath(), getRuntimeLibPath(), - getDiagnosticDocumentationPath(), - postNotification); + sourcekitd::initializeService( + sourcekitdInProc::getSwiftExecutablePath(), + sourcekitdInProc::getRuntimeLibPath(), + sourcekitdInProc::getDiagnosticDocumentationPath(), postNotification); + static std::once_flag flag; + std::call_once(flag, [] { + sourcekitd::PluginInitParams pluginParams( + /*isClientOnly=*/false, sourcekitd::pluginRegisterRequestHandler, + sourcekitd::pluginRegisterCancellationHandler, + sourcekitd::pluginGetOpaqueSwiftIDEInspectionInstance()); + sourcekitd::loadPlugins(registeredPlugins, pluginParams); + }); } } @@ -123,6 +139,13 @@ void sourcekitd_shutdown(void) { } } +void sourcekitd_register_plugin_path(const char *clientPlugin, + const char *servicePlugin) { + (void)clientPlugin; // sourcekitdInProc has no independent client. + if (servicePlugin) + registeredPlugins.push_back(servicePlugin); +} + void sourcekitd::set_interrupted_connection_handler( llvm::function_ref handler) { } diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports index 923989e1f1002..d4f811ed11db4 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports @@ -2,33 +2,68 @@ sourcekitd_cancel_request sourcekitd_request_handle_dispose sourcekitd_initialize sourcekitd_request_array_create +sourcekitd_request_array_get_bool +sourcekitd_request_array_get_count +sourcekitd_request_array_get_int64 +sourcekitd_request_array_get_string +sourcekitd_request_array_get_uid +sourcekitd_request_array_get_value sourcekitd_request_array_set_int64 sourcekitd_request_array_set_string sourcekitd_request_array_set_stringbuf sourcekitd_request_array_set_uid sourcekitd_request_array_set_value +sourcekitd_request_bool_get_value sourcekitd_request_create_from_yaml sourcekitd_request_description_copy sourcekitd_request_description_dump sourcekitd_request_dictionary_create +sourcekitd_request_dictionary_get_bool +sourcekitd_request_dictionary_get_int64 +sourcekitd_request_dictionary_get_string +sourcekitd_request_dictionary_get_uid +sourcekitd_request_dictionary_get_value sourcekitd_request_dictionary_set_int64 sourcekitd_request_dictionary_set_string sourcekitd_request_dictionary_set_stringbuf sourcekitd_request_dictionary_set_uid sourcekitd_request_dictionary_set_value +sourcekitd_request_get_type sourcekitd_request_int64_create -sourcekitd_request_retain +sourcekitd_request_int64_get_value sourcekitd_request_release +sourcekitd_request_retain sourcekitd_request_string_create +sourcekitd_request_string_get_length +sourcekitd_request_string_get_ptr sourcekitd_request_uid_create +sourcekitd_request_uid_get_value +sourcekitd_response_array_create +sourcekitd_response_array_set_int64 +sourcekitd_response_array_set_double +sourcekitd_response_array_set_string +sourcekitd_response_array_set_stringbuf +sourcekitd_response_array_set_uid +sourcekitd_response_array_set_value sourcekitd_response_description_copy sourcekitd_response_description_dump sourcekitd_response_description_dump_filedesc +sourcekitd_response_dictionary_create +sourcekitd_response_dictionary_set_bool +sourcekitd_response_dictionary_set_double +sourcekitd_response_dictionary_set_custom_buffer +sourcekitd_response_dictionary_set_int64 +sourcekitd_response_dictionary_set_string +sourcekitd_response_dictionary_set_stringbuf +sourcekitd_response_dictionary_set_uid +sourcekitd_response_dictionary_set_value sourcekitd_response_dispose +sourcekitd_response_error_create sourcekitd_response_error_get_description sourcekitd_response_error_get_kind sourcekitd_response_get_value sourcekitd_response_is_error +sourcekitd_response_retain sourcekitd_send_request sourcekitd_send_request_sync sourcekitd_set_interrupted_connection_handler @@ -43,27 +78,112 @@ sourcekitd_uid_get_string_ptr sourcekitd_variant_array_apply sourcekitd_variant_array_apply_f sourcekitd_variant_array_get_bool +sourcekitd_variant_array_get_double sourcekitd_variant_array_get_count sourcekitd_variant_array_get_int64 sourcekitd_variant_array_get_string sourcekitd_variant_array_get_uid sourcekitd_variant_array_get_value sourcekitd_variant_bool_get_value +sourcekitd_variant_double_get_value sourcekitd_variant_description_copy sourcekitd_variant_description_dump sourcekitd_variant_description_dump_filedesc sourcekitd_variant_dictionary_apply sourcekitd_variant_dictionary_apply_f sourcekitd_variant_dictionary_get_bool +sourcekitd_variant_dictionary_get_double sourcekitd_variant_dictionary_get_int64 sourcekitd_variant_dictionary_get_string -sourcekitd_variant_dictionary_get_value sourcekitd_variant_dictionary_get_uid +sourcekitd_variant_dictionary_get_value sourcekitd_variant_get_type sourcekitd_variant_json_description_copy sourcekitd_variant_string_get_length sourcekitd_variant_string_get_ptr -sourcekitd_variant_data_get_size sourcekitd_variant_data_get_ptr +sourcekitd_variant_data_get_size sourcekitd_variant_int64_get_value sourcekitd_variant_uid_get_value +sourcekitd_variant_functions_create +sourcekitd_variant_functions_set_get_type +sourcekitd_variant_functions_set_array_apply +sourcekitd_variant_functions_set_array_get_bool +sourcekitd_variant_functions_set_array_get_double +sourcekitd_variant_functions_set_array_get_count +sourcekitd_variant_functions_set_array_get_int64 +sourcekitd_variant_functions_set_array_get_string +sourcekitd_variant_functions_set_array_get_uid +sourcekitd_variant_functions_set_array_get_value +sourcekitd_variant_functions_set_bool_get_value +sourcekitd_variant_functions_set_double_get_value +sourcekitd_variant_functions_set_dictionary_apply +sourcekitd_variant_functions_set_dictionary_get_bool +sourcekitd_variant_functions_set_dictionary_get_double +sourcekitd_variant_functions_set_dictionary_get_int64 +sourcekitd_variant_functions_set_dictionary_get_string +sourcekitd_variant_functions_set_dictionary_get_value +sourcekitd_variant_functions_set_dictionary_get_uid +sourcekitd_variant_functions_set_string_get_length +sourcekitd_variant_functions_set_string_get_ptr +sourcekitd_variant_functions_set_int64_get_value +sourcekitd_variant_functions_set_uid_get_value +sourcekitd_variant_functions_set_data_get_size +sourcekitd_variant_functions_set_data_get_ptr +sourcekitd_plugin_initialize_is_client_only +sourcekitd_plugin_initialize_custom_buffer_start +sourcekitd_plugin_initialize_uid_get_from_cstr +sourcekitd_plugin_initialize_uid_get_string_ptr +sourcekitd_plugin_initialize_register_request_handler +sourcekitd_plugin_initialize_register_cancellable_request_handler +sourcekitd_plugin_initialize_register_cancellation_handler +sourcekitd_plugin_initialize_register_custom_buffer +sourcekitd_plugin_initialize_get_swift_ide_inspection_instance +sourcekitd_register_plugin_path +sourcekitd_load_client_plugins +swiftide_cancel_request +swiftide_complete +swiftide_complete_cancellable +swiftide_completion_item_description_copy +swiftide_completion_item_get_associated_kind +swiftide_completion_item_get_associated_usrs +swiftide_completion_item_get_diagnostic +swiftide_completion_item_get_doc_brief +swiftide_completion_item_get_flair +swiftide_completion_item_get_kind +swiftide_completion_item_get_label +swiftide_completion_item_get_module_name +swiftide_completion_item_get_num_bytes_to_erase +swiftide_completion_item_get_semantic_context +swiftide_completion_item_get_source_text +swiftide_completion_item_get_type_name +swiftide_completion_item_get_type_relation +swiftide_completion_item_has_diagnostic +swiftide_completion_item_import_depth +swiftide_completion_item_is_not_recommended +swiftide_completion_item_is_system +swiftide_completion_item_not_recommended_reason +swiftide_completion_request_create +swiftide_completion_request_dispose +swiftide_completion_request_set_add_call_with_no_default_args +swiftide_completion_request_set_add_inits_to_top_level +swiftide_completion_request_set_annotate_result +swiftide_completion_request_set_include_objectliterals +swiftide_completion_result_description_copy +swiftide_completion_result_dispose +swiftide_completion_result_foreach_baseexpr_typename +swiftide_completion_result_get_completion_at_index +swiftide_completion_result_get_completions +swiftide_completion_result_get_error_description +swiftide_completion_result_get_kind +swiftide_completion_result_is_cancelled +swiftide_completion_result_is_error +swiftide_completion_result_is_reusing_astcontext +swiftide_connection_create +swiftide_connection_create_with_inspection_instance +swiftide_connection_dispose +swiftide_connection_mark_cached_compiler_instance_should_be_invalidated +swiftide_fuzzy_match_pattern_create +swiftide_fuzzy_match_pattern_dispose +swiftide_fuzzy_match_pattern_matches_candidate +swiftide_set_file_contents diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp index cc97e5f5aa735..931f084a0b7b3 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp @@ -238,6 +238,9 @@ void sourcekitd_request_handle_dispose(sourcekitd_request_handle_t handle) { xpc_release(msg); } +static std::vector registeredClientPlugins; +static std::vector registeredServicePlugins; + /// To avoid repeated crashes, used to notify the service to delay typechecking /// in the editor for a certain amount of seconds. static std::atomic SemanticEditorDelaySecondsNum; @@ -246,6 +249,14 @@ static void handleInternalInitRequest(xpc_object_t reply) { size_t Delay = SemanticEditorDelaySecondsNum; if (Delay != 0) xpc_dictionary_set_uint64(reply, xpc::KeySemaEditorDelay, Delay); + + if (!registeredServicePlugins.empty()) { + auto plugins = xpc_array_create(nullptr, 0); + for (const auto &plugin : registeredServicePlugins) + xpc_array_set_string(plugins, XPC_ARRAY_APPEND, plugin.c_str()); + xpc_dictionary_set_value(reply, xpc::KeyPlugins, plugins); + xpc_release(plugins); + } } static void handleInternalUIDRequest(xpc_object_t XVal, @@ -343,10 +354,21 @@ static void initializeXPCClient() { xpc_connection_resume(GlobalConn); } +void sourcekitd_load_client_plugins(void) { + static std::once_flag flag; + std::call_once(flag, [] { + sourcekitd::PluginInitParams pluginParams( + /*isClientOnly=*/true, /*registerRequestHandler=*/nullptr, + /*registerCancellationHandler=*/nullptr); + loadPlugins(registeredClientPlugins, pluginParams); + }); +} + void sourcekitd_initialize(void) { if (sourcekitd::initializeClient()) { LOG_INFO_FUNC(High, "initializing"); initializeXPCClient(); + sourcekitd_load_client_plugins(); } } @@ -358,6 +380,15 @@ void sourcekitd_shutdown(void) { } } +void sourcekitd_register_plugin_path(const char *clientPlugin, + const char *servicePlugin) { + assert(!GlobalConn && "plugin registered after sourcekitd_initialize"); + if (clientPlugin) + registeredClientPlugins.push_back(clientPlugin); + if (servicePlugin) + registeredServicePlugins.push_back(servicePlugin); +} + static xpc_connection_t getGlobalConnection() { assert(GlobalConn); return GlobalConn; diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.exports b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.exports index 923989e1f1002..d354134cfba60 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.exports @@ -43,18 +43,21 @@ sourcekitd_uid_get_string_ptr sourcekitd_variant_array_apply sourcekitd_variant_array_apply_f sourcekitd_variant_array_get_bool +sourcekitd_variant_array_get_double sourcekitd_variant_array_get_count sourcekitd_variant_array_get_int64 sourcekitd_variant_array_get_string sourcekitd_variant_array_get_uid sourcekitd_variant_array_get_value sourcekitd_variant_bool_get_value +sourcekitd_variant_double_get_value sourcekitd_variant_description_copy sourcekitd_variant_description_dump sourcekitd_variant_description_dump_filedesc sourcekitd_variant_dictionary_apply sourcekitd_variant_dictionary_apply_f sourcekitd_variant_dictionary_get_bool +sourcekitd_variant_dictionary_get_double sourcekitd_variant_dictionary_get_int64 sourcekitd_variant_dictionary_get_string sourcekitd_variant_dictionary_get_value @@ -67,3 +70,36 @@ sourcekitd_variant_data_get_size sourcekitd_variant_data_get_ptr sourcekitd_variant_int64_get_value sourcekitd_variant_uid_get_value +sourcekitd_variant_functions_create +sourcekitd_variant_functions_set_get_type +sourcekitd_variant_functions_set_array_apply +sourcekitd_variant_functions_set_array_get_bool +sourcekitd_variant_functions_set_array_get_double +sourcekitd_variant_functions_set_array_get_count +sourcekitd_variant_functions_set_array_get_int64 +sourcekitd_variant_functions_set_array_get_string +sourcekitd_variant_functions_set_array_get_uid +sourcekitd_variant_functions_set_array_get_value +sourcekitd_variant_functions_set_bool_get_value +sourcekitd_variant_functions_set_double_get_value +sourcekitd_variant_functions_set_dictionary_apply +sourcekitd_variant_functions_set_dictionary_get_bool +sourcekitd_variant_functions_set_dictionary_get_double +sourcekitd_variant_functions_set_dictionary_get_int64 +sourcekitd_variant_functions_set_dictionary_get_string +sourcekitd_variant_functions_set_dictionary_get_value +sourcekitd_variant_functions_set_dictionary_get_uid +sourcekitd_variant_functions_set_string_get_length +sourcekitd_variant_functions_set_string_get_ptr +sourcekitd_variant_functions_set_int64_get_value +sourcekitd_variant_functions_set_uid_get_value +sourcekitd_variant_functions_set_data_get_size +sourcekitd_variant_functions_set_data_get_ptr +sourcekitd_plugin_initialize_is_client_only +sourcekitd_plugin_initialize_custom_buffer_start +sourcekitd_plugin_initialize_uid_get_from_cstr +sourcekitd_plugin_initialize_uid_get_string_ptr +sourcekitd_plugin_initialize_register_request_handler +sourcekitd_plugin_initialize_register_custom_buffer +sourcekitd_register_plugin_path +sourcekitd_load_client_plugins diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp index 690ceca03540d..d3262c58cd142 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp @@ -341,7 +341,6 @@ static void getInitializationInfo(xpc_connection_t peer) { assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY); uint64_t Delay = xpc_dictionary_get_uint64(reply, xpc::KeySemaEditorDelay); - xpc_release(reply); if (Delay != 0) { llvm::SmallString<4> Buf; @@ -351,6 +350,23 @@ static void getInitializationInfo(xpc_connection_t peer) { } setenv("SOURCEKIT_DELAY_SEMA_EDITOR", Buf.c_str(), /*overwrite=*/1); } + + // Only call once, in case there is a second connection. + static std::once_flag flag; + std::call_once(flag, [reply] { + std::vector registeredPlugins; + xpc_object_t plugins = xpc_dictionary_get_value(reply, xpc::KeyPlugins); + if (plugins && xpc_get_type(plugins) == XPC_TYPE_ARRAY) + for (size_t i = 0, e = xpc_array_get_count(plugins); i < e; ++i) + registeredPlugins.push_back(xpc_array_get_string(plugins, i)); + sourcekitd::PluginInitParams pluginParams( + /*isClientOnly=*/false, sourcekitd::pluginRegisterRequestHandler, + sourcekitd::pluginRegisterCancellationHandler, + sourcekitd::pluginGetOpaqueSwiftIDEInspectionInstance()); + sourcekitd::loadPlugins(registeredPlugins, pluginParams); + }); + + xpc_release(reply); } static void sourcekitdServer_event_handler(xpc_connection_t peer) { diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CompactArray.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CompactArray.h index 17ddabdaa5e95..5cdd8c8f32beb 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CompactArray.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CompactArray.h @@ -162,11 +162,11 @@ struct CompactVariantFuncs { static bool dictionary_apply(sourcekitd_variant_t dict, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { void *Buf = (void *)dict.data[1]; size_t Index = dict.data[2]; - return T::dictionary_apply(Buf, Index, applier); + return T::dictionary_apply(Buf, Index, applier, context); } static VariantFunctions Funcs; @@ -174,27 +174,30 @@ struct CompactVariantFuncs { template VariantFunctions CompactVariantFuncs::Funcs = { - get_type, - nullptr/*Annot_array_apply*/, - nullptr/*Annot_array_get_bool*/, - nullptr/*Annot_array_get_count*/, - nullptr/*Annot_array_get_int64*/, - nullptr/*Annot_array_get_string*/, - nullptr/*Annot_array_get_uid*/, - nullptr/*Annot_array_get_value*/, - nullptr/*Annot_bool_get_value*/, - dictionary_apply, - nullptr/*Annot_dictionary_get_bool*/, - nullptr/*Annot_dictionary_get_int64*/, - nullptr/*Annot_dictionary_get_string*/, - nullptr/*Annot_dictionary_get_value*/, - nullptr/*Annot_dictionary_get_uid*/, - nullptr/*Annot_string_get_length*/, - nullptr/*Annot_string_get_ptr*/, - nullptr/*Annot_int64_get_value*/, - nullptr/*Annot_uid_get_value*/, - nullptr/*Annot_data_get_size*/, - nullptr/*Annot_data_get_ptr*/, + get_type, + nullptr /*Annot_array_apply*/, + nullptr /*Annot_array_get_bool*/, + nullptr /*Annot_array_get_double*/, + nullptr /*Annot_array_get_count*/, + nullptr /*Annot_array_get_int64*/, + nullptr /*Annot_array_get_string*/, + nullptr /*Annot_array_get_uid*/, + nullptr /*Annot_array_get_value*/, + nullptr /*Annot_bool_get_value*/, + nullptr /*Annot_double_get_value*/, + dictionary_apply, + nullptr /*Annot_dictionary_get_bool*/, + nullptr /*Annot_dictionary_get_double*/, + nullptr /*Annot_dictionary_get_int64*/, + nullptr /*Annot_dictionary_get_string*/, + nullptr /*Annot_dictionary_get_value*/, + nullptr /*Annot_dictionary_get_uid*/, + nullptr /*Annot_string_get_length*/, + nullptr /*Annot_string_get_ptr*/, + nullptr /*Annot_int64_get_value*/, + nullptr /*Annot_uid_get_value*/, + nullptr /*Annot_data_get_size*/, + nullptr /*Annot_data_get_ptr*/, }; template @@ -221,29 +224,31 @@ struct CompactArrayFuncs { template VariantFunctions CompactArrayFuncs::Funcs = { - get_type, - nullptr/*AnnotArray_array_apply*/, - nullptr/*AnnotArray_array_get_bool*/, - array_get_count, - nullptr/*AnnotArray_array_get_int64*/, - nullptr/*AnnotArray_array_get_string*/, - nullptr/*AnnotArray_array_get_uid*/, - array_get_value, - nullptr/*AnnotArray_bool_get_value*/, - nullptr/*AnnotArray_dictionary_apply*/, - nullptr/*AnnotArray_dictionary_get_bool*/, - nullptr/*AnnotArray_dictionary_get_int64*/, - nullptr/*AnnotArray_dictionary_get_string*/, - nullptr/*AnnotArray_dictionary_get_value*/, - nullptr/*AnnotArray_dictionary_get_uid*/, - nullptr/*AnnotArray_string_get_length*/, - nullptr/*AnnotArray_string_get_ptr*/, - nullptr/*AnnotArray_int64_get_value*/, - nullptr/*AnnotArray_uid_get_value*/, - nullptr/*Annot_data_get_size*/, - nullptr/*Annot_data_get_ptr*/, + get_type, + nullptr /*AnnotArray_array_apply*/, + nullptr /*AnnotArray_array_get_bool*/, + nullptr /*AnnotArray_array_get_double*/, + array_get_count, + nullptr /*AnnotArray_array_get_int64*/, + nullptr /*AnnotArray_array_get_string*/, + nullptr /*AnnotArray_array_get_uid*/, + array_get_value, + nullptr /*AnnotArray_bool_get_value*/, + nullptr /*AnnotArray_double_get_value*/, + nullptr /*AnnotArray_dictionary_apply*/, + nullptr /*AnnotArray_dictionary_get_bool*/, + nullptr /*AnnotArray_dictionary_get_double*/, + nullptr /*AnnotArray_dictionary_get_int64*/, + nullptr /*AnnotArray_dictionary_get_string*/, + nullptr /*AnnotArray_dictionary_get_value*/, + nullptr /*AnnotArray_dictionary_get_uid*/, + nullptr /*AnnotArray_string_get_length*/, + nullptr /*AnnotArray_string_get_ptr*/, + nullptr /*AnnotArray_int64_get_value*/, + nullptr /*AnnotArray_uid_get_value*/, + nullptr /*Annot_data_get_size*/, + nullptr /*Annot_data_get_ptr*/, }; - } #endif diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal-XPC.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal-XPC.h index a2226740074cd..4a137f9368c7a 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal-XPC.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal-XPC.h @@ -26,6 +26,7 @@ static const char *KeyMsgResponse = "response"; static const char *KeyCancelToken = "cancel_token"; static const char *KeyCancelRequest = "cancel_request"; static const char *KeyDisposeRequestHandle = "dispose_request_handle"; +static const char *KeyPlugins = "plugins"; enum class Message { Initialization, diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h index fb8343aa92b77..eec8a7754f8bd 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h @@ -14,6 +14,7 @@ #define LLVM_SOURCEKITD_INTERNAL_H #include "SourceKit/Support/CancellationToken.h" +#include "sourcekitd/plugin.h" #include "sourcekitd/sourcekitd.h" #include "llvm/ADT/STLExtras.h" #include @@ -33,11 +34,11 @@ namespace SourceKit { bool sourcekitd_variant_dictionary_apply_impl( sourcekitd_variant_t dict, - llvm::function_ref applier); + sourcekitd_variant_dictionary_applier_f_t applier, void *context); bool sourcekitd_variant_array_apply_impl( - sourcekitd_variant_t array, - llvm::function_ref applier); + sourcekitd_variant_t array, sourcekitd_variant_array_applier_f_t applier, + void *context); namespace sourcekitd { @@ -47,7 +48,7 @@ using SourceKit::SourceKitCancellationToken; static const unsigned ProtocolMajorVersion = 1; static const unsigned ProtocolMinorVersion = 0; -enum class CustomBufferKind { +enum class CustomBufferKind : size_t { TokenAnnotationsArray, DeclarationsArray, DocSupportAnnotationArray, @@ -58,7 +59,8 @@ enum class CustomBufferKind { AttributesArray, ExpressionTypeArray, VariableTypeArray, - RawData + RawData, + CustomBufferKind_End }; class ResponseBuilder { @@ -164,6 +166,10 @@ bool shutdownClient(); void set_interrupted_connection_handler(llvm::function_ref handler); +/// Register a custom buffer kind. Must be called only during plugin loading. +void pluginRegisterCustomBufferKind(uint64_t kind, + sourcekitd_variant_functions_t funcs); + void printRequestObject(sourcekitd_object_t Obj, llvm::raw_ostream &OS); void printResponse(sourcekitd_response_t Resp, llvm::raw_ostream &OS); @@ -185,6 +191,11 @@ static inline sourcekitd_variant_t makeIntVariant(int64_t value) { static inline sourcekitd_variant_t makeBoolVariant(bool value) { return {{ 0, value, SOURCEKITD_VARIANT_TYPE_BOOL }}; } +static inline sourcekitd_variant_t makeDoubleVariant(double value) { + uint64_t data; + std::memcpy(&data, &value, sizeof(double)); + return {{0, data, SOURCEKITD_VARIANT_TYPE_DOUBLE}}; +} static inline sourcekitd_variant_t makeStringVariant(const char *value) { return {{ 0, (uintptr_t)value, SOURCEKITD_VARIANT_TYPE_STRING }}; } @@ -197,33 +208,59 @@ static inline sourcekitd_variant_t makeUIDVariant(sourcekitd_uid_t value) { /// /// sourcekitd_variant_t contains a pointer to such a structure. struct VariantFunctions { - sourcekitd_variant_type_t (*get_type)(sourcekitd_variant_t obj); - bool (*array_apply)( - sourcekitd_variant_t array, - llvm::function_ref applier); - bool (*array_get_bool)(sourcekitd_variant_t array, size_t index); - size_t (*array_get_count)(sourcekitd_variant_t array); - int64_t (*array_get_int64)(sourcekitd_variant_t array, size_t index); - const char *(*array_get_string)(sourcekitd_variant_t array, size_t index); - sourcekitd_uid_t (*array_get_uid)(sourcekitd_variant_t array, size_t index); - sourcekitd_variant_t (*array_get_value)(sourcekitd_variant_t array, size_t index); - bool (*bool_get_value)(sourcekitd_variant_t obj); - bool (*dictionary_apply)( - sourcekitd_variant_t dict, - llvm::function_ref applier); - bool (*dictionary_get_bool)(sourcekitd_variant_t dict, sourcekitd_uid_t key); - int64_t (*dictionary_get_int64)(sourcekitd_variant_t dict, sourcekitd_uid_t key); - const char *(*dictionary_get_string)(sourcekitd_variant_t dict, sourcekitd_uid_t key); - sourcekitd_variant_t (*dictionary_get_value)(sourcekitd_variant_t dict, sourcekitd_uid_t key); - sourcekitd_uid_t (*dictionary_get_uid)(sourcekitd_variant_t dict, sourcekitd_uid_t key); - size_t (*string_get_length)(sourcekitd_variant_t obj); - const char *(*string_get_ptr)(sourcekitd_variant_t obj); - int64_t (*int64_get_value)(sourcekitd_variant_t obj); - sourcekitd_uid_t (*uid_get_value)(sourcekitd_variant_t obj); - size_t (*data_get_size)(sourcekitd_variant_t obj); - const void *(*data_get_ptr)(sourcekitd_variant_t obj); + sourcekitd_variant_functions_get_type_t get_type; + sourcekitd_variant_functions_array_apply_t array_apply; + sourcekitd_variant_functions_array_get_bool_t array_get_bool; + sourcekitd_variant_functions_array_get_double_t array_get_double; + sourcekitd_variant_functions_array_get_count_t array_get_count; + sourcekitd_variant_functions_array_get_int64_t array_get_int64; + sourcekitd_variant_functions_array_get_string_t array_get_string; + sourcekitd_variant_functions_array_get_uid_t array_get_uid; + sourcekitd_variant_functions_array_get_value_t array_get_value; + sourcekitd_variant_functions_bool_get_value_t bool_get_value; + sourcekitd_variant_functions_double_get_value_t double_get_value; + sourcekitd_variant_functions_dictionary_apply_t dictionary_apply; + sourcekitd_variant_functions_dictionary_get_bool_t dictionary_get_bool; + sourcekitd_variant_functions_dictionary_get_double_t dictionary_get_double; + sourcekitd_variant_functions_dictionary_get_int64_t dictionary_get_int64; + sourcekitd_variant_functions_dictionary_get_string_t dictionary_get_string; + sourcekitd_variant_functions_dictionary_get_value_t dictionary_get_value; + sourcekitd_variant_functions_dictionary_get_uid_t dictionary_get_uid; + sourcekitd_variant_functions_string_get_length_t string_get_length; + sourcekitd_variant_functions_string_get_ptr_t string_get_ptr; + sourcekitd_variant_functions_int64_get_value_t int64_get_value; + sourcekitd_variant_functions_uid_get_value_t uid_get_value; + sourcekitd_variant_functions_data_get_size_t data_get_size; + sourcekitd_variant_functions_data_get_ptr_t data_get_ptr; }; +// Parameters for plugin initialization. +struct PluginInitParams { + bool isClientOnly; + uint64_t customBufferStart = (uint64_t)CustomBufferKind::CustomBufferKind_End; + sourcekitd_uid_get_from_cstr_t uidGetFromCstr = sourcekitd_uid_get_from_cstr; + sourcekitd_uid_get_string_ptr_t uidGetStringPtr = + sourcekitd_uid_get_string_ptr; + std::function + registerRequestHandler; + std::function + registerCancellationHandler; + std::function + registerCustomBuffer; + void *opaqueIDEInspectionInstance; + + PluginInitParams(bool isClientOnly, + std::function + registerRequestHandler, + std::function + registerCancellationHandler, + void *opaqueIDEInspectionInstance = nullptr); +}; + +void loadPlugins(llvm::ArrayRef registeredPlugins, + PluginInitParams &pluginParams); + +VariantFunctions *getPluginVariantFunctions(size_t BufKind); } #endif diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/RequestResponsePrinterBase.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/RequestResponsePrinterBase.h index ebdf8a6ade1bc..760b75d0fb293 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/RequestResponsePrinterBase.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/RequestResponsePrinterBase.h @@ -89,6 +89,8 @@ class RequestResponsePrinterBase { OS << Val; } + void visitDouble(double Val) { OS << Val; } + void visitString(llvm::StringRef Str) { OS << '\"'; // Avoid raw_ostream's write_escaped, we don't want to escape unicode diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Service.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Service.h index d99c243104135..141c24f0e2462 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Service.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Service.h @@ -14,6 +14,7 @@ #define LLVM_SOURCEKITD_SERVICE_H #include "SourceKit/Support/CancellationToken.h" +#include "sourcekitd/plugin.h" #include "sourcekitd/sourcekitd.h" #include "llvm/ADT/StringRef.h" @@ -35,6 +36,22 @@ void initializeService( /// Shutdown the service. void shutdownService(); +/// Register a custom request handler. Must be called only during plugin +/// loading. +void pluginRegisterRequestHandler( + sourcekitd_cancellable_request_handler_t handler); + +/// Register a cancellation handler that will be called when a request is +/// cancelled. +/// This function is called even for cancelled requests that are handled by +/// sourcekitd itself and not the plugin. If the plugin doesn't know the request +/// handle to be cancelled, it should ignore the cancellation request. +/// Must be called only during plugin loading. +void pluginRegisterCancellationHandler( + sourcekitd_cancellation_handler_t handler); + +void *pluginGetOpaqueSwiftIDEInspectionInstance(); + typedef std::function ResponseReceiver; void handleRequest(sourcekitd_object_t Request, diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/plugin.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/plugin.h new file mode 100644 index 0000000000000..545a9a450ac5a --- /dev/null +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/plugin.h @@ -0,0 +1,402 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 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 LLVM_SOURCEKITD_PLUGIN_H +#define LLVM_SOURCEKITD_PLUGIN_H + +#include "sourcekitd/sourcekitd.h" + +SOURCEKITD_BEGIN_DECLS + +typedef void *sourcekitd_variant_functions_t; + +typedef sourcekitd_variant_type_t (*sourcekitd_variant_functions_get_type_t)( + sourcekitd_variant_t obj); +typedef bool (*sourcekitd_variant_functions_array_apply_t)( + sourcekitd_variant_t array, sourcekitd_variant_array_applier_f_t applier, + void *context); +typedef bool (*sourcekitd_variant_functions_array_get_bool_t)( + sourcekitd_variant_t array, size_t index); +typedef double (*sourcekitd_variant_functions_array_get_double_t)( + sourcekitd_variant_t array, size_t index); +typedef size_t (*sourcekitd_variant_functions_array_get_count_t)( + sourcekitd_variant_t array); +typedef int64_t (*sourcekitd_variant_functions_array_get_int64_t)( + sourcekitd_variant_t array, size_t index); +typedef const char *(*sourcekitd_variant_functions_array_get_string_t)( + sourcekitd_variant_t array, size_t index); +typedef sourcekitd_uid_t (*sourcekitd_variant_functions_array_get_uid_t)( + sourcekitd_variant_t array, size_t index); +typedef sourcekitd_variant_t (*sourcekitd_variant_functions_array_get_value_t)( + sourcekitd_variant_t array, size_t index); +typedef bool (*sourcekitd_variant_functions_bool_get_value_t)( + sourcekitd_variant_t obj); +typedef double (*sourcekitd_variant_functions_double_get_value_t)( + sourcekitd_variant_t obj); +typedef bool (*sourcekitd_variant_functions_dictionary_apply_t)( + sourcekitd_variant_t dict, + sourcekitd_variant_dictionary_applier_f_t applier, void *context); +typedef bool (*sourcekitd_variant_functions_dictionary_get_bool_t)( + sourcekitd_variant_t dict, sourcekitd_uid_t key); +typedef double (*sourcekitd_variant_functions_dictionary_get_double_t)( + sourcekitd_variant_t dict, sourcekitd_uid_t key); +typedef int64_t (*sourcekitd_variant_functions_dictionary_get_int64_t)( + sourcekitd_variant_t dict, sourcekitd_uid_t key); +typedef const char *(*sourcekitd_variant_functions_dictionary_get_string_t)( + sourcekitd_variant_t dict, sourcekitd_uid_t key); +typedef sourcekitd_variant_t ( + *sourcekitd_variant_functions_dictionary_get_value_t)( + sourcekitd_variant_t dict, sourcekitd_uid_t key); +typedef sourcekitd_uid_t (*sourcekitd_variant_functions_dictionary_get_uid_t)( + sourcekitd_variant_t dict, sourcekitd_uid_t key); +typedef size_t (*sourcekitd_variant_functions_string_get_length_t)( + sourcekitd_variant_t obj); +typedef const char *(*sourcekitd_variant_functions_string_get_ptr_t)( + sourcekitd_variant_t obj); +typedef int64_t (*sourcekitd_variant_functions_int64_get_value_t)( + sourcekitd_variant_t obj); +typedef sourcekitd_uid_t (*sourcekitd_variant_functions_uid_get_value_t)( + sourcekitd_variant_t obj); +typedef size_t (*sourcekitd_variant_functions_data_get_size_t)( + sourcekitd_variant_t obj); +typedef const void *(*sourcekitd_variant_functions_data_get_ptr_t)( + sourcekitd_variant_t obj); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_variant_functions_t +sourcekitd_variant_functions_create(); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_get_type( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_get_type_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_apply( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_apply_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_bool( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_bool_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_double( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_double_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_count( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_count_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_int64( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_int64_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_string( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_string_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_uid( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_uid_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_array_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_value_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_bool_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_bool_get_value_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_double_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_double_get_value_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_apply( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_apply_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_get_bool( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_bool_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_get_double( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_double_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_get_int64( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_int64_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_get_string( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_string_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_value_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_dictionary_get_uid( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_uid_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_string_get_length( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_string_get_length_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_string_get_ptr( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_string_get_ptr_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_int64_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_int64_get_value_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_uid_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_uid_get_value_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_data_get_size( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_data_get_size_t f); +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_variant_functions_set_data_get_ptr( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_data_get_ptr_t f); + +#if SOURCEKITD_HAS_BLOCKS + +/// Legacy request handler predating cancellation support. Should be removed +/// when all clients have migrated to sourcekitd_cancellable_request_handler_t. +typedef bool (^sourcekitd_request_handler_t)(sourcekitd_object_t, + void (^)(sourcekitd_response_t)); +/// Handle the request specified by the \c sourcekitd_object_t and keep track +/// of it using the \c sourcekitd_request_handle_t. If the cancellation handler +/// specified by \c sourcekitd_plugin_initialize_register_cancellation_handler +/// is called with the this request handle, the request should be cancelled. +typedef bool (^sourcekitd_cancellable_request_handler_t)( + sourcekitd_object_t, sourcekitd_request_handle_t, + void (^)(sourcekitd_response_t)); +typedef void (^sourcekitd_cancellation_handler_t)(sourcekitd_request_handle_t); +typedef sourcekitd_uid_t (*sourcekitd_uid_get_from_cstr_t)(const char *string); +typedef const char *(*sourcekitd_uid_get_string_ptr_t)(sourcekitd_uid_t); + +typedef void *sourcekitd_plugin_initialize_params_t; +typedef void (*sourcekitd_plugin_initialize_t)( + sourcekitd_plugin_initialize_params_t); +typedef void (*sourcekitd_plugin_initialize_2_t)( + sourcekitd_plugin_initialize_params_t, const char *sourcekit_path); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL bool + sourcekitd_plugin_initialize_is_client_only( + sourcekitd_plugin_initialize_params_t); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL uint64_t + sourcekitd_plugin_initialize_custom_buffer_start( + sourcekitd_plugin_initialize_params_t); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL sourcekitd_uid_get_from_cstr_t + sourcekitd_plugin_initialize_uid_get_from_cstr( + sourcekitd_plugin_initialize_params_t); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL sourcekitd_uid_get_string_ptr_t + sourcekitd_plugin_initialize_uid_get_string_ptr( + sourcekitd_plugin_initialize_params_t); + +/// Legacy registration of request handlers predating cancellation support. +/// Should be removed when all clients have migrated to cancellable request +/// handlers. +SOURCEKITD_DEPRECATED( + "Use sourcekitd_plugin_initialize_register_cancellable_request_handler " + "instead") +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void + sourcekitd_plugin_initialize_register_request_handler( + sourcekitd_plugin_initialize_params_t, sourcekitd_request_handler_t); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void + sourcekitd_plugin_initialize_register_cancellable_request_handler( + sourcekitd_plugin_initialize_params_t, + sourcekitd_cancellable_request_handler_t); + +/// Adds a function that will be called when a request is cancelled. +/// The cancellation handler is called even for cancelled requests that are +/// handled by sourcekitd itself and not the plugin. If the plugin doesn't know +/// the request handle to be cancelled, it should ignore the cancellation +/// request. +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void + sourcekitd_plugin_initialize_register_cancellation_handler( + sourcekitd_plugin_initialize_params_t, + sourcekitd_cancellation_handler_t); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_plugin_initialize_register_custom_buffer( + sourcekitd_plugin_initialize_params_t, uint64_t kind, + sourcekitd_variant_functions_t funcs); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void * + sourcekitd_plugin_initialize_get_swift_ide_inspection_instance( + sourcekitd_plugin_initialize_params_t); + +#endif // SOURCEKITD_HAS_BLOCKS + +//============================================================================// +// Request +//============================================================================// + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_variant_type_t +sourcekitd_request_get_type(sourcekitd_object_t obj); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL2 SOURCEKITD_WARN_RESULT sourcekitd_object_t +sourcekitd_request_dictionary_get_value(sourcekitd_object_t dict, + sourcekitd_uid_t key); + +/// The underlying C string for the specified key. NULL if the value for the +/// specified key is not a C string value or if there is no value for the +/// specified key. +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL SOURCEKITD_WARN_RESULT const char * +sourcekitd_request_dictionary_get_string(sourcekitd_object_t dict, + sourcekitd_uid_t key); + +/// The underlying \c int64 value for the specified key. 0 if the +/// value for the specified key is not an integer value or if there is no +/// value for the specified key. +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL SOURCEKITD_WARN_RESULT int64_t +sourcekitd_request_dictionary_get_int64(sourcekitd_object_t dict, + sourcekitd_uid_t key); + +/// The underlying \c bool value for the specified key. false if the +/// value for the specified key is not a Boolean value or if there is no +/// value for the specified key. +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL SOURCEKITD_WARN_RESULT bool +sourcekitd_request_dictionary_get_bool(sourcekitd_object_t dict, + sourcekitd_uid_t key); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL sourcekitd_uid_t +sourcekitd_request_dictionary_get_uid(sourcekitd_object_t dict, + sourcekitd_uid_t key); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT size_t +sourcekitd_request_array_get_count(sourcekitd_object_t array); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_object_t +sourcekitd_request_array_get_value(sourcekitd_object_t array, size_t index); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT const char * +sourcekitd_request_array_get_string(sourcekitd_object_t array, size_t index); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT int64_t +sourcekitd_request_array_get_int64(sourcekitd_object_t array, size_t index); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT bool +sourcekitd_request_array_get_bool(sourcekitd_object_t array, size_t index); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_uid_t +sourcekitd_request_array_get_uid(sourcekitd_object_t array, size_t index); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT int64_t +sourcekitd_request_int64_get_value(sourcekitd_object_t obj); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT bool +sourcekitd_request_bool_get_value(sourcekitd_object_t obj); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT size_t +sourcekitd_request_string_get_length(sourcekitd_object_t obj); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT const char * +sourcekitd_request_string_get_ptr(sourcekitd_object_t obj); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_uid_t +sourcekitd_request_uid_get_value(sourcekitd_object_t obj); + +//============================================================================// +// Response +//============================================================================// + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 sourcekitd_response_t +sourcekitd_response_retain(sourcekitd_response_t object); + +SOURCEKITD_PUBLIC +sourcekitd_response_t sourcekitd_response_error_create(sourcekitd_error_t kind, + const char *description); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_response_t +sourcekitd_response_dictionary_create(const sourcekitd_uid_t *keys, + const sourcekitd_response_t *values, + size_t count); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_response_dictionary_set_value(sourcekitd_response_t dict, + sourcekitd_uid_t key, + sourcekitd_response_t value); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_response_dictionary_set_string(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const char *string); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_response_dictionary_set_stringbuf(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const char *buf, size_t length); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL2 void +sourcekitd_response_dictionary_set_int64(sourcekitd_response_t dict, + sourcekitd_uid_t key, int64_t val); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL2 void +sourcekitd_response_dictionary_set_bool(sourcekitd_response_t dict, + sourcekitd_uid_t key, bool val); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL2 void +sourcekitd_response_dictionary_set_double(sourcekitd_response_t dict, + sourcekitd_uid_t key, double val); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_response_dictionary_set_uid(sourcekitd_response_t dict, + sourcekitd_uid_t key, + sourcekitd_uid_t uid); + +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_response_t +sourcekitd_response_array_create(const sourcekitd_response_t *objects, + size_t count); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL3 void +sourcekitd_response_array_set_value(sourcekitd_response_t array, size_t index, + sourcekitd_response_t value); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL3 void +sourcekitd_response_array_set_string(sourcekitd_response_t array, size_t index, + const char *string); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL3 void +sourcekitd_response_array_set_stringbuf(sourcekitd_response_t array, + size_t index, const char *buf, + size_t length); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 void +sourcekitd_response_array_set_int64(sourcekitd_response_t array, size_t index, + int64_t val); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 void +sourcekitd_response_array_set_double(sourcekitd_response_t array, size_t index, + double val); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL1 SOURCEKITD_NONNULL3 void +sourcekitd_response_array_set_uid(sourcekitd_response_t array, size_t index, + sourcekitd_uid_t uid); + +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL void +sourcekitd_response_dictionary_set_custom_buffer(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const void *ptr, size_t size); + +SOURCEKITD_END_DECLS + +#endif diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h index 316758b9631b1..11e58ea7a4965 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h @@ -25,7 +25,7 @@ /// The policy about the sourcekitd API is to keep it source and ABI compatible, /// thus SOURCEKITD_VERSION_MAJOR is expected to remain stable. #define SOURCEKITD_VERSION_MAJOR 0 -#define SOURCEKITD_VERSION_MINOR 4 +#define SOURCEKITD_VERSION_MINOR 5 #define SOURCEKITD_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -89,6 +89,22 @@ SOURCEKITD_BEGIN_DECLS +/// Register plugin paths. +/// +/// This must be called before 'sourcekitd_initialize()' or +/// 'sourcekitd_load_client_plugins()'. +SOURCEKITD_PUBLIC void +sourcekitd_register_plugin_path(const char *clientPlugin, + const char *servicePlugin); + +/// Load and initialzie registered client plugins. +/// +/// NOTE: This function is called implicitly by 'sourcekitd_initialize()'. Only +/// clients that cannot call 'sourcekitd_initialize()' should need to call this +/// directly. Also, all clients must register the same plugins in the same +/// order. +SOURCEKITD_PUBLIC void sourcekitd_load_client_plugins(void); + /// Initializes structures needed across the rest of the sourcekitd API. /// /// Must be called before any other sourcekitd call. @@ -312,8 +328,7 @@ typedef enum { SOURCEKITD_VARIANT_TYPE_STRING = 4, SOURCEKITD_VARIANT_TYPE_UID = 5, SOURCEKITD_VARIANT_TYPE_BOOL = 6, - // Reserved for future addition - // SOURCEKITD_VARIANT_TYPE_DOUBLE = 7, + SOURCEKITD_VARIANT_TYPE_DOUBLE = 7, SOURCEKITD_VARIANT_TYPE_DATA = 8, } sourcekitd_variant_type_t; @@ -389,6 +404,13 @@ bool sourcekitd_variant_dictionary_get_bool(sourcekitd_variant_t dict, sourcekitd_uid_t key); +/// The underlying \c double value for the specified key. 0.0 if the +/// value for the specified key is not a double value or if there is no +/// value for the specified key. +SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL SOURCEKITD_WARN_RESULT double +sourcekitd_variant_dictionary_get_double(sourcekitd_variant_t dict, + sourcekitd_uid_t key); + /// The underlying \c sourcekitd_uid_t value for the specified key. NULL if the /// value for the specified key is not a uid value or if there is no /// value for the specified key. @@ -460,6 +482,9 @@ SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT bool sourcekitd_variant_array_get_bool(sourcekitd_variant_t array, size_t index); +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT double +sourcekitd_variant_array_get_double(sourcekitd_variant_t array, size_t index); + SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT sourcekitd_uid_t sourcekitd_variant_array_get_uid(sourcekitd_variant_t array, size_t index); @@ -514,6 +539,9 @@ SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT bool sourcekitd_variant_bool_get_value(sourcekitd_variant_t obj); +SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT double +sourcekitd_variant_double_get_value(sourcekitd_variant_t obj); + SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT size_t sourcekitd_variant_string_get_length(sourcekitd_variant_t obj); diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitdInProc-Internal.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitdInProc-Internal.h new file mode 100644 index 0000000000000..08cc5a5f4080c --- /dev/null +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitdInProc-Internal.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 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 LLVM_SOURCEKITDINPROC_INTERNAL_H +#define LLVM_SOURCEKITDINPROC_INTERNAL_H + +#include + +namespace sourcekitdInProc { +std::string getRuntimeLibPath(); +std::string getSwiftExecutablePath(); +std::string getDiagnosticDocumentationPath(); +} // namespace sourcekitdInProc + +#endif diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp index b21c649835715..a6e16f70dc25f 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp @@ -90,8 +90,8 @@ class CodeCompletionResultsArray { static bool dictionary_apply(void *Buf, size_t Index, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { CompactArrayReaderTy Reader(Buf); sourcekitd_uid_t Kind; @@ -124,11 +124,12 @@ class CodeCompletionResultsArray { bool NotRecommended = Flags & 0x2; bool IsSystem = Flags & 0x1; -#define APPLY(K, Ty, Field) \ - do { \ - sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ - sourcekitd_variant_t var = make##Ty##Variant(Field); \ - if (!applier(key, var)) return false; \ +#define APPLY(K, Ty, Field) \ + do { \ + sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ + sourcekitd_variant_t var = make##Ty##Variant(Field); \ + if (!applier(key, var, context)) \ + return false; \ } while (0) APPLY(KeyKind, UID, Kind); diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DeclarationsArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DeclarationsArray.cpp index 45d19bf6b17c0..c7116023a6d37 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/DeclarationsArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/DeclarationsArray.cpp @@ -56,17 +56,16 @@ class DeclarationsArray { Reader.readEntries(Index, Kind, Offset, Length, USR); } - static bool - apply(sourcekitd_uid_t Kind, unsigned Offset, unsigned Length, - const char *USR, - llvm::function_ref - applier) { + static bool apply(sourcekitd_uid_t Kind, unsigned Offset, unsigned Length, + const char *USR, + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { #define APPLY(K, Ty, Field) \ do { \ sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ sourcekitd_variant_t var = make##Ty##Variant(Field); \ - if (!applier(key, var)) \ + if (!applier(key, var, context)) \ return false; \ } while (0) @@ -131,10 +130,10 @@ struct CompactVariantFuncs { return Fn(key, Kind, Offset, Length, USR); } - static bool dictionary_apply( - sourcekitd_variant_t dict, - llvm::function_ref - applier) { + static bool + dictionary_apply(sourcekitd_variant_t dict, + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { void *Buf = (void *)dict.data[1]; size_t Index = dict.data[2]; @@ -143,7 +142,8 @@ struct CompactVariantFuncs { unsigned Length; const char *USR; DeclarationsArray::readElements(Buf, Index, Kind, Offset, Length, USR); - return DeclarationsArray::apply(Kind, Offset, Length, USR, applier); + return DeclarationsArray::apply(Kind, Offset, Length, USR, applier, + context); } static int64_t dictionary_get_int64(sourcekitd_variant_t dict, @@ -171,14 +171,17 @@ VariantFunctions CompactVariantFuncs::Funcs = { get_type, nullptr /*Annot_array_apply*/, nullptr /*Annot_array_get_bool*/, + nullptr /*Annot_array_get_double*/, nullptr /*Annot_array_get_count*/, nullptr /*Annot_array_get_int64*/, nullptr /*Annot_array_get_string*/, nullptr /*Annot_array_get_uid*/, nullptr /*Annot_array_get_value*/, nullptr /*Annot_bool_get_value*/, + nullptr /*Annot_double_get_value*/, dictionary_apply, nullptr /*Annot_dictionary_get_bool*/, + nullptr /*Annot_dictionary_get_double*/, dictionary_get_int64, dictionary_get_string, nullptr /*Annot_dictionary_get_value*/, diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp index ccf2ea1420baf..9358edb7a285e 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp @@ -403,7 +403,7 @@ uint64_t DocStructureArrayReader::getHeaderValue(unsigned index) const { do { \ sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ sourcekitd_variant_t var = make##Ty##Variant(Field); \ - if (!applier(key, var)) \ + if (!applier(key, var, context)) \ return false; \ } while (0) @@ -414,8 +414,8 @@ struct ElementReader { static bool dictionary_apply(void *buffer, size_t index, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { CompactArrayReaderTy reader(buffer); sourcekitd_uid_t kind; @@ -434,8 +434,8 @@ struct InheritedTypeReader { static bool dictionary_apply(void *buffer, size_t index, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { CompactArrayReaderTy reader(buffer); const char *value = nullptr; @@ -451,9 +451,8 @@ struct AttributesReader { static bool dictionary_apply(void *buffer, size_t index, - llvm::function_ref applier) { - + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { CompactArrayReaderTy reader(buffer); sourcekitd_uid_t value; unsigned offset; @@ -470,8 +469,8 @@ struct AttributesReader { struct DocStructureReader { static bool dictionary_apply(void *buffer, size_t index, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { auto reader = DocStructureArrayReader(buffer); auto node = reader.readStructure(index); @@ -509,7 +508,7 @@ struct DocStructureReader { sourcekitd_variant_t var = { \ {(uintptr_t)getVariantFunctionsFor##Kind##Array(), (uintptr_t)Buf, \ Off}}; \ - if (!applier(key, var)) \ + if (!applier(key, var, context)) \ return false; \ } while (0) @@ -571,14 +570,17 @@ VariantFunctions DocStructureArrayFuncs::funcs = { get_type, nullptr /*AnnotArray_array_apply*/, nullptr /*AnnotArray_array_get_bool*/, + nullptr /*AnnotArray_array_get_double*/, array_get_count, nullptr /*AnnotArray_array_get_int64*/, nullptr /*AnnotArray_array_get_string*/, nullptr /*AnnotArray_array_get_uid*/, array_get_value, nullptr /*AnnotArray_bool_get_value*/, + nullptr /*AnnotArray_double_get_value*/, nullptr /*AnnotArray_dictionary_apply*/, nullptr /*AnnotArray_dictionary_get_bool*/, + nullptr /*AnnotArray_dictionary_get_double*/, nullptr /*AnnotArray_dictionary_get_int64*/, nullptr /*AnnotArray_dictionary_get_string*/, nullptr /*AnnotArray_dictionary_get_value*/, diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocSupportAnnotationArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocSupportAnnotationArray.cpp index d28c8d9548593..8cba123276eac 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/DocSupportAnnotationArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocSupportAnnotationArray.cpp @@ -63,11 +63,11 @@ class DocSupportAnnotationArray { const char *, unsigned, unsigned> CompactArrayReaderTy; - + static bool dictionary_apply(void *Buf, size_t Index, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { CompactArrayReaderTy Reader(Buf); sourcekitd_uid_t Kind; @@ -83,11 +83,12 @@ class DocSupportAnnotationArray { Offset, Length); -#define APPLY(K, Ty, Field) \ - do { \ - sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ - sourcekitd_variant_t var = make##Ty##Variant(Field); \ - if (!applier(key, var)) return false; \ +#define APPLY(K, Ty, Field) \ + do { \ + sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ + sourcekitd_variant_t var = make##Ty##Variant(Field); \ + if (!applier(key, var, context)) \ + return false; \ } while (0) APPLY(KeyKind, UID, Kind); diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/ExpressionTypeArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/ExpressionTypeArray.cpp index 33592c38f4544..386c6bb86efe0 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/ExpressionTypeArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/ExpressionTypeArray.cpp @@ -71,15 +71,16 @@ class ExpressionTypeReader { static bool dictionary_apply(void *buffer, size_t index, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { ExpressionTypeReader reader((char*)buffer); auto result = reader.getExpression(index); -#define APPLY(K, Ty, Field) \ - do { \ - sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ - sourcekitd_variant_t var = make##Ty##Variant(Field); \ - if (!applier(key, var)) return false; \ +#define APPLY(K, Ty, Field) \ + do { \ + sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ + sourcekitd_variant_t var = make##Ty##Variant(Field); \ + if (!applier(key, var, context)) \ + return false; \ } while (0) #define APPLY_ARRAY(Kind, Key) \ @@ -87,8 +88,9 @@ class ExpressionTypeReader { sourcekitd_uid_t key = SKDUIDFromUIdent(Key); \ sourcekitd_variant_t var = { \ {(uintptr_t)getVariantFunctionsFor##Kind##Array(), (uintptr_t)buffer, \ - index}}; \ - if (!applier(key, var)) return false; \ + index}}; \ + if (!applier(key, var, context)) \ + return false; \ } while (0) APPLY(KeyExpressionOffset, Int, result.ExprOffset); @@ -128,27 +130,30 @@ struct ProtocolListFuncs { }// end of anonymous namespace VariantFunctions ProtocolListFuncs::Funcs = { - get_type, - nullptr /*AnnotArray_array_apply*/, - nullptr /*AnnotArray_array_get_bool*/, - array_get_count, - nullptr /*AnnotArray_array_get_int64*/, - nullptr /*AnnotArray_array_get_string*/, - nullptr /*AnnotArray_array_get_uid*/, - array_get_value, - nullptr /*AnnotArray_bool_get_value*/, - nullptr /*AnnotArray_dictionary_apply*/, - nullptr /*AnnotArray_dictionary_get_bool*/, - nullptr /*AnnotArray_dictionary_get_int64*/, - nullptr /*AnnotArray_dictionary_get_string*/, - nullptr /*AnnotArray_dictionary_get_value*/, - nullptr /*AnnotArray_dictionary_get_uid*/, - nullptr /*AnnotArray_string_get_length*/, - nullptr /*AnnotArray_string_get_ptr*/, - nullptr /*AnnotArray_int64_get_value*/, - nullptr /*AnnotArray_uid_get_value*/, - nullptr /*Annot_data_get_size*/, - nullptr /*Annot_data_get_ptr*/, + get_type, + nullptr /*AnnotArray_array_apply*/, + nullptr /*AnnotArray_array_get_bool*/, + nullptr /*AnnotArray_array_get_double*/, + array_get_count, + nullptr /*AnnotArray_array_get_int64*/, + nullptr /*AnnotArray_array_get_string*/, + nullptr /*AnnotArray_array_get_uid*/, + array_get_value, + nullptr /*AnnotArray_bool_get_value*/, + nullptr /*AnnotArray_double_get_value*/, + nullptr /*AnnotArray_dictionary_apply*/, + nullptr /*AnnotArray_dictionary_get_bool*/, + nullptr /*AnnotArray_dictionary_get_double*/, + nullptr /*AnnotArray_dictionary_get_int64*/, + nullptr /*AnnotArray_dictionary_get_string*/, + nullptr /*AnnotArray_dictionary_get_value*/, + nullptr /*AnnotArray_dictionary_get_uid*/, + nullptr /*AnnotArray_string_get_length*/, + nullptr /*AnnotArray_string_get_ptr*/, + nullptr /*AnnotArray_int64_get_value*/, + nullptr /*AnnotArray_uid_get_value*/, + nullptr /*Annot_data_get_size*/, + nullptr /*Annot_data_get_ptr*/, }; struct ExpressionTypeArrayBuilder::Implementation { @@ -230,27 +235,30 @@ ExpressionTypeArrayBuilder::createBuffer() { } VariantFunctions ExpressionTypeArrayBuilder::Funcs = { - Implementation::get_type, - nullptr /*AnnotArray_array_apply*/, - nullptr /*AnnotArray_array_get_bool*/, - Implementation::array_get_count, - nullptr /*AnnotArray_array_get_int64*/, - nullptr /*AnnotArray_array_get_string*/, - nullptr /*AnnotArray_array_get_uid*/, - Implementation::array_get_value, - nullptr /*AnnotArray_bool_get_value*/, - nullptr /*AnnotArray_dictionary_apply*/, - nullptr /*AnnotArray_dictionary_get_bool*/, - nullptr /*AnnotArray_dictionary_get_int64*/, - nullptr /*AnnotArray_dictionary_get_string*/, - nullptr /*AnnotArray_dictionary_get_value*/, - nullptr /*AnnotArray_dictionary_get_uid*/, - nullptr /*AnnotArray_string_get_length*/, - nullptr /*AnnotArray_string_get_ptr*/, - nullptr /*AnnotArray_int64_get_value*/, - nullptr /*AnnotArray_uid_get_value*/, - nullptr /*Annot_data_get_size*/, - nullptr /*Annot_data_get_ptr*/, + Implementation::get_type, + nullptr /*AnnotArray_array_apply*/, + nullptr /*AnnotArray_array_get_bool*/, + nullptr /*AnnotArray_array_get_double*/, + Implementation::array_get_count, + nullptr /*AnnotArray_array_get_int64*/, + nullptr /*AnnotArray_array_get_string*/, + nullptr /*AnnotArray_array_get_uid*/, + Implementation::array_get_value, + nullptr /*AnnotArray_bool_get_value*/, + nullptr /*AnnotArray_double_get_value*/, + nullptr /*AnnotArray_dictionary_apply*/, + nullptr /*AnnotArray_dictionary_get_bool*/, + nullptr /*AnnotArray_dictionary_get_double*/, + nullptr /*AnnotArray_dictionary_get_int64*/, + nullptr /*AnnotArray_dictionary_get_string*/, + nullptr /*AnnotArray_dictionary_get_value*/, + nullptr /*AnnotArray_dictionary_get_uid*/, + nullptr /*AnnotArray_string_get_length*/, + nullptr /*AnnotArray_string_get_ptr*/, + nullptr /*AnnotArray_int64_get_value*/, + nullptr /*AnnotArray_uid_get_value*/, + nullptr /*Annot_data_get_size*/, + nullptr /*Annot_data_get_ptr*/, }; VariantFunctions * diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/RawData.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/RawData.cpp index 6c7bf05038d7c..5eeadbecc3b1c 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/RawData.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/RawData.cpp @@ -31,27 +31,30 @@ struct RawDataFuncs { }; VariantFunctions RawDataFuncs::Funcs = { - get_type, - nullptr /*AnnotArray_array_apply*/, - nullptr /*AnnotArray_array_get_bool*/, - nullptr /*Annot_array_array_get_count*/, - nullptr /*AnnotArray_array_get_int64*/, - nullptr /*AnnotArray_array_get_string*/, - nullptr /*AnnotArray_array_get_uid*/, - nullptr /*AnnotArray_array_get_value*/, - nullptr /*AnnotArray_bool_get_value*/, - nullptr /*AnnotArray_dictionary_apply*/, - nullptr /*AnnotArray_dictionary_get_bool*/, - nullptr /*AnnotArray_dictionary_get_int64*/, - nullptr /*AnnotArray_dictionary_get_string*/, - nullptr /*AnnotArray_dictionary_get_value*/, - nullptr /*AnnotArray_dictionary_get_uid*/, - nullptr /*AnnotArray_string_get_length*/, - nullptr /*AnnotArray_string_get_ptr*/, - nullptr /*AnnotArray_int64_get_value*/, - nullptr /*AnnotArray_uid_get_value*/, - data_get_size, - data_get_ptr, + get_type, + nullptr /*AnnotArray_array_apply*/, + nullptr /*AnnotArray_array_get_bool*/, + nullptr /*AnnotArray_array_get_double*/, + nullptr /*Annot_array_array_get_count*/, + nullptr /*AnnotArray_array_get_int64*/, + nullptr /*AnnotArray_array_get_string*/, + nullptr /*AnnotArray_array_get_uid*/, + nullptr /*AnnotArray_array_get_value*/, + nullptr /*AnnotArray_bool_get_value*/, + nullptr /*AnnotArray_double_get_value*/, + nullptr /*AnnotArray_dictionary_apply*/, + nullptr /*AnnotArray_dictionary_get_bool*/, + nullptr /*AnnotArray_dictionary_get_double*/, + nullptr /*AnnotArray_dictionary_get_int64*/, + nullptr /*AnnotArray_dictionary_get_string*/, + nullptr /*AnnotArray_dictionary_get_value*/, + nullptr /*AnnotArray_dictionary_get_uid*/, + nullptr /*AnnotArray_string_get_length*/, + nullptr /*AnnotArray_string_get_ptr*/, + nullptr /*AnnotArray_int64_get_value*/, + nullptr /*AnnotArray_uid_get_value*/, + data_get_size, + data_get_ptr, }; VariantFunctions *sourcekitd::getVariantFunctionsForRawData() { diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/TokenAnnotationsArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/TokenAnnotationsArray.cpp index ac3ac61f0b46b..6f501f140c366 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/TokenAnnotationsArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/TokenAnnotationsArray.cpp @@ -81,18 +81,17 @@ class TokenAnnotationsArray { IsSystem = LengthAndIsSystem & 0x1; } - static bool apply(sourcekitd_uid_t Kind, - unsigned Offset, - unsigned Length, + static bool apply(sourcekitd_uid_t Kind, unsigned Offset, unsigned Length, bool IsSystem, - llvm::function_ref applier) { - -#define APPLY(K, Ty, Field) \ - do { \ - sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ - sourcekitd_variant_t var = make##Ty##Variant(Field); \ - if (!applier(key, var)) return false; \ + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { + +#define APPLY(K, Ty, Field) \ + do { \ + sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ + sourcekitd_variant_t var = make##Ty##Variant(Field); \ + if (!applier(key, var, context)) \ + return false; \ } while (0) APPLY(KeyKind, UID, Kind); @@ -162,11 +161,11 @@ struct CompactVariantFuncs { return Fn(key, Kind, Offset, Length, IsSystem); } - + static bool dictionary_apply(sourcekitd_variant_t dict, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { void *Buf = (void*)dict.data[1]; size_t Index = dict.data[2]; @@ -176,7 +175,8 @@ struct CompactVariantFuncs { bool IsSystem; TokenAnnotationsArray::readElements(Buf, Index, Kind, Offset, Length, IsSystem); - return TokenAnnotationsArray::apply(Kind, Offset, Length, IsSystem, applier); + return TokenAnnotationsArray::apply(Kind, Offset, Length, IsSystem, applier, + context); } static bool dictionary_get_bool(sourcekitd_variant_t dict, @@ -200,27 +200,30 @@ struct CompactVariantFuncs { }; VariantFunctions CompactVariantFuncs::Funcs = { - get_type, - nullptr/*Annot_array_apply*/, - nullptr/*Annot_array_get_bool*/, - nullptr/*Annot_array_get_count*/, - nullptr/*Annot_array_get_int64*/, - nullptr/*Annot_array_get_string*/, - nullptr/*Annot_array_get_uid*/, - nullptr/*Annot_array_get_value*/, - nullptr/*Annot_bool_get_value*/, - dictionary_apply, - dictionary_get_bool, - dictionary_get_int64, - nullptr/*Annot_dictionary_get_string*/, - nullptr/*Annot_dictionary_get_value*/, - dictionary_get_uid, - nullptr/*Annot_string_get_length*/, - nullptr/*Annot_string_get_ptr*/, - nullptr/*Annot_int64_get_value*/, - nullptr/*Annot_uid_get_value*/, - nullptr/*Annot_data_get_size*/, - nullptr/*Annot_data_get_ptr*/, + get_type, + nullptr /*Annot_array_apply*/, + nullptr /*Annot_array_get_bool*/, + nullptr /*Annot_array_get_double*/, + nullptr /*Annot_array_get_count*/, + nullptr /*Annot_array_get_int64*/, + nullptr /*Annot_array_get_string*/, + nullptr /*Annot_array_get_uid*/, + nullptr /*Annot_array_get_value*/, + nullptr /*Annot_bool_get_value*/, + nullptr /*Annot_double_get_value*/, + dictionary_apply, + dictionary_get_bool, + nullptr /*Annot_dictionary_get_double*/, + dictionary_get_int64, + nullptr /*Annot_dictionary_get_string*/, + nullptr /*Annot_dictionary_get_value*/, + dictionary_get_uid, + nullptr /*Annot_string_get_length*/, + nullptr /*Annot_string_get_ptr*/, + nullptr /*Annot_int64_get_value*/, + nullptr /*Annot_uid_get_value*/, + nullptr /*Annot_data_get_size*/, + nullptr /*Annot_data_get_ptr*/, }; } // namespace sourcekitd diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/VariableTypeArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/VariableTypeArray.cpp index 39ed448a28cb3..05aa8a8f378da 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/VariableTypeArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/VariableTypeArray.cpp @@ -62,17 +62,17 @@ class VariableTypeReader { const char *readPrintedType(unsigned Offset) { return PrintedTypes + Offset; } - static bool dictionary_apply( - void *Buffer, size_t Index, - llvm::function_ref - Applier) { + static bool + dictionary_apply(void *Buffer, size_t Index, + sourcekitd_variant_dictionary_applier_f_t Applier, + void *Context) { VariableTypeReader Reader((char *)Buffer); auto Result = Reader.getVariable(Index); #define APPLY(K, Ty, Field) \ do { \ sourcekitd_uid_t Key = SKDUIDFromUIdent(K); \ sourcekitd_variant_t Var = make##Ty##Variant(Field); \ - if (!Applier(Key, Var)) \ + if (!Applier(Key, Var, Context)) \ return false; \ } while (0) @@ -157,14 +157,17 @@ VariantFunctions VariableTypeArrayBuilder::Funcs = { Implementation::get_type, nullptr /*AnnotArray_array_apply*/, nullptr /*AnnotArray_array_get_bool*/, + nullptr /*AnnotArray_array_get_double*/, Implementation::array_get_count, nullptr /*AnnotArray_array_get_int64*/, nullptr /*AnnotArray_array_get_string*/, nullptr /*AnnotArray_array_get_uid*/, Implementation::array_get_value, nullptr /*AnnotArray_bool_get_value*/, + nullptr /*AnnotArray_double_get_value*/, nullptr /*AnnotArray_dictionary_apply*/, nullptr /*AnnotArray_dictionary_get_bool*/, + nullptr /*AnnotArray_dictionary_get_double*/, nullptr /*AnnotArray_dictionary_get_int64*/, nullptr /*AnnotArray_dictionary_get_string*/, nullptr /*AnnotArray_dictionary_get_value*/, diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp index b8e4f1442c3b5..de3d85ecc953b 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp @@ -16,6 +16,7 @@ #include "sourcekitd/RequestResponsePrinterBase.h" #include "SourceKit/Support/Logging.h" #include "SourceKit/Support/UIdent.h" +#include "swift/Basic/LoadDynamicLibrary.h" #include "swift/Basic/StringExtras.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" @@ -27,6 +28,13 @@ #include "llvm/Support/YAMLParser.h" #include +#if defined(_WIN32) && !defined(__CYGWIN__) +#define NOMINMAX +#include +#else +#include +#endif + using namespace SourceKit; using namespace sourcekitd; using llvm::ArrayRef; @@ -63,6 +71,47 @@ bool sourcekitd::compareDictKeys(UIdent LHS, UIdent RHS) { return LHSOrder < RHSOrder; } +namespace { + +/// This a near-copy of llvm::function_ref, but that exposes its members +/// publicly so we can efficiently wrap the applier functions below. +template +class applier_function_ref; + +template +class applier_function_ref { +public: + Ret (*callback)(Params... params, void *context) = nullptr; + void *context; + + template + static Ret callback_fn(Params... params, void *context) { + return (*reinterpret_cast(context))( + std::forward(params)...); + } + + template + applier_function_ref( + Callable &&callable, + std::enable_if_t< + !std::is_same>, + applier_function_ref>::value> * = nullptr) + : callback(callback_fn::type>), + context(reinterpret_cast(&callable)) {} + + Ret operator()(Params... params) const { + return callback(std::forward(params)..., context); + } +}; +} // end anonymous namespace + +static bool variant_dictionary_apply( + sourcekitd_variant_t dict, + applier_function_ref + applier) { + return sourcekitd_variant_dictionary_apply_impl(dict, applier.callback, + applier.context); +} namespace { template (this)->visitBool( sourcekitd_variant_bool_get_value(Obj)); + case SOURCEKITD_VARIANT_TYPE_DOUBLE: + return static_cast(this)->visitDouble( + sourcekitd_variant_double_get_value(Obj)); case SOURCEKITD_VARIANT_TYPE_STRING: { size_t Len = sourcekitd_variant_string_get_length(Obj); const char *Ptr = sourcekitd_variant_string_get_ptr(Obj); @@ -224,6 +275,82 @@ bool sourcekitd::shutdownClient() { return true; } +extern "C" const char __dso_handle[]; + +static void withCurrentLibraryPath(llvm::function_ref body) { +#if defined(_WIN32) && !defined(__CYGWIN__) + char path[MAX_PATH]; + HMODULE currentModule = NULL; + + if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCWSTR) &withCurrentLibraryPath, ¤tModule) == 0) { + int error = GetLastError(); + LOG_WARN("plugin-loading", "failed to determine current Windows module. Error: " << error); + return body(nullptr); + } + if (GetModuleFileNameA(currentModule, path, sizeof(path)) == 0) { + int error = GetLastError(); + LOG_WARN("plugin-loading", "failed to path of current Windows module. Error: " << error); + return body(nullptr); + } + return body(path); +#else + Dl_info dlinfo; + dladdr(__dso_handle, &dlinfo); + return body(dlinfo.dli_fname); +#endif +} + +static void loadPlugin(StringRef plugin, PluginInitParams &pluginParams) { + std::string err; + auto *handle = swift::loadLibrary(plugin.str().c_str(), &err); + if (!handle) { + LOG_WARN("plugin-loading", + "failed to load plugin '" << plugin << "': " << err); + return; + } + + auto *plugin_init_2 = (sourcekitd_plugin_initialize_2_t)swift::getAddressOfSymbol( + handle, "sourcekitd_plugin_initialize_2"); + if (plugin_init_2) { + withCurrentLibraryPath([&](const char *currentLibraryPath) { + plugin_init_2(&pluginParams, currentLibraryPath); + }); + return; + } + + // Fall back to the legacy sourcekitd_plugin_initialize function. + auto *plugin_init = (sourcekitd_plugin_initialize_t)swift::getAddressOfSymbol( + handle, "sourcekitd_plugin_initialize"); + if (plugin_init) { + plugin_init(&pluginParams); + return; + } + + LOG_WARN("plugin-loading", + "plugin '" + << plugin + << "' missing expected symbol: sourcekitd_plugin_initialize_2 or sourcekitd_plugin_initialize"); +} + +void sourcekitd::loadPlugins(ArrayRef registeredPlugins, + PluginInitParams &pluginParams) { + // Load from environment variable first so that it will override registered + // plugins. + StringRef envPlugins = getenv("SOURCEKIT_PLUGINS"); + while (!envPlugins.empty()) { + StringRef plugin; + std::tie(plugin, envPlugins) = envPlugins.split(":"); + assert(!plugin.empty()); + loadPlugin(plugin, pluginParams); + } + + // Load registered plugins. + for (const auto &path : registeredPlugins) + loadPlugin(path, pluginParams); +} + void sourcekitd_response_description_dump(sourcekitd_response_t resp) { // Avoid colors here, we don't properly detect that the debug window inside @@ -319,7 +446,7 @@ sourcekitd_variant_dictionary_get_value(sourcekitd_variant_t dict, // Default implementation: // Linear search for the key/value pair via sourcekitd_variant_dictionary_apply. sourcekitd_variant_t result = makeNullVariant(); - sourcekitd_variant_dictionary_apply_impl( + variant_dictionary_apply( dict, [&](sourcekitd_uid_t curr_key, sourcekitd_variant_t curr_value) { if (curr_key == key) { result = curr_value; @@ -343,6 +470,13 @@ sourcekitd_variant_dictionary_get_string(sourcekitd_variant_t dict, sourcekitd_variant_dictionary_get_value(dict, key)); } +static bool variant_dictionary_applier_block_f(sourcekitd_uid_t key, + sourcekitd_variant_t value, + void *context) { + auto *block = (sourcekitd_variant_dictionary_applier_t *)context; + return (*block)(key, value); +} + int64_t sourcekitd_variant_dictionary_get_int64(sourcekitd_variant_t dict, sourcekitd_uid_t key) { @@ -367,6 +501,17 @@ sourcekitd_variant_dictionary_get_bool(sourcekitd_variant_t dict, sourcekitd_variant_dictionary_get_value(dict, key)); } +double sourcekitd_variant_dictionary_get_double(sourcekitd_variant_t dict, + sourcekitd_uid_t key) { + if (auto fn = VAR_FN(dict, dictionary_get_double)) + return fn(dict, key); + + // Default implementation: + // Get the value via sourcekitd_variant_dictionary_get_value. + return sourcekitd_variant_double_get_value( + sourcekitd_variant_dictionary_get_value(dict, key)); +} + sourcekitd_uid_t sourcekitd_variant_dictionary_get_uid(sourcekitd_variant_t dict, sourcekitd_uid_t key) { @@ -383,16 +528,16 @@ sourcekitd_variant_dictionary_get_uid(sourcekitd_variant_t dict, bool sourcekitd_variant_dictionary_apply(sourcekitd_variant_t dict, sourcekitd_variant_dictionary_applier_t applier) { - return sourcekitd_variant_dictionary_apply_impl(dict, applier); + return sourcekitd_variant_dictionary_apply_impl( + dict, variant_dictionary_applier_block_f, &applier); } #endif -bool -sourcekitd_variant_dictionary_apply_impl( - sourcekitd_variant_t dict, - llvm::function_ref applier) { +bool sourcekitd_variant_dictionary_apply_impl( + sourcekitd_variant_t dict, + sourcekitd_variant_dictionary_applier_f_t applier, void *context) { if (auto fn = VAR_FN(dict, dictionary_apply)) - return fn(dict, applier); + return fn(dict, applier, context); // Default implementation: // Treat as empty container. @@ -403,11 +548,7 @@ bool sourcekitd_variant_dictionary_apply_f(sourcekitd_variant_t dict, sourcekitd_variant_dictionary_applier_f_t applier, void *context) { - return sourcekitd_variant_dictionary_apply_impl( - dict, - [&](sourcekitd_uid_t key, sourcekitd_variant_t value) { - return applier(key, value, context); - }); + return sourcekitd_variant_dictionary_apply_impl(dict, applier, context); } size_t @@ -461,6 +602,17 @@ sourcekitd_variant_array_get_bool(sourcekitd_variant_t array, size_t index) { sourcekitd_variant_array_get_value(array, index)); } +double sourcekitd_variant_array_get_double(sourcekitd_variant_t array, + size_t index) { + if (auto fn = VAR_FN(array, array_get_double)) + return fn(array, index); + + // Default implementation: + // Get the value via sourcekitd_variant_array_get_value. + return sourcekitd_variant_double_get_value( + sourcekitd_variant_array_get_value(array, index)); +} + sourcekitd_uid_t sourcekitd_variant_array_get_uid(sourcekitd_variant_t array, size_t index) { if (auto fn = VAR_FN(array, array_get_uid)) @@ -472,24 +624,33 @@ sourcekitd_variant_array_get_uid(sourcekitd_variant_t array, size_t index) { sourcekitd_variant_array_get_value(array, index)); } +static bool variant_array_applier_block_f(size_t index, + sourcekitd_variant_t obj, + void *context) { + auto *block = (sourcekitd_variant_array_applier_t *)context; + return (*block)(index, obj); +} + #if SOURCEKITD_HAS_BLOCKS bool sourcekitd_variant_array_apply(sourcekitd_variant_t array, sourcekitd_variant_array_applier_t applier) { - return sourcekitd_variant_array_apply_impl(array, applier); + return sourcekitd_variant_array_apply_impl( + array, variant_array_applier_block_f, &applier); } #endif bool sourcekitd_variant_array_apply_impl( - sourcekitd_variant_t array, - llvm::function_ref applier) { + sourcekitd_variant_t array, sourcekitd_variant_array_applier_f_t applier, + void *context) { if (auto fn = VAR_FN(array, array_apply)) - return fn(array, applier); + return fn(array, applier, context); // Default implementation: // Iterate over elements via a for-loop. for (size_t i = 0, e = sourcekitd_variant_array_get_count(array); i != e; ++i) { - bool Continue = applier(i, sourcekitd_variant_array_get_value(array, i)); + bool Continue = + applier(i, sourcekitd_variant_array_get_value(array, i), context); if (!Continue) return false; } @@ -499,10 +660,7 @@ bool sourcekitd_variant_array_apply_impl( bool sourcekitd_variant_array_apply_f( sourcekitd_variant_t array, sourcekitd_variant_array_applier_f_t applier, void *context) { - return sourcekitd_variant_array_apply_impl( - array, [&](size_t index, sourcekitd_variant_t value) { - return applier(index, value, context); - }); + return sourcekitd_variant_array_apply_impl(array, applier, context); } int64_t @@ -525,6 +683,17 @@ sourcekitd_variant_bool_get_value(sourcekitd_variant_t obj) { return obj.data[1]; } +double sourcekitd_variant_double_get_value(sourcekitd_variant_t obj) { + if (auto fn = VAR_FN(obj, double_get_value)) + return fn(obj); + + // Default implementation: + // Assume this is a variant encapsulating the basic type. + double result; + std::memcpy(&result, &obj.data[1], sizeof(double)); + return result; +} + size_t sourcekitd_variant_string_get_length(sourcekitd_variant_t obj) { if (auto fn = VAR_FN(obj, string_get_length)) @@ -767,3 +936,271 @@ void YAMLRequestParser::initError(StringRef Desc, llvm::yaml::Node *Node, Range.End.getPointer() - Range.Start.getPointer()); Error.append(Text.begin(), Text.end()); } + +sourcekitd_variant_functions_t sourcekitd_variant_functions_create() { + auto *vfuncs = new VariantFunctions(); + // Zero-initialize. + memset(vfuncs, 0, sizeof(VariantFunctions)); + return vfuncs; +} + +void sourcekitd_variant_functions_set_get_type( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_get_type_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->get_type = f; +} +void sourcekitd_variant_functions_set_array_apply( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_apply_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_apply = f; +} +void sourcekitd_variant_functions_set_array_get_bool( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_bool_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_bool = f; +} +void sourcekitd_variant_functions_set_array_get_double( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_double_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_double = f; +} +void sourcekitd_variant_functions_set_array_get_count( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_count_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_count = f; +} +void sourcekitd_variant_functions_set_array_get_int64( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_int64_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_int64 = f; +} +void sourcekitd_variant_functions_set_array_get_string( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_string_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_string = f; +} +void sourcekitd_variant_functions_set_array_get_uid( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_uid_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_uid = f; +} +void sourcekitd_variant_functions_set_array_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_array_get_value_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->array_get_value = f; +} +void sourcekitd_variant_functions_set_bool_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_bool_get_value_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->bool_get_value = f; +} +void sourcekitd_variant_functions_set_double_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_double_get_value_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->double_get_value = f; +} +void sourcekitd_variant_functions_set_dictionary_apply( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_apply_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_apply = f; +} +void sourcekitd_variant_functions_set_dictionary_get_bool( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_bool_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_get_bool = f; +} +void sourcekitd_variant_functions_set_dictionary_get_double( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_double_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_get_double = f; +} +void sourcekitd_variant_functions_set_dictionary_get_int64( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_int64_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_get_int64 = f; +} +void sourcekitd_variant_functions_set_dictionary_get_string( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_string_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_get_string = f; +} +void sourcekitd_variant_functions_set_dictionary_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_value_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_get_value = f; +} +void sourcekitd_variant_functions_set_dictionary_get_uid( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_dictionary_get_uid_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->dictionary_get_uid = f; +} +void sourcekitd_variant_functions_set_string_get_length( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_string_get_length_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->string_get_length = f; +} +void sourcekitd_variant_functions_set_string_get_ptr( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_string_get_ptr_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->string_get_ptr = f; +} +void sourcekitd_variant_functions_set_int64_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_int64_get_value_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->int64_get_value = f; +} +void sourcekitd_variant_functions_set_uid_get_value( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_uid_get_value_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->uid_get_value = f; +} +void sourcekitd_variant_functions_set_data_get_size( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_data_get_size_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->data_get_size = f; +} +void sourcekitd_variant_functions_set_data_get_ptr( + sourcekitd_variant_functions_t funcs, + sourcekitd_variant_functions_data_get_ptr_t f) { + auto *vfuncs = static_cast(funcs); + vfuncs->data_get_ptr = f; +} + +bool sourcekitd_plugin_initialize_is_client_only( + sourcekitd_plugin_initialize_params_t _params) { + auto ¶ms = *static_cast(_params); + return params.isClientOnly; +} + +uint64_t sourcekitd_plugin_initialize_custom_buffer_start( + sourcekitd_plugin_initialize_params_t _params) { + auto ¶ms = *static_cast(_params); + return params.customBufferStart; +} + +sourcekitd_uid_get_from_cstr_t sourcekitd_plugin_initialize_uid_get_from_cstr( + sourcekitd_plugin_initialize_params_t _params) { + auto ¶ms = *static_cast(_params); + return params.uidGetFromCstr; +} + +sourcekitd_uid_get_string_ptr_t sourcekitd_plugin_initialize_uid_get_string_ptr( + sourcekitd_plugin_initialize_params_t _params) { + auto ¶ms = *static_cast(_params); + return params.uidGetStringPtr; +} + +void sourcekitd_plugin_initialize_register_request_handler( + sourcekitd_plugin_initialize_params_t _params, + sourcekitd_request_handler_t handler) { + auto ¶ms = *static_cast(_params); + auto handler_wrapper = + ^bool(sourcekitd_object_t req, sourcekitd_request_handle_t, + void (^resp)(sourcekitd_response_t)) { + return handler(req, resp); + }; + params.registerRequestHandler(handler_wrapper); +} + +void sourcekitd_plugin_initialize_register_cancellable_request_handler( + sourcekitd_plugin_initialize_params_t _params, + sourcekitd_cancellable_request_handler_t handler) { + auto ¶ms = *static_cast(_params); + params.registerRequestHandler(handler); +} + +void sourcekitd_plugin_initialize_register_cancellation_handler( + sourcekitd_plugin_initialize_params_t _params, + sourcekitd_cancellation_handler_t handler) { + auto ¶ms = *static_cast(_params); + params.registerCancellationHandler(handler); +} + +void sourcekitd_plugin_initialize_register_custom_buffer( + sourcekitd_plugin_initialize_params_t _params, uint64_t kind, + sourcekitd_variant_functions_t funcs) { + auto ¶ms = *static_cast(_params); + params.registerCustomBuffer(kind, funcs); +} + +void *sourcekitd_plugin_initialize_get_swift_ide_inspection_instance( + sourcekitd_plugin_initialize_params_t _params) { + auto ¶ms = *static_cast(_params); + return params.opaqueIDEInspectionInstance; +} + +PluginInitParams::PluginInitParams( + bool isClientOnly, + std::function + registerRequestHandler, + std::function + registerCancellationHandler, + void *opaqueIDEInspectionInstance) + : isClientOnly(isClientOnly) { + assert(isClientOnly || (registerRequestHandler != nullptr && + registerCancellationHandler != nullptr)); + // Note: we pass in registerRequestHandler rather than accessing + // sourcekitd::pluginRegisterRequestHandler so that when constructing + // parameters from the sourcekitd client library it does not pull in all of + // request handling when linking. + if (!isClientOnly) { + this->registerRequestHandler = registerRequestHandler; + this->registerCancellationHandler = registerCancellationHandler; + } + registerCustomBuffer = [this](uint64_t kind, + sourcekitd_variant_functions_t funcs) { + sourcekitd::pluginRegisterCustomBufferKind(kind, funcs); + customBufferStart = std::max(customBufferStart, kind + 1); + }; + this->opaqueIDEInspectionInstance = opaqueIDEInspectionInstance; +} + +// MARK: Plugin variant functions + +// Note: only modified during plugin loading. +static std::vector PluginVariantFunctions; + +VariantFunctions *sourcekitd::getPluginVariantFunctions(size_t BufKind) { + size_t index = BufKind - (size_t)CustomBufferKind::CustomBufferKind_End; + if (index >= PluginVariantFunctions.size() || + PluginVariantFunctions[index] == nullptr) { + llvm::report_fatal_error( + "unknown custom buffer kind; possible plugin loading failure"); + } + return PluginVariantFunctions[index]; +} + +void sourcekitd::pluginRegisterCustomBufferKind( + uint64_t kind, sourcekitd_variant_functions_t funcs) { + auto index = kind - (uint64_t)CustomBufferKind::CustomBufferKind_End; + if (index < PluginVariantFunctions.size()) { + assert(PluginVariantFunctions[index] == nullptr && + "overwriting existing buffer"); + } else { + PluginVariantFunctions.resize(index + 1); + } + PluginVariantFunctions[index] = static_cast(funcs); +} diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp index 336646b57ead5..be34dd275d371 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp @@ -50,9 +50,11 @@ class SKDObject : public ThreadSafeRefCountedBaseVPTR { Int64, UID, Bool, + Double, CustomData, Error, }; + private: ObjectKind Kind; protected: @@ -78,6 +80,7 @@ class SKDObject : public ThreadSafeRefCountedBaseVPTR { virtual std::optional getString() const { return std::nullopt; } virtual const char *getCString() const { return nullptr; } virtual bool getBool() const { return false; } + virtual double getDouble() const { return 0.0; } virtual const void *getDataPtr() const { return nullptr; } virtual size_t getDataSize() const { return 0; } }; @@ -101,8 +104,8 @@ class SKDDictionary: public SKDObject { return it != Storage.end() ? it->second : nullptr; } - bool - apply(llvm::function_ref Applier) const { + bool apply( + llvm::function_ref Applier) const { for (const auto& kv : Storage) { if (!Applier(kv.first, kv.second)) return false; @@ -236,6 +239,31 @@ class SKDBool: public SKDObject { bool Storage; }; +class SKDDouble : public SKDObject { +public: + SKDDouble(double Value) : SKDObject(ObjectKind::Double), Storage(Value) {} + + sourcekitd_variant_type_t getVariantType() const override { + return SOURCEKITD_VARIANT_TYPE_DOUBLE; + } + + double getDouble() const override { return Storage; } + + static bool classof(const SKDObject *O) { + return O->getKind() == ObjectKind::Double; + } + +private: + double Storage; +}; + +} // end anonymous namespace + +static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object); +static sourcekitd_variant_t variantFromSKDObjectPtr(const SKDObject *Object); + +namespace { + class SKDCustomData: public SKDObject { public: SKDCustomData(std::unique_ptr MemBuf) @@ -260,8 +288,10 @@ class SKDCustomData: public SKDObject { return SOURCEKITD_VARIANT_TYPE_ARRAY; case CustomBufferKind::RawData: return SOURCEKITD_VARIANT_TYPE_DATA; - } - llvm::report_fatal_error("sourcekitd object did not resolve to a known type"); + default: + return getPluginVariantFunctions(static_cast(getBufferKind())) + ->get_type(variantFromSKDObjectPtr(this)); + } } CustomBufferKind getBufferKind() const { @@ -480,6 +510,86 @@ sourcekitd_request_dictionary_set_uid(sourcekitd_object_t dict, static_cast(dict)->set(key, new SKDUID(uid)); } +sourcekitd_object_t +sourcekitd_request_dictionary_get_value(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return static_cast(static_cast(dict)->get(key).get()); +} + +const char *sourcekitd_request_dictionary_get_string(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + auto value = static_cast(dict)->get(key); + if (!value) { + return nullptr; + } + return value->getCString(); +} + +int64_t sourcekitd_request_dictionary_get_int64(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return *static_cast(dict)->get(key)->getInt64(); +} + +bool sourcekitd_request_dictionary_get_bool(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return static_cast(dict)->get(key)->getBool(); +} + +sourcekitd_uid_t sourcekitd_request_dictionary_get_uid(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return static_cast(dict)->get(key)->getUID(); +} + +size_t sourcekitd_request_array_get_count(sourcekitd_object_t array) { + return static_cast(array)->getCount(); +} + +sourcekitd_object_t +sourcekitd_request_array_get_value(sourcekitd_object_t array, size_t index) { + return static_cast(static_cast(array)->get(index).get()); +} + +const char *sourcekitd_request_array_get_string(sourcekitd_object_t array, + size_t index) { + return static_cast(array)->get(index)->getCString(); +} + +int64_t sourcekitd_request_array_get_int64(sourcekitd_object_t array, + size_t index) { + return *static_cast(array)->get(index)->getInt64(); +} + +bool sourcekitd_request_array_get_bool(sourcekitd_object_t array, + size_t index) { + return static_cast(array)->get(index)->getBool(); +} + +sourcekitd_uid_t sourcekitd_request_array_get_uid(sourcekitd_object_t array, + size_t index) { + return static_cast(array)->get(index)->getUID(); +} + +int64_t sourcekitd_request_int64_get_value(sourcekitd_object_t obj) { + return *static_cast(obj)->getInt64(); +} + +bool sourcekitd_request_bool_get_value(sourcekitd_object_t obj) { + return static_cast(obj)->getBool(); +} + +size_t sourcekitd_request_string_get_length(sourcekitd_object_t obj) { + return static_cast(obj)->getString()->size(); +} + +const char *sourcekitd_request_string_get_ptr(sourcekitd_object_t obj) { + return static_cast(obj)->getCString(); +} + +sourcekitd_uid_t sourcekitd_request_uid_get_value(sourcekitd_object_t obj) { + return static_cast(obj)->getUID(); +} + + sourcekitd_object_t sourcekitd_request_array_create(const sourcekitd_object_t *objects, size_t count) { @@ -566,8 +676,6 @@ sourcekitd_response_error_get_description(sourcekitd_response_t obj) { llvm::report_fatal_error("invalid sourcekitd error object"); } -static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object); - sourcekitd_variant_t sourcekitd_response_get_value(sourcekitd_response_t resp) { if (sourcekitd_response_is_error(resp)) @@ -815,6 +923,12 @@ sourcekitd::createErrorRequestFailed(StringRef Description) { Description)); } +sourcekitd_response_t +sourcekitd::createErrorRequestInterrupted(StringRef Description) { + return retained(new SKDError(SOURCEKITD_ERROR_CONNECTION_INTERRUPTED, + Description)); +} + sourcekitd_response_t sourcekitd::createErrorRequestCancelled() { return retained(new SKDError(SOURCEKITD_ERROR_REQUEST_CANCELLED, @@ -836,10 +950,11 @@ static sourcekitd_variant_type_t SKDVar_get_type(sourcekitd_variant_t var) { static bool SKDVar_array_apply( sourcekitd_variant_t array, - llvm::function_ref applier) { + sourcekitd_variant_array_applier_f_t applier, + void *context) { return dyn_cast(SKD_OBJ(array))->apply([&](size_t Index, SKDObjectRef Object){ - return applier(Index, variantFromSKDObject(Object)); + return applier(Index, variantFromSKDObject(Object), context); }); } @@ -847,6 +962,11 @@ static bool SKDVar_array_get_bool(sourcekitd_variant_t array, size_t index) { return SKD_OBJ(array)->get(index)->getBool(); } +static double SKDVar_array_get_double(sourcekitd_variant_t array, + size_t index) { + return SKD_OBJ(array)->get(index)->getDouble(); +} + static size_t SKDVar_array_get_count(sourcekitd_variant_t array) { return SKD_OBJ(array)->getCount(); } @@ -874,12 +994,17 @@ static bool SKDVar_bool_get_value(sourcekitd_variant_t obj) { return SKD_OBJ(obj)->getBool(); } +static double SKDVar_double_get_value(sourcekitd_variant_t obj) { + return SKD_OBJ(obj)->getDouble(); +} + static bool SKDVar_dictionary_apply( sourcekitd_variant_t dict, - llvm::function_ref applier) { + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { return dyn_cast(SKD_OBJ(dict))->apply([&](sourcekitd_uid_t Key, SKDObjectRef Object){ - return applier(Key, variantFromSKDObject(Object)); + return applier(Key, variantFromSKDObject(Object), context); }); } @@ -891,6 +1016,14 @@ SKDVar_dictionary_get_bool(sourcekitd_variant_t dict, sourcekitd_uid_t key) { return false; } +static double SKDVar_dictionary_get_double(sourcekitd_variant_t dict, + sourcekitd_uid_t key) { + if (auto Object = SKD_OBJ(dict)->get(key)) { + return Object->getDouble(); + } + return 0.0; +} + static int64_t SKDVar_dictionary_get_int64(sourcekitd_variant_t dict, sourcekitd_uid_t key) { if (auto Object = SKD_OBJ(dict)->get(key)) { @@ -946,30 +1079,37 @@ static size_t SKDVar_data_get_size(sourcekitd_variant_t obj) { } static VariantFunctions SKDVariantFuncs = { - SKDVar_get_type, - SKDVar_array_apply, - SKDVar_array_get_bool, - SKDVar_array_get_count, - SKDVar_array_get_int64, - SKDVar_array_get_string, - SKDVar_array_get_uid, - SKDVar_array_get_value, - SKDVar_bool_get_value, - SKDVar_dictionary_apply, - SKDVar_dictionary_get_bool, - SKDVar_dictionary_get_int64, - SKDVar_dictionary_get_string, - SKDVar_dictionary_get_value, - SKDVar_dictionary_get_uid, - SKDVar_string_get_length, - SKDVar_string_get_ptr, - SKDVar_int64_get_value, - SKDVar_uid_get_value, - SKDVar_data_get_size, - SKDVar_data_get_ptr, + SKDVar_get_type, + SKDVar_array_apply, + SKDVar_array_get_bool, + SKDVar_array_get_double, + SKDVar_array_get_count, + SKDVar_array_get_int64, + SKDVar_array_get_string, + SKDVar_array_get_uid, + SKDVar_array_get_value, + SKDVar_bool_get_value, + SKDVar_double_get_value, + SKDVar_dictionary_apply, + SKDVar_dictionary_get_bool, + SKDVar_dictionary_get_double, + SKDVar_dictionary_get_int64, + SKDVar_dictionary_get_string, + SKDVar_dictionary_get_value, + SKDVar_dictionary_get_uid, + SKDVar_string_get_length, + SKDVar_string_get_ptr, + SKDVar_int64_get_value, + SKDVar_uid_get_value, + SKDVar_data_get_size, + SKDVar_data_get_ptr, }; static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object) { + return variantFromSKDObjectPtr(Object.get()); +} + +static sourcekitd_variant_t variantFromSKDObjectPtr(const SKDObject *Object) { if (!Object) return makeNullVariant(); @@ -1010,8 +1150,159 @@ static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object) { return {{ (uintptr_t)getVariantFunctionsForRawData(), (uintptr_t)DataObject->getDataPtr(), (uintptr_t)DataObject->getDataSize() }}; + default: + return {{(uintptr_t)getPluginVariantFunctions( + static_cast(DataObject->getBufferKind())), + (uintptr_t)DataObject->getDataPtr(), + (uintptr_t)DataObject->getDataSize()}}; } } - - return {{ (uintptr_t)&SKDVariantFuncs, (uintptr_t)Object.get(), 0 }}; + + return {{(uintptr_t)&SKDVariantFuncs, (uintptr_t)Object, 0}}; +} + +sourcekitd_response_t +sourcekitd_response_error_create(sourcekitd_error_t kind, + const char *description) { + SKDError *error = new SKDError(kind, description); + return retained(error); +} + +sourcekitd_response_t +sourcekitd_response_dictionary_create(const sourcekitd_uid_t *keys, + const sourcekitd_response_t *values, + size_t count) { + // Request and response dictionaries are represented by the same type. + return sourcekitd_request_dictionary_create(keys, values, count); +} + +void sourcekitd_response_dictionary_set_value(sourcekitd_response_t dict, + sourcekitd_uid_t key, + sourcekitd_response_t value) { + static_cast(dict)->set(key, static_cast(value)); +} + +void sourcekitd_response_dictionary_set_string(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const char *string) { + static_cast(dict)->set(key, new SKDString(std::string(string))); +} + +void sourcekitd_response_dictionary_set_stringbuf(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const char *buf, + size_t length) { + llvm::SmallString<512> SS; + SS += StringRef(buf, length); + sourcekitd_response_dictionary_set_string(dict, key, SS.c_str()); +} + +void sourcekitd_response_dictionary_set_int64(sourcekitd_response_t dict, + sourcekitd_uid_t key, + int64_t val) { + static_cast(dict)->set(key, new SKDInt64(val)); +} + +void sourcekitd_response_dictionary_set_bool(sourcekitd_response_t dict, + sourcekitd_uid_t key, bool val) { + static_cast(dict)->set(key, new SKDBool(val)); +} + +void sourcekitd_response_dictionary_set_double(sourcekitd_response_t dict, + sourcekitd_uid_t key, + double val) { + static_cast(dict)->set(key, new SKDDouble(val)); +} + +void sourcekitd_response_dictionary_set_uid(sourcekitd_response_t dict, + sourcekitd_uid_t key, + sourcekitd_uid_t uid) { + static_cast(dict)->set(key, new SKDUID(uid)); +} + +sourcekitd_response_t +sourcekitd_response_array_create(const sourcekitd_response_t *objects, + size_t count) { + // Request and response arrays are represented by the same type. + return sourcekitd_request_array_create(objects, count); +} + +void sourcekitd_response_array_set_value(sourcekitd_response_t array, + size_t index, + sourcekitd_response_t value) { + static_cast(array)->set(index, static_cast(value)); +} + +void sourcekitd_response_array_set_string(sourcekitd_response_t array, + size_t index, const char *string) { + static_cast(array)->set(index, + new SKDString(std::string(string))); +} + +void sourcekitd_response_array_set_stringbuf(sourcekitd_response_t array, + size_t index, const char *buf, + size_t length) { + llvm::SmallString<512> SS; + SS += StringRef(buf, length); + sourcekitd_response_array_set_string(array, index, SS.c_str()); +} + +void sourcekitd_response_array_set_int64(sourcekitd_response_t array, + size_t index, int64_t val) { + static_cast(array)->set(index, new SKDInt64(val)); +} + +void sourcekitd_response_array_set_double(sourcekitd_response_t array, + size_t index, double val) { + static_cast(array)->set(index, new SKDDouble(val)); +} + +void sourcekitd_response_array_set_uid(sourcekitd_response_t array, + size_t index, sourcekitd_uid_t uid) { + static_cast(array)->set(index, new SKDUID(uid)); +} + +sourcekitd_response_t sourcekitd_response_retain(sourcekitd_response_t object) { + return retained(static_cast(object)); +} + +sourcekitd_variant_type_t sourcekitd_request_get_type(sourcekitd_object_t obj) { + if (!obj) { + return SOURCEKITD_VARIANT_TYPE_NULL; + } + switch (static_cast(obj)->getKind()) { + case SKDObject::ObjectKind::Dictionary: + return SOURCEKITD_VARIANT_TYPE_DICTIONARY; + case SKDObject::ObjectKind::Array: + return SOURCEKITD_VARIANT_TYPE_ARRAY; + case SKDObject::ObjectKind::String: + return SOURCEKITD_VARIANT_TYPE_STRING; + case SKDObject::ObjectKind::Int64: + return SOURCEKITD_VARIANT_TYPE_INT64; + case SKDObject::ObjectKind::UID: + return SOURCEKITD_VARIANT_TYPE_UID; + case SKDObject::ObjectKind::Bool: + return SOURCEKITD_VARIANT_TYPE_BOOL; + case SKDObject::ObjectKind::Double: + return SOURCEKITD_VARIANT_TYPE_DOUBLE; + case SKDObject::ObjectKind::CustomData: + return static_cast(obj)->getVariantType(); + case SKDObject::ObjectKind::Error: + llvm_unreachable("Should not be part of a request"); + } +} + +void sourcekitd_response_dictionary_set_custom_buffer( + sourcekitd_response_t dict, sourcekitd_uid_t key, const void *ptr, + size_t size) { +#ifndef NDEBUG + assert(size >= sizeof(uint64_t)); + auto bufKind = *(const uint64_t *)ptr; + assert(bufKind >= (uint64_t)CustomBufferKind::CustomBufferKind_End); +#endif + std::unique_ptr Buf; + Buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size); + memcpy(Buf->getBufferStart(), ptr, size); + static_cast(dict)->set(key, + new SKDCustomData(std::move(Buf))); } diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp index ae861b4a37bdc..08d92f5a00c5e 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp @@ -84,7 +84,6 @@ class CustomXPCData { return createKindAndString(Kind::ErrorRequestCancelled, Description); } -private: static CustomXPCData createKindAndString(Kind K, StringRef Str) { llvm::SmallVector Buf; Buf.push_back((char)K); @@ -460,6 +459,81 @@ sourcekitd_request_dictionary_set_uid(sourcekitd_object_t dict, xpc_dictionary_set_uint64(dict, strFromUID(key), uintptr_t(uid)); } +sourcekitd_object_t +sourcekitd_request_dictionary_get_value(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return xpc_dictionary_get_value(dict, strFromUID(key)); +} + +const char *sourcekitd_request_dictionary_get_string(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return xpc_dictionary_get_string(dict, strFromUID(key)); +} + +int64_t sourcekitd_request_dictionary_get_int64(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return xpc_dictionary_get_int64(dict, strFromUID(key)); +} + +bool sourcekitd_request_dictionary_get_bool(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return xpc_dictionary_get_bool(dict, strFromUID(key)); +} + +sourcekitd_uid_t sourcekitd_request_dictionary_get_uid(sourcekitd_object_t dict, + sourcekitd_uid_t key) { + return (sourcekitd_uid_t)xpc_dictionary_get_uint64(dict, strFromUID(key)); +} + +size_t sourcekitd_request_array_get_count(sourcekitd_object_t array) { + return xpc_array_get_count(array); +} + +sourcekitd_object_t +sourcekitd_request_array_get_value(sourcekitd_object_t array, size_t index) { + return xpc_array_get_value(array, index); +} + +const char *sourcekitd_request_array_get_string(sourcekitd_object_t array, + size_t index) { + return xpc_array_get_string(array, index); +} + +int64_t sourcekitd_request_array_get_int64(sourcekitd_object_t array, + size_t index) { + return xpc_array_get_int64(array, index); +} + +bool sourcekitd_request_array_get_bool(sourcekitd_object_t array, + size_t index) { + return xpc_array_get_bool(array, index); +} + +sourcekitd_uid_t sourcekitd_request_array_get_uid(sourcekitd_object_t array, + size_t index) { + return (sourcekitd_uid_t)xpc_array_get_uint64(array, index); +} + +int64_t sourcekitd_request_int64_get_value(sourcekitd_object_t obj) { + return xpc_int64_get_value(obj); +} + +bool sourcekitd_request_bool_get_value(sourcekitd_object_t obj) { + return xpc_bool_get_value(obj); +} + +size_t sourcekitd_request_string_get_length(sourcekitd_object_t obj) { + return xpc_string_get_length(obj); +} + +const char *sourcekitd_request_string_get_ptr(sourcekitd_object_t obj) { + return xpc_string_get_string_ptr(obj); +} + +sourcekitd_uid_t sourcekitd_request_uid_get_value(sourcekitd_object_t obj) { + return (sourcekitd_uid_t)xpc_uint64_get_value(obj); +} + sourcekitd_object_t sourcekitd_request_array_create(const sourcekitd_object_t *objects, size_t count) { @@ -608,6 +682,8 @@ static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) { return SOURCEKITD_VARIANT_TYPE_INT64; if (type == XPC_TYPE_BOOL) return SOURCEKITD_VARIANT_TYPE_BOOL; + if (type == XPC_TYPE_DOUBLE) + return SOURCEKITD_VARIANT_TYPE_DOUBLE; if (type == XPC_TYPE_STRING) return SOURCEKITD_VARIANT_TYPE_STRING; // Take over XPC's UINT64 to mean SourceKitD's UID. @@ -617,32 +693,35 @@ static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) { return SOURCEKITD_VARIANT_TYPE_UID; if (type == XPC_TYPE_DATA) { - switch(CUSTOM_BUF_KIND(obj)) { - case CustomBufferKind::TokenAnnotationsArray: - case CustomBufferKind::DeclarationsArray: - case CustomBufferKind::DocSupportAnnotationArray: - case CustomBufferKind::CodeCompletionResultsArray: - case CustomBufferKind::DocStructureArray: - case CustomBufferKind::InheritedTypesArray: - case CustomBufferKind::DocStructureElementArray: - case CustomBufferKind::AttributesArray: - case CustomBufferKind::ExpressionTypeArray: - case CustomBufferKind::VariableTypeArray: + auto BufKind = (size_t)CUSTOM_BUF_KIND(obj); + switch (BufKind) { + case (size_t)CustomBufferKind::TokenAnnotationsArray: + case (size_t)CustomBufferKind::DeclarationsArray: + case (size_t)CustomBufferKind::DocSupportAnnotationArray: + case (size_t)CustomBufferKind::CodeCompletionResultsArray: + case (size_t)CustomBufferKind::DocStructureArray: + case (size_t)CustomBufferKind::InheritedTypesArray: + case (size_t)CustomBufferKind::DocStructureElementArray: + case (size_t)CustomBufferKind::AttributesArray: + case (size_t)CustomBufferKind::ExpressionTypeArray: + case (size_t)CustomBufferKind::VariableTypeArray: return SOURCEKITD_VARIANT_TYPE_ARRAY; - case CustomBufferKind::RawData: + case (size_t)CustomBufferKind::RawData: return SOURCEKITD_VARIANT_TYPE_DATA; + default: + return getPluginVariantFunctions(BufKind)->get_type( + variantFromXPCObject(obj)); } } llvm::report_fatal_error("sourcekitd object did not resolve to a known type"); } -static bool XPCVar_array_apply( - sourcekitd_variant_t array, - llvm::function_ref applier) { - return xpc_array_apply(XPC_OBJ(array), - ^(size_t index, xpc_object_t obj) { - return applier(index, variantFromXPCObject(obj)); +static bool XPCVar_array_apply(sourcekitd_variant_t array, + sourcekitd_variant_array_applier_f_t applier, + void *context) { + return xpc_array_apply(XPC_OBJ(array), ^(size_t index, xpc_object_t obj) { + return applier(index, variantFromXPCObject(obj), context); }); } @@ -650,6 +729,11 @@ static bool XPCVar_array_get_bool(sourcekitd_variant_t array, size_t index) { return xpc_array_get_bool(XPC_OBJ(array), index); } +static double XPCVar_array_get_double(sourcekitd_variant_t array, + size_t index) { + return xpc_array_get_double(XPC_OBJ(array), index); +} + static size_t XPCVar_array_get_count(sourcekitd_variant_t array) { return xpc_array_get_count(XPC_OBJ(array)); } @@ -676,13 +760,19 @@ static bool XPCVar_bool_get_value(sourcekitd_variant_t obj) { return xpc_bool_get_value(XPC_OBJ(obj)); } -static bool XPCVar_dictionary_apply( - sourcekitd_variant_t dict, - llvm::function_ref applier) { - return xpc_dictionary_apply(XPC_OBJ(dict), - ^(const char *key, xpc_object_t obj) { - return applier(sourcekitd_uid_get_from_cstr(key),variantFromXPCObject(obj)); - }); +static double XPCVar_double_get_value(sourcekitd_variant_t obj) { + return xpc_double_get_value(XPC_OBJ(obj)); +} + +static bool +XPCVar_dictionary_apply(sourcekitd_variant_t dict, + sourcekitd_variant_dictionary_applier_f_t applier, + void *context) { + return xpc_dictionary_apply( + XPC_OBJ(dict), ^(const char *key, xpc_object_t obj) { + return applier(sourcekitd_uid_get_from_cstr(key), + variantFromXPCObject(obj), context); + }); } static bool @@ -690,6 +780,11 @@ XPCVar_dictionary_get_bool(sourcekitd_variant_t dict, sourcekitd_uid_t key) { return xpc_dictionary_get_bool(XPC_OBJ(dict), strFromUID(key)); } +static double XPCVar_dictionary_get_double(sourcekitd_variant_t dict, + sourcekitd_uid_t key) { + return xpc_dictionary_get_double(XPC_OBJ(dict), strFromUID(key)); +} + static int64_t XPCVar_dictionary_get_int64(sourcekitd_variant_t dict, sourcekitd_uid_t key) { return xpc_dictionary_get_int64(XPC_OBJ(dict), strFromUID(key)); @@ -736,29 +831,31 @@ static sourcekitd_uid_t XPCVar_uid_get_value(sourcekitd_variant_t obj) { return sourcekitd_uid_t(xpc_uint64_get_value(XPC_OBJ(obj))); } - static VariantFunctions XPCVariantFuncs = { - XPCVar_get_type, - XPCVar_array_apply, - XPCVar_array_get_bool, - XPCVar_array_get_count, - XPCVar_array_get_int64, - XPCVar_array_get_string, - XPCVar_array_get_uid, - XPCVar_array_get_value, - XPCVar_bool_get_value, - XPCVar_dictionary_apply, - XPCVar_dictionary_get_bool, - XPCVar_dictionary_get_int64, - XPCVar_dictionary_get_string, - XPCVar_dictionary_get_value, - XPCVar_dictionary_get_uid, - XPCVar_string_get_length, - XPCVar_string_get_ptr, - XPCVar_int64_get_value, - XPCVar_uid_get_value, - XPCVar_data_get_size, - XPCVar_data_get_ptr, + XPCVar_get_type, + XPCVar_array_apply, + XPCVar_array_get_bool, + XPCVar_array_get_double, + XPCVar_array_get_count, + XPCVar_array_get_int64, + XPCVar_array_get_string, + XPCVar_array_get_uid, + XPCVar_array_get_value, + XPCVar_bool_get_value, + XPCVar_double_get_value, + XPCVar_dictionary_apply, + XPCVar_dictionary_get_bool, + XPCVar_dictionary_get_double, + XPCVar_dictionary_get_int64, + XPCVar_dictionary_get_string, + XPCVar_dictionary_get_value, + XPCVar_dictionary_get_uid, + XPCVar_string_get_length, + XPCVar_string_get_ptr, + XPCVar_int64_get_value, + XPCVar_uid_get_value, + XPCVar_data_get_size, + XPCVar_data_get_ptr, }; static sourcekitd_variant_t variantFromXPCObject(xpc_object_t obj) { @@ -766,43 +863,200 @@ static sourcekitd_variant_t variantFromXPCObject(xpc_object_t obj) { return makeNullVariant(); if (xpc_get_type(obj) == XPC_TYPE_DATA) { - switch(CUSTOM_BUF_KIND(obj)) { - case CustomBufferKind::TokenAnnotationsArray: + auto BufKind = (size_t)CUSTOM_BUF_KIND(obj); + switch (BufKind) { + case (size_t)CustomBufferKind::TokenAnnotationsArray: return {{ (uintptr_t)getVariantFunctionsForTokenAnnotationsArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::DeclarationsArray: + case (size_t)CustomBufferKind::DeclarationsArray: return {{(uintptr_t)getVariantFunctionsForDeclarationsArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0}}; - case CustomBufferKind::DocSupportAnnotationArray: + case (size_t)CustomBufferKind::DocSupportAnnotationArray: return {{ (uintptr_t)getVariantFunctionsForDocSupportAnnotationArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::CodeCompletionResultsArray: + case (size_t)CustomBufferKind::CodeCompletionResultsArray: return {{ (uintptr_t)getVariantFunctionsForCodeCompletionResultsArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::DocStructureArray: + case (size_t)CustomBufferKind::DocStructureArray: return {{ (uintptr_t)getVariantFunctionsForDocStructureArray(), (uintptr_t)CUSTOM_BUF_START(obj), ~size_t(0) }}; - case CustomBufferKind::InheritedTypesArray: + case (size_t)CustomBufferKind::InheritedTypesArray: return {{ (uintptr_t)getVariantFunctionsForInheritedTypesArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::DocStructureElementArray: + case (size_t)CustomBufferKind::DocStructureElementArray: return {{ (uintptr_t)getVariantFunctionsForDocStructureElementArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::AttributesArray: + case (size_t)CustomBufferKind::AttributesArray: return {{ (uintptr_t)getVariantFunctionsForAttributesArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::ExpressionTypeArray: + case (size_t)CustomBufferKind::ExpressionTypeArray: return {{ (uintptr_t)getVariantFunctionsForExpressionTypeArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case CustomBufferKind::VariableTypeArray: + case (size_t)CustomBufferKind::VariableTypeArray: return {{ (uintptr_t)getVariantFunctionsForVariableTypeArray(), (uintptr_t)CUSTOM_BUF_START(obj), 0 }}; - case sourcekitd::CustomBufferKind::RawData: + case (size_t)sourcekitd::CustomBufferKind::RawData: return {{ (uintptr_t)getVariantFunctionsForRawData(), (uintptr_t)CUSTOM_BUF_START(obj), (uintptr_t)CUSTOM_BUF_SIZE(obj) }}; + default: + return {{(uintptr_t)getPluginVariantFunctions(BufKind), + (uintptr_t)CUSTOM_BUF_START(obj), + (uintptr_t)CUSTOM_BUF_SIZE(obj)}}; } } return {{ (uintptr_t)&XPCVariantFuncs, (uintptr_t)obj, 0 }}; } + +sourcekitd_response_t +sourcekitd_response_error_create(sourcekitd_error_t kind, + const char *description) { + CustomXPCData::Kind xpcKind; + switch (kind) { + case SOURCEKITD_ERROR_REQUEST_INVALID: + xpcKind = CustomXPCData::Kind::ErrorRequestInvalid; + break; + case SOURCEKITD_ERROR_REQUEST_FAILED: + xpcKind = CustomXPCData::Kind::ErrorRequestFailed; + break; + case SOURCEKITD_ERROR_CONNECTION_INTERRUPTED: + xpcKind = CustomXPCData::Kind::ErrorRequestInterrupted; + break; + case SOURCEKITD_ERROR_REQUEST_CANCELLED: + xpcKind = CustomXPCData::Kind::ErrorRequestCancelled; + break; + } + return CustomXPCData::createKindAndString(xpcKind, description).getXObj(); +} + +sourcekitd_response_t +sourcekitd_response_dictionary_create(const sourcekitd_uid_t *keys, + const sourcekitd_response_t *values, + size_t count) { + llvm::SmallVector Keys; + Keys.reserve(count); + for (size_t i = 0; i < count; ++i) + Keys.push_back(strFromUID(keys[i])); + return xpc_dictionary_create(Keys.data(), values, count); +} + +void sourcekitd_response_dictionary_set_value(sourcekitd_response_t dict, + sourcekitd_uid_t key, + sourcekitd_response_t value) { + xpc_dictionary_set_value(dict, strFromUID(key), value); +} + +void sourcekitd_response_dictionary_set_string(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const char *string) { + xpc_dictionary_set_string(dict, strFromUID(key), string); +} + +void sourcekitd_response_dictionary_set_stringbuf(sourcekitd_response_t dict, + sourcekitd_uid_t key, + const char *buf, + size_t length) { + llvm::SmallString<512> SS; + SS += StringRef(buf, length); + sourcekitd_response_dictionary_set_string(dict, key, SS.c_str()); +} + +void sourcekitd_response_dictionary_set_int64(sourcekitd_response_t dict, + sourcekitd_uid_t key, + int64_t val) { + xpc_dictionary_set_int64(dict, strFromUID(key), val); +} + +void sourcekitd_response_dictionary_set_bool(sourcekitd_response_t dict, + sourcekitd_uid_t key, bool val) { + xpc_dictionary_set_bool(dict, strFromUID(key), val); +} + +void sourcekitd_response_dictionary_set_double(sourcekitd_response_t dict, + sourcekitd_uid_t key, + double val) { + xpc_dictionary_set_double(dict, strFromUID(key), val); +} + +void sourcekitd_response_dictionary_set_uid(sourcekitd_response_t dict, + sourcekitd_uid_t key, + sourcekitd_uid_t uid) { + xpc_dictionary_set_uint64(dict, strFromUID(key), uintptr_t(uid)); +} + +sourcekitd_response_t +sourcekitd_response_array_create(const sourcekitd_response_t *objects, + size_t count) { + return xpc_array_create(objects, count); +} + +void sourcekitd_response_array_set_value(sourcekitd_response_t array, + size_t index, + sourcekitd_response_t value) { + xpc_array_set_value(array, index, value); +} + +void sourcekitd_response_array_set_string(sourcekitd_response_t array, + size_t index, const char *string) { + xpc_array_set_string(array, index, string); +} + +void sourcekitd_response_array_set_stringbuf(sourcekitd_response_t array, + size_t index, const char *buf, + size_t length) { + llvm::SmallString<512> SS; + SS += StringRef(buf, length); + sourcekitd_response_array_set_string(array, index, SS.c_str()); +} + +void sourcekitd_response_array_set_int64(sourcekitd_response_t array, + size_t index, int64_t val) { + xpc_array_set_int64(array, index, val); +} + +void sourcekitd_response_array_set_double(sourcekitd_response_t array, + size_t index, double val) { + xpc_array_set_double(array, index, val); +} + +void sourcekitd_response_array_set_uid(sourcekitd_response_t array, + size_t index, sourcekitd_uid_t uid) { + xpc_array_set_uint64(array, index, uintptr_t(uid)); +} + +sourcekitd_response_t sourcekitd_response_retain(sourcekitd_response_t object) { + return xpc_retain(object); +} + +sourcekitd_variant_type_t sourcekitd_request_get_type(sourcekitd_object_t obj) { + xpc_type_t XType = xpc_get_type(obj); + if (XType == XPC_TYPE_DICTIONARY) + return SOURCEKITD_VARIANT_TYPE_DICTIONARY; + if (XType == XPC_TYPE_ARRAY) + return SOURCEKITD_VARIANT_TYPE_ARRAY; + if (XType == XPC_TYPE_INT64) + return SOURCEKITD_VARIANT_TYPE_INT64; + if (XType == XPC_TYPE_BOOL) + return SOURCEKITD_VARIANT_TYPE_BOOL; + if (XType == XPC_TYPE_UINT64) + return SOURCEKITD_VARIANT_TYPE_UID; + if (XType == XPC_TYPE_STRING) + return SOURCEKITD_VARIANT_TYPE_STRING; + if (XType == XPC_TYPE_NULL) + return SOURCEKITD_VARIANT_TYPE_NULL; + llvm::report_fatal_error("unkown sourcekitd_object_t type"); +} + +void sourcekitd_response_dictionary_set_custom_buffer( + sourcekitd_response_t dict, sourcekitd_uid_t key, const void *ptr, + size_t size) { +#ifndef NDEBUG + assert(size >= sizeof(uint64_t)); + auto bufKind = *(const uint64_t *)ptr; + assert(bufKind >= (uint64_t)CustomBufferKind::CustomBufferKind_End); +#endif + xpc_object_t xdata = xpc_data_create(ptr, size); + xpc_dictionary_set_value(dict, strFromUID(key), xdata); + xpc_release(xdata); +} diff --git a/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp index 67cca2a4bfc16..c3e802a5c056f 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp @@ -19,6 +19,7 @@ #include "sourcekitd/Service.h" #include "sourcekitd/TokenAnnotationsArray.h" #include "sourcekitd/VariableTypeArray.h" +#include "sourcekitd/plugin.h" #include "SourceKit/Core/Context.h" #include "SourceKit/Core/LangSupport.h" @@ -43,6 +44,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Mutex.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/VirtualFileSystem.h" @@ -51,6 +53,7 @@ #include // FIXME: Portability. +#include #include using namespace sourcekitd; @@ -104,6 +107,53 @@ static void fillDiagnosticInfo(ResponseBuilder::Dictionary ParentElem, static SourceKit::Context *GlobalCtx = nullptr; +namespace SourceKit { +class PluginSupport { + std::vector RequestHandlers; + std::vector CancellationHandlers; + llvm::sys::Mutex Mtx; + +public: + ~PluginSupport() { + for (auto &Handler : RequestHandlers) { + Block_release(Handler); + } + RequestHandlers.clear(); + } + + void addRequestHandler(sourcekitd_cancellable_request_handler_t Handler) { + RequestHandlers.push_back(Block_copy(Handler)); + } + + /// Register a cancellation handler that will be called when a request is + /// cancelled. + void addCancellationHandler(sourcekitd_cancellation_handler_t Handler) { + CancellationHandlers.push_back(Block_copy(Handler)); + } + + bool handleRequest(sourcekitd_object_t Req, + sourcekitd_request_handle_t Handle, ResponseReceiver Rec) { + auto ReceiverWrapper = ^void(sourcekitd_response_t Response) { + Rec(Response); + }; + for (auto &Handler : RequestHandlers) { + if (Handler(Req, Handle, ReceiverWrapper)) { + return true; + } + } + return false; + } + + /// Inform all cancellation handlers in the plugins that the request with the + /// given handle has been cancelled. + void cancelRequest(sourcekitd_request_handle_t Handle) { + for (auto &CancellationHandler : CancellationHandlers) { + CancellationHandler(Handle); + } + } +}; +} // end namespace SourceKit + // NOTE: if we had a connection context, these stats should move into it. static Statistic numRequests(UIdentFromSKDUID(KindStatNumRequests), "# of requests (total)"); @@ -117,9 +167,11 @@ void sourcekitd::initializeService( INITIALIZE_LLVM(); initializeSwiftModules(); llvm::EnablePrettyStackTrace(); - GlobalCtx = new SourceKit::Context(swiftExecutablePath, runtimeLibPath, - diagnosticDocumentationPath, - SourceKit::createSwiftLangSupport); + GlobalCtx = new SourceKit::Context( + swiftExecutablePath, runtimeLibPath, diagnosticDocumentationPath, + SourceKit::createSwiftLangSupport, [](SourceKit::Context &Ctx) { + return std::make_shared(); + }); auto noteCenter = GlobalCtx->getNotificationCenter(); noteCenter->addDocumentUpdateNotificationReceiver([postNotification](StringRef DocumentName) { @@ -402,6 +454,9 @@ void sourcekitd::handleRequest(sourcekitd_object_t Req, } void sourcekitd::cancelRequest(SourceKitCancellationToken CancellationToken) { + // Inform all plugins that the request has been cancelled, even if the request + // wasn't handled by a plugin. + getGlobalContext().getPlugins()->cancelRequest(CancellationToken); getGlobalContext().getRequestTracker()->cancel(CancellationToken); } @@ -2065,6 +2120,12 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) { ++numRequests; + if (getGlobalContext().getPlugins()->handleRequest(ReqObj, CancellationToken, + Rec)) { + // Handled by plugin. + return; + } + RequestDict Req(ReqObj); if (auto SimulateLongRequestDuration = @@ -4357,3 +4418,19 @@ static void enableCompileNotifications(bool value) { trace::unregisterConsumer(&compileConsumer); } } + +void sourcekitd::pluginRegisterRequestHandler( + sourcekitd_cancellable_request_handler_t handler) { + getGlobalContext().getPlugins()->addRequestHandler(handler); +} + +void sourcekitd::pluginRegisterCancellationHandler( + sourcekitd_cancellation_handler_t handler) { + getGlobalContext().getPlugins()->addCancellationHandler(handler); +} + +void *sourcekitd::pluginGetOpaqueSwiftIDEInspectionInstance() { + return getGlobalContext() + .getSwiftLangSupport() + .getOpaqueSwiftIDEInspectionInstance(); +} diff --git a/unittests/SourceKit/SwiftLang/CloseTest.cpp b/unittests/SourceKit/SwiftLang/CloseTest.cpp index 783163338b00d..e2d989f467208 100644 --- a/unittests/SourceKit/SwiftLang/CloseTest.cpp +++ b/unittests/SourceKit/SwiftLang/CloseTest.cpp @@ -83,6 +83,7 @@ class CloseTest : public ::testing::Test { Ctx = std::make_shared( getSwiftExecutablePath(), getRuntimeLibPath(), /*diagnosticDocumentationPath*/ "", SourceKit::createSwiftLangSupport, + [](SourceKit::Context &Ctx){ return nullptr; }, /*dispatchOnMain=*/false); } diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp index 73fb945b7ad22..4cfdc664296ba 100644 --- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp +++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp @@ -72,6 +72,7 @@ class CursorInfoTest : public ::testing::Test { getRuntimeLibPath(), /*diagnosticDocumentationPath*/ "", SourceKit::createSwiftLangSupport, + [](SourceKit::Context &Ctx){ return nullptr; }, /*dispatchOnMain=*/false)) { INITIALIZE_LLVM(); // This is avoiding destroying \p SourceKit::Context because another diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp index 7e27aa3eebcf3..e5f6cd9e9a90b 100644 --- a/unittests/SourceKit/SwiftLang/EditingTest.cpp +++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp @@ -133,6 +133,7 @@ class EditTest : public ::testing::Test { getRuntimeLibPath(), /*diagnosticDocumentationPath*/ "", SourceKit::createSwiftLangSupport, + [](SourceKit::Context &Ctx){ return nullptr; }, /*dispatchOnMain=*/false); auto localDocUpdState = std::make_shared(); Ctx->getNotificationCenter()->addDocumentUpdateNotificationReceiver( diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 2dca31f424f2c..2bfdd51d82641 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -14,11 +14,11 @@ # Buildbots for Darwin OSes #===------------------------------------------------------------------------===# [preset: mixin_buildbot_install_components] -swift-install-components=back-deployment;compiler;clang-builtin-headers;libexec;stdlib;sdk-overlay;static-mirror-lib;editor-integration;tools;toolchain-tools;testsuite-tools;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers +swift-install-components=back-deployment;compiler;clang-builtin-headers;libexec;stdlib;sdk-overlay;static-mirror-lib;editor-integration;tools;toolchain-tools;testsuite-tools;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers [preset: mixin_buildbot_install_components_with_clang] -swift-install-components=autolink-driver;back-deployment;compiler;clang-resource-dir-symlink;libexec;stdlib;sdk-overlay;static-mirror-lib;toolchain-tools;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers +swift-install-components=autolink-driver;back-deployment;compiler;clang-resource-dir-symlink;libexec;stdlib;sdk-overlay;static-mirror-lib;toolchain-tools;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers llvm-install-components=llvm-ar;llvm-ranlib;llvm-cov;llvm-profdata;IndexStore;clang;clang-resource-headers;compiler-rt;clangd;dsymutil;LTO;clang-features-file;lld [preset: mixin_buildbot_trunk_base] @@ -2977,7 +2977,7 @@ darwin-toolchain-display-name=Swift Development Snapshot darwin-toolchain-name=swift-DEVELOPMENT-SNAPSHOT darwin-toolchain-version=3.999.999 llvm-install-components=clang;clang-resource-headers;compiler-rt;libclang;libclang-headers;dsymutil;clang-features-file -swift-install-components=back-deployment;compiler;clang-builtin-headers;stdlib;libexec;sdk-overlay;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers +swift-install-components=back-deployment;compiler;clang-builtin-headers;stdlib;libexec;sdk-overlay;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers symbols-package=%(symbols_package)s install-symroot=%(install_symroot)s diff --git a/utils/build.ps1 b/utils/build.ps1 index d35fa3709da4f..f56afeb097708 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -2578,6 +2578,7 @@ function Test-SourceKitLSP { "-Xswiftc", "-I$($SourceCache)\sourcekit-lsp\Sources\CAtomics\include", "-Xswiftc", "-I$($SourceCache)\sourcekit-lsp\Sources\CSourcekitd\include", "-Xlinker", "$(Get-HostProjectBinaryCache SourceKitLSP)\lib\CSourcekitd.lib", + "-Xswiftc", "-I$($SourceCache)\sourcekit-lsp\Sources\CCompletionScoring\include", "-Xswiftc", "-I$(Get-HostProjectBinaryCache SourceKitLSP)\swift", "-Xlinker", "-L$(Get-HostProjectBinaryCache SourceKitLSP)\lib" ) @@ -2591,6 +2592,10 @@ function Test-SourceKitLSP { # Log with the highest log level to simplify debugging of CI failures. $env:SOURCEKIT_LSP_LOG_LEVEL="debug" + # The Windows build doesn't build the SourceKit plugins into the SwiftPM build directory (it builds them using CMake). + # Tell the tests where to find the just-built plugins. + $env:SOURCEKIT_LSP_TEST_PLUGIN_PATHS="$($HostArch.ToolchainInstallRoot)\usr\lib" + Build-SPMProject ` -Action TestParallel ` -Src "$SourceCache\sourcekit-lsp" `