File indexing completed on 2024-05-12 04:37:57
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 "declarationid.h" 0008 0009 #include "ducontext.h" 0010 #include "topducontext.h" 0011 #include "duchain.h" 0012 #include "declaration.h" 0013 #include "persistentsymboltable.h" 0014 #include "instantiationinformation.h" 0015 0016 #include <util/convenientfreelist.h> 0017 0018 namespace KDevelop { 0019 DeclarationId::DeclarationId(const IndexedQualifiedIdentifier& id, uint additionalId, 0020 const IndexedInstantiationInformation& specialization) 0021 : m_indirectData{id, additionalId} 0022 , m_isDirect(false) 0023 , m_specialization(specialization) 0024 { 0025 } 0026 0027 DeclarationId::DeclarationId(const IndexedDeclaration& decl, 0028 const IndexedInstantiationInformation& specialization) 0029 : m_directData(decl) 0030 , m_isDirect(true) 0031 , m_specialization(specialization) 0032 { 0033 } 0034 0035 DeclarationId::DeclarationId(const DeclarationId& rhs) 0036 : m_isDirect(rhs.m_isDirect) 0037 , m_specialization(rhs.m_specialization) 0038 { 0039 if (!m_isDirect) { 0040 // IndexedQualifiedIdentifier doesn't like zero-initialization... 0041 new (&m_indirectData.identifier) IndexedQualifiedIdentifier(rhs.m_indirectData.identifier); 0042 m_indirectData.additionalIdentity = rhs.m_indirectData.additionalIdentity; 0043 } else { 0044 m_directData = rhs.m_directData; 0045 } 0046 } 0047 0048 DeclarationId::~DeclarationId() 0049 { 0050 if (!m_isDirect) { 0051 m_indirectData.~Indirect(); 0052 } 0053 } 0054 0055 DeclarationId& DeclarationId::operator=(const DeclarationId& rhs) 0056 { 0057 if (&rhs == this) 0058 return *this; 0059 0060 m_isDirect = rhs.m_isDirect; 0061 m_specialization = rhs.m_specialization; 0062 if (!m_isDirect) { 0063 m_indirectData = rhs.m_indirectData; 0064 } else { 0065 m_directData = rhs.m_directData; 0066 } 0067 return *this; 0068 } 0069 0070 bool DeclarationId::isDirect() const 0071 { 0072 return m_isDirect; 0073 } 0074 0075 void DeclarationId::setSpecialization(const IndexedInstantiationInformation& spec) 0076 { 0077 m_specialization = spec; 0078 } 0079 0080 IndexedInstantiationInformation DeclarationId::specialization() const 0081 { 0082 return m_specialization; 0083 } 0084 0085 KDevVarLengthArray<Declaration*> DeclarationId::declarations(const TopDUContext* top) const 0086 { 0087 KDevVarLengthArray<Declaration*> ret; 0088 0089 if (m_isDirect == false) { 0090 //Find the declaration by its qualified identifier and additionalIdentity 0091 QualifiedIdentifier id(m_indirectData.identifier); 0092 0093 auto visitDeclaration = [&](const IndexedDeclaration& indexedDecl) { 0094 auto decl = indexedDecl.data(); 0095 if (decl && m_indirectData.additionalIdentity == decl->additionalIdentity()) { 0096 // Hit 0097 ret.append(decl); 0098 } 0099 return PersistentSymbolTable::VisitorState::Continue; 0100 }; 0101 0102 if (top) { 0103 //Do filtering 0104 PersistentSymbolTable::self().visitFilteredDeclarations(id, top->recursiveImportIndices(), 0105 visitDeclaration); 0106 } else { 0107 //Just accept anything 0108 PersistentSymbolTable::self().visitDeclarations(id, [&](const IndexedDeclaration& indexedDecl) { 0109 ///@todo think this over once we don't pull in all imported top-context any more 0110 //Don't trigger loading of top-contexts from here, it will create a lot of problems 0111 if (DUChain::self()->isInMemory(indexedDecl.topContextIndex())) { 0112 return visitDeclaration(indexedDecl); 0113 } 0114 return PersistentSymbolTable::VisitorState::Continue; 0115 }); 0116 } 0117 } else { 0118 Declaration* decl = m_directData.declaration(); 0119 if (decl) 0120 ret.append(decl); 0121 } 0122 0123 if (!ret.isEmpty() && m_specialization.index()) { 0124 KDevVarLengthArray<Declaration*> newRet; 0125 for (Declaration* decl : qAsConst(ret)) { 0126 Declaration* specialized = decl->specialize(m_specialization, top ? top : decl->topContext()); 0127 if (specialized) 0128 newRet.append(specialized); 0129 } 0130 0131 return newRet; 0132 } 0133 return ret; 0134 } 0135 0136 Declaration* DeclarationId::declaration(const TopDUContext* top, bool instantiateIfRequired) const 0137 { 0138 Declaration* ret = nullptr; 0139 0140 if (m_isDirect == false) { 0141 //Find the declaration by its qualified identifier and additionalIdentity 0142 QualifiedIdentifier id(m_indirectData.identifier); 0143 0144 auto visitDeclaration = [&](const IndexedDeclaration& indexedDecl) { 0145 auto decl = indexedDecl.data(); 0146 if (decl && m_indirectData.additionalIdentity == decl->additionalIdentity()) { 0147 // Hit 0148 ret = decl; 0149 if (!ret->isForwardDeclaration()) { 0150 return PersistentSymbolTable::VisitorState::Break; 0151 } 0152 } 0153 return PersistentSymbolTable::VisitorState::Continue; 0154 }; 0155 0156 if (top) { 0157 // Do filtering 0158 PersistentSymbolTable::self().visitFilteredDeclarations(id, top->recursiveImportIndices(), 0159 visitDeclaration); 0160 } else { 0161 //Just accept anything 0162 PersistentSymbolTable::self().visitDeclarations(id, [&](const IndexedDeclaration& indexedDecl) { 0163 ///@todo think this over once we don't pull in all imported top-context any more 0164 //Don't trigger loading of top-contexts from here, it will create a lot of problems 0165 if (DUChain::self()->isInMemory(indexedDecl.topContextIndex())) { 0166 return visitDeclaration(indexedDecl); 0167 } 0168 return PersistentSymbolTable::VisitorState::Continue; 0169 }); 0170 } 0171 } else { 0172 //Find the declaration by m_topContext and m_declaration 0173 ret = m_directData.declaration(); 0174 } 0175 0176 if (ret) { 0177 if (m_specialization.isValid()) { 0178 const TopDUContext* topContextForSpecialization = top; 0179 if (!instantiateIfRequired) 0180 topContextForSpecialization = nullptr; //If we don't want to instantiate new declarations, set the top-context to zero, so specialize(..) will only look-up 0181 else if (!topContextForSpecialization) 0182 topContextForSpecialization = ret->topContext(); 0183 0184 return ret->specialize(m_specialization, topContextForSpecialization); 0185 } else { 0186 return ret; 0187 } 0188 } else 0189 return nullptr; 0190 } 0191 0192 QualifiedIdentifier DeclarationId::qualifiedIdentifier() const 0193 { 0194 if (!m_isDirect) { 0195 QualifiedIdentifier baseIdentifier = m_indirectData.identifier.identifier(); 0196 if (!m_specialization.index()) 0197 return baseIdentifier; 0198 return m_specialization.information().applyToIdentifier(baseIdentifier); 0199 } else { 0200 Declaration* decl = declaration(nullptr); 0201 if (decl) 0202 return decl->qualifiedIdentifier(); 0203 0204 return QualifiedIdentifier(i18n("(unknown direct declaration)")); 0205 } 0206 0207 return QualifiedIdentifier(i18n("(missing)")) + m_indirectData.identifier.identifier(); 0208 } 0209 }