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

0001 /*
0002     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0003     SPDX-FileCopyrightText: 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #ifndef KDEVPLATFORM_DUCONTEXT_H
0009 #define KDEVPLATFORM_DUCONTEXT_H
0010 
0011 #include <QHash>
0012 #include <QList>
0013 #include <QSet>
0014 #include <QVector>
0015 
0016 #include <util/kdevvarlengtharray.h>
0017 
0018 #include "identifier.h"
0019 #include "duchainbase.h"
0020 #include "types/abstracttype.h"
0021 #include "duchainpointer.h"
0022 #include "declarationid.h"
0023 #include "indexedducontext.h"
0024 
0025 #include "navigation/abstractnavigationwidget.h"
0026 
0027 class QWidget;
0028 
0029 namespace KDevelop {
0030 class Declaration;
0031 class DUChain;
0032 class Use;
0033 class TopDUContext;
0034 class DUContext;
0035 class DUContextData;
0036 
0037 class KDEVPLATFORMLANGUAGE_EXPORT DUChainVisitor
0038 {
0039 public:
0040     virtual void visit(DUContext* context) = 0;
0041     virtual void visit(Declaration* declaration) = 0;
0042     virtual ~DUChainVisitor();
0043 };
0044 
0045 using DUContextPointer = DUChainPointer<DUContext>;
0046 
0047 /**
0048  * A single context in source code, represented as a node in a
0049  * directed acyclic graph.
0050  *
0051  * Access to context objects must be serialised by holding the
0052  * chain lock, ie. DUChain::lock().
0053  *
0054  * NOTE: A du-context can be freely edited as long as it's parent-context is zero.
0055  * In the moment the parent-context is set, the context may only be edited when it
0056  * is allowed to edited it's top-level context(@see TopLevelContext::inDUChain()
0057  *
0058  * @todo change child relationships to a linked list within the context?
0059  */
0060 class KDEVPLATFORMLANGUAGE_EXPORT DUContext
0061     : public DUChainBase
0062 {
0063     friend class Use;
0064     friend class Declaration;
0065     friend class DeclarationData;
0066     friend class DUContextData;
0067     friend class DUContextDynamicData;
0068     friend class Definition;
0069     friend class VisibleDeclarationIterator;
0070 
0071 public:
0072     /**
0073      * Constructor. No convenience methods, as the initialisation order is important,
0074      *
0075      * @param anonymous Whether the context should be added as an anonymous context to the parent. That way the context can never be found through any of the parent's member-functions.
0076      *
0077      * If the parent is in the symbol table and the context is not anonymous, it will also be added to the symbol table. You need a write-lock to the DUChain then
0078      */
0079     explicit DUContext(const RangeInRevision& range, DUContext* parent = nullptr, bool anonymous = false);
0080     explicit DUContext(DUContextData&);
0081 
0082     /**
0083      * Destructor. Will delete all child contexts which are defined within
0084      * the same file as this context.
0085      */
0086     ~DUContext() override;
0087 
0088     DUContext& operator=(const DUContext& rhs) = delete;
0089 
0090     enum ContextType : quint8 {
0091         Global /**< A context that declares functions, namespaces or classes */,
0092         Namespace /**< A context that declares namespace members */,
0093         Class /**< A context that declares class members */,
0094         Function /**< A context that declares function-arguments */,
0095         Template /**< A context that declares template-parameters */,
0096         Enum /**< A context that contains a list of enumerators */,
0097         Helper    /**< A helper context. This context is treated specially during search:
0098                    *   when searching within the imports of a context, and that context's parent
0099                    *   is a context of type DUContext::Helper, then the upwards search is continued
0100                    *   into that helper(The decision happens in shouldSearchInParent)  */,
0101         Other /**< Represents executable code, like for example within a compound-statement */
0102     };
0103 
0104     enum SearchFlag {
0105         NoSearchFlags = 0 /**< Searching for everything */,
0106         InImportedParentContext = 1 /**< Internal, do not use from outside */,
0107         OnlyContainerTypes = 2 /**< Not implemented yet */,
0108         DontSearchInParent =
0109             4 /**< IF  this flag is set, findDeclarations(..) will not search for the identifier in parent-contexts(which does not include imported parent-contexts) */,
0110         NoUndefinedTemplateParams =
0111             8 /**< For languages that support templates(like C++). If this is set, the search should fail as soon as undefined template-parameters are involved. */,
0112         DirectQualifiedLookup =
0113             16 /**< When this flag is used, the searched qualified identifier should NOT be split up into it's components and looked up one by one. Currently only plays a role in C++ specific parts. */,
0114         NoFiltering =
0115             32 /**< Should be set when no filtering at all is wished, not even filtering that is natural for the underlying language(For example in C++, constructors are filtered out be default) */,
0116         OnlyFunctions =
0117             64 /**< When this is given, only function-declarations are returned. In case of C++, this also means that constructors can be retrieved, while normally they are filtered out. */,
0118         NoImportsCheck =
0119             128 /**< With this parameter, a global search will return all matching items, from all contexts, not only from imported ones. */,
0120         NoSelfLookUp =
0121             256 /**< With this parameter, the special-treatment during search that allows finding the context-class by its name is disabled. */,
0122         DontResolveAliases = 512 /**< Disables the resolution of alias declarations in the returned list*/,
0123         LastSearchFlag = 1024
0124     };
0125 
0126     Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
0127 
0128     ContextType type() const;
0129     void setType(ContextType type);
0130 
0131     /**
0132      * If this context was opened by a declaration or definition, this returns that item.
0133      *
0134      * The returned declaration/definition will have this context set as @c internalContext()
0135      */
0136     Declaration* owner() const;
0137     /**
0138      * Sets the declaration/definition, and also updates it's internal context (they are strictly paired together).
0139      *
0140      * The declaration has to be part of the same top-context.
0141      */
0142     void setOwner(Declaration* decl);
0143 
0144     /**
0145      * Calculate the depth of this context, from the top level context in the file.
0146      */
0147     int depth() const;
0148 
0149     /**
0150      * Find the top context.
0151      */
0152     TopDUContext* topContext() const override;
0153 
0154     /**
0155      * Visits all duchain objects in the whole duchain.
0156      *
0157      * Classes that hold a unique link to duchain objects like instantiations
0158      * have to pass the visitor over to those classes.
0159      * */
0160     virtual void visit(DUChainVisitor& visitor);
0161 
0162     /**
0163      * Find the context which most specifically covers @p position.
0164      *
0165      * The search is recursive, so the most specific context is found.
0166      *
0167      * @param includeBorders When this is true, contexts will also be found that
0168      *                           have the position on their borders.
0169      *
0170      * @warning This uses the ranges in the local revision of the document (at last parsing time).
0171      *          Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first.
0172      */
0173     DUContext* findContextAt(const CursorInRevision& position, bool includeBorders = false) const;
0174 
0175     /**
0176      * Find a child declaration that has a rang that covers the given @p position.
0177      *
0178      * The search is local, not recursive.
0179      *
0180      * @warning This uses the ranges in the local revision of the document (at last parsing time).
0181      *          Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first.
0182      */
0183     Declaration* findDeclarationAt(const CursorInRevision& position) const;
0184 
0185     /**
0186      * Find the context which most specifically covers @a range.
0187      *
0188      * @warning This uses the ranges in the local revision of the document (at last parsing time).
0189      *          Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first.
0190      */
0191     DUContext* findContextIncluding(const RangeInRevision& range) const;
0192 
0193     /**
0194      * Calculate the fully qualified scope identifier.
0195      */
0196     QualifiedIdentifier scopeIdentifier(bool includeClasses = false) const;
0197 
0198     /**
0199      * Returns true if this context has the same scope identifier as the given one.
0200      *
0201      * @note This is much more efficient than computing the identifiers through @c scopeIdentifier(..)
0202      * and comparing them
0203      */
0204     bool equalScopeIdentifier(const DUContext* rhs) const;
0205 
0206     /**
0207      * Scope identifier, used to qualify the identifiers occurring in each context.
0208      *
0209      * This is the part relative to the parent context.
0210      */
0211     QualifiedIdentifier localScopeIdentifier() const;
0212 
0213     /**
0214      * Same as @c localScopeIdentifier(), but faster.
0215      */
0216     IndexedQualifiedIdentifier indexedLocalScopeIdentifier() const;
0217 
0218     /**
0219      * Scope identifier, used to qualify the identifiers occurring in each context
0220      * This must not be called once this context has children.
0221      */
0222     void setLocalScopeIdentifier(const QualifiedIdentifier& identifier);
0223 
0224     /**
0225      * Returns whether this context is listed in the symbol table (Namespaces and classes)
0226      */
0227     bool inSymbolTable() const;
0228 
0229     /**
0230      * Move this object into/out of the symbol table.
0231      *
0232      * @note You need to have a duchain write lock, unless this is a TopDUContext.
0233      */
0234     void setInSymbolTable(bool inSymbolTable);
0235 
0236     /**
0237      * Returns the immediate parent context of this context.
0238      */
0239     DUContext* parentContext() const;
0240 
0241     /**
0242      * Represents an imported parent context.
0243      */
0244     struct KDEVPLATFORMLANGUAGE_EXPORT Import
0245     {
0246         /**
0247          * @note DUChain must be read-locked when this is called
0248          */
0249         Import(DUContext* context, const DUContext* importer,
0250                const CursorInRevision& position = CursorInRevision::invalid());
0251         Import() : position(CursorInRevision::invalid()) { }
0252         explicit Import(const DeclarationId& id, const CursorInRevision& position = CursorInRevision::invalid());
0253 
0254         bool operator==(const Import& rhs) const
0255         {
0256             return m_context == rhs.m_context && m_declaration == rhs.m_declaration;
0257         }
0258 
0259         /**
0260          * @param topContext The top-context from where to start searching.
0261          *                   This is important to find the correct imports
0262          *                   in the case of templates or similar structures.
0263          */
0264         DUContext* context(const TopDUContext* topContext, bool instantiateIfRequired = true) const;
0265 
0266         /**
0267          * Returns the top-context index, if this import is not a specialization import.
0268          */
0269         uint topContextIndex() const
0270         {
0271             return m_context.topContextIndex();
0272         }
0273 
0274         IndexedDUContext indexedContext() const
0275         {
0276             return m_context;
0277         }
0278 
0279         /**
0280          * Returns true if this import is direct.
0281          *
0282          * That is, the import is not referred to by its identifier,
0283          * but rather directly by its index.
0284          */
0285         bool isDirect() const;
0286 
0287         /**
0288          * If this import is indirect, returns the imported declaration-id
0289          */
0290         DeclarationId indirectDeclarationId() const
0291         {
0292             return m_declaration;
0293         }
0294 
0295         CursorInRevision position;
0296 
0297 private:
0298         //Either we store m_declaration, or m_context. That way we can resolve specialized contexts.
0299         ///@todo Compress using union
0300         DeclarationId m_declaration;
0301         IndexedDUContext m_context;
0302     };
0303 
0304     /**
0305      * Returns the list of imported parent contexts for this context.
0306      *
0307      * @warning The list may contain objects that are not valid any more,
0308      *          i.e. data() returns zero, @see addImportedParentContext)
0309      * @warning The import structure may contain loops if this is a TopDUContext,
0310      *          so be careful when traversing the tree.
0311      * @note This is expensive.
0312      */
0313     virtual QVector<Import> importedParentContexts() const;
0314 
0315     /**
0316      * If the given context is directly imported into this one, and
0317      * @c addImportedParentContext(..) was called with a valid cursor,
0318      * this will return that position. Otherwise an invalid cursor is returned.
0319      */
0320     virtual CursorInRevision importPosition(const DUContext* target) const;
0321 
0322     /**
0323      * Returns true if this context imports @param origin at any depth, else false.
0324      */
0325     virtual bool imports(const DUContext* origin,
0326                          const CursorInRevision& position = CursorInRevision::invalid()) const;
0327 
0328     /**
0329      * Adds an imported context.
0330      *
0331      * @param anonymous If this is true, the import will not be registered at the imported context.
0332      *                  This allows du-chain contexts importing without having a write-lock.
0333      * @param position Position where the context is imported. This is mainly important in C++ with included files.
0334      *
0335      * If the context is already imported, only the position is updated.
0336      *
0337      * @note Be sure to have set the text location first, so that the chain is sorted correctly.
0338      */
0339     virtual void addImportedParentContext(DUContext* context,
0340                                           const CursorInRevision& position = CursorInRevision::invalid(),
0341                                           bool anonymous = false, bool temporary = false);
0342 
0343     /**
0344      * Adds an imported context, which may be indirect.
0345      *
0346      * @warning This is only allowed if this context is _NOT_ a top-context.
0347      * @warning When using this mechanism, this context will not be registered as importer to the other one.
0348      * @warning The given import _must_ be indirect.
0349      *
0350      * @return true if the import was already imported before, else false.
0351      */
0352     bool addIndirectImport(const DUContext::Import& import);
0353 
0354     /**
0355      * Removes a child context.
0356      */
0357     virtual void removeImportedParentContext(DUContext* context);
0358 
0359     /**
0360      * Clear all imported parent contexts.
0361      */
0362     virtual void clearImportedParentContexts();
0363 
0364     /**
0365      * If this is set to true, all declarations that are added to this context
0366      * will also be visible in the parent-context.
0367      *
0368      * They will be visible in the parent using @c findDeclarations(...) and
0369      * @c findLocalDeclarations(...), but will not be in the list of @c localDeclarations(...).
0370      */
0371     void setPropagateDeclarations(bool propagate);
0372 
0373     bool isPropagateDeclarations() const;
0374 
0375     /**
0376      * Returns the list of contexts importing this context.
0377      *
0378      * @note Very expensive, since the importers top-contexts need to be loaded.
0379      */
0380     virtual QVector<DUContext*> importers() const;
0381 
0382     /**
0383      * Returns the list of indexed importers.
0384      *
0385      * Cheap, because nothing needs to be loaded.
0386      */
0387     KDevVarLengthArray<IndexedDUContext> indexedImporters() const;
0388 
0389     /**
0390      * Returns the list of immediate child contexts for this context.
0391      *
0392      * @note This is expensive.
0393      */
0394     QVector<DUContext*> childContexts() const;
0395 
0396     /**
0397      * Clears and deletes all child contexts recursively.
0398      *
0399      * This will not cross file boundaries.
0400      */
0401     void deleteChildContextsRecursively();
0402 
0403     /**
0404      * Resort the child contexts by their range.
0405      *
0406      * You must call this when you manually change the range of child contexts in a way
0407      * that could break the internal range sorting.
0408      */
0409     void resortChildContexts();
0410 
0411     /**
0412      * Returns true if this declaration is accessible through the du-chain,
0413      * and thus cannot be edited without a du-chain write lock
0414      */
0415     virtual bool inDUChain() const;
0416 
0417     /**
0418      * Retrieve the context which is specialized with the given
0419      * @a specialization as seen from the given @a topContext.
0420      *
0421      * @param specialization the specialization index (see DeclarationId)
0422      * @param topContext the top context representing the perspective from which to specialize.
0423      *                   if @p topContext is zero, only already existing specializations are returned,
0424      *                   and if none exists, zero is returned.
0425      * @param upDistance upwards distance in the context-structure of the
0426      *                   given specialization-info. This allows specializing children.
0427      */
0428     virtual DUContext* specialize(const IndexedInstantiationInformation& specialization,
0429                                   const TopDUContext* topContext, int upDistance = 0);
0430 
0431     /**
0432      * Searches for and returns a declaration with a given @p identifier in this context, which
0433      * is currently active at the given text @p position, with the given type @p dataType.
0434      * In fact, only items are returned that are declared BEFORE that position.
0435      *
0436      * @param identifier the identifier of the definition to search for
0437      * @param position the text position to search for
0438      * @param topContext the top-context from where a completion is triggered.
0439      *                   This is needed so delayed types (templates in C++) can be resolved in the correct context.
0440      * @param dataType the type to match, or null for no type matching.
0441      *
0442      * @returns the requested declaration if one was found, otherwise null.
0443      *
0444      * @warning this may return declarations which are not in this tree, you may need to lock them too...
0445      */
0446     QList<Declaration*> findDeclarations(const QualifiedIdentifier& identifier,
0447                                          const CursorInRevision& position = CursorInRevision::invalid(),
0448                                          const AbstractType::Ptr& dataType = AbstractType::Ptr(),
0449                                          const TopDUContext* topContext = nullptr,
0450                                          SearchFlags flags = NoSearchFlags) const;
0451 
0452     /**
0453      * Searches for and returns a declaration with a given @a identifier in this context, which
0454      * is currently active at the given text @a position.
0455      *
0456      * @param identifier the identifier of the definition to search for
0457      * @param topContext the top-context from where a completion is triggered.
0458      *                   This is needed so delayed types(templates in C++) can be resolved in the correct context.
0459      * @param position   the text position to search for
0460      *
0461      * @returns the requested declaration if one was found, otherwise null.
0462      *
0463      * @warning this may return declarations which are not in this tree, you may need to lock them too...
0464      *
0465      * @overload
0466      */
0467     QList<Declaration*> findDeclarations(const IndexedIdentifier& identifier,
0468                                          const CursorInRevision& position = CursorInRevision::invalid(),
0469                                          const TopDUContext* topContext = nullptr,
0470                                          SearchFlags flags = NoSearchFlags) const;
0471 
0472     /**
0473      * Prefer the version above for speed reasons.
0474      */
0475     QList<Declaration*> findDeclarations(const Identifier& identifier,
0476                                          const CursorInRevision& position = CursorInRevision::invalid(),
0477                                          const TopDUContext* topContext = nullptr,
0478                                          SearchFlags flags = NoSearchFlags) const;
0479 
0480     /**
0481      * Returns the type of any @a identifier defined in this context, or
0482      * null if one is not found.
0483      *
0484      * Does not search imported parent-contexts(like base-classes).
0485      */
0486     QList<Declaration*> findLocalDeclarations(const IndexedIdentifier& identifier,
0487                                               const CursorInRevision& position = CursorInRevision::invalid(),
0488                                               const TopDUContext* topContext = nullptr,
0489                                               const AbstractType::Ptr& dataType = AbstractType::Ptr(),
0490                                               SearchFlags flags = NoSearchFlags) const;
0491 
0492     /**
0493      * Prefer the version above for speed reasons.
0494      */
0495     QList<Declaration*> findLocalDeclarations(const Identifier& identifier,
0496                                               const CursorInRevision& position = CursorInRevision::invalid(),
0497                                               const TopDUContext* topContext = nullptr,
0498                                               const AbstractType::Ptr& dataType = AbstractType::Ptr(),
0499                                               SearchFlags flags = NoSearchFlags) const;
0500 
0501     /**
0502      * Clears all local declarations.
0503      *
0504      * Does not delete the declaration; the caller assumes ownership.
0505      */
0506     QVector<Declaration*> clearLocalDeclarations();
0507 
0508     /**
0509      * Clears all local declarations.
0510      *
0511      * Deletes these declarations, as the context has ownership.
0512      */
0513     void deleteLocalDeclarations();
0514 
0515     /**
0516      * Returns all local declarations
0517      *
0518      * @param source A source-context that is needed to instantiate template-declarations in some cases.
0519      *               If it is zero, that signalizes that missing members should not be instantiated.
0520      */
0521     virtual QVector<Declaration*> localDeclarations(const TopDUContext* source = nullptr) const;
0522 
0523     /**
0524      * Resort the local declarations by their range.
0525      *
0526      * You must call this when you manually change the range of declarations in a way
0527      * that could break the internal range sorting.
0528      */
0529     void resortLocalDeclarations();
0530 
0531     /**
0532      * Searches for the most specific context for the given cursor @p position in the given @p url.
0533      *
0534      * @param position the text position to search for
0535      * @param parent the parent context to search from (this is mostly an internal detail, but if you only
0536      *               want to search in a subbranch of the chain, you may specify the parent here)
0537      *
0538      * @returns the requested context if one was found, otherwise null.
0539      */
0540     DUContext* findContext(const CursorInRevision& position, DUContext* parent = nullptr) const;
0541 
0542     /**
0543      * Iterates the tree to see if the provided @a context is a subcontext of this context.
0544      *
0545      * @returns true if @a context is a subcontext, otherwise false.
0546      */
0547     bool parentContextOf(DUContext* context) const;
0548 
0549     /**
0550      * Return a list of all reachable declarations for a given cursor @p position in a given @p url.
0551      *
0552      * @param position the text position to search for
0553      * @param topContext the top-context from where a completion is triggered.
0554      *                   This is needed so delayed types(templates in C++) can be resolved
0555      *                   in the correct context.
0556      * @param searchInParents should declarations from parent-contexts be listed?
0557      *                        If false, only declarations from this and imported contexts will be returned.
0558      *
0559      * The returned declarations are paired together with their inheritance-depth,
0560      * which is the count of steps to into other contexts that were needed to find the declaration.
0561      * Declarations reached through a namespace- or global-context are offsetted by 1000.
0562      *
0563      * This also includes Declarations from sub-contexts that were propagated upwards
0564      * using @c setPropagateDeclarations(true).
0565      *
0566      * @returns the requested declarations, if any were active at that location.
0567      *          Declarations propagated into this context(@c setPropagateDeclarations) are included.
0568      */
0569     QVector<QPair<Declaration*, int>> allDeclarations(const CursorInRevision& position,
0570                                                       const TopDUContext* topContext,
0571                                                       bool searchInParents = true) const;
0572 
0573     /**
0574      * Delete and remove all slaves (uses, declarations, definitions, contexts) that are not in the given set.
0575      */
0576     void cleanIfNotEncountered(const QSet<DUChainBase*>& encountered);
0577 
0578     /**
0579      * Uses:
0580      * A "Use" represents any position in a document where a Declaration is used literally.
0581      * For efficiency, since there can be many many uses, they are managed efficiently by
0582      * TopDUContext and DUContext. In TopDUContext, the used declarations are registered
0583      * and assigned a "Declaration-Index" while calling TopDUContext::indexForUsedDeclaration.
0584      * From such a declaration-index, the declaration can be retrieved back by calling
0585      * @c TopDUContext::usedDeclarationForIndex.
0586      *
0587      * The actual uses are stored within DUContext, where each use consists of a range and
0588      * the declaration-index of the used declaration.
0589      * */
0590 
0591     /**
0592      * Return a vector of all uses which occur in this context.
0593      *
0594      * To get the actual declarations, use @c TopDUContext::usedDeclarationForIndex(..)
0595      * with the declarationIndex.
0596      */
0597     const Use* uses() const;
0598 
0599     /**
0600      * Returns the count of uses that can be accessed through @c uses()
0601      */
0602     int usesCount() const;
0603 
0604     /**
0605      * Determines whether the given declaration has uses or not
0606      */
0607     static bool declarationHasUses(Declaration* decl);
0608 
0609     /**
0610      * Find the use which encompasses @a position, if one exists.
0611      * @return The local index of the use, or -1
0612      */
0613     int findUseAt(const CursorInRevision& position) const;
0614 
0615     /**
0616      * @note The change must not break the ordering
0617      */
0618     void changeUseRange(int useIndex, const RangeInRevision& range);
0619 
0620     /**
0621      * Assigns the declaration represented by @p declarationIndex
0622      * to the use with index @p useIndex.
0623      */
0624     void setUseDeclaration(int useIndex, int declarationIndex);
0625 
0626     /**
0627      * Creates a new use of the declaration given  through @p declarationIndex.
0628      * The index must be retrieved through @c TopDUContext::indexForUsedDeclaration(..).
0629      *
0630      * @param range The range of the use
0631      * @param insertBefore A hint where in the vector of uses to insert the use.
0632      *                     Must be correct so the order is preserved(ordered by position),
0633      *                     or -1 to automatically choose the position.
0634      *
0635      * @return Local index of the created use
0636      */
0637     int createUse(int declarationIndex, const RangeInRevision& range, int insertBefore = -1);
0638 
0639     /**
0640      * Deletes the use number @p index.
0641      *
0642      * @param index is the position in the vector of uses, not a used declaration index.
0643      */
0644     void deleteUse(int index);
0645 
0646     /**
0647      * Clear and delete all uses in this context.
0648      */
0649     virtual void deleteUses();
0650 
0651     /**
0652      * Recursively delete all uses in this context and all its child-contexts
0653      */
0654     virtual void deleteUsesRecursively();
0655 
0656     /**
0657      * Can be specialized by languages to create a navigation/information-widget.
0658      *
0659      * The returned widget will be owned by the caller.
0660      *
0661      * @param decl A member-declaration of this context the navigation-widget should be created for.
0662      *            Zero to create a widget for this context.
0663      * @param topContext Top-context from where the navigation-widget is triggered.
0664      *                   In C++, this is needed to resolve forward-declarations.
0665      *
0666      * Can return zero which disables the navigation widget.
0667      *
0668      * If you setProperty("DoNotCloseOnCursorMove", true) on the widget returned,
0669      * then the widget will not close when the cursor moves in the document, which
0670      * enables you to change the document contents from the widget without immediately closing the widget.
0671      */
0672     virtual AbstractNavigationWidget*
0673     createNavigationWidget(Declaration* decl = nullptr, TopDUContext* topContext = nullptr,
0674                            AbstractNavigationWidget::DisplayHints hints = AbstractNavigationWidget::NoHints) const;
0675 
0676     enum {
0677         Identity = 2
0678     };
0679 
0680     /**
0681      * Represents multiple qualified identifiers in a way that is better
0682      * to manipulate and allows applying namespace-aliases or -imports easily.
0683      *
0684      * A SearchItem generally represents a tree of identifiers, and represents
0685      * all the qualified identifiers that can be constructed by walking
0686      * along the tree starting at an arbitrary root-node into the depth using the "next" pointers.
0687      *
0688      * The insertion order in the hierarchy determines the order of the represented list.
0689      */
0690     struct KDEVPLATFORMLANGUAGE_EXPORT SearchItem
0691         : public QSharedData
0692     {
0693         using Ptr = QExplicitlySharedDataPointer<SearchItem>;
0694         using PtrList = KDevVarLengthArray<Ptr, 256>;
0695 
0696         /**
0697          * Constructs a representation of the given @p id qualified identifier,
0698          * starting at its index @p start.
0699          *
0700          * @param nextItem is set as next item to the last item in the chain
0701          */
0702         explicit SearchItem(const QualifiedIdentifier& id, const Ptr& nextItem = Ptr(), int start = 0);
0703 
0704         /**
0705          * Constructs a representation of the given @p id qualified identifier,
0706          * starting at its index @p start.
0707          *
0708          * @param nextItems is set as next item to the last item in the chain
0709          */
0710         SearchItem(const QualifiedIdentifier& id, const PtrList& nextItems, int start = 0);
0711 
0712         SearchItem(bool explicitlyGlobal, const IndexedIdentifier& id, const PtrList& nextItems);
0713         SearchItem(bool explicitlyGlobal, const IndexedIdentifier& id, const Ptr& nextItem);
0714 
0715         bool isEmpty() const;
0716         bool hasNext() const;
0717 
0718         /**
0719          * Appends the given item to every item that can be reached from this item,
0720          * and not only to the end items.
0721          *
0722          * The effect to search is that the given item is searched with all prefixes
0723          * contained in this earch-item prepended.
0724          *
0725          * @warning This changes all contained sub-nodes, but they can be shared with
0726          *          other SearchItem trees. You should not use this on SearchItem trees
0727          *          that have shared nodes with other trees.
0728          *
0729          * @note These functions ignore explicitly global items.
0730          */
0731         void addToEachNode(const Ptr& item);
0732         void addToEachNode(const PtrList& items);
0733 
0734         /**
0735          * Returns true if the given identifier matches one of the identifiers
0736          * represented by this SearchItem. Does not respect the explicitlyGlobal flag
0737          */
0738         bool match(const QualifiedIdentifier& id, int offset = 0) const;
0739 
0740         /**
0741          * @note expensive
0742          */
0743         QVector<QualifiedIdentifier> toList(const QualifiedIdentifier& prefix = QualifiedIdentifier()) const;
0744 
0745         void addNext(const Ptr& other);
0746 
0747         bool isExplicitlyGlobal;
0748         IndexedIdentifier identifier;
0749         PtrList next;
0750     };
0751 
0752     ///@todo Should be protected, moved here temporarily until I have figured
0753     ///out why the gcc 4.1.3 fails in cppducontext.h:212, which should work (within kdevelop)
0754 
0755     /// Declaration search implementation
0756 
0757     using DeclarationList = QList<Declaration*>;
0758 
0759     /**
0760      * This is a more complex interface to the declaration search engine.
0761      *
0762      * Always prefer @c findDeclarations(..) when possible.
0763      *
0764      * Advantage of this interface:
0765      * - You can search multiple identifiers at one time.
0766      *   However, those should be aliased identifiers for one single item, because
0767      *   search might stop as soon as one item is found.
0768      * - The source top-context is needed to correctly resolve template-parameters
0769      *
0770      * @param position A valid position, if in doubt use textRange().end()
0771      *
0772      * @warning @p position must be valid!
0773      *
0774      * @param depth Depth of the search in parents. This is used to prevent endless
0775      *              recursions in endless import loops.
0776      *
0777      *
0778      * @return whether the search was successful. If it is false, it had to be stopped
0779      *         for special reasons (like some flags)
0780      */
0781     virtual bool findDeclarationsInternal(const SearchItem::PtrList& identifiers,
0782                                           const CursorInRevision& position, const AbstractType::Ptr& dataType,
0783                                           DeclarationList& ret, const TopDUContext* source, SearchFlags flags,
0784                                           uint depth) const;
0785 
0786     /**
0787      * Returns the qualified identifier @p id with all aliases (for example namespace imports) applied
0788      *
0789      * Example: If the namespace 'Foo' is imported, and id is 'Bar',
0790      *           then the returned list is 'Bar' and 'Foo::Bar'
0791      */
0792     QVector<QualifiedIdentifier> fullyApplyAliases(const QualifiedIdentifier& id,
0793                                                    const TopDUContext* source) const;
0794 
0795 protected:
0796 
0797     /**
0798      * After one scope was searched, this function is asked whether more
0799      * results should be collected. Override it, for example to collect overloaded functions.
0800      *
0801      * The default-implementation returns true as soon as @p decls is not empty.
0802      */
0803     virtual bool foundEnough(const DeclarationList& decls, SearchFlags flags) const;
0804 
0805     /**
0806      * Merges definitions and their inheritance-depth up all branches of the
0807      * definition-use chain into one hash.
0808      *
0809      * This includes declarations propagated from sub-contexts.
0810      *
0811      * @param hadContexts is used to count together all contexts that already were
0812      *                visited, so they are not visited again.
0813      */
0814     virtual void mergeDeclarationsInternal(QVector<QPair<Declaration*, int>>& definitions,
0815                                            const CursorInRevision& position,
0816                                            QHash<const DUContext*, bool>& hadContexts,
0817                                            const TopDUContext* source,
0818                                            bool searchInParents = true, int currentDepth = 0) const;
0819 
0820     void findLocalDeclarationsInternal(const Identifier& identifier,
0821                                        const CursorInRevision& position,
0822                                        const AbstractType::Ptr& dataType,
0823                                        DeclarationList& ret,
0824                                        const TopDUContext* source,
0825                                        SearchFlags flags) const;
0826 
0827     virtual void findLocalDeclarationsInternal(const IndexedIdentifier& identifier,
0828                                                const CursorInRevision& position,
0829                                                const AbstractType::Ptr& dataType,
0830                                                DeclarationList& ret,
0831                                                const TopDUContext* source,
0832                                                SearchFlags flags) const;
0833 
0834     /**
0835      * Applies namespace-imports and namespace-aliases and returns
0836      * possible absolute identifiers that need to be searched.
0837      *
0838      * @param targetIdentifiers will be filled with all identifiers that should
0839      *                          be searched for, instead of identifier.
0840      * @param onlyImports if this is true, namespace-aliases will not be respected,
0841      *                    but only imports. This is faster.
0842      */
0843     void applyAliases(const SearchItem::PtrList& identifiers, SearchItem::PtrList& targetIdentifiers,
0844                       const CursorInRevision& position, bool canBeNamespace, bool onlyImports = false) const;
0845     /**
0846      * Applies the aliases that need to be applied when moving the search
0847      * from this context up to the parent-context.
0848      *
0849      * The default-implementation adds a set of identifiers with the own local
0850      * identifier prefixed, if this is a namespace.
0851      *
0852      * For C++, this is needed when searching out of a namespace, so the item
0853      * can be found within that namespace in another place.
0854      */
0855     virtual void applyUpwardsAliases(SearchItem::PtrList& identifiers, const TopDUContext* source) const;
0856 
0857     DUContext(DUContextData& dd, const RangeInRevision& range, DUContext* parent = nullptr, bool anonymous = false);
0858 
0859     /**
0860      * Just uses the data from the given context. Doesn't copy or change anything,
0861      * and the data will not be deleted on this contexts destruction.
0862      */
0863     DUContext(DUContext& useDataFrom);
0864 
0865     /**
0866      * Whether this context, or any of its parent contexts, has been inserte
0867      * anonymously into the du-chain
0868      *
0869      * @see DUContext::DUContext
0870      */
0871     bool isAnonymous() const;
0872 
0873     /**
0874      * This is called whenever the search needs to do the decision whether it
0875      * should be continued in the parent context.
0876      *
0877      * It is not called when the DontSearchInParent flag is set. Else this should
0878      * be overridden to do language-specific logic.
0879      *
0880      * The default implementation returns false if the flag InImportedParentContext is set.
0881      */
0882     virtual bool shouldSearchInParent(SearchFlags flags) const;
0883 
0884 private:
0885     void initFromTopContext();
0886     void rebuildDynamicData(DUContext* parent, uint ownIndex) override;
0887 
0888     friend class TopDUContext;
0889     friend class IndexedDUContext;
0890     friend class LocalIndexedDUContext;
0891     friend class TopDUContextDynamicData;
0892 
0893     DUCHAIN_DECLARE_DATA(DUContext)
0894     class DUContextDynamicData* m_dynamicData;
0895 };
0896 
0897 /**
0898  * This is the identifier that can be used to search namespace-import declarations,
0899  * and should be used to store namespace-imports.
0900  *
0901  * It is stored statically for performance-reasons, so it doesn't need to be
0902  * constructed every time it is used.
0903  *
0904  * @see NamespaceAliasDeclaration.
0905  */
0906 KDEVPLATFORMLANGUAGE_EXPORT const Identifier& globalImportIdentifier();
0907 
0908 /**
0909  * This is the identifier that can be used to search namespace-alias declarations.
0910  *
0911  * It is stored statically for performance-reasons, so it doesn't need to be
0912  * constructed every time it is used.
0913  *
0914  * @see NamespaceAliasDeclaration.
0915  */
0916 KDEVPLATFORMLANGUAGE_EXPORT const Identifier& globalAliasIdentifier();
0917 
0918 /**
0919  * This is the identifier that can be used to search namespace-import declarations,
0920  * and should be used to store namespace-imports.
0921  *
0922  * It is stored statically for performance-reasons, so it doesn't need to be
0923  * constructed every time it is used.
0924  *
0925  * @see NamespaceAliasDeclaration.
0926  */
0927 KDEVPLATFORMLANGUAGE_EXPORT const IndexedIdentifier& globalIndexedImportIdentifier();
0928 
0929 /**
0930  * This is the identifier that can be used to search namespace-alias declarations.
0931  *
0932  * It is stored statically for performance-reasons, so it doesn't need to be
0933  * constructed every time it is used.
0934  *
0935  * @see NamespaceAliasDeclaration.
0936  */
0937 KDEVPLATFORMLANGUAGE_EXPORT const IndexedIdentifier& globalIndexedAliasIdentifier();
0938 
0939 /**
0940  * Collects all uses of the given @p declarationIndex
0941  */
0942 KDEVPLATFORMLANGUAGE_EXPORT QVector<RangeInRevision> allUses(DUContext* context,
0943                                                              int declarationIndex,
0944                                                              bool noEmptyRanges = false);
0945 }
0946 
0947 Q_DECLARE_TYPEINFO(KDevelop::DUContext::Import, Q_MOVABLE_TYPE);
0948 
0949 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug dbg, const KDevelop::DUContext::Import& import);
0950 
0951 #endif // KDEVPLATFORM_DUCONTEXT_H