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