File indexing completed on 2024-05-12 04:38:02

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #ifndef KDEVPLATFORM_INDEXEDDECLARATION_H
0008 #define KDEVPLATFORM_INDEXEDDECLARATION_H
0009 
0010 #include <language/languageexport.h>
0011 
0012 #include "indexedtopducontext.h"
0013 #include <language/util/kdevhash.h>
0014 
0015 namespace KDevelop {
0016 class Declaration;
0017 
0018 /**
0019  * Represents a declaration only by its global indices
0020  */
0021 class KDEVPLATFORMLANGUAGE_EXPORT IndexedDeclaration
0022 {
0023 public:
0024     IndexedDeclaration(const Declaration* decl = nullptr);
0025     IndexedDeclaration(uint topContext, uint declarationIndex);
0026 
0027     /**
0028      * \warning Duchain must be read locked
0029      */
0030     Declaration* declaration() const;
0031 
0032     /**
0033      * \warning Duchain must be read locked
0034      */
0035     Declaration* data() const
0036     {
0037         return declaration();
0038     }
0039 
0040     inline bool operator==(const IndexedDeclaration& rhs) const
0041     {
0042         return m_topContext == rhs.m_topContext && m_declarationIndex == rhs.m_declarationIndex;
0043     }
0044 
0045     inline bool operator!=(const IndexedDeclaration& rhs) const { return !operator==(rhs); }
0046 
0047     inline uint hash() const
0048     {
0049         if (isDummy())
0050             return 0;
0051         return KDevHash() << m_topContext << m_declarationIndex;
0052     }
0053 
0054     ///@warning The duchain needs to be locked when this is called
0055     inline bool isValid() const
0056     {
0057         return !isDummy() && declaration() != nullptr;
0058     }
0059 
0060     inline bool operator<(const IndexedDeclaration& rhs) const
0061     {
0062         Q_ASSERT(!isDummy());
0063         return m_topContext < rhs.m_topContext ||
0064                (m_topContext == rhs.m_topContext && m_declarationIndex < rhs.m_declarationIndex);
0065     }
0066 
0067     /**
0068      * \return Index of the Declaration within the top context
0069      */
0070     inline uint localIndex() const
0071     {
0072         if (isDummy())
0073             return 0;
0074         else
0075             return m_declarationIndex;
0076     }
0077 
0078     inline uint topContextIndex() const
0079     {
0080         if (isDummy())
0081             return 0;
0082         else
0083             return m_topContext;
0084     }
0085 
0086     inline IndexedTopDUContext indexedTopContext() const
0087     {
0088         if (isDummy())
0089             return IndexedTopDUContext();
0090         else
0091             return IndexedTopDUContext(m_topContext);
0092     }
0093 
0094     /**
0095      * The following functions allow storing 2 integers in this object and marking it as a dummy,
0096      * which makes the isValid() function always return false for this object, and use the integers
0097      * for other purposes.
0098      *
0099      * Clears the contained data
0100      */
0101     void setIsDummy(bool dummy)
0102     {
0103         if (isDummy() == dummy)
0104             return;
0105         if (dummy)
0106             m_topContext = 1u << 31u;
0107         else
0108             m_topContext = 0;
0109         m_declarationIndex = 0;
0110     }
0111 
0112     inline bool isDummy() const
0113     {
0114         //We use the second highest bit to mark dummies, because the highest is used for the sign bit of stored
0115         //integers
0116         return ( bool )(m_topContext & static_cast<uint>(1u << 31u));
0117     }
0118 
0119     inline QPair<uint, uint> dummyData() const
0120     {
0121         Q_ASSERT(isDummy());
0122         return qMakePair(m_topContext & (~(1u << 31u)), m_declarationIndex);
0123     }
0124 
0125     /**
0126      * \warning Do not call this when this object is valid.
0127      *
0128      * The first integer loses one bit of precision.
0129      */
0130     void setDummyData(QPair<uint, uint> data)
0131     {
0132         Q_ASSERT(isDummy());
0133 
0134         m_topContext = data.first;
0135         m_declarationIndex = data.second;
0136         Q_ASSERT(!isDummy());
0137         m_topContext |= (1u << 31u); //Mark as dummy
0138         Q_ASSERT(isDummy());
0139         Q_ASSERT(dummyData() == data);
0140     }
0141 
0142 private:
0143     uint m_topContext;
0144     uint m_declarationIndex;
0145 };
0146 
0147 inline uint qHash(const IndexedDeclaration& decl)
0148 {
0149     return decl.hash();
0150 }
0151 }
0152 
0153 Q_DECLARE_METATYPE(KDevelop::IndexedDeclaration)
0154 Q_DECLARE_TYPEINFO(KDevelop::IndexedDeclaration, Q_MOVABLE_TYPE);
0155 
0156 #endif // KDEVPLATFORM_INDEXEDDECLARATION_H