File indexing completed on 2024-05-12 04:37:59
0001 /* 0002 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0003 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #ifndef KDEVPLATFORM_DUCHAINBASE_H 0009 #define KDEVPLATFORM_DUCHAINBASE_H 0010 0011 #include <language/languageexport.h> 0012 #include "appendedlist.h" 0013 #include "duchainpointer.h" 0014 #include <language/editor/persistentmovingrange.h> 0015 #include <language/editor/rangeinrevision.h> 0016 0017 namespace KTextEditor { 0018 class Cursor; 0019 class Range; 0020 } 0021 0022 namespace KDevelop { 0023 class DUContext; 0024 class TopDUContext; 0025 class DUChainBase; 0026 class IndexedString; 0027 0028 ///Use this to declare the data functions in your DUChainBase based class. @warning Behind this macro, the access will be "public". 0029 #define DUCHAIN_DECLARE_DATA(Class) \ 0030 inline class Class ## Data * d_func_dynamic() { makeDynamic(); return reinterpret_cast<Class ## Data*>(d_ptr); } \ 0031 inline const class Class ## Data* d_func() const { return reinterpret_cast<const Class ## Data*>(d_ptr); } \ 0032 public: using Data = Class ## Data; \ 0033 private: 0034 0035 #define DUCHAIN_D(Class) const Class ## Data * const d = d_func() 0036 #define DUCHAIN_D_DYNAMIC(Class) Class ## Data * const d = d_func_dynamic() 0037 0038 ///@note When a data-item is stored on disk, no destructors of contained items will be called while destruction. 0039 ///DUChainBase assumes that each item that has constant data, is stored on disk. 0040 ///However the destructor is called even on constant items, when they have been replaced with a dynamic item. 0041 ///This tries to keep constructor/destructor count consistency persistently, which allows doing static reference-counting 0042 ///using contained classes in their constructor/destructors(For example the class Utils::StorableSet). 0043 ///This means that the data of all items that are stored to disk _MUST_ be made constant before their destruction. 0044 ///This also means that every item that is "semantically" deleted, _MUST_ have dynamic data before its destruction. 0045 ///This also means that DUChainBaseData based items should never be cloned using memcpy, but rather always using the copy-constructor, 0046 ///even if both sides are constant. 0047 class KDEVPLATFORMLANGUAGE_EXPORT DUChainBaseData 0048 { 0049 public: 0050 DUChainBaseData() 0051 { 0052 initializeAppendedLists(); 0053 } 0054 0055 DUChainBaseData(const DUChainBaseData& rhs) : m_range(rhs.m_range) 0056 , classId(rhs.classId) 0057 { 0058 initializeAppendedLists(); 0059 } 0060 0061 ~DUChainBaseData() 0062 { 0063 freeAppendedLists(); 0064 } 0065 0066 DUChainBaseData& operator=(const DUChainBaseData& rhs) = delete; 0067 0068 RangeInRevision m_range; 0069 0070 APPENDED_LISTS_STUB(DUChainBaseData) 0071 0072 quint16 classId = 0; 0073 0074 bool isDynamic() const 0075 { 0076 return m_dynamic; 0077 } 0078 0079 /** 0080 * Internal setup for the data structure. 0081 * 0082 * This must be called from actual class that belongs to this data(not parent classes), and the class must have the 0083 * "Identity" enumerator with a unique identity. Do NOT call this in copy-constructors! 0084 */ 0085 template <class T> 0086 void setClassId(T*) 0087 { 0088 static_assert(T::Identity < std::numeric_limits<decltype(classId)>::max(), "Class ID out of bounds"); 0089 classId = T::Identity; 0090 } 0091 0092 uint classSize() const; 0093 0094 ///This is called whenever the data-object is being deleted memory-wise, but not semantically(Which means it stays on disk) 0095 ///Implementations of parent-classes must always be called 0096 void freeDynamicData() 0097 { 0098 } 0099 0100 ///Used to decide whether a constructed item should create constant data. 0101 ///The default is "false", so dynamic data is created by default. 0102 ///This is stored thread-locally. 0103 static bool& shouldCreateConstantData(); 0104 0105 ///Returns whether initialized objects should be created as dynamic objects 0106 static bool appendedListDynamicDefault() 0107 { 0108 return !shouldCreateConstantData(); 0109 } 0110 }; 0111 0112 /** 0113 * Base class for definition-use chain objects. 0114 * 0115 * This class provides a thread safe pointer type to reference duchain objects 0116 * while the DUChain mutex is not held (\see DUChainPointer) 0117 */ 0118 0119 class KDEVPLATFORMLANGUAGE_EXPORT DUChainBase 0120 { 0121 public: 0122 /** 0123 * Constructor. 0124 * 0125 * \param range range of the alias declaration's identifier 0126 */ 0127 explicit DUChainBase(const RangeInRevision& range); 0128 /// Destructor 0129 virtual ~DUChainBase(); 0130 0131 /** 0132 * Determine the top context to which this object belongs. 0133 */ 0134 virtual TopDUContext* topContext() const; 0135 0136 /** 0137 * Returns a special pointer that can be used to track the existence of a du-chain object across locking-cycles. 0138 * @see DUChainPointerData 0139 * */ 0140 const QExplicitlySharedDataPointer<DUChainPointerData>& weakPointer() const; 0141 0142 virtual IndexedString url() const; 0143 0144 enum { 0145 Identity = 1 0146 }; 0147 0148 ///After this was called, the data-pointer is dynamic. It is cloned if needed. 0149 void makeDynamic(); 0150 0151 explicit DUChainBase(DUChainBaseData& dd); 0152 0153 DUChainBase& operator=(const DUChainBase& rhs) = delete; 0154 0155 ///This must only be used to change the storage-location or storage-kind(dynamic/constant) of the data, but 0156 ///the data must always be equal! 0157 virtual void setData(DUChainBaseData*, bool constructorCalled = true); 0158 0159 ///Returns the range assigned to this object, in the document revision when this document was last parsed. 0160 RangeInRevision range() const; 0161 0162 ///Changes the range assigned to this object, in the document revision when this document is parsed. 0163 void setRange(const RangeInRevision& range); 0164 0165 ///Returns the range assigned to this object, transformed into the current revision of the document. 0166 ///@warning This must only be called from the foreground thread, or with the foreground lock acquired. 0167 KTextEditor::Range rangeInCurrentRevision() const; 0168 0169 ///Returns the range assigned to this object, transformed into the current revision of the document. 0170 ///The returned object is unique at each call, so you can use it and change it in whatever way you want. 0171 ///@warning This must only be called from the foreground thread, or with the foreground lock acquired. 0172 PersistentMovingRange::Ptr createRangeMoving() const; 0173 0174 ///Transforms the given cursor in the current document revision to its according position 0175 ///in the parsed document containing this duchain object. The resulting cursor will be directly comparable to the non-translated 0176 ///range() members in the duchain, but only for one duchain locking cycle. 0177 ///@warning This must only be called from the foreground thread, or with the foreground lock acquired. 0178 CursorInRevision transformToLocalRevision(const KTextEditor::Cursor& cursor) const; 0179 0180 ///Transforms the given range in the current document revision to its according position 0181 ///in the parsed document containing this duchain object. The resulting cursor will be directly comparable to the non-translated 0182 ///range() members in the duchain, but only for one duchain locking cycle. 0183 ///@warning This must only be called from the foreground thread, or with the foreground lock acquired. 0184 RangeInRevision transformToLocalRevision(const KTextEditor::Range& range) const; 0185 0186 KTextEditor::Cursor transformFromLocalRevision(const CursorInRevision& cursor) const; 0187 0188 KTextEditor::Range transformFromLocalRevision(const RangeInRevision& range) const; 0189 0190 protected: 0191 /** 0192 * Creates a duchain object that uses the data of the given one, and will not delete it on destruction. 0193 * The data will be shared, and this object must be deleted before the given one is. 0194 */ 0195 DUChainBase(DUChainBase& rhs); 0196 0197 /** 0198 * Constructor for copy constructors in subclasses. 0199 * 0200 * \param dd data to use. 0201 * \param range text range which this object covers. 0202 */ 0203 DUChainBase(DUChainBaseData& dd, const RangeInRevision& range); 0204 0205 ///Called after loading to rebuild the dynamic data. If this is a context, this should recursively work on all sub-contexts. 0206 virtual void rebuildDynamicData(DUContext* parent, uint ownIndex); 0207 0208 /// Data pointer that is shared across all the inheritance hierarchy 0209 DUChainBaseData* d_ptr; 0210 0211 private: 0212 0213 mutable QExplicitlySharedDataPointer<DUChainPointerData> m_ptr; 0214 0215 public: 0216 DUCHAIN_DECLARE_DATA(DUChainBase) 0217 }; 0218 } 0219 0220 #endif // KDEVPLATFORM_DUCHAINBASE_H