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

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-or-later
0006 */
0007 
0008 #ifndef DUCONTEXTDYNAMICDATA_H
0009 #define DUCONTEXTDYNAMICDATA_H
0010 
0011 #include "ducontextdata.h"
0012 
0013 namespace KDevelop {
0014 ///This class contains data that is only runtime-dependent and does not need to be stored to disk
0015 class DUContextDynamicData
0016 {
0017 private:
0018     inline const DUContextData* d_func() const { return m_context->d_func(); }
0019     inline DUContextData* d_func_dynamic() { return m_context->d_func_dynamic(); }
0020     static inline const DUContextData* ctx_d_func(DUContext* ctx) { return ctx->d_func(); }
0021     static inline DUContextDynamicData* ctx_dynamicData(DUContext* ctx) { return ctx->m_dynamicData; }
0022 
0023 public:
0024     explicit DUContextDynamicData(DUContext*);
0025     DUContextPointer m_parentContext;
0026 
0027     TopDUContext* m_topContext;
0028 
0029     uint m_indexInTopContext; //Index of this DUContext in the top-context
0030 
0031     DUContext* m_context;
0032 
0033     // cache of unserialized child contexts
0034     QVector<DUContext*> m_childContexts;
0035     // cache of unserialized local declarations
0036     QVector<Declaration*> m_localDeclarations;
0037 
0038     /**
0039      * Adds a child context.
0040      *
0041      * \note Be sure to have set the text location first, so that
0042      * the chain is sorted correctly.
0043      */
0044     void addChildContext(DUContext* context);
0045 
0046     /**Removes the context from childContexts
0047      * @return Whether a context was removed
0048      * */
0049     bool removeChildContext(DUContext* context);
0050 
0051     void addImportedChildContext(DUContext* context);
0052     void removeImportedChildContext(DUContext* context);
0053 
0054     void addDeclaration(Declaration* declaration);
0055 
0056     /**Removes the declaration from localDeclarations
0057      * @return Whether a declaration was removed
0058      * */
0059     bool removeDeclaration(Declaration* declaration);
0060 
0061     //Files the scope identifier into target
0062     void scopeIdentifier(bool includeClasses, QualifiedIdentifier& target) const;
0063 
0064     //Iterates through all visible declarations within a given context, including the ones propagated from sub-contexts
0065     class VisibleDeclarationIterator
0066     {
0067 public:
0068         struct StackEntry
0069         {
0070             explicit StackEntry(const DUContextDynamicData* data = nullptr)
0071                 : data(data)
0072                 , index(0)
0073                 , nextChild(0)
0074             {
0075             }
0076 
0077             const DUContextDynamicData* data;
0078             int index;
0079             uint nextChild;
0080         };
0081 
0082         explicit VisibleDeclarationIterator(const DUContextDynamicData* data)
0083             : current(data)
0084         {
0085             toValidPosition();
0086         }
0087 
0088         inline Declaration* operator*() const
0089         {
0090             return current.data ? current.data->m_localDeclarations.value(current.index) : nullptr;
0091         }
0092 
0093         inline VisibleDeclarationIterator& operator++()
0094         {
0095             ++current.index;
0096             toValidPosition();
0097             return *this;
0098         }
0099 
0100         inline operator bool() const
0101         {
0102             return current.data && !current.data->m_localDeclarations.isEmpty();
0103         }
0104 
0105         // Moves the cursor to the next valid position, from an invalid one
0106         void toValidPosition()
0107         {
0108             if (!current.data || current.index < current.data->m_localDeclarations.size()) {
0109                 // still valid
0110                 return;
0111             }
0112 
0113             do {
0114                 // Check if we can proceed into a propagating child-context
0115                 for (int a = current.nextChild; a < current.data->m_childContexts.size(); ++a) {
0116                     DUContext* child = current.data->m_childContexts[a];
0117 
0118                     if (ctx_d_func(child)->m_propagateDeclarations) {
0119                         current.nextChild = a + 1;
0120                         stack.append(current);
0121                         current = StackEntry(ctx_dynamicData(child));
0122                         toValidPosition();
0123                         return;
0124                     }
0125                 }
0126 
0127                 //Go up and into the next valid context
0128                 if (stack.isEmpty()) {
0129                     current = StackEntry();
0130                     return;
0131                 }
0132 
0133                 current = stack.back();
0134                 stack.pop_back();
0135             } while (true);
0136         }
0137 
0138         StackEntry current;
0139 
0140         KDevVarLengthArray<StackEntry> stack;
0141     };
0142 
0143     /**
0144      * Returns true if this context is imported by the given one, on any level.
0145      * */
0146     bool imports(const DUContext* context, const TopDUContext* source,
0147                  QSet<const DUContextDynamicData*>* recursionGuard) const;
0148 };
0149 }
0150 
0151 Q_DECLARE_TYPEINFO(KDevelop::DUContextDynamicData::VisibleDeclarationIterator::StackEntry, Q_MOVABLE_TYPE);
0152 
0153 #endif