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