1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
/*
SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef KDEVPLATFORM_DECLARATION_ID_H
#define KDEVPLATFORM_DECLARATION_ID_H
#include "indexeddeclaration.h"
#include "identifier.h"
#include "instantiationinformation.h"
#include <language/util/kdevhash.h>
//krazy:excludeall=dpointer
namespace KDevelop {
class Declaration;
class TopDUContext;
/**
* \short Allows clearly identifying a Declaration.
*
* DeclarationId is needed to uniquely address Declarations that are in another top-context,
* because there may be multiple parsed versions of a file.
*
* There are two forms of DeclarationId, one indirect and one direct. The direct form
* holds a reference to the Declaration instance, whereas the indirect form stores the qualified
* identifier and an additional index to disambiguate instances of multiple declarations with the same
* identifier.
*
* Both forms also have a specialization index. It can be used in a language-specific way to pick other
* versions of the declaration. When the declaration is found, Declaration::specialize() is called on
* the found declaration with this value, and the returned value is the actually found declaration.
*
* \note This only works when the Declaration is in the symbol table.
* */
class KDEVPLATFORMLANGUAGE_EXPORT DeclarationId
{
public:
/**
* Constructor for indirect access to a declaration. The resulting DeclarationId will not
* have a direct reference to the Declaration, but will look it up as needed.
*
* \param id Identifier for this declaration id.
* \param additionalId Additional index to disambiguate
* \param specialization Specialization index (see class documentation).
*/
explicit DeclarationId(const IndexedQualifiedIdentifier& id = IndexedQualifiedIdentifier(),
uint additionalId = 0,
const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation());
/**
* Constructor for direct access to a declaration. The resulting DeclarationId will
* directly reference the Declaration
*
* \param decl Declaration to reference.
* \param specialization Specialization index (see class documentation).
*/
explicit DeclarationId(const IndexedDeclaration& decl,
const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation());
DeclarationId(const DeclarationId& rhs);
~DeclarationId();
DeclarationId& operator=(const DeclarationId& rhs);
/**
* Equality operator.
*
* \param rhs declaration identifier to compare.
* \returns true if equal, otherwise false.
*/
bool operator==(const DeclarationId& rhs) const
{
if (m_isDirect != rhs.m_isDirect)
return false;
if (!m_isDirect)
return m_indirectData.identifier == rhs.m_indirectData.identifier
&& m_indirectData.additionalIdentity == rhs.m_indirectData.additionalIdentity
&& m_specialization == rhs.m_specialization;
else
return m_directData == rhs.m_directData && m_specialization == rhs.m_specialization;
}
/**
* Not equal operator.
*
* \param rhs declaration identifier to compare.
* \returns true if not equal, otherwise false.
*/
bool operator!=(const DeclarationId& rhs) const
{
return !operator==(rhs);
}
/**
* Determine whether this declaration identifier references a valid declaration.
*/
bool isValid() const
{
return (m_isDirect && m_directData.isValid()) || m_indirectData.identifier.isValid();
}
/**
* Hash function for this declaration identifier.
*
* \warning This may return different hashes for the same declaration,
* depending on whether the id is direct or indirect,
* and thus you cannot compare hashes for declaration equality (use operator==() instead)
*/
uint hash() const
{
if (m_isDirect)
return KDevHash() << m_directData.hash() << m_specialization.index();
else
return KDevHash() << m_indirectData.identifier.index() << m_indirectData.additionalIdentity <<
m_specialization.index();
}
/**
* Retrieve the declaration, from the perspective of \a context.
* In order to be retrievable, the declaration must be in the symbol table.
*
* \param context Context in which to search for the Declaration.
* \param instantiateIfRequired Whether the declaration should be instantiated if required
* \returns the referenced Declaration, or null if none was found.
* */
Declaration* declaration(const TopDUContext* context, bool instantiateIfRequired = true) const;
/**
* Same as declaration(..), but returns all matching declarations if there are multiple.
* This also returns found forward-declarations.
*/
KDevVarLengthArray<Declaration*> declarations(const TopDUContext* context) const;
/**
* Set the specialization index (see class documentation).
*
* \param spec the new specialization index.
*/
void setSpecialization(const IndexedInstantiationInformation& spec);
/**
* Retrieve the specialization index (see class documentation).
*
* \returns the specialization index.
*/
IndexedInstantiationInformation specialization() const;
/**
* Determine whether this DeclarationId directly references a Declaration by indices,
* or if it uses identifiers and other data to reference the Declaration.
*
* \returns true if direct, false if indirect.
*/
bool isDirect() const;
/**
* Return the qualified identifier for this declaration.
*
* \warning This is relatively expensive, and not 100% correct in all cases(actually a top-context would be needed to resolve this correctly),
* so avoid using this, except for debugging purposes.
*/
QualifiedIdentifier qualifiedIdentifier() const;
private:
/// An indirect reference to the declaration, which uses the symbol-table for lookup. Should be preferred for all
/// declarations that are in the symbol-table
struct Indirect
{
IndexedQualifiedIdentifier identifier;
/// Hash from signature, or similar. Used to disambiguate multiple declarations of the same name.
uint additionalIdentity;
Indirect& operator=(const Indirect& rhs) = default;
};
union {
Indirect m_indirectData;
IndexedDeclaration m_directData;
};
bool m_isDirect;
// Can be used in a language-specific way to pick other versions of the declaration.
// When the declaration is found, pickSpecialization is called on the found declaration
// with this value, and the returned value is the actually found declaration.
IndexedInstantiationInformation m_specialization;
};
inline uint qHash(const KDevelop::DeclarationId& id)
{
return id.hash();
}
}
Q_DECLARE_TYPEINFO(KDevelop::DeclarationId, Q_MOVABLE_TYPE);
#endif
|