File indexing completed on 2024-05-12 04:38:03

0001 /*
0002     SPDX-FileCopyrightText: 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "instantiationinformation.h"
0008 #include "identifier.h"
0009 #include "serialization/itemrepository.h"
0010 #include "serialization/itemrepositoryreferencecounting.h"
0011 #include <serialization/repositorymanager.h>
0012 #include "types/typeutils.h"
0013 #include <typeinfo>
0014 #include "types/typealiastype.h"
0015 #include "types/typerepository.h"
0016 
0017 namespace KDevelop {
0018 DEFINE_LIST_MEMBER_HASH(InstantiationInformation, templateParameters, IndexedType)
0019 
0020 QualifiedIdentifier InstantiationInformation::applyToIdentifier(const QualifiedIdentifier& id) const
0021 {
0022     QualifiedIdentifier ret;
0023     if (id.count() > 1) {
0024         ret = id;
0025         ret.pop();
0026         if (previousInstantiationInformation.index())
0027             ret = previousInstantiationInformation.information().applyToIdentifier(ret);
0028     }
0029 
0030     Identifier lastId(id.last());
0031 
0032     KDevVarLengthArray<IndexedTypeIdentifier> oldTemplateIdentifiers;
0033     for (uint a = 0; a < lastId.templateIdentifiersCount(); ++a)
0034         oldTemplateIdentifiers.append(lastId.templateIdentifier(a));
0035 
0036     lastId.clearTemplateIdentifiers();
0037 
0038     for (uint a = 0; a < templateParametersSize(); ++a) {
0039         if (templateParameters()[a].abstractType()) {
0040             lastId.appendTemplateIdentifier(IndexedTypeIdentifier(templateParameters()[a].abstractType()->toString(),
0041                                                                   true));
0042         } else {
0043             lastId.appendTemplateIdentifier(
0044                 ( uint ) oldTemplateIdentifiers.size() > a ? oldTemplateIdentifiers[a] : IndexedTypeIdentifier());
0045         }
0046     }
0047 
0048     for (int a = templateParametersSize(); a < oldTemplateIdentifiers.size(); ++a)
0049         lastId.appendTemplateIdentifier(oldTemplateIdentifiers[a]);
0050 
0051     ret.push(lastId);
0052     return ret;
0053 }
0054 
0055 void InstantiationInformation::addTemplateParameter(const KDevelop::AbstractType::Ptr& type)
0056 {
0057     templateParametersList().append(IndexedType(type));
0058 }
0059 
0060 QString InstantiationInformation::toString(bool local) const
0061 {
0062     QString ret;
0063     if (previousInstantiationInformation.index() && !local)
0064         ret = previousInstantiationInformation.information().toString() + QLatin1String("::");
0065     ret += QLatin1Char('<');
0066     QStringList types;
0067     types.reserve(templateParametersSize());
0068     for (uint a = 0; a < templateParametersSize(); ++a) {
0069         if (templateParameters()[a].abstractType())
0070             types.append(templateParameters()[a].abstractType()->toString());
0071         else
0072             // TODO: what should be here instead?
0073             types.append(QString());
0074     }
0075 
0076     ret += QLatin1Char('<') + types.join(QLatin1String(", ")) + QLatin1Char('>');
0077     return ret;
0078 }
0079 
0080 InstantiationInformation::InstantiationInformation() : m_refCount(0)
0081 {
0082     initializeAppendedLists();
0083 }
0084 
0085 InstantiationInformation::InstantiationInformation(const InstantiationInformation& rhs,
0086                                                    bool dynamic) : previousInstantiationInformation(
0087         rhs.previousInstantiationInformation)
0088     , m_refCount(0)
0089 {
0090     initializeAppendedLists(dynamic);
0091     copyListsFrom(rhs);
0092 }
0093 
0094 InstantiationInformation::~InstantiationInformation()
0095 {
0096     freeAppendedLists();
0097 }
0098 
0099 InstantiationInformation& InstantiationInformation::operator=(const InstantiationInformation& rhs)
0100 {
0101     previousInstantiationInformation = rhs.previousInstantiationInformation;
0102     copyListsFrom(rhs);
0103     return *this;
0104 }
0105 
0106 bool InstantiationInformation::operator==(const InstantiationInformation& rhs) const
0107 {
0108     if (!(previousInstantiationInformation == rhs.previousInstantiationInformation))
0109         return false;
0110     return listsEqual(rhs);
0111 }
0112 
0113 uint InstantiationInformation::hash() const
0114 {
0115     KDevHash kdevhash;
0116     FOREACH_FUNCTION(const IndexedType &param, templateParameters) {
0117         kdevhash << param.hash();
0118     }
0119     return kdevhash << previousInstantiationInformation.index();
0120 }
0121 
0122 using InstantiationInformationRepository
0123     = ItemRepository<InstantiationInformation, AppendedListItemRequest<InstantiationInformation>, true,
0124                      QRecursiveMutex>;
0125 using InstantiationInformationRepositoryManager = RepositoryManager<InstantiationInformationRepository>;
0126 
0127 template <>
0128 class ItemRepositoryFor<IndexedInstantiationInformation>
0129 {
0130     friend struct LockedItemRepository;
0131     static InstantiationInformationRepository& repo()
0132     {
0133         static InstantiationInformationRepositoryManager manager(QStringLiteral("Instantiation Information Repository"),
0134                                                                  typeRepositoryMutex());
0135         return *manager.repository();
0136     }
0137 };
0138 
0139 uint standardInstantiationInformationIndex()
0140 {
0141     static uint idx = LockedItemRepository::write<IndexedInstantiationInformation>(
0142         [standardInstantiationInformation = InstantiationInformation()](InstantiationInformationRepository& repo) {
0143             return repo.index(standardInstantiationInformation);
0144         });
0145     return idx;
0146 }
0147 
0148 void initInstantiationInformationRepository()
0149 {
0150     standardInstantiationInformationIndex();
0151 }
0152 
0153 IndexedInstantiationInformation::IndexedInstantiationInformation(uint index) : m_index(index)
0154 {
0155     if (m_index == standardInstantiationInformationIndex())
0156         m_index = 0;
0157 
0158     if (m_index) {
0159         ItemRepositoryReferenceCounting::inc(this);
0160     }
0161 }
0162 
0163 // NOTE: the definitions of ItemRepositoryReferenceCounting's inc(), dec() and setIndex() are so
0164 // complex that they can throw exceptions for many reasons. Yet some special member functions of
0165 // IndexedInstantiationInformation, which call them, are implicitly (the destructor) or explicitly
0166 // noexcept. The noexcept-ness of these functions is important for correctness and performance.
0167 // This is safe at the moment, because the entire KDevPlatformLanguage library, that contains
0168 // IndexedInstantiationInformation, is compiled with exceptions disabled (-fno-exceptions), which
0169 // already prevents exception propagation to a caller of any non-inline function in this library.
0170 
0171 IndexedInstantiationInformation::IndexedInstantiationInformation(const IndexedInstantiationInformation& rhs) noexcept
0172     : m_index(rhs.m_index)
0173 {
0174     if (m_index) {
0175         ItemRepositoryReferenceCounting::inc(this);
0176     }
0177 }
0178 
0179 IndexedInstantiationInformation& IndexedInstantiationInformation::operator=(const IndexedInstantiationInformation& rhs) noexcept
0180 {
0181     const auto checkIndex = [](unsigned int index) { return index != 0; };
0182     ItemRepositoryReferenceCounting::setIndex(this, m_index, rhs.m_index, checkIndex);
0183     return *this;
0184 }
0185 
0186 IndexedInstantiationInformation::~IndexedInstantiationInformation()
0187 {
0188     if (m_index) {
0189         ItemRepositoryReferenceCounting::dec(this);
0190     }
0191 }
0192 
0193 bool IndexedInstantiationInformation::isValid() const
0194 {
0195     return m_index;
0196 }
0197 
0198 const InstantiationInformation& IndexedInstantiationInformation::information() const
0199 {
0200     auto index = m_index ? m_index : standardInstantiationInformationIndex();
0201     // TODO: it's probably unsafe to return the const& here, as the repo won't be locked during access anymore
0202     return *LockedItemRepository::read<IndexedInstantiationInformation>(
0203         [index](const InstantiationInformationRepository& repo) { return repo.itemFromIndex(index); });
0204 }
0205 
0206 IndexedInstantiationInformation InstantiationInformation::indexed() const
0207 {
0208     auto index = LockedItemRepository::write<IndexedInstantiationInformation>(
0209         [this](InstantiationInformationRepository& repo) { return repo.index(*this); });
0210     return IndexedInstantiationInformation(index);
0211 }
0212 }