[SourceKit] Add mechanism to load plugins for request handling into SourceKit

This allows us to load plugins into the sourcekitd service to handle requests (currently only used for code completion). This allows us to implement parts of sourcekitd in Swift and outside of the compiler repository, making it easier to iterated on them because the compiler doesn’t need to be rebuilt.
This commit is contained in:
Alex Hoppen
2025-01-03 14:04:21 +01:00
parent ed2f43e67d
commit b6c94aecc3
37 changed files with 3100 additions and 142 deletions

View File

@@ -31,6 +31,7 @@ namespace llvm {
namespace SourceKit {
class LangSupport;
class NotificationCenter;
class PluginSupport;
class GlobalConfig {
public:
@@ -169,6 +170,7 @@ class Context {
std::shared_ptr<NotificationCenter> NotificationCtr;
std::shared_ptr<GlobalConfig> Config;
std::shared_ptr<RequestTracker> ReqTracker;
std::shared_ptr<PluginSupport> Plugins;
std::shared_ptr<SlowRequestSimulator> SlowRequestSim;
public:
@@ -176,6 +178,8 @@ public:
StringRef DiagnosticDocumentationPath,
llvm::function_ref<std::unique_ptr<LangSupport>(Context &)>
LangSupportFactoryFn,
llvm::function_ref<std::shared_ptr<PluginSupport>(Context &)>
PluginSupportFactoryFn,
bool shouldDispatchNotificationsOnMain = true);
~Context();
@@ -192,6 +196,8 @@ public:
std::shared_ptr<GlobalConfig> getGlobalConfiguration() { return Config; }
std::shared_ptr<PluginSupport> getPlugins() { return Plugins; }
std::shared_ptr<SlowRequestSimulator> getSlowRequestSimulator() {
return SlowRequestSim;
}

View File

@@ -1024,6 +1024,8 @@ public:
virtual ~LangSupport() { }
virtual void *getOpaqueSwiftIDEInspectionInstance() { return nullptr; }
virtual void globalConfigurationUpdated(std::shared_ptr<GlobalConfig> Config) {};
virtual void dependencyUpdated() {}

View File

@@ -40,6 +40,8 @@ SourceKit::Context::Context(
StringRef DiagnosticDocumentationPath,
llvm::function_ref<std::unique_ptr<LangSupport>(Context &)>
LangSupportFactoryFn,
llvm::function_ref<std::shared_ptr<PluginSupport>(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() {

View File

@@ -534,6 +534,10 @@ public:
// LangSupport Interface
//==========================================================================//
void *getOpaqueSwiftIDEInspectionInstance() override {
return IDEInspectionInst.get();
}
void globalConfigurationUpdated(std::shared_ptr<GlobalConfig> Config) override;
void dependencyUpdated() override;

View File

@@ -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

View File

@@ -0,0 +1,900 @@
//===----------------------------------------------------------------------===//
//
// 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 <mutex>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#else
#include <dlfcn.h>
#endif
using namespace swift;
using namespace swift::ide;
using namespace sourcekitdInProc;
static std::string getRuntimeResourcesPath();
using FileSystemRef = llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>;
namespace {
struct CompletionResult;
class SharedStringInMemoryFS : public llvm::vfs::InMemoryFileSystem {
SmallVector<std::shared_ptr<std::string>, 8> strings;
public:
SharedStringInMemoryFS(
const llvm::StringMap<std::shared_ptr<std::string>> &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<IDEInspectionInstance> ownedIDEInspectionInstance;
llvm::StringMap<std::shared_ptr<std::string>> modifiedFiles;
std::shared_ptr<CodeCompletionCache> completionCache;
std::string swiftExecutablePath;
std::string runtimeResourcePath;
std::string diagnosticsDocumentationPath;
std::shared_ptr<SourceKit::RequestTracker> requestTracker;
public:
std::unique_ptr<CompletionResult> currentResponse;
const time_t sessionTimestamp;
Connection(IDEInspectionInstance *ideInspectionInstance)
: ideInspectionInstance(ideInspectionInstance),
completionCache(std::make_shared<CodeCompletionCache>()),
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<std::string>(contents);
} else {
modifiedFiles.erase(path);
}
}
std::shared_ptr<CodeCompletionCache> 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<const char *> args,
FileSystemRef fileSystem, ide::CodeCompletionContext &completionContext,
SourceKit::SourceKitCancellationToken cancellationToken,
llvm::function_ref<void(CancellableResult<CodeCompleteResult>)> 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<IDEInspectionInstance *>(opaqueIDESwiftInspectionInstance);
return static_cast<swiftide_connection_t>(new Connection(inspectInstance));
}
void swiftide_connection_dispose(swiftide_connection_t conn) {
assert(conn);
delete static_cast<Connection *>(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<Connection *>(_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<Connection *>(_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> 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<CodeCompletionResult *> 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<const char *> compilerArguments;
bool annotateResult = false;
bool includeObjectLiterals = true;
bool addInitsToTopLevel = false;
bool addCallWithNoDefaultArgs = true;
CompletionRequest(const char *path, unsigned offset, ArrayRef<const char *>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<Connection *>(_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<CompletionRequest *>(_req);
}
void swiftide_completion_request_set_annotate_result(
swiftide_completion_request_t _req, bool annotate) {
auto &req = *static_cast<CompletionRequest *>(_req);
req.annotateResult = annotate;
}
void swiftide_completion_request_set_include_objectliterals(
swiftide_completion_request_t _req, bool flag) {
auto &req = *static_cast<CompletionRequest *>(_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<CompletionRequest *>(_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<CompletionRequest *>(_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<Connection *>(_conn);
auto &req = *static_cast<CompletionRequest *>(_req);
if (conn->currentResponse) {
llvm::report_fatal_error(
"must dispose of previous response before completing again");
}
conn->currentResponse = std::make_unique<CompletionResult>(*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<CodeCompleteResult> 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<swiftide_completion_response_t>(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<const char *> args,
FileSystemRef fileSystem, ide::CodeCompletionContext &completionContext,
SourceKit::SourceKitCancellationToken cancellationToken,
llvm::function_ref<void(CancellableResult<CodeCompleteResult>)> callback) {
using ResultType = CancellableResult<CodeCompleteResult>;
// 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<std::atomic<bool>>(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<CompletionResult *>(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<CompletionResult *>(_result);
return result.hasError();
}
const char *swiftide_completion_result_get_error_description(
swiftide_completion_response_t _result) {
auto &result = *static_cast<CompletionResult *>(_result);
return result.error.c_str();
}
bool swiftide_completion_result_is_cancelled(
swiftide_completion_response_t _result) {
auto result = static_cast<CompletionResult *>(_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<CompletionResult *>(_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<CompletionResult *>(_result);
if (result.hasError() || result.getCompletions().empty()) {
completions_handler(nullptr, nullptr, 0);
return;
}
std::vector<const char *> 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<CompletionResult *>(_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<CompletionResult *>(_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<CompletionResult *>(_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<CompletionResult *>(_response);
return response.context.ReusingASTContext;
}
const char *
swiftide_completion_item_description_copy(swiftide_completion_item_t _item) {
auto &item = *static_cast<CodeCompletionResult *>(_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<CompletionResult *>(_response);
auto &item = *static_cast<CodeCompletionResult *>(_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<CompletionResult *>(_response);
auto &item = *static_cast<CodeCompletionResult *>(_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<CompletionResult *>(_response);
auto &item = *static_cast<CodeCompletionResult *>(_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<CodeCompletionResult *>(_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<CodeCompletionResult *>(_item);
llvm::SmallVector<const char *, 4> 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<CodeCompletionResult *>(_item);
// FIXME: keep this in sync with ide::CodeCompletionResult
return static_cast<swiftide_completion_item_kind_t>(item.getKind());
}
uint32_t
swiftide_completion_item_get_associated_kind(swiftide_completion_item_t _item) {
auto &item = *static_cast<CodeCompletionResult *>(_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<uint32_t>(item.getLiteralKind());
case CodeCompletionResultKind::Keyword:
return static_cast<uint32_t>(item.getKeywordKind());
default:
return 0;
}
}
uint32_t swiftide_completion_item_get_semantic_context(
swiftide_completion_item_t _item) {
auto &item = *static_cast<CodeCompletionResult *>(_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<CodeCompletionResult *>(_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<CodeCompletionResult *>(_item);
return item.isNotRecommended();
}
uint32_t swiftide_completion_item_not_recommended_reason(
swiftide_completion_item_t _item) {
auto &item = *static_cast<CodeCompletionResult *>(_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<CodeCompletionResult *>(_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<CompletionResult *>(_response);
auto &item = *static_cast<CodeCompletionResult *>(_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<CodeCompletionResult *>(_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<CodeCompletionResult *>(_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<CodeCompletionResult *>(_item);
return item.getNumBytesToErase();
}
uint32_t
swiftide_completion_item_get_type_relation(swiftide_completion_item_t _item) {
auto &item = *static_cast<CodeCompletionResult *>(_item);
// FIXME: keep this in sync with ide::CodeCompletionResult
return static_cast<swiftide_completion_type_relation_t>(
item.getExpectedTypeRelation());
}
uint32_t swiftide_completion_item_import_depth(swiftide_completion_response_t _response, swiftide_completion_item_t _item) {
auto &response = *static_cast<CompletionResult *>(_response);
auto &item = *static_cast<CodeCompletionResult *>(_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<swiftide_fuzzy_match_pattern_t>(
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<FuzzyStringMatcher *>(_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<FuzzyStringMatcher *>(_pattern);
}
static std::string getRuntimeResourcesPath() {
auto libPath = getRuntimeLibPath();
llvm::SmallString<128> libPathTmp(libPath);
llvm::sys::path::append(libPathTmp, "swift");
return libPathTmp.str().str();
}

View File

@@ -0,0 +1,417 @@
//===----------------------------------------------------------------------===//
//
// 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 <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/// 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

View File

@@ -1,5 +1,7 @@
framework module sourcekitdInProc {
umbrella header "sourcekitd.h"
header "plugin.h"
header "CodeCompletionSwiftInterop.h"
export *
module * { export * }
}

View File

@@ -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

View File

@@ -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<char> &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<std::string> 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<void()> handler) {
}

View File

@@ -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,85 @@ 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_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

View File

@@ -238,6 +238,9 @@ void sourcekitd_request_handle_dispose(sourcekitd_request_handle_t handle) {
xpc_release(msg);
}
static std::vector<std::string> registeredClientPlugins;
static std::vector<std::string> 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<size_t> 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;

View File

@@ -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

View File

@@ -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<std::string> 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) {

View File

@@ -162,11 +162,11 @@ struct CompactVariantFuncs {
static bool
dictionary_apply(sourcekitd_variant_t dict,
llvm::function_ref<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> 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;
@@ -177,14 +177,17 @@ VariantFunctions CompactVariantFuncs<T>::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*/,
nullptr/*Annot_dictionary_get_int64*/,
nullptr/*Annot_dictionary_get_string*/,
nullptr/*Annot_dictionary_get_value*/,
@@ -224,14 +227,17 @@ VariantFunctions CompactArrayFuncs<T>::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*/,

View File

@@ -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,

View File

@@ -13,6 +13,8 @@
#ifndef LLVM_SOURCEKITD_INTERNAL_H
#define LLVM_SOURCEKITD_INTERNAL_H
#include "sourcekitd/plugin.h"
#include "SourceKit/Support/CancellationToken.h"
#include "sourcekitd/sourcekitd.h"
#include "llvm/ADT/STLExtras.h"
@@ -33,11 +35,11 @@ namespace SourceKit {
bool sourcekitd_variant_dictionary_apply_impl(
sourcekitd_variant_t dict,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)> applier);
sourcekitd_variant_dictionary_applier_f_t applier, void *context);
bool sourcekitd_variant_array_apply_impl(
sourcekitd_variant_t array,
llvm::function_ref<bool(size_t, sourcekitd_variant_t)> applier);
sourcekitd_variant_t array, sourcekitd_variant_array_applier_f_t applier,
void *context);
namespace sourcekitd {
@@ -58,7 +60,8 @@ enum class CustomBufferKind {
AttributesArray,
ExpressionTypeArray,
VariableTypeArray,
RawData
RawData,
CustomBufferKind_End
};
class ResponseBuilder {
@@ -164,6 +167,10 @@ bool shutdownClient();
void set_interrupted_connection_handler(llvm::function_ref<void()> 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 +192,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 +209,57 @@ 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<bool(size_t, sourcekitd_variant_t)> 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<bool(sourcekitd_uid_t, sourcekitd_variant_t)> 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<void(sourcekitd_cancellable_request_handler_t)>
registerRequestHandler;
std::function<void(sourcekitd_cancellation_handler_t)>
registerCancellationHandler;
std::function<void(uint64_t, sourcekitd_variant_functions_t)>
registerCustomBuffer;
void *opaqueIDEInspectionInstance;
PluginInitParams(bool isClientOnly,
std::function<void(sourcekitd_cancellable_request_handler_t)>
registerRequestHandler,
std::function<void(sourcekitd_cancellation_handler_t)>
registerCancellationHandler,
void *opaqueIDEInspectionInstance = nullptr);
};
void loadPlugins(llvm::ArrayRef<std::string> registeredPlugins,
PluginInitParams &pluginParams);
}
#endif

View File

@@ -89,6 +89,10 @@ public:
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

View File

@@ -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<void(sourcekitd_response_t)> ResponseReceiver;
void handleRequest(sourcekitd_object_t Request,

View File

@@ -0,0 +1,399 @@
//===----------------------------------------------------------------------===//
//
// 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);
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

View File

@@ -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,23 @@
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 +329,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 +405,14 @@ 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 +484,10 @@ 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 +542,10 @@ 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);

View File

@@ -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 <string>
namespace sourcekitdInProc {
std::string getRuntimeLibPath();
std::string getSwiftExecutablePath();
std::string getDiagnosticDocumentationPath();
} // namespace sourcekitdInProc
#endif

View File

@@ -90,8 +90,8 @@ public:
static bool
dictionary_apply(void *Buf, size_t Index,
llvm::function_ref<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> applier) {
sourcekitd_variant_dictionary_applier_f_t applier,
void *context) {
CompactArrayReaderTy Reader(Buf);
sourcekitd_uid_t Kind;
@@ -128,7 +128,7 @@ public:
do { \
sourcekitd_uid_t key = SKDUIDFromUIdent(K); \
sourcekitd_variant_t var = make##Ty##Variant(Field); \
if (!applier(key, var)) return false; \
if (!applier(key, var, context)) return false; \
} while (0)
APPLY(KeyKind, UID, Kind);

View File

@@ -59,14 +59,14 @@ public:
static bool
apply(sourcekitd_uid_t Kind, unsigned Offset, unsigned Length,
const char *USR,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)>
applier) {
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)
@@ -133,8 +133,8 @@ struct CompactVariantFuncs<DeclarationsArray> {
static bool dictionary_apply(
sourcekitd_variant_t dict,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)>
applier) {
sourcekitd_variant_dictionary_applier_f_t applier,
void *context) {
void *Buf = (void *)dict.data[1];
size_t Index = dict.data[2];
@@ -143,7 +143,8 @@ struct CompactVariantFuncs<DeclarationsArray> {
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 +172,17 @@ VariantFunctions CompactVariantFuncs<DeclarationsArray>::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*/,

View File

@@ -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<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> 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<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> 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<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> 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<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> 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*/,

View File

@@ -66,8 +66,8 @@ public:
static bool
dictionary_apply(void *Buf, size_t Index,
llvm::function_ref<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> applier) {
sourcekitd_variant_dictionary_applier_f_t applier,
void *context) {
CompactArrayReaderTy Reader(Buf);
sourcekitd_uid_t Kind;
@@ -87,7 +87,7 @@ public:
do { \
sourcekitd_uid_t key = SKDUIDFromUIdent(K); \
sourcekitd_variant_t var = make##Ty##Variant(Field); \
if (!applier(key, var)) return false; \
if (!applier(key, var, context)) return false; \
} while (0)
APPLY(KeyKind, UID, Kind);

View File

@@ -71,15 +71,15 @@ public:
static bool
dictionary_apply(void *buffer, size_t index,
llvm::function_ref<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> 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; \
if (!applier(key, var, context)) return false; \
} while (0)
#define APPLY_ARRAY(Kind, Key) \
@@ -88,7 +88,7 @@ public:
sourcekitd_variant_t var = { \
{(uintptr_t)getVariantFunctionsFor##Kind##Array(), (uintptr_t)buffer, \
index}}; \
if (!applier(key, var)) return false; \
if (!applier(key, var, context)) return false; \
} while (0)
APPLY(KeyExpressionOffset, Int, result.ExprOffset);
@@ -131,14 +131,17 @@ VariantFunctions ProtocolListFuncs::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*/,
@@ -233,14 +236,17 @@ VariantFunctions ExpressionTypeArrayBuilder::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*/,

View File

@@ -34,14 +34,17 @@ VariantFunctions RawDataFuncs::Funcs = {
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*/,

View File

@@ -85,14 +85,14 @@ public:
unsigned Offset,
unsigned Length,
bool IsSystem,
llvm::function_ref<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> applier) {
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)) return false; \
if (!applier(key, var, context)) return false; \
} while (0)
APPLY(KeyKind, UID, Kind);
@@ -165,8 +165,8 @@ struct CompactVariantFuncs<TokenAnnotationsArray> {
static bool
dictionary_apply(sourcekitd_variant_t dict,
llvm::function_ref<bool(sourcekitd_uid_t,
sourcekitd_variant_t)> applier) {
sourcekitd_variant_dictionary_applier_f_t applier,
void *context) {
void *Buf = (void*)dict.data[1];
size_t Index = dict.data[2];
@@ -176,7 +176,8 @@ struct CompactVariantFuncs<TokenAnnotationsArray> {
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,
@@ -203,14 +204,17 @@ VariantFunctions CompactVariantFuncs<TokenAnnotationsArray>::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,
dictionary_get_bool,
nullptr/*Annot_dictionary_get_double*/,
dictionary_get_int64,
nullptr/*Annot_dictionary_get_string*/,
nullptr/*Annot_dictionary_get_value*/,

View File

@@ -64,15 +64,14 @@ public:
static bool dictionary_apply(
void *Buffer, size_t Index,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)>
Applier) {
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 +156,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*/,

View File

@@ -27,6 +27,8 @@
#include "llvm/Support/YAMLParser.h"
#include <mutex>
#include <dlfcn.h>
using namespace SourceKit;
using namespace sourcekitd;
using llvm::ArrayRef;
@@ -63,6 +65,46 @@ 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 <typename Fn> class applier_function_ref;
template <typename Ret, typename... Params>
class applier_function_ref<Ret(Params...)> {
public:
Ret (*callback)(Params... params, void *context) = nullptr;
void *context;
template <typename Callable>
static Ret callback_fn(Params... params, void *context) {
return (*reinterpret_cast<Callable *>(context))(
std::forward<Params>(params)...);
}
template <typename Callable>
applier_function_ref(
Callable &&callable,
std::enable_if_t<
!std::is_same<std::remove_cv_t<std::remove_reference_t<Callable>>,
applier_function_ref>::value> * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
context(reinterpret_cast<void *>(&callable)) {}
Ret operator()(Params... params) const {
return callback(std::forward<Params>(params)..., context);
}
};
} // end anonymous namespace
static bool variant_dictionary_apply(
sourcekitd_variant_t dict,
applier_function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)>
applier) {
return sourcekitd_variant_dictionary_apply_impl(dict, applier.callback,
applier.context);
}
namespace {
template <typename ImplClass,
@@ -83,7 +125,7 @@ public:
case SOURCEKITD_VARIANT_TYPE_DICTIONARY: {
DictMap Dict;
DictMap &DictRef = Dict;
sourcekitd_variant_dictionary_apply_impl(
variant_dictionary_apply(
Obj,
[&](sourcekitd_uid_t key, sourcekitd_variant_t value) {
DictRef.push_back({UIdentFromSKDUID(key), value});
@@ -105,6 +147,8 @@ public:
case SOURCEKITD_VARIANT_TYPE_BOOL:
return static_cast<ImplClass*>(this)->visitBool(
sourcekitd_variant_bool_get_value(Obj));
case SOURCEKITD_VARIANT_TYPE_DOUBLE:
return static_cast<ImplClass*>(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 +268,45 @@ bool sourcekitd::shutdownClient() {
return true;
}
static void loadPlugin(StringRef plugin, PluginInitParams &pluginParams) {
auto *handle = dlopen(plugin.str().c_str(), RTLD_FIRST | RTLD_LAZY);
if (!handle) {
LOG_WARN("plugin-loading",
"failed to load plugin '" << plugin << "': " << dlerror());
return;
}
auto *plugin_init = (sourcekitd_plugin_initialize_t)dlsym(
handle, "sourcekitd_plugin_initialize");
if (!plugin_init) {
LOG_WARN("plugin-loading",
"plugin '"
<< plugin
<< "' missing expected symbol: sourcekitd_plugin_initialize");
return;
}
plugin_init(&pluginParams);
}
void sourcekitd::loadPlugins(ArrayRef<std::string> 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 +402,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 +426,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 +457,18 @@ 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 +485,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(
bool sourcekitd_variant_dictionary_apply_impl(
sourcekitd_variant_t dict,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)> applier) {
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 +505,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 +559,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 +581,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<bool(size_t, sourcekitd_variant_t)> 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 +617,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 +640,18 @@ 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 +894,244 @@ 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.
bzero(vfuncs, 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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(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<VariantFunctions *>(funcs);
vfuncs->data_get_ptr = f;
}
bool sourcekitd_plugin_initialize_is_client_only(
sourcekitd_plugin_initialize_params_t _params) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
return params.isClientOnly;
}
uint64_t sourcekitd_plugin_initialize_custom_buffer_start(
sourcekitd_plugin_initialize_params_t _params) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
return params.customBufferStart;
}
sourcekitd_uid_get_from_cstr_t sourcekitd_plugin_initialize_uid_get_from_cstr(
sourcekitd_plugin_initialize_params_t _params) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
return params.uidGetFromCstr;
}
sourcekitd_uid_get_string_ptr_t sourcekitd_plugin_initialize_uid_get_string_ptr(
sourcekitd_plugin_initialize_params_t _params) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
return params.uidGetStringPtr;
}
void sourcekitd_plugin_initialize_register_request_handler(
sourcekitd_plugin_initialize_params_t _params,
sourcekitd_request_handler_t handler) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_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 &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
params.registerRequestHandler(handler);
}
void sourcekitd_plugin_initialize_register_cancellation_handler(
sourcekitd_plugin_initialize_params_t _params,
sourcekitd_cancellation_handler_t handler) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_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 &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
params.registerCustomBuffer(kind, funcs);
}
void *sourcekitd_plugin_initialize_get_swift_ide_inspection_instance(
sourcekitd_plugin_initialize_params_t _params) {
auto &params = *static_cast<sourcekitd::PluginInitParams *>(_params);
return params.opaqueIDEInspectionInstance;
}
PluginInitParams::PluginInitParams(
bool isClientOnly,
std::function<void(sourcekitd_cancellable_request_handler_t)>
registerRequestHandler,
std::function<void(sourcekitd_cancellation_handler_t)>
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;
}

View File

@@ -50,6 +50,7 @@ public:
Int64,
UID,
Bool,
Double,
CustomData,
Error,
};
@@ -78,6 +79,7 @@ public:
virtual std::optional<StringRef> 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; }
};
@@ -236,6 +238,25 @@ private:
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;
};
class SKDCustomData: public SKDObject {
public:
SKDCustomData(std::unique_ptr<llvm::MemoryBuffer> MemBuf)
@@ -847,6 +868,10 @@ 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,6 +899,10 @@ 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<bool(sourcekitd_uid_t, sourcekitd_variant_t)> applier) {
@@ -891,6 +920,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)) {
@@ -949,14 +986,17 @@ static VariantFunctions SKDVariantFuncs = {
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,

View File

@@ -84,7 +84,6 @@ public:
return createKindAndString(Kind::ErrorRequestCancelled, Description);
}
private:
static CustomXPCData createKindAndString(Kind K, StringRef Str) {
llvm::SmallVector<char, 128> 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) {
@@ -596,6 +670,18 @@ sourcekitd_response_get_value(sourcekitd_response_t resp) {
((const void*)(((const uint64_t*)xpc_data_get_bytes_ptr(xobj))+1))
#define CUSTOM_BUF_SIZE(xobj) (xpc_data_get_length(xobj) - sizeof(uint64_t))
// Note: only modified during plugin loading.
static std::vector<VariantFunctions *> PluginVariantFunctions;
VariantFunctions *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];
}
static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) {
xpc_object_t obj = XPC_OBJ(var);
@@ -608,6 +694,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,20 +705,23 @@ 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));
}
}
@@ -639,10 +730,11 @@ static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) {
static bool XPCVar_array_apply(
sourcekitd_variant_t array,
llvm::function_ref<bool(size_t, sourcekitd_variant_t)> applier) {
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));
return applier(index, variantFromXPCObject(obj), context);
});
}
@@ -650,6 +742,10 @@ 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,12 +772,17 @@ static bool XPCVar_bool_get_value(sourcekitd_variant_t obj) {
return xpc_bool_get_value(XPC_OBJ(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,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)> applier) {
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));
return applier(sourcekitd_uid_get_from_cstr(key),variantFromXPCObject(obj), context);
});
}
@@ -690,6 +791,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));
@@ -741,14 +847,17 @@ static VariantFunctions XPCVariantFuncs = {
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,
@@ -766,43 +875,211 @@ 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<const char *, 8> 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::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<VariantFunctions *>(funcs);
}
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);
}

View File

@@ -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 <optional>
// FIXME: Portability.
#include <Block.h>
#include <dispatch/dispatch.h>
using namespace sourcekitd;
@@ -104,6 +107,53 @@ static void fillDiagnosticInfo(ResponseBuilder::Dictionary ParentElem,
static SourceKit::Context *GlobalCtx = nullptr;
namespace SourceKit {
class PluginSupport {
std::vector<sourcekitd_cancellable_request_handler_t> RequestHandlers;
std::vector<sourcekitd_cancellation_handler_t> 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<PluginSupport>();
});
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();
}

View File

@@ -83,6 +83,7 @@ public:
Ctx = std::make_shared<SourceKit::Context>(
getSwiftExecutablePath(), getRuntimeLibPath(),
/*diagnosticDocumentationPath*/ "", SourceKit::createSwiftLangSupport,
[](SourceKit::Context &Ctx){ return nullptr; },
/*dispatchOnMain=*/false);
}

View File

@@ -72,6 +72,7 @@ public:
getRuntimeLibPath(),
/*diagnosticDocumentationPath*/ "",
SourceKit::createSwiftLangSupport,
[](SourceKit::Context &Ctx){ return nullptr; },
/*dispatchOnMain=*/false)) {
INITIALIZE_LLVM();
// This is avoiding destroying \p SourceKit::Context because another

View File

@@ -133,6 +133,7 @@ public:
getRuntimeLibPath(),
/*diagnosticDocumentationPath*/ "",
SourceKit::createSwiftLangSupport,
[](SourceKit::Context &Ctx){ return nullptr; },
/*dispatchOnMain=*/false);
auto localDocUpdState = std::make_shared<DocUpdateMutexState>();
Ctx->getNotificationCenter()->addDocumentUpdateNotificationReceiver(