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