1 /* 2 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 3 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 4 5 SPDX-License-Identifier: LGPL-2.0-or-later 6 */ 7 8 #ifndef DUCONTEXTDYNAMICDATA_H 9 #define DUCONTEXTDYNAMICDATA_H 10 11 #include "ducontextdata.h" 12 13 namespace KDevelop { 14 ///This class contains data that is only runtime-dependent and does not need to be stored to disk 15 class DUContextDynamicData 16 { 17 private: d_func()18 inline const DUContextData* d_func() const { return m_context->d_func(); } d_func_dynamic()19 inline DUContextData* d_func_dynamic() { return m_context->d_func_dynamic(); } ctx_d_func(DUContext * ctx)20 static inline const DUContextData* ctx_d_func(DUContext* ctx) { return ctx->d_func(); } ctx_dynamicData(DUContext * ctx)21 static inline DUContextDynamicData* ctx_dynamicData(DUContext* ctx) { return ctx->m_dynamicData; } 22 23 public: 24 explicit DUContextDynamicData(DUContext*); 25 DUContextPointer m_parentContext; 26 27 TopDUContext* m_topContext; 28 29 uint m_indexInTopContext; //Index of this DUContext in the top-context 30 31 DUContext* m_context; 32 33 // cache of unserialized child contexts 34 QVector<DUContext*> m_childContexts; 35 // cache of unserialized local declarations 36 QVector<Declaration*> m_localDeclarations; 37 38 /** 39 * Adds a child context. 40 * 41 * \note Be sure to have set the text location first, so that 42 * the chain is sorted correctly. 43 */ 44 void addChildContext(DUContext* context); 45 46 /**Removes the context from childContexts 47 * @return Whether a context was removed 48 * */ 49 bool removeChildContext(DUContext* context); 50 51 void addImportedChildContext(DUContext* context); 52 void removeImportedChildContext(DUContext* context); 53 54 void addDeclaration(Declaration* declaration); 55 56 /**Removes the declaration from localDeclarations 57 * @return Whether a declaration was removed 58 * */ 59 bool removeDeclaration(Declaration* declaration); 60 61 //Files the scope identifier into target 62 void scopeIdentifier(bool includeClasses, QualifiedIdentifier& target) const; 63 64 //Iterates through all visible declarations within a given context, including the ones propagated from sub-contexts 65 class VisibleDeclarationIterator 66 { 67 public: 68 struct StackEntry 69 { 70 explicit StackEntry(const DUContextDynamicData* data = nullptr) dataStackEntry71 : data(data) 72 , index(0) 73 , nextChild(0) 74 { 75 } 76 77 const DUContextDynamicData* data; 78 int index; 79 uint nextChild; 80 }; 81 VisibleDeclarationIterator(const DUContextDynamicData * data)82 explicit VisibleDeclarationIterator(const DUContextDynamicData* data) 83 : current(data) 84 { 85 toValidPosition(); 86 } 87 88 inline Declaration* operator*() const 89 { 90 return current.data ? current.data->m_localDeclarations.value(current.index) : nullptr; 91 } 92 93 inline VisibleDeclarationIterator& operator++() 94 { 95 ++current.index; 96 toValidPosition(); 97 return *this; 98 } 99 100 inline operator bool() const 101 { 102 return current.data && !current.data->m_localDeclarations.isEmpty(); 103 } 104 105 // Moves the cursor to the next valid position, from an invalid one toValidPosition()106 void toValidPosition() 107 { 108 if (!current.data || current.index < current.data->m_localDeclarations.size()) { 109 // still valid 110 return; 111 } 112 113 do { 114 // Check if we can proceed into a propagating child-context 115 for (int a = current.nextChild; a < current.data->m_childContexts.size(); ++a) { 116 DUContext* child = current.data->m_childContexts[a]; 117 118 if (ctx_d_func(child)->m_propagateDeclarations) { 119 current.nextChild = a + 1; 120 stack.append(current); 121 current = StackEntry(ctx_dynamicData(child)); 122 toValidPosition(); 123 return; 124 } 125 } 126 127 //Go up and into the next valid context 128 if (stack.isEmpty()) { 129 current = StackEntry(); 130 return; 131 } 132 133 current = stack.back(); 134 stack.pop_back(); 135 } while (true); 136 } 137 138 StackEntry current; 139 140 KDevVarLengthArray<StackEntry> stack; 141 }; 142 143 /** 144 * Returns true if this context is imported by the given one, on any level. 145 * */ 146 bool imports(const DUContext* context, const TopDUContext* source, 147 QSet<const DUContextDynamicData*>* recursionGuard) const; 148 }; 149 } 150 151 Q_DECLARE_TYPEINFO(KDevelop::DUContextDynamicData::VisibleDeclarationIterator::StackEntry, Q_MOVABLE_TYPE); 152 153 #endif 154