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