| 757 | ///@todo Implement a cache so at least the global import checks don't need to be done repeatedly. The cache should be thread-local, using DUChainPointer for the hashed items, and when an item was deleted, it should be discarded |
| 758 | template <class Acceptor> |
| 759 | bool TopDUContext::applyAliases(const QualifiedIdentifier& previous, const SearchItem::Ptr& identifier, |
| 760 | Acceptor& accept, const CursorInRevision& position, bool canBeNamespace, |
| 761 | ApplyAliasesBuddyInfo* buddy, uint recursionDepth) const |
| 762 | { |
| 763 | if (recursionDepth > maxApplyAliasesRecursion) { |
| 764 | const auto searches = identifier->toList(); |
| 765 | QualifiedIdentifier id; |
| 766 | if (!searches.isEmpty()) |
| 767 | id = searches.first(); |
| 768 | |
| 769 | qCDebug(LANGUAGE) << "maximum apply-aliases recursion reached while searching" << id; |
| 770 | } |
| 771 | bool foundAlias = false; |
| 772 | |
| 773 | QualifiedIdentifier id(previous); |
| 774 | id.push(identifier->identifier); |
| 775 | |
| 776 | if (!id.inRepository()) |
| 777 | return true; //If the qualified identifier is not in the identifier repository, it cannot be registered anywhere, so there's nothing we need to do |
| 778 | |
| 779 | if (!identifier->next.isEmpty() || canBeNamespace) { //If it cannot be a namespace, the last part of the scope will be ignored |
| 780 | //Search for namespace-aliases, by using globalAliasIdentifier, which is inserted into the symbol-table by NamespaceAliasDeclaration |
| 781 | QualifiedIdentifier aliasId(id); |
| 782 | aliasId.push(globalIndexedAliasIdentifier()); |
| 783 | |
| 784 | #ifdef DEBUG_SEARCH |
| 785 | qCDebug(LANGUAGE) << "checking" << id.toString(); |
| 786 | #endif |
| 787 | |
| 788 | if (aliasId.inRepository()) { |
| 789 | DeclarationChecker check(this, position, AbstractType::Ptr(), NoSearchFlags, nullptr); |
| 790 | |
| 791 | bool isDone = false; |
| 792 | // The first part of the identifier has been found as a namespace-alias. |
| 793 | // In c++, we only need the first alias. However, just to be correct, follow them all for now. |
| 794 | // This efficiently filters the visible declarations out of all declarations |
| 795 | PersistentSymbolTable::self().visitFilteredDeclarations( |
| 796 | aliasId, recursiveImportIndices(), [&](const IndexedDeclaration& indexedAliasDecl) { |
| 797 | auto* aliasDecl = indexedAliasDecl.data(); |
| 798 | if (!aliasDecl) |
| 799 | return PersistentSymbolTable::VisitorState::Continue; |
| 800 | |
| 801 | if (!check(aliasDecl)) |
| 802 | return PersistentSymbolTable::VisitorState::Continue; |
| 803 | |
| 804 | if (aliasDecl->kind() != Declaration::NamespaceAlias) |
| 805 | return PersistentSymbolTable::VisitorState::Continue; |
| 806 | |
| 807 | if (foundAlias) |
| 808 | return PersistentSymbolTable::VisitorState::Break; |
| 809 | |
| 810 | Q_ASSERT(dynamic_cast<NamespaceAliasDeclaration*>(aliasDecl)); |
| 811 | |
| 812 | auto* alias = static_cast<NamespaceAliasDeclaration*>(aliasDecl); |
| 813 | |
| 814 | foundAlias = true; |
| 815 | |
| 816 | QualifiedIdentifier importIdentifier = alias->importIdentifier(); |
nothing calls this directly
no test coverage detected