| //===--- sourcekitdAPI-InProc.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/sourcekitd.h" |
| #include "sourcekitd/Internal.h" |
| #include "sourcekitd/CodeCompletionResultsArray.h" |
| #include "sourcekitd/DocStructureArray.h" |
| #include "sourcekitd/DocSupportAnnotationArray.h" |
| #include "sourcekitd/TokenAnnotationsArray.h" |
| #include "sourcekitd/Logging.h" |
| #include "SourceKit/Core/LLVM.h" |
| #include "SourceKit/Support/UIdent.h" |
| #include "swift/Basic/ThreadSafeRefCounted.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/IntrusiveRefCntPtr.h" |
| |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| |
| #include <map> |
| |
| using namespace SourceKit; |
| using namespace sourcekitd; |
| |
| namespace { |
| class SKDObject; |
| typedef RefPtr<SKDObject> SKDObjectRef; |
| |
| class SKDObject : public ThreadSafeRefCountedBaseVPTR { |
| public: |
| enum class ObjectKind { |
| Dictionary, |
| Array, |
| String, |
| Int64, |
| UID, |
| Bool, |
| CustomData, |
| Error, |
| }; |
| private: |
| ObjectKind Kind; |
| protected: |
| SKDObject(ObjectKind K) : Kind(K) {} |
| public: |
| SKDObject(SKDObject const&) = delete; |
| SKDObject &operator=(SKDObject const&) = delete; |
| |
| ObjectKind getKind() const { return Kind; } |
| |
| virtual sourcekitd_variant_type_t getVariantType() const = 0; |
| |
| virtual void set(sourcekitd_uid_t Key, SKDObjectRef Value) {} |
| virtual void set(size_t Index, SKDObjectRef Value) {} |
| |
| virtual SKDObjectRef get(sourcekitd_uid_t Key) const { return nullptr; } |
| |
| virtual SKDObjectRef get(size_t Index) const { return nullptr; } |
| virtual size_t getCount() const { return 0; } |
| |
| virtual sourcekitd_uid_t getUID() const { return nullptr; } |
| virtual Optional<int64_t> getInt64() const { return None; } |
| virtual Optional<StringRef> getString() const { return None; } |
| virtual const char *getCString() const { return nullptr; } |
| virtual bool getBool() const { return false; } |
| }; |
| |
| class SKDDictionary: public SKDObject { |
| public: |
| SKDDictionary() : SKDObject(ObjectKind::Dictionary) {} |
| SKDDictionary(SKDDictionary const&) = delete; |
| SKDDictionary &operator=(SKDDictionary const&) = delete; |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| return SOURCEKITD_VARIANT_TYPE_DICTIONARY; |
| } |
| |
| void set(sourcekitd_uid_t Key, SKDObjectRef Value) override { |
| Storage[Key] = Value; |
| } |
| |
| SKDObjectRef get(sourcekitd_uid_t Key) const override { |
| auto it = Storage.find(Key); |
| return it != Storage.end() ? it->second : nullptr; |
| } |
| |
| bool |
| apply(llvm::function_ref<bool(sourcekitd_uid_t, SKDObjectRef)> Applier) const { |
| for (const auto& kv : Storage) { |
| if (!Applier(kv.first, kv.second)) |
| return false; |
| } |
| return true; |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::Dictionary; |
| } |
| private: |
| std::map<sourcekitd_uid_t, SKDObjectRef> Storage; |
| }; |
| |
| class SKDArray: public SKDObject { |
| public: |
| SKDArray() : SKDObject(ObjectKind::Array) {} |
| SKDArray(SKDArray const&) = delete; |
| SKDArray &operator=(SKDArray const&) = delete; |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| return SOURCEKITD_VARIANT_TYPE_ARRAY; |
| } |
| |
| void set(size_t Index, SKDObjectRef Value) override { |
| if (Index == SOURCEKITD_ARRAY_APPEND) { |
| Storage.push_back(Value); |
| } else { |
| Storage[Index] = Value; |
| } |
| } |
| |
| SKDObjectRef get(size_t Index) const override { |
| return Storage[Index]; |
| } |
| |
| size_t getCount() const override { |
| return Storage.size(); |
| } |
| |
| bool apply(llvm::function_ref<bool(size_t, SKDObjectRef)> Applier) const { |
| for (size_t i = 0; i < Storage.size(); ++i) { |
| if (!Applier(i, Storage[i])) |
| return false; |
| } |
| return true; |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::Array; |
| } |
| private: |
| std::vector<SKDObjectRef> Storage; |
| }; |
| |
| class SKDString: public SKDObject { |
| public: |
| SKDString(std::string &&Value) : SKDObject(ObjectKind::String), Storage(Value) {} |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| return SOURCEKITD_VARIANT_TYPE_STRING; |
| } |
| |
| Optional<StringRef> getString() const override { |
| return Optional<StringRef>(Storage); |
| } |
| |
| const char *getCString() const override { |
| return Storage.c_str(); |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::String; |
| } |
| private: |
| std::string Storage; |
| }; |
| |
| class SKDInt64: public SKDObject { |
| public: |
| SKDInt64(int64_t Value) : SKDObject(ObjectKind::Int64), Storage(Value) {} |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| return SOURCEKITD_VARIANT_TYPE_INT64; |
| } |
| |
| Optional<int64_t> getInt64() const override { |
| return Storage; |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::Int64; |
| } |
| private: |
| int64_t Storage; |
| }; |
| |
| class SKDUID: public SKDObject { |
| public: |
| SKDUID(sourcekitd_uid_t Value) : SKDObject(ObjectKind::UID), Storage(Value) {} |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| return SOURCEKITD_VARIANT_TYPE_UID; |
| } |
| |
| sourcekitd_uid_t getUID() const override { |
| return Storage; |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::UID; |
| } |
| private: |
| sourcekitd_uid_t Storage; |
| }; |
| |
| class SKDBool: public SKDObject { |
| public: |
| SKDBool(bool Value) : SKDObject(ObjectKind::Bool), Storage(Value) {} |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| return SOURCEKITD_VARIANT_TYPE_BOOL; |
| } |
| |
| bool getBool() const override { |
| return Storage; |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::Bool; |
| } |
| private: |
| bool Storage; |
| }; |
| |
| class SKDCustomData: public SKDObject { |
| public: |
| SKDCustomData(CustomBufferKind BufferKind, |
| std::unique_ptr<llvm::MemoryBuffer>& MemBuf) |
| : SKDObject(ObjectKind::CustomData), BufferKind(BufferKind), |
| BufferPtr(llvm::MemoryBuffer::getMemBufferCopy( |
| MemBuf->getBuffer(), |
| MemBuf->getBufferIdentifier())) |
| {} |
| |
| SKDCustomData(SKDCustomData const&) = delete; |
| SKDCustomData &operator=(SKDCustomData const&) = delete; |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| switch (BufferKind) { |
| case CustomBufferKind::TokenAnnotationsArray: |
| case CustomBufferKind::DocSupportAnnotationArray: |
| case CustomBufferKind::CodeCompletionResultsArray: |
| 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"); |
| } |
| |
| CustomBufferKind getBufferKind() const { |
| return BufferKind; |
| } |
| |
| const void *getDataPtr() const { |
| return BufferPtr->getBuffer().data(); |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::CustomData; |
| } |
| private: |
| CustomBufferKind BufferKind; |
| std::unique_ptr<llvm::MemoryBuffer> BufferPtr; |
| }; |
| |
| class SKDError: public SKDObject { |
| public: |
| SKDError(sourcekitd_error_t ErrorKind, StringRef Description) |
| : SKDObject(ObjectKind::Error), ErrorKind(ErrorKind), Description(Description) {} |
| |
| SKDError(SKDError const&) = delete; |
| SKDError &operator=(SKDError const&) = delete; |
| |
| sourcekitd_variant_type_t getVariantType() const override { |
| llvm::report_fatal_error("sourcekitd error object is not a variant type"); |
| } |
| |
| sourcekitd_error_t getErrorKind() const { |
| return ErrorKind; |
| } |
| |
| const std::string &getDescription() const { |
| return Description; |
| } |
| |
| static bool classof(const SKDObject *O) { |
| return O->getKind() == ObjectKind::Error; |
| } |
| private: |
| sourcekitd_error_t ErrorKind; |
| std::string Description; |
| }; |
| |
| 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) { |
| auto Object = static_cast<SKDObject *>(Obj); |
| |
| if (auto DictionaryObject = dyn_cast<SKDDictionary>(Object)) { |
| DictMap Dict; |
| DictionaryObject->apply([&](sourcekitd_uid_t Key, SKDObjectRef Element){ |
| UIdent UID = UIdentFromSKDUID(Key); |
| Dict.push_back({ UID, Element.get() }); |
| return true; |
| }); |
| std::sort(Dict.begin(), Dict.end(), compKeys); |
| return static_cast<ImplClass*>(this)->visitDictionary(Dict); |
| } |
| if (auto ArrayObject = dyn_cast<SKDArray>(Object)) { |
| std::vector<sourcekitd_object_t> Vec; |
| ArrayObject->apply([&](size_t Index, SKDObjectRef Element){ |
| Vec.push_back(Element.get()); |
| return true; |
| }); |
| return static_cast<ImplClass*>(this)->visitArray(Vec); |
| } |
| if (auto SKDUID = Object->getUID()) { |
| UIdent UID = UIdentFromSKDUID(SKDUID); |
| return static_cast<ImplClass*>(this)->visitUID(UID.getName()); |
| } |
| if (auto CString = Object->getCString()) { |
| return static_cast<ImplClass*>(this)->visitString(CString); |
| } |
| auto OptInt = Object->getInt64(); |
| if (OptInt.hasValue()) { |
| return static_cast<ImplClass*>(this)->visitInt64(OptInt.getValue()); |
| } |
| llvm_unreachable("unknown sourcekitd_object_t"); |
| } |
| }; |
| |
| class SKDObjectPrinter : public SKDObjectVisitor<SKDObjectPrinter> { |
| raw_ostream &OS; |
| unsigned Indent; |
| public: |
| SKDObjectPrinter(raw_ostream &OS, unsigned Indent = 0) |
| : OS(OS), Indent(Indent) { } |
| |
| void visitDictionary(const DictMap &Map) { |
| OS << "{\n"; |
| Indent += 2; |
| for (unsigned i = 0, e = Map.size(); i != e; ++i) { |
| auto &Pair = Map[i]; |
| OS.indent(Indent); |
| OSColor(OS, DictKeyColor) << Pair.first.getName(); |
| OS << ": "; |
| SKDObjectPrinter(OS, Indent).visit(Pair.second); |
| if (i < e-1) |
| OS << ','; |
| OS << '\n'; |
| } |
| Indent -= 2; |
| OS.indent(Indent) << '}'; |
| } |
| |
| void visitArray(ArrayRef<sourcekitd_object_t> Arr) { |
| OS << "[\n"; |
| Indent += 2; |
| for (unsigned i = 0, e = Arr.size(); i != e; ++i) { |
| auto Obj = Arr[i]; |
| OS.indent(Indent); |
| SKDObjectPrinter(OS, Indent).visit(Obj); |
| if (i < e-1) |
| OS << ','; |
| OS << '\n'; |
| } |
| Indent -= 2; |
| OS.indent(Indent) << ']'; |
| } |
| |
| void visitInt64(int64_t Val) { |
| OS << Val; |
| } |
| |
| void visitString(StringRef Str) { |
| OS << '\"'; |
| // Avoid raw_ostream's write_escaped, we don't want to escape unicode |
| // characters because it will be invalid JSON. |
| writeEscaped(Str, OS); |
| OS << '\"'; |
| } |
| |
| void visitUID(StringRef UID) { |
| OSColor(OS, UIDColor) << UID; |
| } |
| }; |
| |
| static SKDObject *retained(SKDObject *object) { |
| object->Retain(); |
| return object; |
| } |
| |
| } // anonymous namespace |
| |
| //===----------------------------------------------------------------------===// |
| // Public Request API |
| //===----------------------------------------------------------------------===// |
| |
| sourcekitd_object_t |
| sourcekitd_request_retain(sourcekitd_object_t object) { |
| return retained(static_cast<SKDObject *>(object)); |
| } |
| |
| void sourcekitd_request_release(sourcekitd_object_t object) { |
| static_cast<SKDObject *>(object)->Release(); |
| } |
| |
| sourcekitd_object_t |
| sourcekitd_request_dictionary_create(const sourcekitd_uid_t *keys, |
| const sourcekitd_object_t *values, |
| size_t count) { |
| SKDDictionary *Dict = new SKDDictionary(); |
| for (size_t i = 0; i < count; ++i) { |
| Dict->set(keys[i], static_cast<SKDObject *>(values[i])); |
| } |
| return retained(Dict); |
| } |
| |
| void |
| sourcekitd_request_dictionary_set_value(sourcekitd_object_t dict, |
| sourcekitd_uid_t key, |
| sourcekitd_object_t value) { |
| static_cast<SKDObject *>(dict)->set(key, static_cast<SKDObject *>(value)); |
| } |
| |
| void sourcekitd_request_dictionary_set_string(sourcekitd_object_t dict, |
| sourcekitd_uid_t key, |
| const char *string) { |
| static_cast<SKDObject *>(dict)->set(key, new SKDString(std::string(string))); |
| } |
| |
| void |
| sourcekitd_request_dictionary_set_stringbuf(sourcekitd_object_t dict, |
| sourcekitd_uid_t key, |
| const char *buf, size_t length) { |
| static_cast<SKDObject *>(dict)->set(key, |
| new SKDString(std::string(buf, length))); |
| } |
| |
| void sourcekitd_request_dictionary_set_int64(sourcekitd_object_t dict, |
| sourcekitd_uid_t key, |
| int64_t val) { |
| static_cast<SKDObject *>(dict)->set(key, new SKDInt64(val)); |
| } |
| |
| void |
| sourcekitd_request_dictionary_set_uid(sourcekitd_object_t dict, |
| sourcekitd_uid_t key, |
| sourcekitd_uid_t uid) { |
| static_cast<SKDObject *>(dict)->set(key, new SKDUID(uid)); |
| } |
| |
| sourcekitd_object_t |
| sourcekitd_request_array_create(const sourcekitd_object_t *objects, |
| size_t count) { |
| SKDArray *Array = new SKDArray(); |
| for (size_t i = 0; i < count; ++i) { |
| Array->set(SOURCEKITD_ARRAY_APPEND, static_cast<SKDObject *>(objects[i])); |
| } |
| return retained(Array); |
| } |
| |
| void |
| sourcekitd_request_array_set_value(sourcekitd_object_t array, size_t index, |
| sourcekitd_object_t value) { |
| static_cast<SKDObject *>(array)->set(index, static_cast<SKDObject *>(value)); |
| } |
| |
| void |
| sourcekitd_request_array_set_string(sourcekitd_object_t array, size_t index, |
| const char *string) { |
| static_cast<SKDObject *>(array)->set(index, |
| new SKDString(std::string(string))); |
| } |
| |
| void |
| sourcekitd_request_array_set_stringbuf(sourcekitd_object_t array, size_t index, |
| const char *buf, size_t length) { |
| static_cast<SKDObject *>(array)->set(index, |
| new SKDString(std::string(buf, length))); |
| } |
| |
| void |
| sourcekitd_request_array_set_int64(sourcekitd_object_t array, size_t index, |
| int64_t val) { |
| static_cast<SKDObject *>(array)->set(index, new SKDInt64(val)); |
| } |
| |
| void |
| sourcekitd_request_array_set_uid(sourcekitd_object_t array, size_t index, |
| sourcekitd_uid_t uid) { |
| static_cast<SKDObject *>(array)->set(index, new SKDUID(uid)); |
| } |
| |
| |
| sourcekitd_object_t |
| sourcekitd_request_int64_create(int64_t val) { |
| return retained(new SKDInt64(val)); |
| } |
| |
| sourcekitd_object_t |
| sourcekitd_request_string_create(const char *string) { |
| return retained(new SKDString(std::string(string))); |
| } |
| |
| sourcekitd_object_t |
| sourcekitd_request_uid_create(sourcekitd_uid_t uid) { |
| return retained(new SKDUID(uid)); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Public Response API |
| //===----------------------------------------------------------------------===// |
| |
| void |
| sourcekitd_response_dispose(sourcekitd_response_t obj) { |
| static_cast<SKDObject *>(obj)->Release(); |
| } |
| |
| bool |
| sourcekitd_response_is_error(sourcekitd_response_t obj) { |
| return isa<SKDError>(static_cast<SKDObject *>(obj)); |
| } |
| |
| sourcekitd_error_t |
| sourcekitd_response_error_get_kind(sourcekitd_response_t obj) { |
| if (auto *Error = dyn_cast<SKDError>(static_cast<SKDObject *>(obj))) |
| return Error->getErrorKind(); |
| llvm::report_fatal_error("invalid sourcekitd error object"); |
| } |
| |
| const char * |
| sourcekitd_response_error_get_description(sourcekitd_response_t obj) { |
| if (auto *Error = dyn_cast<SKDError>(static_cast<SKDObject *>(obj))) |
| return Error->getDescription().c_str(); |
| llvm::report_fatal_error("invalid sourcekitd error object"); |
| } |
| |
| static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object); |
| |
| sourcekitd_variant_t |
| sourcekitd_response_get_value(sourcekitd_response_t resp) { |
| if (sourcekitd_response_is_error(resp)) |
| return makeNullVariant(); |
| return variantFromSKDObject(static_cast<SKDObject *>(resp)); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Internal Request API |
| //===----------------------------------------------------------------------===// |
| |
| void sourcekitd::printRequestObject(sourcekitd_object_t Obj, raw_ostream &OS) { |
| if (!Obj) { |
| OS << "<<NULL>>"; |
| return; |
| } |
| |
| SKDObjectPrinter(OS).visit(Obj); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Internal ResponseBuilder Implementation |
| //===----------------------------------------------------------------------===// |
| |
| ResponseBuilder::ResponseBuilder() { |
| Impl = retained(new SKDDictionary()); |
| } |
| |
| ResponseBuilder::~ResponseBuilder() { |
| static_cast<SKDObject *>(Impl)->Release(); |
| } |
| |
| ResponseBuilder::ResponseBuilder(const ResponseBuilder &Other) { |
| Impl = retained(static_cast<SKDObject *>(Other.Impl)); |
| } |
| |
| ResponseBuilder &ResponseBuilder::operator =(const ResponseBuilder &Other) { |
| auto Tmp = retained(static_cast<SKDObject *>(Other.Impl)); |
| static_cast<SKDObject *>(Impl)->Release(); |
| Impl = Tmp; |
| return *this; |
| } |
| |
| ResponseBuilder::Dictionary ResponseBuilder::getDictionary() { |
| return Dictionary(Impl); |
| } |
| |
| sourcekitd_response_t ResponseBuilder::createResponse() { |
| return retained(static_cast<SKDObject *>(Impl)); |
| } |
| |
| void ResponseBuilder::Dictionary::set(UIdent Key, SourceKit::UIdent UID) { |
| set(Key, SKDUIDFromUIdent(UID)); |
| } |
| |
| void ResponseBuilder::Dictionary::set(UIdent Key, sourcekitd_uid_t UID) { |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), new SKDUID(UID)); |
| } |
| |
| void ResponseBuilder::Dictionary::set(UIdent Key, const char *Str) { |
| set(Key, StringRef(Str)); |
| } |
| |
| void ResponseBuilder::Dictionary::set(UIdent Key, StringRef Str) { |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), |
| new SKDString(Str)); |
| } |
| |
| void ResponseBuilder::Dictionary::set(UIdent Key, int64_t Val) { |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), new SKDInt64(Val)); |
| } |
| |
| void ResponseBuilder::Dictionary::set(SourceKit::UIdent Key, |
| ArrayRef<StringRef> Strs) { |
| auto ArrayObject = new SKDArray(); |
| for (auto Str : Strs) { |
| ArrayObject->set(SOURCEKITD_ARRAY_APPEND, new SKDString(Str)); |
| } |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), ArrayObject); |
| } |
| |
| void ResponseBuilder::Dictionary::setBool(UIdent Key, bool Val) { |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), new SKDBool(Val)); |
| } |
| |
| ResponseBuilder::Dictionary |
| ResponseBuilder::Dictionary::setDictionary(UIdent Key) { |
| auto DictionaryObject = new SKDDictionary(); |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), DictionaryObject); |
| return Dictionary(DictionaryObject); |
| } |
| |
| void ResponseBuilder::Dictionary::setCustomBuffer( |
| SourceKit::UIdent Key, |
| CustomBufferKind Kind, std::unique_ptr<llvm::MemoryBuffer> MemBuf) { |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), |
| new SKDCustomData(Kind, MemBuf)); |
| } |
| |
| ResponseBuilder::Array |
| ResponseBuilder::Dictionary::setArray(UIdent Key) { |
| auto ArrayObject = new SKDArray(); |
| static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key), ArrayObject); |
| return Array(ArrayObject); |
| } |
| |
| ResponseBuilder::Dictionary ResponseBuilder::Array::appendDictionary() { |
| auto DictionaryObject = new SKDDictionary(); |
| static_cast<SKDObject *>(Impl)->set(SOURCEKITD_ARRAY_APPEND, DictionaryObject); |
| return Dictionary(DictionaryObject); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Internal RequestDict Implementation |
| //===----------------------------------------------------------------------===// |
| |
| sourcekitd_uid_t RequestDict::getUID(UIdent Key) { |
| auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key)); |
| return Object ? Object->getUID() : nullptr; |
| } |
| |
| Optional<StringRef> RequestDict::getString(UIdent Key) { |
| if (auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key))) { |
| return Object->getString(); |
| } |
| return None; |
| } |
| |
| Optional<RequestDict> RequestDict::getDictionary(SourceKit::UIdent Key) { |
| SKDDictionary *DictObject = nullptr; |
| if (auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key))) { |
| DictObject = dyn_cast<SKDDictionary>(Object); |
| } |
| return DictObject ? Optional<RequestDict>(RequestDict(DictObject)) : None; |
| } |
| |
| bool RequestDict::getStringArray(SourceKit::UIdent Key, |
| llvm::SmallVectorImpl<const char *> &Arr, |
| bool isOptional) { |
| auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key)); |
| if (!Object) |
| return !isOptional; |
| auto Array = dyn_cast<SKDArray>(Object); |
| if (!Array) |
| return true; |
| size_t count = Array->getCount(); |
| Arr.reserve(count); |
| for (size_t i = 0; i != count; ++i) { |
| auto Str = Array->get(i)->getCString(); |
| if (!Str) |
| return true; |
| Arr.push_back(Str); |
| } |
| return false; |
| } |
| |
| bool RequestDict::getUIDArray(SourceKit::UIdent Key, |
| llvm::SmallVectorImpl<sourcekitd_uid_t> &Arr, |
| bool isOptional) { |
| auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key)); |
| if (!Object) |
| return !isOptional; |
| auto Array = dyn_cast<SKDArray>(Object); |
| if (!Array) |
| return true; |
| size_t count = Array->getCount(); |
| Arr.reserve(count); |
| for (size_t i = 0; i != count; ++i) { |
| auto UID = Array->get(i)->getUID(); |
| if (!UID) |
| return true; |
| Arr.push_back(UID); |
| } |
| return false; |
| } |
| |
| bool RequestDict::dictionaryArrayApply( |
| SourceKit::UIdent Key, llvm::function_ref<bool(RequestDict)> Applier) { |
| auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key)); |
| if (!Object) |
| return true; |
| auto Array = dyn_cast<SKDArray>(Object); |
| if (!Array) |
| return true; |
| |
| return !Array->apply([&](size_t index, SKDObjectRef object){ |
| auto Dict = dyn_cast<SKDDictionary>(object); |
| if (!Dict) |
| return false; |
| return !Applier(RequestDict(Dict)); |
| }); |
| } |
| |
| bool RequestDict::getInt64(SourceKit::UIdent Key, int64_t &Val, |
| bool isOptional) { |
| auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key)); |
| if (!Object) |
| return !isOptional; |
| Val = Object->getInt64().getValueOr(0); |
| return false; |
| } |
| |
| Optional<int64_t> RequestDict::getOptionalInt64(SourceKit::UIdent Key) { |
| auto Object = static_cast<SKDObject *>(Dict)->get(SKDUIDFromUIdent(Key)); |
| if (!Object) |
| return None; |
| return Object->getInt64().getValueOr(0); |
| } |
| |
| sourcekitd_response_t |
| sourcekitd::createErrorRequestInvalid(const char *Description) { |
| return retained(new SKDError(SOURCEKITD_ERROR_REQUEST_INVALID, |
| StringRef(Description))); |
| } |
| |
| sourcekitd_response_t |
| sourcekitd::createErrorRequestFailed(const char *Description) { |
| return retained(new SKDError(SOURCEKITD_ERROR_REQUEST_FAILED, |
| StringRef(Description))); |
| } |
| |
| sourcekitd_response_t |
| sourcekitd::createErrorRequestCancelled() { |
| return retained(new SKDError(SOURCEKITD_ERROR_REQUEST_CANCELLED, |
| StringRef(""))); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Variant functions |
| //===----------------------------------------------------------------------===// |
| |
| #define SKD_OBJ(var) ((SKDObject *)(var).data[1]) |
| |
| static sourcekitd_variant_type_t SKDVar_get_type(sourcekitd_variant_t var) { |
| if (auto Object = SKD_OBJ(var)) { |
| return Object->getVariantType(); |
| } |
| llvm::report_fatal_error("sourcekitd object did not resolve to a known type"); |
| } |
| |
| static bool SKDVar_array_apply( |
| sourcekitd_variant_t array, |
| llvm::function_ref<bool(size_t, sourcekitd_variant_t)> applier) { |
| return dyn_cast<SKDArray>(SKD_OBJ(array))->apply([&](size_t Index, |
| SKDObjectRef Object){ |
| return applier(Index, variantFromSKDObject(Object)); |
| }); |
| } |
| |
| static bool SKDVar_array_get_bool(sourcekitd_variant_t array, size_t index) { |
| return SKD_OBJ(array)->get(index)->getBool(); |
| } |
| |
| static size_t SKDVar_array_get_count(sourcekitd_variant_t array) { |
| return SKD_OBJ(array)->getCount(); |
| } |
| |
| static int64_t SKDVar_array_get_int64(sourcekitd_variant_t array, size_t index) { |
| return SKD_OBJ(array)->get(index)->getInt64().getValueOr(0); |
| } |
| |
| static const char * |
| SKDVar_array_get_string(sourcekitd_variant_t array, size_t index) { |
| return SKD_OBJ(array)->get(index)->getCString(); |
| } |
| |
| static sourcekitd_uid_t SKDVar_array_get_uid(sourcekitd_variant_t array, |
| size_t index) { |
| return SKD_OBJ(array)->get(index)->getUID(); |
| } |
| |
| static sourcekitd_variant_t |
| SKDVar_array_get_value(sourcekitd_variant_t array, size_t index) { |
| return variantFromSKDObject(SKD_OBJ(array)->get(index)); |
| } |
| |
| static bool SKDVar_bool_get_value(sourcekitd_variant_t obj) { |
| return SKD_OBJ(obj)->getBool(); |
| } |
| |
| static bool SKDVar_dictionary_apply( |
| sourcekitd_variant_t dict, |
| llvm::function_ref<bool(sourcekitd_uid_t, sourcekitd_variant_t)> applier) { |
| return dyn_cast<SKDDictionary>(SKD_OBJ(dict))->apply([&](sourcekitd_uid_t Key, |
| SKDObjectRef Object){ |
| return applier(Key, variantFromSKDObject(Object)); |
| }); |
| } |
| |
| static bool |
| SKDVar_dictionary_get_bool(sourcekitd_variant_t dict, sourcekitd_uid_t key) { |
| if (auto Object = SKD_OBJ(dict)->get(key)) { |
| return Object->getBool(); |
| } |
| return false; |
| } |
| |
| static int64_t |
| SKDVar_dictionary_get_int64(sourcekitd_variant_t dict, sourcekitd_uid_t key) { |
| if (auto Object = SKD_OBJ(dict)->get(key)) { |
| return Object->getInt64().getValueOr(0); |
| } |
| return 0; |
| } |
| |
| static const char * |
| SKDVar_dictionary_get_string(sourcekitd_variant_t dict, sourcekitd_uid_t key) { |
| if (auto Object = SKD_OBJ(dict)->get(key)) { |
| return Object->getCString(); |
| } |
| return nullptr; |
| } |
| |
| static sourcekitd_variant_t |
| SKDVar_dictionary_get_value(sourcekitd_variant_t dict, sourcekitd_uid_t key) { |
| return variantFromSKDObject(SKD_OBJ(dict)->get(key)); |
| } |
| |
| static sourcekitd_uid_t |
| SKDVar_dictionary_get_uid(sourcekitd_variant_t dict, sourcekitd_uid_t key) { |
| if (auto Object = SKD_OBJ(dict)->get(key)) { |
| return Object->getUID(); |
| } |
| return nullptr; |
| } |
| |
| static size_t SKDVar_string_get_length(sourcekitd_variant_t obj) { |
| auto String = SKD_OBJ(obj)->getString(); |
| return String.hasValue() ? String->size() : 0; |
| } |
| |
| static const char *SKDVar_string_get_ptr(sourcekitd_variant_t obj) { |
| return SKD_OBJ(obj)->getCString(); |
| } |
| |
| static int64_t SKDVar_int64_get_value(sourcekitd_variant_t obj) { |
| return SKD_OBJ(obj)->getInt64().getValueOr(0); |
| } |
| |
| static sourcekitd_uid_t SKDVar_uid_get_value(sourcekitd_variant_t obj) { |
| return SKD_OBJ(obj)->getUID(); |
| } |
| |
| |
| static VariantFunctions SKDVariantFuncs = { |
| SKDVar_get_type, |
| SKDVar_array_apply, |
| SKDVar_array_get_bool, |
| SKDVar_array_get_count, |
| SKDVar_array_get_int64, |
| SKDVar_array_get_string, |
| SKDVar_array_get_uid, |
| SKDVar_array_get_value, |
| SKDVar_bool_get_value, |
| SKDVar_dictionary_apply, |
| SKDVar_dictionary_get_bool, |
| SKDVar_dictionary_get_int64, |
| SKDVar_dictionary_get_string, |
| SKDVar_dictionary_get_value, |
| SKDVar_dictionary_get_uid, |
| SKDVar_string_get_length, |
| SKDVar_string_get_ptr, |
| SKDVar_int64_get_value, |
| SKDVar_uid_get_value |
| }; |
| |
| static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object) { |
| if (!Object) |
| return makeNullVariant(); |
| |
| if (auto DataObject = dyn_cast<SKDCustomData>(Object)) { |
| switch(DataObject->getBufferKind()) { |
| case CustomBufferKind::TokenAnnotationsArray: |
| return {{ (uintptr_t)getVariantFunctionsForTokenAnnotationsArray(), |
| (uintptr_t)DataObject->getDataPtr(), 0 }}; |
| case CustomBufferKind::DocSupportAnnotationArray: |
| return {{ (uintptr_t)getVariantFunctionsForDocSupportAnnotationArray(), |
| (uintptr_t)DataObject->getDataPtr(), 0 }}; |
| case CustomBufferKind::CodeCompletionResultsArray: |
| return {{ (uintptr_t)getVariantFunctionsForCodeCompletionResultsArray(), |
| (uintptr_t)DataObject->getDataPtr(), 0 }}; |
| case CustomBufferKind::DocStructureArray: |
| return {{ (uintptr_t)getVariantFunctionsForDocStructureArray(), |
| (uintptr_t)DataObject->getDataPtr(), ~size_t(0) }}; |
| case CustomBufferKind::InheritedTypesArray: |
| return {{ (uintptr_t)getVariantFunctionsForInheritedTypesArray(), |
| (uintptr_t)DataObject->getDataPtr(), 0 }}; |
| case CustomBufferKind::DocStructureElementArray: |
| return {{ (uintptr_t)getVariantFunctionsForDocStructureElementArray(), |
| (uintptr_t)DataObject->getDataPtr(), 0 }}; |
| case CustomBufferKind::AttributesArray: |
| return {{ (uintptr_t)getVariantFunctionsForAttributesArray(), |
| (uintptr_t)DataObject->getDataPtr(), 0 }}; |
| } |
| } |
| |
| return {{ (uintptr_t)&SKDVariantFuncs, (uintptr_t)Object.get(), 0 }}; |
| } |