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 #ifndef KDEVPLATFORM_DECLARATION_ID_H
0008 #define KDEVPLATFORM_DECLARATION_ID_H
0009 
0010 #include "indexeddeclaration.h"
0011 #include "identifier.h"
0012 #include "instantiationinformation.h"
0013 #include <language/util/kdevhash.h>
0014 
0015 //krazy:excludeall=dpointer
0016 
0017 namespace KDevelop {
0018 class Declaration;
0019 class TopDUContext;
0020 
0021 /**
0022  * \short Allows clearly identifying a Declaration.
0023  *
0024  * DeclarationId is needed to uniquely address Declarations that are in another top-context,
0025  * because there may be multiple parsed versions of a file.
0026  *
0027  * There are two forms of DeclarationId, one indirect and one direct.  The direct form
0028  * holds a reference to the Declaration instance, whereas the indirect form stores the qualified
0029  * identifier and an additional index to disambiguate instances of multiple declarations with the same
0030  * identifier.
0031  *
0032  * Both forms also have a specialization index. It can be used in a language-specific way to pick other
0033  * versions of the declaration. When the declaration is found, Declaration::specialize() is called on
0034  * the found declaration with this value, and the returned value is the actually found declaration.
0035  *
0036  * \note This only works when the Declaration is in the symbol table.
0037  * */
0038 class KDEVPLATFORMLANGUAGE_EXPORT DeclarationId
0039 {
0040 public:
0041     /**
0042      * Constructor for indirect access to a declaration.  The resulting DeclarationId will not
0043      * have a direct reference to the Declaration, but will look it up as needed.
0044      *
0045      * \param id Identifier for this declaration id.
0046      * \param additionalId Additional index to disambiguate
0047      * \param specialization Specialization index (see class documentation).
0048      */
0049     explicit DeclarationId(const IndexedQualifiedIdentifier& id = IndexedQualifiedIdentifier(),
0050                            uint additionalId = 0,
0051                            const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation());
0052 
0053     /**
0054      * Constructor for direct access to a declaration.  The resulting DeclarationId will
0055      * directly reference the Declaration
0056      *
0057      * \param decl Declaration to reference.
0058      * \param specialization Specialization index (see class documentation).
0059      */
0060     explicit DeclarationId(const IndexedDeclaration& decl,
0061                            const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation());
0062 
0063     DeclarationId(const DeclarationId& rhs);
0064 
0065     ~DeclarationId();
0066 
0067     DeclarationId& operator=(const DeclarationId& rhs);
0068 
0069     /**
0070      * Equality operator.
0071      *
0072      * \param rhs declaration identifier to compare.
0073      * \returns true if equal, otherwise false.
0074      */
0075     bool operator==(const DeclarationId& rhs) const
0076     {
0077         if (m_isDirect != rhs.m_isDirect)
0078             return false;
0079 
0080         if (!m_isDirect)
0081             return m_indirectData.identifier == rhs.m_indirectData.identifier
0082                    && m_indirectData.additionalIdentity == rhs.m_indirectData.additionalIdentity
0083                    && m_specialization == rhs.m_specialization;
0084         else
0085             return m_directData == rhs.m_directData && m_specialization == rhs.m_specialization;
0086     }
0087 
0088     /**
0089      * Not equal operator.
0090      *
0091      * \param rhs declaration identifier to compare.
0092      * \returns true if not equal, otherwise false.
0093      */
0094     bool operator!=(const DeclarationId& rhs) const
0095     {
0096         return !operator==(rhs);
0097     }
0098 
0099     /**
0100      * Determine whether this declaration identifier references a valid declaration.
0101      */
0102     bool isValid() const
0103     {
0104         return (m_isDirect && m_directData.isValid()) || m_indirectData.identifier.isValid();
0105     }
0106 
0107     /**
0108      * Hash function for this declaration identifier.
0109      *
0110      * \warning This may return different hashes for the same declaration,
0111      *          depending on whether the id is direct or indirect,
0112      *          and thus you cannot compare hashes for declaration equality (use operator==() instead)
0113      */
0114     uint hash() const
0115     {
0116         if (m_isDirect)
0117             return KDevHash() << m_directData.hash() << m_specialization.index();
0118         else
0119             return KDevHash() << m_indirectData.identifier.index() << m_indirectData.additionalIdentity <<
0120                    m_specialization.index();
0121     }
0122 
0123     /**
0124      * Retrieve the declaration, from the perspective of \a context.
0125      * In order to be retrievable, the declaration must be in the symbol table.
0126      *
0127      * \param context Context in which to search for the Declaration.
0128      * \param instantiateIfRequired Whether the declaration should be instantiated if required
0129      * \returns the referenced Declaration, or null if none was found.
0130      * */
0131     Declaration* declaration(const TopDUContext* context, bool instantiateIfRequired = true) const;
0132 
0133     /**
0134      * Same as declaration(..), but returns all matching declarations if there are multiple.
0135      * This also returns found forward-declarations.
0136      */
0137     KDevVarLengthArray<Declaration*> declarations(const TopDUContext* context) const;
0138 
0139     /**
0140      * Set the specialization index (see class documentation).
0141      *
0142      * \param spec the new specialization index.
0143      */
0144     void setSpecialization(const IndexedInstantiationInformation& spec);
0145 
0146     /**
0147      * Retrieve the specialization index (see class documentation).
0148      *
0149      * \returns the specialization index.
0150      */
0151     IndexedInstantiationInformation specialization() const;
0152 
0153     /**
0154      * Determine whether this DeclarationId directly references a Declaration by indices,
0155      * or if it uses identifiers and other data to reference the Declaration.
0156      *
0157      * \returns true if direct, false if indirect.
0158      */
0159     bool isDirect() const;
0160 
0161     /**
0162      * Return the qualified identifier for this declaration.
0163      *
0164      * \warning This is relatively expensive, and not 100% correct in all cases(actually a top-context would be needed to resolve this correctly),
0165      *          so avoid using this, except for debugging purposes.
0166      */
0167     QualifiedIdentifier qualifiedIdentifier() const;
0168 
0169 private:
0170     /// An indirect reference to the declaration, which uses the symbol-table for lookup. Should be preferred for all
0171     /// declarations that are in the symbol-table
0172     struct Indirect
0173     {
0174         IndexedQualifiedIdentifier identifier;
0175         /// Hash from signature, or similar. Used to disambiguate multiple declarations of the same name.
0176         uint additionalIdentity;
0177 
0178         Indirect& operator=(const Indirect& rhs) = default;
0179     };
0180 
0181     union {
0182         Indirect m_indirectData;
0183         IndexedDeclaration m_directData;
0184     };
0185     bool m_isDirect;
0186 
0187     // Can be used in a language-specific way to pick other versions of the declaration.
0188     // When the declaration is found, pickSpecialization is called on the found declaration
0189     // with this value, and the returned value is the actually found declaration.
0190     IndexedInstantiationInformation m_specialization;
0191 };
0192 
0193 inline uint qHash(const KDevelop::DeclarationId& id)
0194 {
0195     return id.hash();
0196 }
0197 }
0198 
0199 Q_DECLARE_TYPEINFO(KDevelop::DeclarationId, Q_MOVABLE_TYPE);
0200 
0201 #endif