File indexing completed on 2024-05-12 04:37:57
0001 /* 0002 SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de> 0003 SPDX-FileCopyrightText: 2014 Kevin Funk <kfunk@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "definitions.h" 0009 0010 #include "appendedlist.h" 0011 #include "declaration.h" 0012 #include "declarationid.h" 0013 #include "duchainpointer.h" 0014 #include <serialization/indexedstring.h> 0015 #include "serialization/itemrepository.h" 0016 0017 namespace KDevelop { 0018 DEFINE_LIST_MEMBER_HASH(DefinitionsItem, definitions, IndexedDeclaration) 0019 0020 class DefinitionsItem 0021 { 0022 public: 0023 DefinitionsItem() 0024 { 0025 initializeAppendedLists(); 0026 } 0027 DefinitionsItem(const DefinitionsItem& rhs, bool dynamic = true) : declaration(rhs.declaration) 0028 { 0029 initializeAppendedLists(dynamic); 0030 copyListsFrom(rhs); 0031 } 0032 0033 ~DefinitionsItem() 0034 { 0035 freeAppendedLists(); 0036 } 0037 0038 DefinitionsItem& operator=(const DefinitionsItem& rhs) = delete; 0039 0040 unsigned int hash() const 0041 { 0042 //We only compare the declaration. This allows us implementing a map, although the item-repository 0043 //originally represents a set. 0044 return declaration.hash(); 0045 } 0046 0047 unsigned int itemSize() const 0048 { 0049 return dynamicSize(); 0050 } 0051 0052 uint classSize() const 0053 { 0054 return sizeof(DefinitionsItem); 0055 } 0056 0057 DeclarationId declaration; 0058 0059 START_APPENDED_LISTS(DefinitionsItem); 0060 APPENDED_LIST_FIRST(DefinitionsItem, IndexedDeclaration, definitions); 0061 END_APPENDED_LISTS(DefinitionsItem, definitions); 0062 }; 0063 0064 class DefinitionsRequestItem 0065 { 0066 public: 0067 0068 DefinitionsRequestItem(const DefinitionsItem& item) : m_item(item) 0069 { 0070 } 0071 enum { 0072 AverageSize = 30 //This should be the approximate average size of an Item 0073 }; 0074 0075 unsigned int hash() const 0076 { 0077 return m_item.hash(); 0078 } 0079 0080 uint itemSize() const 0081 { 0082 return m_item.itemSize(); 0083 } 0084 0085 void createItem(DefinitionsItem* item) const 0086 { 0087 new (item) DefinitionsItem(m_item, false); 0088 } 0089 0090 static void destroy(DefinitionsItem* item, KDevelop::AbstractItemRepository&) 0091 { 0092 item->~DefinitionsItem(); 0093 } 0094 0095 static bool persistent(const DefinitionsItem*) 0096 { 0097 return true; 0098 } 0099 0100 bool equals(const DefinitionsItem* item) const 0101 { 0102 return m_item.declaration == item->declaration; 0103 } 0104 0105 const DefinitionsItem& m_item; 0106 }; 0107 0108 class DefinitionsVisitor 0109 { 0110 public: 0111 DefinitionsVisitor(Definitions* _definitions, const QTextStream& _out) 0112 : definitions(_definitions) 0113 , out(_out) 0114 { 0115 } 0116 0117 bool operator()(const DefinitionsItem* item) 0118 { 0119 QDebug qout(out.device()); 0120 auto id = item->declaration; 0121 const auto allDefinitions = definitions->definitions(id); 0122 0123 qout << "Definitions for" << id.qualifiedIdentifier() << Qt::endl; 0124 for (const IndexedDeclaration& decl : allDefinitions) { 0125 if (decl.data()) { 0126 qout << " " << decl.data()->qualifiedIdentifier() << "in" << decl.data()->url().byteArray() << "at" 0127 << decl.data()->rangeInCurrentRevision() << Qt::endl; 0128 } 0129 } 0130 0131 return true; 0132 } 0133 0134 private: 0135 const Definitions* definitions; 0136 const QTextStream& out; 0137 }; 0138 0139 // Maps declaration-ids to definitions 0140 using DefinitionsRepo = ItemRepository<DefinitionsItem, DefinitionsRequestItem>; 0141 0142 template<> 0143 class ItemRepositoryFor<Definitions> 0144 { 0145 friend struct LockedItemRepository; 0146 static DefinitionsRepo& repo() 0147 { 0148 static QMutex mutex; 0149 static DefinitionsRepo repo { QStringLiteral("Definition Map"), &mutex }; 0150 return repo; 0151 } 0152 }; 0153 0154 Definitions::Definitions() 0155 { 0156 LockedItemRepository::initialize<Definitions>(); 0157 } 0158 0159 void Definitions::addDefinition(const DeclarationId& id, const IndexedDeclaration& definition) 0160 { 0161 DefinitionsItem item; 0162 item.declaration = id; 0163 item.definitionsList().append(definition); 0164 DefinitionsRequestItem request(item); 0165 0166 LockedItemRepository::write<Definitions>([&](DefinitionsRepo& repo) { 0167 uint index = repo.findIndex(item); 0168 0169 if (index) { 0170 // Check whether the item is already in the mapped list, else copy the list into the new created item 0171 const DefinitionsItem* oldItem = repo.itemFromIndex(index); 0172 for (unsigned int a = 0; a < oldItem->definitionsSize(); ++a) { 0173 if (oldItem->definitions()[a] == definition) 0174 return; // Already there 0175 item.definitionsList().append(oldItem->definitions()[a]); 0176 } 0177 0178 repo.deleteItem(index); 0179 } 0180 0181 // This inserts the changed item 0182 repo.index(request); 0183 }); 0184 } 0185 0186 void Definitions::removeDefinition(const DeclarationId& id, const IndexedDeclaration& definition) 0187 { 0188 DefinitionsItem item; 0189 item.declaration = id; 0190 DefinitionsRequestItem request(item); 0191 0192 LockedItemRepository::write<Definitions>([&](DefinitionsRepo& repo) { 0193 uint index = repo.findIndex(item); 0194 0195 if (index) { 0196 // Check whether the item is already in the mapped list, else copy the list into the new created item 0197 const DefinitionsItem* oldItem = repo.itemFromIndex(index); 0198 for (unsigned int a = 0; a < oldItem->definitionsSize(); ++a) 0199 if (!(oldItem->definitions()[a] == definition)) 0200 item.definitionsList().append(oldItem->definitions()[a]); 0201 0202 repo.deleteItem(index); 0203 Q_ASSERT(repo.findIndex(item) == 0); 0204 0205 // This inserts the changed item 0206 if (item.definitionsSize() != 0) 0207 repo.index(request); 0208 } 0209 }); 0210 } 0211 0212 KDevVarLengthArray<IndexedDeclaration> Definitions::definitions(const DeclarationId& id) const 0213 { 0214 KDevVarLengthArray<IndexedDeclaration> ret; 0215 0216 DefinitionsItem item; 0217 item.declaration = id; 0218 DefinitionsRequestItem request(item); 0219 0220 LockedItemRepository::read<Definitions>([&](const DefinitionsRepo& repo) { 0221 uint index = repo.findIndex(item); 0222 0223 if (index) { 0224 const DefinitionsItem* repositoryItem = repo.itemFromIndex(index); 0225 FOREACH_FUNCTION(const IndexedDeclaration& decl, repositoryItem->definitions) 0226 ret.append(decl); 0227 } 0228 }); 0229 0230 return ret; 0231 } 0232 0233 void Definitions::dump(const QTextStream& out) 0234 { 0235 DefinitionsVisitor v(this, out); 0236 LockedItemRepository::read<Definitions>([&](const DefinitionsRepo& repo) { 0237 repo.visitAllItems(v); 0238 }); 0239 } 0240 }