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 }