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 }