File indexing completed on 2024-05-12 04:38:02
0001 /* 0002 SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "importers.h" 0008 0009 #include "declarationid.h" 0010 #include "duchainpointer.h" 0011 #include "serialization/itemrepository.h" 0012 #include "topducontext.h" 0013 0014 namespace KDevelop { 0015 DEFINE_LIST_MEMBER_HASH(ImportersItem, importers, IndexedDUContext) 0016 0017 class ImportersItem 0018 { 0019 public: 0020 ImportersItem() 0021 { 0022 initializeAppendedLists(); 0023 } 0024 ImportersItem(const ImportersItem& rhs, bool dynamic = true) : declaration(rhs.declaration) 0025 { 0026 initializeAppendedLists(dynamic); 0027 copyListsFrom(rhs); 0028 } 0029 0030 ~ImportersItem() 0031 { 0032 freeAppendedLists(); 0033 } 0034 0035 ImportersItem& operator=(const ImportersItem& rhs) = delete; 0036 0037 unsigned int hash() const 0038 { 0039 //We only compare the declaration. This allows us implementing a map, although the item-repository 0040 //originally represents a set. 0041 return declaration.hash(); 0042 } 0043 0044 unsigned int itemSize() const 0045 { 0046 return dynamicSize(); 0047 } 0048 0049 uint classSize() const 0050 { 0051 return sizeof(ImportersItem); 0052 } 0053 0054 DeclarationId declaration; 0055 0056 START_APPENDED_LISTS(ImportersItem); 0057 APPENDED_LIST_FIRST(ImportersItem, IndexedDUContext, importers); 0058 END_APPENDED_LISTS(ImportersItem, importers); 0059 }; 0060 0061 class ImportersRequestItem 0062 { 0063 public: 0064 0065 ImportersRequestItem(const ImportersItem& item) : m_item(item) 0066 { 0067 } 0068 enum { 0069 AverageSize = 30 //This should be the approximate average size of an Item 0070 }; 0071 0072 unsigned int hash() const 0073 { 0074 return m_item.hash(); 0075 } 0076 0077 uint itemSize() const 0078 { 0079 return m_item.itemSize(); 0080 } 0081 0082 void createItem(ImportersItem* item) const 0083 { 0084 new (item) ImportersItem(m_item, false); 0085 } 0086 0087 static void destroy(ImportersItem* item, KDevelop::AbstractItemRepository&) 0088 { 0089 item->~ImportersItem(); 0090 } 0091 0092 static bool persistent(const ImportersItem* /*item*/) 0093 { 0094 return true; 0095 } 0096 0097 bool equals(const ImportersItem* item) const 0098 { 0099 return m_item.declaration == item->declaration; 0100 } 0101 0102 const ImportersItem& m_item; 0103 }; 0104 0105 // Maps declaration-ids to Importers 0106 using ImportersRepo = ItemRepository<ImportersItem, ImportersRequestItem>; 0107 0108 template<> 0109 class ItemRepositoryFor<Importers> 0110 { 0111 friend struct LockedItemRepository; 0112 static ImportersRepo& repo() 0113 { 0114 static QMutex mutex; 0115 static ImportersRepo repo { QStringLiteral("Importer Map"), &mutex }; 0116 return repo; 0117 } 0118 }; 0119 0120 Importers::Importers() 0121 { 0122 LockedItemRepository::initialize<Importers>(); 0123 } 0124 0125 void Importers::addImporter(const DeclarationId& id, const IndexedDUContext& use) 0126 { 0127 ImportersItem item; 0128 item.declaration = id; 0129 item.importersList().append(use); 0130 ImportersRequestItem request(item); 0131 0132 LockedItemRepository::write<Importers>([&](ImportersRepo& repo) { 0133 uint index = repo.findIndex(item); 0134 0135 if (index) { 0136 // Check whether the item is already in the mapped list, else copy the list into the new created item 0137 const ImportersItem* oldItem = repo.itemFromIndex(index); 0138 for (unsigned int a = 0; a < oldItem->importersSize(); ++a) { 0139 if (oldItem->importers()[a] == use) 0140 return; // Already there 0141 item.importersList().append(oldItem->importers()[a]); 0142 } 0143 0144 repo.deleteItem(index); 0145 } 0146 0147 // This inserts the changed item 0148 repo.index(request); 0149 }); 0150 } 0151 0152 void Importers::removeImporter(const DeclarationId& id, const IndexedDUContext& use) 0153 { 0154 ImportersItem item; 0155 item.declaration = id; 0156 ImportersRequestItem request(item); 0157 0158 LockedItemRepository::write<Importers>([&](ImportersRepo& repo) { 0159 uint index = repo.findIndex(item); 0160 0161 if (index) { 0162 // Check whether the item is already in the mapped list, else copy the list into the new created item 0163 const ImportersItem* oldItem = repo.itemFromIndex(index); 0164 for (unsigned int a = 0; a < oldItem->importersSize(); ++a) 0165 if (!(oldItem->importers()[a] == use)) 0166 item.importersList().append(oldItem->importers()[a]); 0167 0168 repo.deleteItem(index); 0169 Q_ASSERT(repo.findIndex(item) == 0); 0170 0171 // This inserts the changed item 0172 if (item.importersSize() != 0) 0173 repo.index(request); 0174 } 0175 }); 0176 } 0177 0178 KDevVarLengthArray<IndexedDUContext> Importers::importers(const DeclarationId& id) const 0179 { 0180 KDevVarLengthArray<IndexedDUContext> ret; 0181 0182 ImportersItem item; 0183 item.declaration = id; 0184 ImportersRequestItem request(item); 0185 0186 LockedItemRepository::read<Importers>([&](const ImportersRepo& repo) { 0187 uint index = repo.findIndex(item); 0188 0189 if (index) { 0190 const ImportersItem* repositoryItem = repo.itemFromIndex(index); 0191 FOREACH_FUNCTION(const IndexedDUContext& decl, repositoryItem->importers) 0192 ret.append(decl); 0193 } 0194 }); 0195 0196 return ret; 0197 } 0198 0199 Importers& Importers::self() 0200 { 0201 static Importers globalImporters; 0202 return globalImporters; 0203 } 0204 }