File indexing completed on 2024-05-12 04:38:05
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 "uses.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(UsesItem, uses, IndexedTopDUContext) 0016 0017 class UsesItem 0018 { 0019 public: 0020 UsesItem() 0021 { 0022 initializeAppendedLists(); 0023 } 0024 UsesItem(const UsesItem& rhs, bool dynamic = true) : declaration(rhs.declaration) 0025 { 0026 initializeAppendedLists(dynamic); 0027 copyListsFrom(rhs); 0028 } 0029 0030 ~UsesItem() 0031 { 0032 freeAppendedLists(); 0033 } 0034 0035 UsesItem& operator=(const UsesItem& 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(UsesItem); 0052 } 0053 0054 DeclarationId declaration; 0055 0056 START_APPENDED_LISTS(UsesItem); 0057 APPENDED_LIST_FIRST(UsesItem, IndexedTopDUContext, uses); 0058 END_APPENDED_LISTS(UsesItem, uses); 0059 }; 0060 0061 class UsesRequestItem 0062 { 0063 public: 0064 0065 UsesRequestItem(const UsesItem& 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(UsesItem* item) const 0083 { 0084 new (item) UsesItem(m_item, false); 0085 } 0086 0087 static void destroy(UsesItem* item, KDevelop::AbstractItemRepository&) 0088 { 0089 item->~UsesItem(); 0090 } 0091 0092 static bool persistent(const UsesItem* /*item*/) 0093 { 0094 return true; 0095 } 0096 0097 bool equals(const UsesItem* item) const 0098 { 0099 return m_item.declaration == item->declaration; 0100 } 0101 0102 const UsesItem& m_item; 0103 }; 0104 0105 // Maps declaration-ids to Uses 0106 using UsesRepo = ItemRepository<UsesItem, UsesRequestItem>; 0107 template<> 0108 class ItemRepositoryFor<Uses> 0109 { 0110 friend struct LockedItemRepository; 0111 static UsesRepo& repo() 0112 { 0113 static QMutex mutex; 0114 static UsesRepo repo { QStringLiteral("Use Map"), &mutex }; 0115 return repo; 0116 } 0117 }; 0118 0119 Uses::Uses() 0120 { 0121 LockedItemRepository::initialize<Uses>(); 0122 } 0123 0124 void Uses::addUse(const DeclarationId& id, const IndexedTopDUContext& use) 0125 { 0126 UsesItem item; 0127 item.declaration = id; 0128 item.usesList().append(use); 0129 UsesRequestItem request(item); 0130 0131 LockedItemRepository::write<Uses>([&](UsesRepo& repo) { 0132 uint index = repo.findIndex(item); 0133 0134 if (index) { 0135 // Check whether the item is already in the mapped list, else copy the list into the new created item 0136 const UsesItem* oldItem = repo.itemFromIndex(index); 0137 for (unsigned int a = 0; a < oldItem->usesSize(); ++a) { 0138 if (oldItem->uses()[a] == use) 0139 return; // Already there 0140 item.usesList().append(oldItem->uses()[a]); 0141 } 0142 0143 repo.deleteItem(index); 0144 } 0145 0146 // This inserts the changed item 0147 repo.index(request); 0148 }); 0149 } 0150 0151 void Uses::removeUse(const DeclarationId& id, const IndexedTopDUContext& use) 0152 { 0153 UsesItem item; 0154 item.declaration = id; 0155 UsesRequestItem request(item); 0156 0157 LockedItemRepository::write<Uses>([&](UsesRepo& repo) { 0158 uint index = repo.findIndex(item); 0159 0160 if (index) { 0161 // Check whether the item is already in the mapped list, else copy the list into the new created item 0162 const UsesItem* oldItem = repo.itemFromIndex(index); 0163 for (unsigned int a = 0; a < oldItem->usesSize(); ++a) 0164 if (!(oldItem->uses()[a] == use)) 0165 item.usesList().append(oldItem->uses()[a]); 0166 0167 repo.deleteItem(index); 0168 Q_ASSERT(repo.findIndex(item) == 0); 0169 0170 // This inserts the changed item 0171 if (item.usesSize() != 0) 0172 repo.index(request); 0173 } 0174 }); 0175 } 0176 0177 bool Uses::hasUses(const DeclarationId& id) const 0178 { 0179 UsesItem item; 0180 item.declaration = id; 0181 0182 return LockedItemRepository::read<Uses>([&item](const UsesRepo& repo) { 0183 return static_cast<bool>(repo.findIndex(item)); 0184 }); 0185 } 0186 0187 KDevVarLengthArray<IndexedTopDUContext> Uses::uses(const DeclarationId& id) const 0188 { 0189 KDevVarLengthArray<IndexedTopDUContext> ret; 0190 0191 UsesItem item; 0192 item.declaration = id; 0193 UsesRequestItem request(item); 0194 0195 LockedItemRepository::read<Uses>([&](const UsesRepo& repo) { 0196 uint index = repo.findIndex(item); 0197 0198 if (index) { 0199 const UsesItem* repositoryItem = repo.itemFromIndex(index); 0200 FOREACH_FUNCTION(const IndexedTopDUContext& decl, repositoryItem->uses) 0201 ret.append(decl); 0202 } 0203 }); 0204 0205 return ret; 0206 } 0207 }