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
|
/*
SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef KDEVPLATFORM_INDEXEDDECLARATION_H
#define KDEVPLATFORM_INDEXEDDECLARATION_H
#include <language/languageexport.h>
#include "indexedtopducontext.h"
#include <language/util/kdevhash.h>
namespace KDevelop {
class Declaration;
/**
* Represents a declaration only by its global indices
*/
class KDEVPLATFORMLANGUAGE_EXPORT IndexedDeclaration
{
public:
IndexedDeclaration(const Declaration* decl = nullptr);
IndexedDeclaration(uint topContext, uint declarationIndex);
/**
* \warning Duchain must be read locked
*/
Declaration* declaration() const;
/**
* \warning Duchain must be read locked
*/
Declaration* data() const
{
return declaration();
}
inline bool operator==(const IndexedDeclaration& rhs) const
{
return m_topContext == rhs.m_topContext && m_declarationIndex == rhs.m_declarationIndex;
}
inline bool operator!=(const IndexedDeclaration& rhs) const { return !operator==(rhs); }
inline uint hash() const
{
if (isDummy())
return 0;
return KDevHash() << m_topContext << m_declarationIndex;
}
///@warning The duchain needs to be locked when this is called
inline bool isValid() const
{
return !isDummy() && declaration() != nullptr;
}
inline bool operator<(const IndexedDeclaration& rhs) const
{
Q_ASSERT(!isDummy());
return m_topContext < rhs.m_topContext ||
(m_topContext == rhs.m_topContext && m_declarationIndex < rhs.m_declarationIndex);
}
/**
* \return Index of the Declaration within the top context
*/
inline uint localIndex() const
{
if (isDummy())
return 0;
else
return m_declarationIndex;
}
inline uint topContextIndex() const
{
if (isDummy())
return 0;
else
return m_topContext;
}
inline IndexedTopDUContext indexedTopContext() const
{
if (isDummy())
return IndexedTopDUContext();
else
return IndexedTopDUContext(m_topContext);
}
/**
* The following functions allow storing 2 integers in this object and marking it as a dummy,
* which makes the isValid() function always return false for this object, and use the integers
* for other purposes.
*
* Clears the contained data
*/
void setIsDummy(bool dummy)
{
if (isDummy() == dummy)
return;
if (dummy)
m_topContext = 1u << 31u;
else
m_topContext = 0;
m_declarationIndex = 0;
}
inline bool isDummy() const
{
//We use the second highest bit to mark dummies, because the highest is used for the sign bit of stored
//integers
return ( bool )(m_topContext & static_cast<uint>(1u << 31u));
}
inline QPair<uint, uint> dummyData() const
{
Q_ASSERT(isDummy());
return qMakePair(m_topContext & (~(1u << 31u)), m_declarationIndex);
}
/**
* \warning Do not call this when this object is valid.
*
* The first integer loses one bit of precision.
*/
void setDummyData(QPair<uint, uint> data)
{
Q_ASSERT(isDummy());
m_topContext = data.first;
m_declarationIndex = data.second;
Q_ASSERT(!isDummy());
m_topContext |= (1u << 31u); //Mark as dummy
Q_ASSERT(isDummy());
Q_ASSERT(dummyData() == data);
}
private:
uint m_topContext;
uint m_declarationIndex;
};
inline uint qHash(const IndexedDeclaration& decl)
{
return decl.hash();
}
}
Q_DECLARE_METATYPE(KDevelop::IndexedDeclaration)
Q_DECLARE_TYPEINFO(KDevelop::IndexedDeclaration, Q_MOVABLE_TYPE);
#endif // KDEVPLATFORM_INDEXEDDECLARATION_H
|