1 /*
2     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
3     SPDX-FileCopyrightText: 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
4 
5     SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #ifndef KDEVPLATFORM_DUCONTEXT_H
9 #define KDEVPLATFORM_DUCONTEXT_H
10 
11 #include <QHash>
12 #include <QList>
13 #include <QSet>
14 #include <QVector>
15 
16 #include <util/kdevvarlengtharray.h>
17 
18 #include "identifier.h"
19 #include "duchainbase.h"
20 #include "types/abstracttype.h"
21 #include "duchainpointer.h"
22 #include "declarationid.h"
23 #include "indexedducontext.h"
24 
25 #include "navigation/abstractnavigationwidget.h"
26 
27 class QWidget;
28 
29 namespace KDevelop {
30 class Declaration;
31 class DUChain;
32 class Use;
33 class TopDUContext;
34 class DUContext;
35 class DUContextData;
36 
37 class KDEVPLATFORMLANGUAGE_EXPORT DUChainVisitor
38 {
39 public:
40     virtual void visit(DUContext* context) = 0;
41     virtual void visit(Declaration* declaration) = 0;
42     virtual ~DUChainVisitor();
43 };
44 
45 using DUContextPointer = DUChainPointer<DUContext>;
46 
47 /**
48  * A single context in source code, represented as a node in a
49  * directed acyclic graph.
50  *
51  * Access to context objects must be serialised by holding the
52  * chain lock, ie. DUChain::lock().
53  *
54  * NOTE: A du-context can be freely edited as long as it's parent-context is zero.
55  * In the moment the parent-context is set, the context may only be edited when it
56  * is allowed to edited it's top-level context(@see TopLevelContext::inDUChain()
57  *
58  * @todo change child relationships to a linked list within the context?
59  */
60 class KDEVPLATFORMLANGUAGE_EXPORT DUContext
61     : public DUChainBase
62 {
63     friend class Use;
64     friend class Declaration;
65     friend class DeclarationData;
66     friend class DUContextData;
67     friend class DUContextDynamicData;
68     friend class Definition;
69     friend class VisibleDeclarationIterator;
70 
71 public:
72     /**
73      * Constructor. No convenience methods, as the initialisation order is important,
74      *
75      * @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.
76      *
77      * If the parent is in the symbol table and the context is not anonymous, it will also be added to the symbol table. You nead a write-lock to the DUChain then
78      */
79     explicit DUContext(const RangeInRevision& range, DUContext* parent = nullptr, bool anonymous = false);
80     explicit DUContext(DUContextData&);
81 
82     /**
83      * Destructor. Will delete all child contexts which are defined within
84      * the same file as this context.
85      */
86     ~DUContext() override;
87 
88     DUContext& operator=(const DUContext& rhs) = delete;
89 
90     enum ContextType : quint8 {
91         Global /**< A context that declares functions, namespaces or classes */,
92         Namespace /**< A context that declares namespace members */,
93         Class /**< A context that declares class members */,
94         Function /**< A context that declares function-arguments */,
95         Template /**< A context that declares template-parameters */,
96         Enum /**< A context that contains a list of enumerators */,
97         Helper    /**< A helper context. This context is treated specially during search:
98                    *   when searching within the imports of a context, and that context's parent
99                    *   is a context of type DUContext::Helper, then the upwards search is continued
100                    *   into that helper(The decision happens in shouldSearchInParent)  */,
101         Other /**< Represents executable code, like for example within a compound-statement */
102     };
103 
104     enum SearchFlag {
105         NoSearchFlags = 0 /**< Searching for everything */,
106         InImportedParentContext = 1 /**< Internal, do not use from outside */,
107         OnlyContainerTypes = 2 /**< Not implemented yet */,
108         DontSearchInParent =
109             4 /**< IF  this flag is set, findDeclarations(..) will not search for the identifier in parent-contexts(which does not include imported parent-contexts) */,
110         NoUndefinedTemplateParams =
111             8 /**< For languages that support templates(like C++). If this is set, the search should fail as soon as undefined template-parameters are involved. */,
112         DirectQualifiedLookup =
113             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. */,
114         NoFiltering =
115             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) */,
116         OnlyFunctions =
117             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. */,
118         NoImportsCheck =
119             128 /**< With this parameter, a global search will return all matching items, from all contexts, not only from imported ones. */,
120         NoSelfLookUp =
121             256 /**< With this parameter, the special-treatment during search that allows finding the context-class by its name is disabled. */,
122         DontResolveAliases = 512 /**< Disables the resolution of alias declarations in the returned list*/,
123         LastSearchFlag = 1024
124     };
125 
126     Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
127 
128     ContextType type() const;
129     void setType(ContextType type);
130 
131     /**
132      * If this context was opened by a declaration or definition, this returns that item.
133      *
134      * The returned declaration/definition will have this context set as @c internalContext()
135      */
136     Declaration* owner() const;
137     /**
138      * Sets the declaration/definition, and also updates it's internal context (they are strictly paired together).
139      *
140      * The declaration has to be part of the same top-context.
141      */
142     void setOwner(Declaration* decl);
143 
144     /**
145      * Calculate the depth of this context, from the top level context in the file.
146      */
147     int depth() const;
148 
149     /**
150      * Find the top context.
151      */
152     TopDUContext* topContext() const override;
153 
154     /**
155      * Visits all duchain objects in the whole duchain.
156      *
157      * Classes that hold a unique link to duchain objects like instantiations
158      * have to pass the visitor over to those classes.
159      * */
160     virtual void visit(DUChainVisitor& visitor);
161 
162     /**
163      * Find the context which most specifically covers @p position.
164      *
165      * The search is recursive, so the most specific context is found.
166      *
167      * @param includeBorders When this is true, contexts will also be found that
168      *                           have the position on their borders.
169      *
170      * @warning This uses the ranges in the local revision of the document (at last parsing time).
171      *          Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first.
172      */
173     DUContext* findContextAt(const CursorInRevision& position, bool includeBorders = false) const;
174 
175     /**
176      * Find a child declaration that has a rang that covers the given @p position.
177      *
178      * The search is local, not recursive.
179      *
180      * @warning This uses the ranges in the local revision of the document (at last parsing time).
181      *          Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first.
182      */
183     Declaration* findDeclarationAt(const CursorInRevision& position) const;
184 
185     /**
186      * Find the context which most specifically covers @a range.
187      *
188      * @warning This uses the ranges in the local revision of the document (at last parsing time).
189      *          Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first.
190      */
191     DUContext* findContextIncluding(const RangeInRevision& range) const;
192 
193     /**
194      * Calculate the fully qualified scope identifier.
195      */
196     QualifiedIdentifier scopeIdentifier(bool includeClasses = false) const;
197 
198     /**
199      * Returns true if this context has the same scope identifier as the given one.
200      *
201      * @note This is much more efficient than computing the identifiers through @c scopeIdentifier(..)
202      * and comparing them
203      */
204     bool equalScopeIdentifier(const DUContext* rhs) const;
205 
206     /**
207      * Scope identifier, used to qualify the identifiers occurring in each context.
208      *
209      * This is the part relative to the parent context.
210      */
211     QualifiedIdentifier localScopeIdentifier() const;
212 
213     /**
214      * Same as @c localScopeIdentifier(), but faster.
215      */
216     IndexedQualifiedIdentifier indexedLocalScopeIdentifier() const;
217 
218     /**
219      * Scope identifier, used to qualify the identifiers occurring in each context
220      * This must not be called once this context has children.
221      */
222     void setLocalScopeIdentifier(const QualifiedIdentifier& identifier);
223 
224     /**
225      * Returns whether this context is listed in the symbol table (Namespaces and classes)
226      */
227     bool inSymbolTable() const;
228 
229     /**
230      * Move this object into/out of the symbol table.
231      *
232      * @note You need to have a duchain write lock, unless this is a TopDUContext.
233      */
234     void setInSymbolTable(bool inSymbolTable);
235 
236     /**
237      * Returns the immediate parent context of this context.
238      */
239     DUContext* parentContext() const;
240 
241     /**
242      * Represents an imported parent context.
243      */
244     struct KDEVPLATFORMLANGUAGE_EXPORT Import
245     {
246         /**
247          * @note DUChain must be read-locked when this is called
248          */
249         Import(DUContext* context, const DUContext* importer,
250                const CursorInRevision& position = CursorInRevision::invalid());
ImportImport251         Import() : position(CursorInRevision::invalid()) { }
252         explicit Import(const DeclarationId& id, const CursorInRevision& position = CursorInRevision::invalid());
253 
254         bool operator==(const Import& rhs) const
255         {
256             return m_context == rhs.m_context && m_declaration == rhs.m_declaration;
257         }
258 
259         /**
260          * @param topContext The top-context from where to start searching.
261          *                   This is important to find the correct imports
262          *                   in the case of templates or similar structures.
263          */
264         DUContext* context(const TopDUContext* topContext, bool instantiateIfRequired = true) const;
265 
266         /**
267          * Returns the top-context index, if this import is not a specialization import.
268          */
topContextIndexImport269         uint topContextIndex() const
270         {
271             return m_context.topContextIndex();
272         }
273 
indexedContextImport274         IndexedDUContext indexedContext() const
275         {
276             return m_context;
277         }
278 
279         /**
280          * Returns true if this import is direct.
281          *
282          * That is, the import is not referred to by its identifier,
283          * but rather directly by its index.
284          */
285         bool isDirect() const;
286 
287         /**
288          * If this import is indirect, returns the imported declaration-id
289          */
indirectDeclarationIdImport290         DeclarationId indirectDeclarationId() const
291         {
292             return m_declaration;
293         }
294 
295         CursorInRevision position;
296 
297 private:
298         //Either we store m_declaration, or m_context. That way we can resolve specialized contexts.
299         ///@todo Compress using union
300         DeclarationId m_declaration;
301         IndexedDUContext m_context;
302     };
303 
304     /**
305      * Returns the list of imported parent contexts for this context.
306      *
307      * @warning The list may contain objects that are not valid any more,
308      *          i.e. data() returns zero, @see addImportedParentContext)
309      * @warning The import structure may contain loops if this is a TopDUContext,
310      *          so be careful when traversing the tree.
311      * @note This is expensive.
312      */
313     virtual QVector<Import> importedParentContexts() const;
314 
315     /**
316      * If the given context is directly imported into this one, and
317      * @c addImportedParentContext(..) was called with a valid cursor,
318      * this will return that position. Otherwise an invalid cursor is returned.
319      */
320     virtual CursorInRevision importPosition(const DUContext* target) const;
321 
322     /**
323      * Returns true if this context imports @param origin at any depth, else false.
324      */
325     virtual bool imports(const DUContext* origin,
326                          const CursorInRevision& position = CursorInRevision::invalid()) const;
327 
328     /**
329      * Adds an imported context.
330      *
331      * @param anonymous If this is true, the import will not be registered at the imported context.
332      *                  This allows du-chain contexts importing without having a write-lock.
333      * @param position Position where the context is imported. This is mainly important in C++ with included files.
334      *
335      * If the context is already imported, only the position is updated.
336      *
337      * @note Be sure to have set the text location first, so that the chain is sorted correctly.
338      */
339     virtual void addImportedParentContext(DUContext* context,
340                                           const CursorInRevision& position = CursorInRevision::invalid(),
341                                           bool anonymous = false, bool temporary = false);
342 
343     /**
344      * Adds an imported context, which may be indirect.
345      *
346      * @warning This is only allowed if this context is _NOT_ a top-context.
347      * @warning When using this mechanism, this context will not be registered as importer to the other one.
348      * @warning The given import _must_ be indirect.
349      *
350      * @return true if the import was already imported before, else false.
351      */
352     bool addIndirectImport(const DUContext::Import& import);
353 
354     /**
355      * Removes a child context.
356      */
357     virtual void removeImportedParentContext(DUContext* context);
358 
359     /**
360      * Clear all imported parent contexts.
361      */
362     virtual void clearImportedParentContexts();
363 
364     /**
365      * If this is set to true, all declarations that are added to this context
366      * will also be visible in the parent-context.
367      *
368      * They will be visible in the parent using @c findDeclarations(...) and
369      * @c findLocalDeclarations(...), but will not be in the list of @c localDeclarations(...).
370      */
371     void setPropagateDeclarations(bool propagate);
372 
373     bool isPropagateDeclarations() const;
374 
375     /**
376      * Returns the list of contexts importing this context.
377      *
378      * @note Very expensive, since the importers top-contexts need to be loaded.
379      */
380     virtual QVector<DUContext*> importers() const;
381 
382     /**
383      * Returns the list of indexed importers.
384      *
385      * Cheap, because nothing needs to be loaded.
386      */
387     KDevVarLengthArray<IndexedDUContext> indexedImporters() const;
388 
389     /**
390      * Returns the list of immediate child contexts for this context.
391      *
392      * @note This is expensive.
393      */
394     QVector<DUContext*> childContexts() const;
395 
396     /**
397      * Clears and deletes all child contexts recursively.
398      *
399      * This will not cross file boundaries.
400      */
401     void deleteChildContextsRecursively();
402 
403     /**
404      * Resort the child contexts by their range.
405      *
406      * You must call this when you manually change the range of child contexts in a way
407      * that could break the internal range sorting.
408      */
409     void resortChildContexts();
410 
411     /**
412      * Returns true if this declaration is accessible through the du-chain,
413      * and thus cannot be edited without a du-chain write lock
414      */
415     virtual bool inDUChain() const;
416 
417     /**
418      * Retrieve the context which is specialized with the given
419      * @a specialization as seen from the given @a topContext.
420      *
421      * @param specialization the specialization index (see DeclarationId)
422      * @param topContext the top context representing the perspective from which to specialize.
423      *                   if @p topContext is zero, only already existing specializations are returned,
424      *                   and if none exists, zero is returned.
425      * @param upDistance upwards distance in the context-structure of the
426      *                   given specialization-info. This allows specializing children.
427      */
428     virtual DUContext* specialize(const IndexedInstantiationInformation& specialization,
429                                   const TopDUContext* topContext, int upDistance = 0);
430 
431     /**
432      * Searches for and returns a declaration with a given @p identifier in this context, which
433      * is currently active at the given text @p position, with the given type @p dataType.
434      * In fact, only items are returned that are declared BEFORE that position.
435      *
436      * @param identifier the identifier of the definition to search for
437      * @param position the text position to search for
438      * @param topContext the top-context from where a completion is triggered.
439      *                   This is needed so delayed types (templates in C++) can be resolved in the correct context.
440      * @param dataType the type to match, or null for no type matching.
441      *
442      * @returns the requested declaration if one was found, otherwise null.
443      *
444      * @warning this may return declarations which are not in this tree, you may need to lock them too...
445      */
446     QList<Declaration*> findDeclarations(const QualifiedIdentifier& identifier,
447                                          const CursorInRevision& position = CursorInRevision::invalid(),
448                                          const AbstractType::Ptr& dataType = AbstractType::Ptr(),
449                                          const TopDUContext* topContext = nullptr,
450                                          SearchFlags flags = NoSearchFlags) const;
451 
452     /**
453      * Searches for and returns a declaration with a given @a identifier in this context, which
454      * is currently active at the given text @a position.
455      *
456      * @param identifier the identifier of the definition to search for
457      * @param topContext the top-context from where a completion is triggered.
458      *                   This is needed so delayed types(templates in C++) can be resolved in the correct context.
459      * @param position   the text position to search for
460      *
461      * @returns the requested declaration if one was found, otherwise null.
462      *
463      * @warning this may return declarations which are not in this tree, you may need to lock them too...
464      *
465      * @overload
466      */
467     QList<Declaration*> findDeclarations(const IndexedIdentifier& identifier,
468                                          const CursorInRevision& position = CursorInRevision::invalid(),
469                                          const TopDUContext* topContext = nullptr,
470                                          SearchFlags flags = NoSearchFlags) const;
471 
472     /**
473      * Prefer the version above for speed reasons.
474      */
475     QList<Declaration*> findDeclarations(const Identifier& identifier,
476                                          const CursorInRevision& position = CursorInRevision::invalid(),
477                                          const TopDUContext* topContext = nullptr,
478                                          SearchFlags flags = NoSearchFlags) const;
479 
480     /**
481      * Returns the type of any @a identifier defined in this context, or
482      * null if one is not found.
483      *
484      * Does not search imported parent-contexts(like base-classes).
485      */
486     QList<Declaration*> findLocalDeclarations(const IndexedIdentifier& identifier,
487                                               const CursorInRevision& position = CursorInRevision::invalid(),
488                                               const TopDUContext* topContext = nullptr,
489                                               const AbstractType::Ptr& dataType = AbstractType::Ptr(),
490                                               SearchFlags flags = NoSearchFlags) const;
491 
492     /**
493      * Prefer the version above for speed reasons.
494      */
495     QList<Declaration*> findLocalDeclarations(const Identifier& identifier,
496                                               const CursorInRevision& position = CursorInRevision::invalid(),
497                                               const TopDUContext* topContext = nullptr,
498                                               const AbstractType::Ptr& dataType = AbstractType::Ptr(),
499                                               SearchFlags flags = NoSearchFlags) const;
500 
501     /**
502      * Clears all local declarations.
503      *
504      * Does not delete the declaration; the caller assumes ownership.
505      */
506     QVector<Declaration*> clearLocalDeclarations();
507 
508     /**
509      * Clears all local declarations.
510      *
511      * Deletes these declarations, as the context has ownership.
512      */
513     void deleteLocalDeclarations();
514 
515     /**
516      * Returns all local declarations
517      *
518      * @param source A source-context that is needed to instantiate template-declarations in some cases.
519      *               If it is zero, that signalizes that missing members should not be instantiated.
520      */
521     virtual QVector<Declaration*> localDeclarations(const TopDUContext* source = nullptr) const;
522 
523     /**
524      * Resort the local declarations by their range.
525      *
526      * You must call this when you manually change the range of declarations in a way
527      * that could break the internal range sorting.
528      */
529     void resortLocalDeclarations();
530 
531     /**
532      * Searches for the most specific context for the given cursor @p position in the given @p url.
533      *
534      * @param position the text position to search for
535      * @param parent the parent context to search from (this is mostly an internal detail, but if you only
536      *               want to search in a subbranch of the chain, you may specify the parent here)
537      *
538      * @returns the requested context if one was found, otherwise null.
539      */
540     DUContext* findContext(const CursorInRevision& position, DUContext* parent = nullptr) const;
541 
542     /**
543      * Iterates the tree to see if the provided @a context is a subcontext of this context.
544      *
545      * @returns true if @a context is a subcontext, otherwise false.
546      */
547     bool parentContextOf(DUContext* context) const;
548 
549     /**
550      * Return a list of all reachable declarations for a given cursor @p position in a given @p url.
551      *
552      * @param position the text position to search for
553      * @param topContext the top-context from where a completion is triggered.
554      *                   This is needed so delayed types(templates in C++) can be resolved
555      *                   in the correct context.
556      * @param searchInParents should declarations from parent-contexts be listed?
557      *                        If false, only declarations from this and imported contexts will be returned.
558      *
559      * The returned declarations are paired together with their inheritance-depth,
560      * which is the count of steps to into other contexts that were needed to find the declaration.
561      * Declarations reached through a namespace- or global-context are offsetted by 1000.
562      *
563      * This also includes Declarations from sub-contexts that were propagated upwards
564      * using @c setPropagateDeclarations(true).
565      *
566      * @returns the requested declarations, if any were active at that location.
567      *          Declarations propagated into this context(@c setPropagateDeclarations) are included.
568      */
569     QVector<QPair<Declaration*, int>> allDeclarations(const CursorInRevision& position,
570                                                       const TopDUContext* topContext,
571                                                       bool searchInParents = true) const;
572 
573     /**
574      * Delete and remove all slaves (uses, declarations, definitions, contexts) that are not in the given set.
575      */
576     void cleanIfNotEncountered(const QSet<DUChainBase*>& encountered);
577 
578     /**
579      * Uses:
580      * A "Use" represents any position in a document where a Declaration is used literally.
581      * For efficiency, since there can be many many uses, they are managed efficiently by
582      * TopDUContext and DUContext. In TopDUContext, the used declarations are registered
583      * and assigned a "Declaration-Index" while calling TopDUContext::indexForUsedDeclaration.
584      * From such a declaration-index, the declaration can be retrieved back by calling
585      * @c TopDUContext::usedDeclarationForIndex.
586      *
587      * The actual uses are stored within DUContext, where each use consists of a range and
588      * the declaration-index of the used declaration.
589      * */
590 
591     /**
592      * Return a vector of all uses which occur in this context.
593      *
594      * To get the actual declarations, use @c TopDUContext::usedDeclarationForIndex(..)
595      * with the declarationIndex.
596      */
597     const Use* uses() const;
598 
599     /**
600      * Returns the count of uses that can be accessed through @c uses()
601      */
602     int usesCount() const;
603 
604     /**
605      * Determines whether the given declaration has uses or not
606      */
607     static bool declarationHasUses(Declaration* decl);
608 
609     /**
610      * Find the use which encompasses @a position, if one exists.
611      * @return The local index of the use, or -1
612      */
613     int findUseAt(const CursorInRevision& position) const;
614 
615     /**
616      * @note The change must not break the ordering
617      */
618     void changeUseRange(int useIndex, const RangeInRevision& range);
619 
620     /**
621      * Assigns the declaration represented by @p declarationIndex
622      * to the use with index @p useIndex.
623      */
624     void setUseDeclaration(int useIndex, int declarationIndex);
625 
626     /**
627      * Creates a new use of the declaration given  through @p declarationIndex.
628      * The index must be retrieved through @c TopDUContext::indexForUsedDeclaration(..).
629      *
630      * @param range The range of the use
631      * @param insertBefore A hint where in the vector of uses to insert the use.
632      *                     Must be correct so the order is preserved(ordered by position),
633      *                     or -1 to automatically choose the position.
634      *
635      * @return Local index of the created use
636      */
637     int createUse(int declarationIndex, const RangeInRevision& range, int insertBefore = -1);
638 
639     /**
640      * Deletes the use number @p index.
641      *
642      * @param index is the position in the vector of uses, not a used declaration index.
643      */
644     void deleteUse(int index);
645 
646     /**
647      * Clear and delete all uses in this context.
648      */
649     virtual void deleteUses();
650 
651     /**
652      * Recursively delete all uses in this context and all its child-contexts
653      */
654     virtual void deleteUsesRecursively();
655 
656     /**
657      * Can be specialized by languages to create a navigation/information-widget.
658      *
659      * The returned widget will be owned by the caller.
660      *
661      * @param decl A member-declaration of this context the navigation-widget should be created for.
662      *            Zero to create a widget for this context.
663      * @param topContext Top-context from where the navigation-widget is triggered.
664      *                   In C++, this is needed to resolve forward-declarations.
665      *
666      * Can return zero which disables the navigation widget.
667      *
668      * If you setProperty("DoNotCloseOnCursorMove", true) on the widget returned,
669      * then the widget will not close when the cursor moves in the document, which
670      * enables you to change the document contents from the widget without immediately closing the widget.
671      */
672     virtual AbstractNavigationWidget*
673     createNavigationWidget(Declaration* decl = nullptr, TopDUContext* topContext = nullptr,
674                            AbstractNavigationWidget::DisplayHints hints = AbstractNavigationWidget::NoHints) const;
675 
676     enum {
677         Identity = 2
678     };
679 
680     /**
681      * Represents multiple qualified identifiers in a way that is better
682      * to manipulate and allows applying namespace-aliases or -imports easily.
683      *
684      * A SearchItem generally represents a tree of identifiers, and represents
685      * all the qualified identifiers that can be constructed by walking
686      * along the tree starting at an arbitrary root-node into the depth using the "next" pointers.
687      *
688      * The insertion order in the hierarchy determines the order of the represented list.
689      */
690     struct KDEVPLATFORMLANGUAGE_EXPORT SearchItem
691         : public QSharedData
692     {
693         using Ptr = QExplicitlySharedDataPointer<SearchItem>;
694         using PtrList = KDevVarLengthArray<Ptr, 256>;
695 
696         /**
697          * Constructs a representation of the given @p id qualified identifier,
698          * starting at its index @p start.
699          *
700          * @param nextItem is set as next item to the last item in the chain
701          */
702         explicit SearchItem(const QualifiedIdentifier& id, const Ptr& nextItem = Ptr(), int start = 0);
703 
704         /**
705          * Constructs a representation of the given @p id qualified identifier,
706          * starting at its index @p start.
707          *
708          * @param nextItems is set as next item to the last item in the chain
709          */
710         SearchItem(const QualifiedIdentifier& id, const PtrList& nextItems, int start = 0);
711 
712         SearchItem(bool explicitlyGlobal, const IndexedIdentifier& id, const PtrList& nextItems);
713         SearchItem(bool explicitlyGlobal, const IndexedIdentifier& id, const Ptr& nextItem);
714 
715         bool isEmpty() const;
716         bool hasNext() const;
717 
718         /**
719          * Appends the given item to every item that can be reached from this item,
720          * and not only to the end items.
721          *
722          * The effect to search is that the given item is searched with all prefixes
723          * contained in this earch-item prepended.
724          *
725          * @warning This changes all contained sub-nodes, but they can be shared with
726          *          other SearchItem trees. You should not use this on SearchItem trees
727          *          that have shared nodes with other trees.
728          *
729          * @note These functions ignore explicitly global items.
730          */
731         void addToEachNode(const Ptr& item);
732         void addToEachNode(const PtrList& items);
733 
734         /**
735          * Returns true if the given identifier matches one of the identifiers
736          * represented by this SearchItem. Does not respect the explicitlyGlobal flag
737          */
738         bool match(const QualifiedIdentifier& id, int offset = 0) const;
739 
740         /**
741          * @note expensive
742          */
743         QVector<QualifiedIdentifier> toList(const QualifiedIdentifier& prefix = QualifiedIdentifier()) const;
744 
745         void addNext(const Ptr& other);
746 
747         bool isExplicitlyGlobal;
748         IndexedIdentifier identifier;
749         PtrList next;
750     };
751 
752     ///@todo Should be protected, moved here temporarily until I have figured
753     ///out why the gcc 4.1.3 fails in cppducontext.h:212, which should work (within kdevelop)
754 
755     /// Declaration search implementation
756 
757     using DeclarationList = QList<Declaration*>;
758 
759     /**
760      * This is a more complex interface to the declaration search engine.
761      *
762      * Always prefer @c findDeclarations(..) when possible.
763      *
764      * Advantage of this interface:
765      * - You can search multiple identifiers at one time.
766      *   However, those should be aliased identifiers for one single item, because
767      *   search might stop as soon as one item is found.
768      * - The source top-context is needed to correctly resolve template-parameters
769      *
770      * @param position A valid position, if in doubt use textRange().end()
771      *
772      * @warning @p position must be valid!
773      *
774      * @param depth Depth of the search in parents. This is used to prevent endless
775      *              recursions in endless import loops.
776      *
777      *
778      * @return whether the search was successful. If it is false, it had to be stopped
779      *         for special reasons (like some flags)
780      */
781     virtual bool findDeclarationsInternal(const SearchItem::PtrList& identifiers,
782                                           const CursorInRevision& position, const AbstractType::Ptr& dataType,
783                                           DeclarationList& ret, const TopDUContext* source, SearchFlags flags,
784                                           uint depth) const;
785 
786     /**
787      * Returns the qualified identifier @p id with all aliases (for example namespace imports) applied
788      *
789      * Example: If the namespace 'Foo' is imported, and id is 'Bar',
790      *           then the returned list is 'Bar' and 'Foo::Bar'
791      */
792     QVector<QualifiedIdentifier> fullyApplyAliases(const QualifiedIdentifier& id,
793                                                    const TopDUContext* source) const;
794 
795 protected:
796 
797     /**
798      * After one scope was searched, this function is asked whether more
799      * results should be collected. Override it, for example to collect overloaded functions.
800      *
801      * The default-implementation returns true as soon as @p decls is not empty.
802      */
803     virtual bool foundEnough(const DeclarationList& decls, SearchFlags flags) const;
804 
805     /**
806      * Merges definitions and their inheritance-depth up all branches of the
807      * definition-use chain into one hash.
808      *
809      * This includes declarations propagated from sub-contexts.
810      *
811      * @param hadContexts is used to count together all contexts that already were
812      *                visited, so they are not visited again.
813      */
814     virtual void mergeDeclarationsInternal(QVector<QPair<Declaration*, int>>& definitions,
815                                            const CursorInRevision& position,
816                                            QHash<const DUContext*, bool>& hadContexts,
817                                            const TopDUContext* source,
818                                            bool searchInParents = true, int currentDepth = 0) const;
819 
820     void findLocalDeclarationsInternal(const Identifier& identifier,
821                                        const CursorInRevision& position,
822                                        const AbstractType::Ptr& dataType,
823                                        DeclarationList& ret,
824                                        const TopDUContext* source,
825                                        SearchFlags flags) const;
826 
827     virtual void findLocalDeclarationsInternal(const IndexedIdentifier& identifier,
828                                                const CursorInRevision& position,
829                                                const AbstractType::Ptr& dataType,
830                                                DeclarationList& ret,
831                                                const TopDUContext* source,
832                                                SearchFlags flags) const;
833 
834     /**
835      * Applies namespace-imports and namespace-aliases and returns
836      * possible absolute identifiers that need to be searched.
837      *
838      * @param targetIdentifiers will be filled with all identifiers that should
839      *                          be searched for, instead of identifier.
840      * @param onlyImports if this is true, namespace-aliases will not be respected,
841      *                    but only imports. This is faster.
842      */
843     void applyAliases(const SearchItem::PtrList& identifiers, SearchItem::PtrList& targetIdentifiers,
844                       const CursorInRevision& position, bool canBeNamespace, bool onlyImports = false) const;
845     /**
846      * Applies the aliases that need to be applied when moving the search
847      * from this context up to the parent-context.
848      *
849      * The default-implementation adds a set of identifiers with the own local
850      * identifier prefixed, if this is a namespace.
851      *
852      * For C++, this is needed when searching out of a namespace, so the item
853      * can be found within that namespace in another place.
854      */
855     virtual void applyUpwardsAliases(SearchItem::PtrList& identifiers, const TopDUContext* source) const;
856 
857     DUContext(DUContextData& dd, const RangeInRevision& range, DUContext* parent = nullptr, bool anonymous = false);
858 
859     /**
860      * Just uses the data from the given context. Doesn't copy or change anything,
861      * and the data will not be deleted on this contexts destruction.
862      */
863     DUContext(DUContext& useDataFrom);
864 
865     /**
866      * Whether this context, or any of its parent contexts, has been inserte
867      * anonymously into the du-chain
868      *
869      * @see DUContext::DUContext
870      */
871     bool isAnonymous() const;
872 
873     /**
874      * This is called whenever the search needs to do the decision whether it
875      * should be continued in the parent context.
876      *
877      * It is not called when the DontSearchInParent flag is set. Else this should
878      * be overridden to do language-specific logic.
879      *
880      * The default implementation returns false if the flag InImportedParentContext is set.
881      */
882     virtual bool shouldSearchInParent(SearchFlags flags) const;
883 
884 private:
885     void initFromTopContext();
886     void rebuildDynamicData(DUContext* parent, uint ownIndex) override;
887 
888     friend class TopDUContext;
889     friend class IndexedDUContext;
890     friend class LocalIndexedDUContext;
891     friend class TopDUContextDynamicData;
892 
893     DUCHAIN_DECLARE_DATA(DUContext)
894     class DUContextDynamicData* m_dynamicData;
895 };
896 
897 /**
898  * This is the identifier that can be used to search namespace-import declarations,
899  * and should be used to store namespace-imports.
900  *
901  * It is stored statically for performance-reasons, so it doesn't need to be
902  * constructed every time it is used.
903  *
904  * @see NamespaceAliasDeclaration.
905  */
906 KDEVPLATFORMLANGUAGE_EXPORT const Identifier& globalImportIdentifier();
907 
908 /**
909  * This is the identifier that can be used to search namespace-alias declarations.
910  *
911  * It is stored statically for performance-reasons, so it doesn't need to be
912  * constructed every time it is used.
913  *
914  * @see NamespaceAliasDeclaration.
915  */
916 KDEVPLATFORMLANGUAGE_EXPORT const Identifier& globalAliasIdentifier();
917 
918 /**
919  * This is the identifier that can be used to search namespace-import declarations,
920  * and should be used to store namespace-imports.
921  *
922  * It is stored statically for performance-reasons, so it doesn't need to be
923  * constructed every time it is used.
924  *
925  * @see NamespaceAliasDeclaration.
926  */
927 KDEVPLATFORMLANGUAGE_EXPORT const IndexedIdentifier& globalIndexedImportIdentifier();
928 
929 /**
930  * This is the identifier that can be used to search namespace-alias declarations.
931  *
932  * It is stored statically for performance-reasons, so it doesn't need to be
933  * constructed every time it is used.
934  *
935  * @see NamespaceAliasDeclaration.
936  */
937 KDEVPLATFORMLANGUAGE_EXPORT const IndexedIdentifier& globalIndexedAliasIdentifier();
938 
939 /**
940  * Collects all uses of the given @p declarationIndex
941  */
942 KDEVPLATFORMLANGUAGE_EXPORT QVector<RangeInRevision> allUses(DUContext* context,
943                                                              int declarationIndex,
944                                                              bool noEmptyRanges = false);
945 }
946 
947 Q_DECLARE_TYPEINFO(KDevelop::DUContext::Import, Q_MOVABLE_TYPE);
948 
949 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug dbg, const KDevelop::DUContext::Import& import);
950 
951 #endif // KDEVPLATFORM_DUCONTEXT_H
952