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 ¶m, 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 }