blob: 4dedc75712856b6c0d7011102b0048e77c5ab84e [file] [log] [blame]
//===--- sourcekitdAPI-XPC.cpp --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "DictionaryKeys.h"
#include "sourcekitd/CodeCompletionResultsArray.h"
#include "sourcekitd/DocStructureArray.h"
#include "sourcekitd/DocSupportAnnotationArray.h"
#include "sourcekitd/TokenAnnotationsArray.h"
#include "sourcekitd/RequestResponsePrinterBase.h"
#include "SourceKit/Support/UIdent.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>
#include <xpc/xpc.h>
using namespace SourceKit;
using namespace sourcekitd;
using llvm::ArrayRef;
using llvm::StringRef;
using llvm::raw_ostream;
namespace {
class CustomXPCData {
public:
enum class Kind : char {
ErrorRequestInvalid,
ErrorRequestFailed,
ErrorRequestInterrupted,
ErrorRequestCancelled
};
explicit CustomXPCData(xpc_object_t xobj) : XObj(xobj) {
assert(xpc_get_type(XObj) == XPC_TYPE_DATA);
assert(getLength() > 0);
}
xpc_object_t getXObj() const { return XObj; }
Kind getKind() const { return Kind(getPtr()[0]); }
const char *getPtr() const {
return (const char *)xpc_data_get_bytes_ptr(XObj);
}
size_t getLength() const {
return xpc_data_get_length(XObj);
}
bool isError() const {
return true; // No other kind for now.
}
const char *getErrorDescription() const {
assert(isError());
assert(getLength() > 1);
return getPtr()+1;
}
static CustomXPCData createErrorRequestInvalid(const char *Description) {
return createKindAndString(Kind::ErrorRequestInvalid, Description);
}
static CustomXPCData createErrorRequestFailed(const char *Description) {
return createKindAndString(Kind::ErrorRequestFailed, Description);
}
static CustomXPCData createErrorRequestInterrupted(const char *Description) {
return createKindAndString(Kind::ErrorRequestInterrupted, Description);
}
static CustomXPCData createErrorRequestCancelled(const char *Description) {
return createKindAndString(Kind::ErrorRequestCancelled, Description);
}
private:
static CustomXPCData createKindAndString(Kind K, const char *Str) {
llvm::SmallVector<char, 128> Buf;
Buf.push_back((char)K);
Buf.append(Str, Str+strlen(Str)+1);
return CustomXPCData(xpc_data_create(Buf.begin(), Buf.size()));
}
xpc_object_t XObj;
};
template <typename ImplClass, typename RetTy = void>
class SKDObjectVisitor {
public:
typedef std::vector<std::pair<UIdent, sourcekitd_object_t>> DictMap;
static bool compKeys(const std::pair<UIdent, sourcekitd_object_t> &LHS,
const std::pair<UIdent, sourcekitd_object_t> &RHS) {
return sourcekitd::compareDictKeys(LHS.first, RHS.first);
}
RetTy visit(sourcekitd_object_t Obj) {
xpc_type_t XType = xpc_get_type(Obj);
if (XType == XPC_TYPE_DICTIONARY) {
DictMap Dict;
DictMap &DictRef = Dict;
xpc_dictionary_apply(Obj, ^(const char *Key, xpc_object_t Value) {
UIdent UID = UIdent(Key);
DictRef.push_back({ UID, Value });
return true;
});
std::sort(Dict.begin(), Dict.end(), compKeys);
return static_cast<ImplClass*>(this)->visitDictionary(Dict);
}
if (XType == XPC_TYPE_ARRAY) {
std::vector<sourcekitd_object_t> Vec;
for (size_t i = 0, e = xpc_array_get_count(Obj); i != e; ++i)
Vec.push_back(xpc_array_get_value(Obj, i));
return static_cast<ImplClass*>(this)->visitArray(Vec);
}
if (XType == XPC_TYPE_INT64)
return static_cast<ImplClass*>(this)->visitInt64(xpc_int64_get_value(Obj));
if (XType == XPC_TYPE_STRING) {
size_t Len = xpc_string_get_length(Obj);
const char *Ptr = xpc_string_get_string_ptr(Obj);
return static_cast<ImplClass*>(this)->visitString(StringRef(Ptr, Len));
}
if (XType == XPC_TYPE_UINT64) {
sourcekitd_uid_t SKDUID = sourcekitd_uid_t(xpc_uint64_get_value(Obj));
UIdent UID = UIdentFromSKDUID(SKDUID);
return static_cast<ImplClass*>(this)->visitUID(UID.getName());
}
llvm_unreachable("unknown sourcekitd_object_t");
}
};
class SKDObjectPrinter : public SKDObjectVisitor<SKDObjectPrinter>,
public RequestResponsePrinterBase<SKDObjectPrinter,
sourcekitd_object_t> {
public:
SKDObjectPrinter(raw_ostream &OS, unsigned Indent = 0)
: RequestResponsePrinterBase(OS, Indent) { }
};
} // anonymous namespace
void sourcekitd::printRequestObject(sourcekitd_object_t Obj, raw_ostream &OS) {
if (!Obj) {
OS << "<<NULL>>";
return;
}
SKDObjectPrinter(OS).visit(Obj);
}
//===----------------------------------------------------------------------===//
// Internal API
//===----------------------------------------------------------------------===//
ResponseBuilder::ResponseBuilder() {
Impl = xpc_dictionary_create(nullptr, nullptr, 0);
}
ResponseBuilder::~ResponseBuilder() {
xpc_release(Impl);
}
ResponseBuilder::ResponseBuilder(const ResponseBuilder &Other) {
Impl = xpc_retain(Other.Impl);
}
ResponseBuilder &ResponseBuilder::operator =(const ResponseBuilder &Other) {
xpc_object_t Tmp = xpc_retain(Other.Impl);
xpc_release(Impl);
Impl = Tmp;
return *this;
}
ResponseBuilder::Dictionary ResponseBuilder::getDictionary() {
return Dictionary(Impl);
}
sourcekitd_response_t ResponseBuilder::createResponse() {
return xpc_retain(Impl);
}
void ResponseBuilder::Dictionary::set(UIdent Key, SourceKit::UIdent UID) {
set(Key, SKDUIDFromUIdent(UID));
}
void ResponseBuilder::Dictionary::set(UIdent Key, sourcekitd_uid_t UID) {
xpc_dictionary_set_uint64(Impl, Key.c_str(), uintptr_t(UID));
}
void ResponseBuilder::Dictionary::set(UIdent Key, const char *Str) {
xpc_dictionary_set_string(Impl, Key.c_str(), Str);
}
void ResponseBuilder::Dictionary::set(UIdent Key, llvm::StringRef Str) {
llvm::SmallString<512> Buf(Str);
xpc_dictionary_set_string(Impl, Key.c_str(), Buf.c_str());
}
void ResponseBuilder::Dictionary::set(UIdent Key, int64_t val) {
xpc_dictionary_set_int64(Impl, Key.c_str(), val);
}
void ResponseBuilder::Dictionary::set(SourceKit::UIdent Key,
ArrayRef<StringRef> Strs) {
llvm::SmallString<128> Buf;
xpc_object_t arr = xpc_array_create(nullptr, 0);
for (auto Str : Strs) {
Buf = Str;
xpc_array_set_string(arr, XPC_ARRAY_APPEND, Buf.c_str());
}
xpc_dictionary_set_value(Impl, Key.c_str(), arr);
xpc_release(arr);
}
void ResponseBuilder::Dictionary::setBool(UIdent Key, bool val) {
xpc_dictionary_set_bool(Impl, Key.c_str(), val);
}
ResponseBuilder::Array
ResponseBuilder::Dictionary::setArray(UIdent Key) {
xpc_object_t arr = xpc_array_create(nullptr, 0);
xpc_dictionary_set_value(Impl, Key.c_str(), arr);
xpc_release(arr);
return Array(arr);
}
ResponseBuilder::Dictionary
ResponseBuilder::Dictionary::setDictionary(UIdent Key) {
xpc_object_t dict = xpc_dictionary_create(nullptr, nullptr, 0);
xpc_dictionary_set_value(Impl, Key.c_str(), dict);
xpc_release(dict);
return Dictionary(dict);
}
void ResponseBuilder::Dictionary::setCustomBuffer(
SourceKit::UIdent Key,
CustomBufferKind Kind, std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
std::unique_ptr<llvm::MemoryBuffer> CustomBuf;
CustomBuf = llvm::MemoryBuffer::getNewUninitMemBuffer(
sizeof(uint64_t) + MemBuf->getBufferSize());
char *BufPtr = (char*)CustomBuf->getBufferStart();
*reinterpret_cast<uint64_t*>(BufPtr) = (uint64_t)Kind;
BufPtr += sizeof(uint64_t);
memcpy(BufPtr, MemBuf->getBufferStart(), MemBuf->getBufferSize());
xpc_object_t xdata = xpc_data_create(CustomBuf->getBufferStart(),
CustomBuf->getBufferSize());
xpc_dictionary_set_value(Impl, Key.c_str(), xdata);
xpc_release(xdata);
}
ResponseBuilder::Dictionary ResponseBuilder::Array::appendDictionary() {
xpc_object_t dict = xpc_dictionary_create(nullptr, nullptr, 0);
xpc_array_append_value(Impl, dict);
xpc_release(dict);
return Dictionary(dict);
}
sourcekitd_uid_t RequestDict::getUID(UIdent Key) {
return sourcekitd_uid_t(xpc_dictionary_get_uint64(Dict, Key.c_str()));
}
Optional<StringRef> RequestDict::getString(UIdent Key) {
xpc_object_t xobj = xpc_dictionary_get_value(Dict, Key.c_str());
if (!xobj)
return None;
if (xpc_get_type(xobj) != XPC_TYPE_STRING)
return None;
return StringRef(xpc_string_get_string_ptr(xobj),
xpc_string_get_length(xobj));
}
Optional<RequestDict> RequestDict::getDictionary(SourceKit::UIdent Key) {
xpc_object_t xobj = xpc_dictionary_get_value(Dict, Key.c_str());
if (!xobj)
return None;
if (xpc_get_type(xobj) != XPC_TYPE_DICTIONARY)
return None;
return RequestDict(xobj);
}
bool RequestDict::getStringArray(SourceKit::UIdent Key,
llvm::SmallVectorImpl<const char *> &Arr,
bool isOptional) {
xpc_object_t xarr = xpc_dictionary_get_value(Dict, Key.c_str());
if (!xarr)
return !isOptional;
if (xpc_get_type(xarr) != XPC_TYPE_ARRAY)
return true;
size_t count = xpc_array_get_count(xarr);
Arr.reserve(count);
for (size_t i = 0; i != count; ++i) {
const char *Str = xpc_array_get_string(xarr, i);
if (!Str)
return true;
Arr.push_back(Str);
}
return false;
}
bool RequestDict::getUIDArray(SourceKit::UIdent Key,
llvm::SmallVectorImpl<sourcekitd_uid_t> &Arr,
bool isOptional) {
xpc_object_t xarr = xpc_dictionary_get_value(Dict, Key.c_str());
if (!xarr)
return !isOptional;
if (xpc_get_type(xarr) != XPC_TYPE_ARRAY)
return true;
size_t count = xpc_array_get_count(xarr);
Arr.reserve(count);
for (size_t i = 0; i != count; ++i) {
auto UID = sourcekitd_uid_t(xpc_array_get_uint64(xarr, i));
if (!UID)
return true;
Arr.push_back(UID);
}
return false;
}
bool RequestDict::dictionaryArrayApply(
SourceKit::UIdent key, llvm::function_ref<bool(RequestDict)> applier) {
xpc_object_t xarr = xpc_dictionary_get_value(Dict, key.c_str());
if (!xarr || xpc_get_type(xarr) != XPC_TYPE_ARRAY)
return true;
size_t count = xpc_array_get_count(xarr);
for (size_t i = 0; i != count; ++i) {
auto xdict = xpc_array_get_value(xarr, i);
if (!xdict || xpc_get_type(xdict) != XPC_TYPE_DICTIONARY)
return true;
if (applier(RequestDict(xdict)))
return true;
}
return false;
}
bool RequestDict::getInt64(SourceKit::UIdent Key, int64_t &Val,
bool isOptional) {
xpc_object_t xobj = xpc_dictionary_get_value(Dict, Key.c_str());
if (!xobj)
return !isOptional;
Val = xpc_int64_get_value(xobj);
return false;
}
Optional<int64_t> RequestDict::getOptionalInt64(SourceKit::UIdent Key) {
xpc_object_t xobj = xpc_dictionary_get_value(Dict, Key.c_str());
if (!xobj)
return None;
return xpc_int64_get_value(xobj);
}
sourcekitd_response_t
sourcekitd::createErrorRequestInvalid(const char *Description) {
return CustomXPCData::createErrorRequestInvalid(Description).getXObj();
}
sourcekitd_response_t
sourcekitd::createErrorRequestFailed(const char *Description) {
return CustomXPCData::createErrorRequestFailed(Description).getXObj();
}
sourcekitd_response_t
sourcekitd::createErrorRequestInterrupted(const char *Description) {
return CustomXPCData::createErrorRequestInterrupted(Description).getXObj();
}
sourcekitd_response_t
sourcekitd::createErrorRequestCancelled() {
return CustomXPCData::createErrorRequestCancelled("").getXObj();
}
//===----------------------------------------------------------------------===//
// Public Request API
//===----------------------------------------------------------------------===//
static inline const char *strFromUID(sourcekitd_uid_t uid) {
return UIdentFromSKDUID(uid).c_str();
}
sourcekitd_object_t
sourcekitd_request_retain(sourcekitd_object_t object) {
return xpc_retain(object);
}
void sourcekitd_request_release(sourcekitd_object_t object) {
xpc_release(object);
}
sourcekitd_object_t
sourcekitd_request_dictionary_create(const sourcekitd_uid_t *keys,
const sourcekitd_object_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_request_dictionary_set_value(sourcekitd_object_t dict,
sourcekitd_uid_t key,
sourcekitd_object_t value) {
xpc_dictionary_set_value(dict, strFromUID(key), value);
}
void sourcekitd_request_dictionary_set_string(sourcekitd_object_t dict,
sourcekitd_uid_t key,
const char *string) {
xpc_dictionary_set_string(dict, strFromUID(key), string);
}
void
sourcekitd_request_dictionary_set_stringbuf(sourcekitd_object_t dict,
sourcekitd_uid_t key,
const char *buf, size_t length) {
llvm::SmallString<512> SS;
SS += StringRef(buf, length);
sourcekitd_request_dictionary_set_string(dict, key, SS.c_str());
}
void sourcekitd_request_dictionary_set_int64(sourcekitd_object_t dict,
sourcekitd_uid_t key,
int64_t val) {
xpc_dictionary_set_int64(dict, strFromUID(key), val);
}
void
sourcekitd_request_dictionary_set_uid(sourcekitd_object_t dict,
sourcekitd_uid_t key,
sourcekitd_uid_t uid) {
xpc_dictionary_set_uint64(dict, strFromUID(key), uintptr_t(uid));
}
sourcekitd_object_t
sourcekitd_request_array_create(const sourcekitd_object_t *objects,
size_t count) {
return xpc_array_create(objects, count);
}
void
sourcekitd_request_array_set_value(sourcekitd_object_t array, size_t index,
sourcekitd_object_t value) {
xpc_array_set_value(array, index, value);
}
void
sourcekitd_request_array_set_string(sourcekitd_object_t array, size_t index,
const char *string) {
xpc_array_set_string(array, index, string);
}
void
sourcekitd_request_array_set_stringbuf(sourcekitd_object_t array, size_t index,
const char *buf, size_t length) {
llvm::SmallString<512> SS;
SS += StringRef(buf, length);
sourcekitd_request_array_set_string(array, index, SS.c_str());
}
void
sourcekitd_request_array_set_int64(sourcekitd_object_t array, size_t index,
int64_t val) {
xpc_array_set_int64(array, index, val);
}
void
sourcekitd_request_array_set_uid(sourcekitd_object_t array, size_t index,
sourcekitd_uid_t uid) {
xpc_array_set_uint64(array, index, uintptr_t(uid));
}
sourcekitd_object_t
sourcekitd_request_int64_create(int64_t val) {
return xpc_int64_create(val);
}
sourcekitd_object_t
sourcekitd_request_string_create(const char *string) {
return xpc_string_create(string);
}
sourcekitd_object_t
sourcekitd_request_uid_create(sourcekitd_uid_t uid) {
return xpc_uint64_create(uintptr_t(uid));
}
//===----------------------------------------------------------------------===//
// Public Response API
//===----------------------------------------------------------------------===//
void
sourcekitd_response_dispose(sourcekitd_response_t obj) {
xpc_release(obj);
}
bool
sourcekitd_response_is_error(sourcekitd_response_t obj) {
xpc_type_t type = xpc_get_type(obj);
if (type == XPC_TYPE_ERROR)
return true;
if (type == XPC_TYPE_DATA) {
CustomXPCData Dat(obj);
return Dat.isError();
}
return false;
}
sourcekitd_error_t
sourcekitd_response_error_get_kind(sourcekitd_response_t obj) {
xpc_type_t type = xpc_get_type(obj);
if (type == XPC_TYPE_ERROR) {
if (obj == XPC_ERROR_CONNECTION_INTERRUPTED)
return SOURCEKITD_ERROR_CONNECTION_INTERRUPTED;
// This can originate if the client initiated shutdown.
if (obj == XPC_ERROR_CONNECTION_INVALID)
return SOURCEKITD_ERROR_REQUEST_CANCELLED;
}
if (type == XPC_TYPE_DATA) {
CustomXPCData Dat(obj);
switch (Dat.getKind()) {
case CustomXPCData::Kind::ErrorRequestInvalid:
return SOURCEKITD_ERROR_REQUEST_INVALID;
case CustomXPCData::Kind::ErrorRequestFailed:
return SOURCEKITD_ERROR_REQUEST_FAILED;
case CustomXPCData::Kind::ErrorRequestInterrupted:
return SOURCEKITD_ERROR_CONNECTION_INTERRUPTED;
case CustomXPCData::Kind::ErrorRequestCancelled:
return SOURCEKITD_ERROR_REQUEST_CANCELLED;
}
}
llvm::report_fatal_error("sourcekitd error did not resolve to a known kind");
}
const char *
sourcekitd_response_error_get_description(sourcekitd_response_t obj) {
xpc_type_t type = xpc_get_type(obj);
if (type == XPC_TYPE_ERROR)
return xpc_dictionary_get_string(obj, XPC_ERROR_KEY_DESCRIPTION);
if (type == XPC_TYPE_DATA) {
CustomXPCData Dat(obj);
if (Dat.isError())
return Dat.getErrorDescription();
}
llvm::report_fatal_error("invalid sourcekitd error object");
}
static sourcekitd_variant_t variantFromXPCObject(xpc_object_t obj);
sourcekitd_variant_t
sourcekitd_response_get_value(sourcekitd_response_t resp) {
if (sourcekitd_response_is_error(resp))
return makeNullVariant();
return variantFromXPCObject(resp);
}
//===----------------------------------------------------------------------===//
// Variant functions
//===----------------------------------------------------------------------===//
#define XPC_OBJ(var) ((xpc_object_t)(var).data[1])
#define CUSTOM_BUF_KIND(xobj) \
((CustomBufferKind)*(uint64_t*)xpc_data_get_bytes_ptr(xobj))
#define CUSTOM_BUF_START(xobj) \
((void*)(((uint64_t*)xpc_data_get_bytes_ptr(xobj))+1))
static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) {
xpc_object_t obj = XPC_OBJ(var);
xpc_type_t type = xpc_get_type(obj);
if (type == XPC_TYPE_DICTIONARY)
return SOURCEKITD_VARIANT_TYPE_DICTIONARY;
if (type == XPC_TYPE_ARRAY)
return SOURCEKITD_VARIANT_TYPE_ARRAY;
if (type == XPC_TYPE_INT64)
return SOURCEKITD_VARIANT_TYPE_INT64;
if (type == XPC_TYPE_BOOL)
return SOURCEKITD_VARIANT_TYPE_BOOL;
if (type == XPC_TYPE_STRING)
return SOURCEKITD_VARIANT_TYPE_STRING;
// Take over XPC's UINT64 to mean SourceKitD's UID.
// This means that UINT64 will not be available to be constructed in a
// sourcekitd message.
if (type == XPC_TYPE_UINT64)
return SOURCEKITD_VARIANT_TYPE_UID;
if (type == XPC_TYPE_DATA) {
switch(CUSTOM_BUF_KIND(obj)) {
case CustomBufferKind::TokenAnnotationsArray:
return SOURCEKITD_VARIANT_TYPE_ARRAY;
case CustomBufferKind::DocSupportAnnotationArray:
return SOURCEKITD_VARIANT_TYPE_ARRAY;
case CustomBufferKind::CodeCompletionResultsArray:
return SOURCEKITD_VARIANT_TYPE_ARRAY;
case CustomBufferKind::DocStructureArray:
case CustomBufferKind::InheritedTypesArray:
case CustomBufferKind::DocStructureElementArray:
case CustomBufferKind::AttributesArray:
return SOURCEKITD_VARIANT_TYPE_ARRAY;
}
}
llvm::report_fatal_error("sourcekitd object did not resolve to a known type");
}
static bool XPCVar_array_apply(
sourcekitd_variant_t array,
llvm::function_ref<bool(size_t, sourcekitd_variant_t)> applier) {
return xpc_array_apply(XPC_OBJ(array),
^(size_t index, xpc_object_t obj) {
return applier(index, variantFromXPCObject(obj));
});
}
static bool XPCVar_array_get_bool(sourcekitd_variant_t array, size_t index) {
return xpc_array_get_bool(XPC_OBJ(array), index);
}
static size_t XPCVar_array_get_count(sourcekitd_variant_t array) {
return xpc_array_get_count(XPC_OBJ(array));
}
static int64_t XPCVar_array_get_int64(sourcekitd_variant_t array, size_t index) {
return xpc_array_get_int64(XPC_OBJ(array), index);
}
static const char *
XPCVar_array_get_string(sourcekitd_variant_t array, size_t index) {
return xpc_array_get_string(XPC_OBJ(array), index);
}
static sourcekitd_uid_t XPCVar_array_get_uid(sourcekitd_variant_t array, size_t index) {
return sourcekitd_uid_t(xpc_array_get_uint64(XPC_OBJ(array), index));
}
static sourcekitd_variant_t
XPCVar_array_get_value(sourcekitd_variant_t array, size_t index) {
return variantFromXPCObject(xpc_array_get_value(XPC_OBJ(array), index));
}
static bool XPCVar_bool_get_value(sourcekitd_variant_t obj) {
return xpc_bool_get_value(XPC_OBJ(obj));
}
static bool XPCVar_dictionary_apply(
sourcekitd_variant_t dict,
llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)> applier) {
return xpc_dictionary_apply(XPC_OBJ(dict),
^(const char *key, xpc_object_t obj) {
return applier(sourcekitd_uid_get_from_cstr(key),variantFromXPCObject(obj));
});
}
static bool
XPCVar_dictionary_get_bool(sourcekitd_variant_t dict, sourcekitd_uid_t key) {
return xpc_dictionary_get_bool(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));
}
static const char *
XPCVar_dictionary_get_string(sourcekitd_variant_t dict, sourcekitd_uid_t key) {
return xpc_dictionary_get_string(XPC_OBJ(dict), strFromUID(key));
}
static sourcekitd_variant_t
XPCVar_dictionary_get_value(sourcekitd_variant_t dict, sourcekitd_uid_t key) {
return variantFromXPCObject(
xpc_dictionary_get_value(XPC_OBJ(dict), strFromUID(key)));
}
static sourcekitd_uid_t
XPCVar_dictionary_get_uid(sourcekitd_variant_t dict, sourcekitd_uid_t key) {
return sourcekitd_uid_t(
xpc_dictionary_get_uint64(XPC_OBJ(dict), strFromUID(key)));
}
static size_t XPCVar_string_get_length(sourcekitd_variant_t obj) {
return xpc_string_get_length(XPC_OBJ(obj));
}
static const char *XPCVar_string_get_ptr(sourcekitd_variant_t obj) {
return xpc_string_get_string_ptr(XPC_OBJ(obj));
}
static int64_t XPCVar_int64_get_value(sourcekitd_variant_t obj) {
return xpc_int64_get_value(XPC_OBJ(obj));
}
static sourcekitd_uid_t XPCVar_uid_get_value(sourcekitd_variant_t obj) {
return sourcekitd_uid_t(xpc_uint64_get_value(XPC_OBJ(obj)));
}
static VariantFunctions XPCVariantFuncs = {
XPCVar_get_type,
XPCVar_array_apply,
XPCVar_array_get_bool,
XPCVar_array_get_count,
XPCVar_array_get_int64,
XPCVar_array_get_string,
XPCVar_array_get_uid,
XPCVar_array_get_value,
XPCVar_bool_get_value,
XPCVar_dictionary_apply,
XPCVar_dictionary_get_bool,
XPCVar_dictionary_get_int64,
XPCVar_dictionary_get_string,
XPCVar_dictionary_get_value,
XPCVar_dictionary_get_uid,
XPCVar_string_get_length,
XPCVar_string_get_ptr,
XPCVar_int64_get_value,
XPCVar_uid_get_value
};
static sourcekitd_variant_t variantFromXPCObject(xpc_object_t obj) {
if (!obj)
return makeNullVariant();
if (xpc_get_type(obj) == XPC_TYPE_DATA) {
switch(CUSTOM_BUF_KIND(obj)) {
case CustomBufferKind::TokenAnnotationsArray:
return {{ (uintptr_t)getVariantFunctionsForTokenAnnotationsArray(),
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
case CustomBufferKind::DocSupportAnnotationArray:
return {{ (uintptr_t)getVariantFunctionsForDocSupportAnnotationArray(),
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
case CustomBufferKind::CodeCompletionResultsArray:
return {{ (uintptr_t)getVariantFunctionsForCodeCompletionResultsArray(),
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
case CustomBufferKind::DocStructureArray:
return {{ (uintptr_t)getVariantFunctionsForDocStructureArray(),
(uintptr_t)CUSTOM_BUF_START(obj), ~size_t(0) }};
case CustomBufferKind::InheritedTypesArray:
return {{ (uintptr_t)getVariantFunctionsForInheritedTypesArray(),
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
case CustomBufferKind::DocStructureElementArray:
return {{ (uintptr_t)getVariantFunctionsForDocStructureElementArray(),
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
case CustomBufferKind::AttributesArray:
return {{ (uintptr_t)getVariantFunctionsForAttributesArray(),
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
}
}
return {{ (uintptr_t)&XPCVariantFuncs, (uintptr_t)obj, 0 }};
}