1 /* 2 SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de> 3 4 SPDX-License-Identifier: LGPL-2.0-only 5 */ 6 7 #ifndef KDEVPLATFORM_INDEXEDDECLARATION_H 8 #define KDEVPLATFORM_INDEXEDDECLARATION_H 9 10 #include <language/languageexport.h> 11 12 #include "indexedtopducontext.h" 13 #include <language/util/kdevhash.h> 14 15 namespace KDevelop { 16 class Declaration; 17 18 /** 19 * Represents a declaration only by its global indices 20 */ 21 class KDEVPLATFORMLANGUAGE_EXPORT IndexedDeclaration 22 { 23 public: 24 IndexedDeclaration(const Declaration* decl = nullptr); 25 IndexedDeclaration(uint topContext, uint declarationIndex); 26 27 /** 28 * \warning Duchain must be read locked 29 */ 30 Declaration* declaration() const; 31 32 /** 33 * \warning Duchain must be read locked 34 */ data()35 Declaration* data() const 36 { 37 return declaration(); 38 } 39 40 inline bool operator==(const IndexedDeclaration& rhs) const 41 { 42 return m_topContext == rhs.m_topContext && m_declarationIndex == rhs.m_declarationIndex; 43 } 44 hash()45 inline uint hash() const 46 { 47 if (isDummy()) 48 return 0; 49 return KDevHash() << m_topContext << m_declarationIndex; 50 } 51 52 ///@warning The duchain needs to be locked when this is called isValid()53 inline bool isValid() const 54 { 55 return !isDummy() && declaration() != nullptr; 56 } 57 58 inline bool operator<(const IndexedDeclaration& rhs) const 59 { 60 Q_ASSERT(!isDummy()); 61 return m_topContext < rhs.m_topContext || 62 (m_topContext == rhs.m_topContext && m_declarationIndex < rhs.m_declarationIndex); 63 } 64 65 /** 66 * \return Index of the Declaration within the top context 67 */ localIndex()68 inline uint localIndex() const 69 { 70 if (isDummy()) 71 return 0; 72 else 73 return m_declarationIndex; 74 } 75 topContextIndex()76 inline uint topContextIndex() const 77 { 78 if (isDummy()) 79 return 0; 80 else 81 return m_topContext; 82 } 83 indexedTopContext()84 inline IndexedTopDUContext indexedTopContext() const 85 { 86 if (isDummy()) 87 return IndexedTopDUContext(); 88 else 89 return IndexedTopDUContext(m_topContext); 90 } 91 92 /** 93 * The following functions allow storing 2 integers in this object and marking it as a dummy, 94 * which makes the isValid() function always return false for this object, and use the integers 95 * for other purposes. 96 * 97 * Clears the contained data 98 */ setIsDummy(bool dummy)99 void setIsDummy(bool dummy) 100 { 101 if (isDummy() == dummy) 102 return; 103 if (dummy) 104 m_topContext = 1u << 31u; 105 else 106 m_topContext = 0; 107 m_declarationIndex = 0; 108 } 109 isDummy()110 inline bool isDummy() const 111 { 112 //We use the second highest bit to mark dummies, because the highest is used for the sign bit of stored 113 //integers 114 return ( bool )(m_topContext & static_cast<uint>(1u << 31u)); 115 } 116 dummyData()117 inline QPair<uint, uint> dummyData() const 118 { 119 Q_ASSERT(isDummy()); 120 return qMakePair(m_topContext & (~(1u << 31u)), m_declarationIndex); 121 } 122 123 /** 124 * \warning Do not call this when this object is valid. 125 * 126 * The first integer loses one bit of precision. 127 */ setDummyData(QPair<uint,uint> data)128 void setDummyData(QPair<uint, uint> data) 129 { 130 Q_ASSERT(isDummy()); 131 132 m_topContext = data.first; 133 m_declarationIndex = data.second; 134 Q_ASSERT(!isDummy()); 135 m_topContext |= (1u << 31u); //Mark as dummy 136 Q_ASSERT(isDummy()); 137 Q_ASSERT(dummyData() == data); 138 } 139 140 private: 141 uint m_topContext; 142 uint m_declarationIndex; 143 }; 144 qHash(const IndexedDeclaration & decl)145inline uint qHash(const IndexedDeclaration& decl) 146 { 147 return decl.hash(); 148 } 149 } 150 151 Q_DECLARE_METATYPE(KDevelop::IndexedDeclaration) 152 Q_DECLARE_TYPEINFO(KDevelop::IndexedDeclaration, Q_MOVABLE_TYPE); 153 154 #endif // KDEVPLATFORM_INDEXEDDECLARATION_H 155