| //===--- TokenAnnotationsArray.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 "sourcekitd/TokenAnnotationsArray.h" |
| #include "sourcekitd/CompactArray.h" |
| #include "SourceKit/Core/LLVM.h" |
| #include "SourceKit/Support/UIdent.h" |
| #include "DictionaryKeys.h" |
| |
| #include "llvm/Support/MemoryBuffer.h" |
| |
| using namespace SourceKit; |
| using namespace sourcekitd; |
| |
| struct TokenAnnotationsArrayBuilder::Implementation { |
| CompactArrayBuilder<UIdent, |
| unsigned, |
| unsigned> Builder; |
| }; |
| |
| TokenAnnotationsArrayBuilder::TokenAnnotationsArrayBuilder() |
| : Impl(*new Implementation()) { |
| |
| } |
| |
| TokenAnnotationsArrayBuilder::~TokenAnnotationsArrayBuilder() { |
| delete &Impl; |
| } |
| |
| void TokenAnnotationsArrayBuilder::add( |
| UIdent Kind, |
| unsigned Offset, |
| unsigned Length, |
| bool IsSystem) { |
| |
| assert(Length <= (unsigned(-1) >> 1)); |
| unsigned LengthAndIsSystem = (Length << 1) | IsSystem; |
| Impl.Builder.addEntry(Kind, |
| Offset, |
| LengthAndIsSystem); |
| } |
| |
| bool TokenAnnotationsArrayBuilder::empty() const { |
| return Impl.Builder.empty(); |
| } |
| |
| std::unique_ptr<llvm::MemoryBuffer> |
| TokenAnnotationsArrayBuilder::createBuffer() { |
| return Impl.Builder.createBuffer(CustomBufferKind::TokenAnnotationsArray); |
| } |
| |
| namespace { |
| |
| class TokenAnnotationsArray { |
| public: |
| typedef CompactArrayReader<sourcekitd_uid_t, |
| unsigned, |
| unsigned> CompactArrayReaderTy; |
| |
| static void readElements(void *Buf, size_t Index, |
| sourcekitd_uid_t &Kind, |
| unsigned &Offset, |
| unsigned &Length, |
| bool &IsSystem) { |
| CompactArrayReaderTy Reader(Buf); |
| unsigned LengthAndIsSystem; |
| Reader.readEntries(Index, |
| Kind, |
| Offset, |
| LengthAndIsSystem); |
| Length = LengthAndIsSystem >> 1; |
| IsSystem = LengthAndIsSystem & 0x1; |
| } |
| |
| static bool apply(sourcekitd_uid_t Kind, |
| unsigned Offset, |
| unsigned Length, |
| bool IsSystem, |
| llvm::function_ref<bool(sourcekitd_uid_t, |
| sourcekitd_variant_t)> applier) { |
| |
| #define APPLY(K, Ty, Field) \ |
| do { \ |
| sourcekitd_uid_t key = SKDUIDFromUIdent(K); \ |
| sourcekitd_variant_t var = make##Ty##Variant(Field); \ |
| if (!applier(key, var)) return false; \ |
| } while (0) |
| |
| APPLY(KeyKind, UID, Kind); |
| APPLY(KeyOffset, Int, Offset); |
| APPLY(KeyLength, Int, Length); |
| if (IsSystem) |
| APPLY(KeyIsSystem, Bool, IsSystem); |
| |
| return true; |
| } |
| |
| static bool getBool(sourcekitd_uid_t Key, |
| sourcekitd_uid_t Kind, |
| unsigned Offset, |
| unsigned Length, |
| bool IsSystem) { |
| if (Key == SKDUIDFromUIdent(KeyIsSystem)) |
| return IsSystem; |
| return false; |
| } |
| |
| static int64_t getInt(sourcekitd_uid_t Key, |
| sourcekitd_uid_t Kind, |
| unsigned Offset, |
| unsigned Length, |
| bool IsSystem) { |
| if (Key == SKDUIDFromUIdent(KeyOffset)) |
| return Offset; |
| if (Key == SKDUIDFromUIdent(KeyLength)) |
| return Length; |
| return 0; |
| } |
| |
| static sourcekitd_uid_t getUID(sourcekitd_uid_t Key, |
| sourcekitd_uid_t Kind, |
| unsigned Offset, |
| unsigned Length, |
| bool IsSystem) { |
| if (Key == SKDUIDFromUIdent(KeyKind)) |
| return Kind; |
| return nullptr; |
| } |
| }; |
| |
| } // end anonymous namespace |
| |
| namespace sourcekitd { |
| |
| template <> |
| struct CompactVariantFuncs<TokenAnnotationsArray> { |
| static sourcekitd_variant_type_t get_type(sourcekitd_variant_t var) { |
| return SOURCEKITD_VARIANT_TYPE_DICTIONARY; |
| } |
| |
| template <typename FnTy> |
| static auto getElement(sourcekitd_variant_t dict, sourcekitd_uid_t key, |
| const FnTy &Fn) -> decltype(Fn(nullptr, nullptr, 0, 0, false)) { |
| void *Buf = (void*)dict.data[1]; |
| size_t Index = dict.data[2]; |
| |
| sourcekitd_uid_t Kind; |
| unsigned Offset; |
| unsigned Length; |
| bool IsSystem; |
| TokenAnnotationsArray::readElements(Buf, Index, |
| Kind, Offset, Length, IsSystem); |
| |
| return Fn(key, Kind, Offset, Length, IsSystem); |
| } |
| |
| static bool |
| dictionary_apply(sourcekitd_variant_t dict, |
| llvm::function_ref<bool(sourcekitd_uid_t, |
| sourcekitd_variant_t)> applier) { |
| void *Buf = (void*)dict.data[1]; |
| size_t Index = dict.data[2]; |
| |
| sourcekitd_uid_t Kind; |
| unsigned Offset; |
| unsigned Length; |
| bool IsSystem; |
| TokenAnnotationsArray::readElements(Buf, Index, |
| Kind, Offset, Length, IsSystem); |
| return TokenAnnotationsArray::apply(Kind, Offset, Length, IsSystem, applier); |
| } |
| |
| static bool dictionary_get_bool(sourcekitd_variant_t dict, |
| sourcekitd_uid_t key) { |
| return getElement(dict, key, TokenAnnotationsArray::getBool); |
| } |
| |
| static int64_t dictionary_get_int64(sourcekitd_variant_t dict, |
| sourcekitd_uid_t key) { |
| |
| return getElement(dict, key, TokenAnnotationsArray::getInt); |
| } |
| |
| static sourcekitd_uid_t dictionary_get_uid(sourcekitd_variant_t dict, |
| sourcekitd_uid_t key) { |
| |
| return getElement(dict, key, TokenAnnotationsArray::getUID); |
| } |
| |
| static VariantFunctions Funcs; |
| }; |
| |
| VariantFunctions CompactVariantFuncs<TokenAnnotationsArray>::Funcs = { |
| get_type, |
| nullptr/*Annot_array_apply*/, |
| nullptr/*Annot_array_get_bool*/, |
| nullptr/*Annot_array_get_count*/, |
| nullptr/*Annot_array_get_int64*/, |
| nullptr/*Annot_array_get_string*/, |
| nullptr/*Annot_array_get_uid*/, |
| nullptr/*Annot_array_get_value*/, |
| nullptr/*Annot_bool_get_value*/, |
| dictionary_apply, |
| dictionary_get_bool, |
| dictionary_get_int64, |
| nullptr/*Annot_dictionary_get_string*/, |
| nullptr/*Annot_dictionary_get_value*/, |
| dictionary_get_uid, |
| nullptr/*Annot_string_get_length*/, |
| nullptr/*Annot_string_get_ptr*/, |
| nullptr/*Annot_int64_get_value*/, |
| nullptr/*Annot_uid_get_value*/, |
| nullptr/*Annot_data_get_size*/, |
| nullptr/*Annot_data_get_ptr*/, |
| }; |
| |
| } // namespace sourcekitd |
| |
| VariantFunctions * |
| sourcekitd::getVariantFunctionsForTokenAnnotationsArray() { |
| return &CompactArrayFuncs<TokenAnnotationsArray>::Funcs; |
| } |