Warning, file /kdevelop/kdevelop/kdevplatform/language/duchain/navigation/abstractincludenavigationcontext.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "abstractincludenavigationcontext.h" 0008 0009 #include <KLocalizedString> 0010 0011 #include <language/duchain/duchain.h> 0012 #include <language/duchain/parsingenvironment.h> 0013 #include <language/duchain/declaration.h> 0014 #include <language/duchain/duchainlock.h> 0015 0016 namespace KDevelop { 0017 AbstractIncludeNavigationContext::AbstractIncludeNavigationContext(const IncludeItem& item, 0018 const TopDUContextPointer& topContext, 0019 const ParsingEnvironmentType& type) 0020 : AbstractNavigationContext(topContext) 0021 , m_type(type) 0022 , m_item(item) 0023 {} 0024 0025 TopDUContext* pickContextWithData(const QList<TopDUContext*>& duchains, uint maxDepth, 0026 const ParsingEnvironmentType& type, 0027 bool forcePick = true) 0028 { 0029 TopDUContext* duchain = nullptr; 0030 0031 for (TopDUContext* ctx : duchains) { 0032 if (!ctx->parsingEnvironmentFile() || ctx->parsingEnvironmentFile()->type() != type) 0033 continue; 0034 0035 if (ctx->childContexts().count() != 0 0036 && (duchain == nullptr || ctx->childContexts().count() > duchain->childContexts().count())) { 0037 duchain = ctx; 0038 } 0039 if (ctx->localDeclarations().count() != 0 0040 && (duchain == nullptr || ctx->localDeclarations().count() > duchain->localDeclarations().count())) { 0041 duchain = ctx; 0042 } 0043 } 0044 0045 if (!duchain && maxDepth != 0) { 0046 if (maxDepth != 0) { 0047 for (TopDUContext* ctx : duchains) { 0048 QList<TopDUContext*> children; 0049 const auto importedParentContexts = ctx->importedParentContexts(); 0050 for (const DUContext::Import& import : importedParentContexts) { 0051 if (import.context(nullptr)) 0052 children << import.context(nullptr)->topContext(); 0053 } 0054 0055 duchain = pickContextWithData(children, maxDepth - 1, type, false); 0056 if (duchain) 0057 break; 0058 } 0059 } 0060 } 0061 0062 if (!duchain && !duchains.isEmpty() && forcePick) 0063 duchain = duchains.first(); 0064 0065 return duchain; 0066 } 0067 0068 QString AbstractIncludeNavigationContext::html(bool shorten) 0069 { 0070 clear(); 0071 modifyHtml() += QStringLiteral("<html><body><p>"); 0072 0073 QUrl u = m_item.url(); 0074 NavigationAction action(u, KTextEditor::Cursor(0, 0)); 0075 makeLink(u.toDisplayString(QUrl::PreferLocalFile), u.toString(), action); 0076 modifyHtml() += QStringLiteral("<br />"); 0077 0078 DUChainReadLocker lock; 0079 QList<TopDUContext*> duchains = DUChain::self()->chainsForDocument(u); 0080 //Pick the one duchain for this document that has the most child-contexts/declarations. 0081 //This prevents picking a context that is empty due to header-guards. 0082 TopDUContext* duchain = pickContextWithData(duchains, 2, m_type); 0083 0084 if (duchain) { 0085 getFileInfo(duchain); 0086 if (!shorten) { 0087 modifyHtml() += labelHighlight(i18n("Declarations:")) + QLatin1String("<br />"); 0088 bool first = true; 0089 QVector<IdentifierPair> decs; 0090 addDeclarationsFromContext(duchain, first, decs); 0091 } 0092 } else if (duchains.isEmpty()) { 0093 modifyHtml() += i18n("not parsed yet"); 0094 } 0095 0096 modifyHtml() += QStringLiteral("</p></body></html>"); 0097 return currentHtml(); 0098 } 0099 0100 void AbstractIncludeNavigationContext::getFileInfo(TopDUContext* duchain) 0101 { 0102 modifyHtml() += 0103 QStringLiteral("%1: %2 %3: %4").arg(labelHighlight(i18nc("Files included into this file", "Includes"))).arg( 0104 duchain->importedParentContexts().count()).arg(labelHighlight(i18nc( 0105 "Count of files this file was included into", 0106 "Included by"))).arg( 0107 duchain->importers().count()); 0108 modifyHtml() += QStringLiteral("<br />"); 0109 } 0110 0111 QString AbstractIncludeNavigationContext::name() const 0112 { 0113 return m_item.name; 0114 } 0115 0116 bool AbstractIncludeNavigationContext::filterDeclaration(Declaration* /*decl*/) 0117 { 0118 return true; 0119 } 0120 0121 void AbstractIncludeNavigationContext::addDeclarationsFromContext(KDevelop::DUContext* ctx, bool& first, 0122 QVector<IdentifierPair>& addedDeclarations, 0123 const QString& indent) 0124 { 0125 //modifyHtml() += indent + ctx->localScopeIdentifier().toString() + "{<br />"; 0126 QVector<DUContext*> children = ctx->childContexts(); 0127 QVector<Declaration*> declarations = ctx->localDeclarations(); 0128 0129 QVector<DUContext*>::const_iterator childIterator = children.constBegin(); 0130 QVector<Declaration*>::const_iterator declarationIterator = declarations.constBegin(); 0131 0132 while (childIterator != children.constEnd() || declarationIterator != declarations.constEnd()) { 0133 //Show declarations/contexts in the order they appear in the file 0134 int currentDeclarationLine = -1; 0135 int currentContextLine = -1; 0136 if (declarationIterator != declarations.constEnd()) 0137 currentDeclarationLine = (*declarationIterator)->rangeInCurrentRevision().start().line(); 0138 0139 if (childIterator != children.constEnd()) 0140 currentDeclarationLine = (*childIterator)->rangeInCurrentRevision().start().line(); 0141 0142 if ((currentDeclarationLine <= currentContextLine || currentContextLine == -1 || 0143 childIterator == children.constEnd()) && declarationIterator != declarations.constEnd()) { 0144 IdentifierPair id = qMakePair(static_cast<int>((*declarationIterator)->kind()), 0145 (*declarationIterator)->qualifiedIdentifier().index()); 0146 if (!addedDeclarations.contains(id) && filterDeclaration(*declarationIterator)) { 0147 //Show the declaration 0148 if (!first) 0149 modifyHtml() += QStringLiteral(", "); 0150 else 0151 first = false; 0152 0153 modifyHtml() += QString(indent + declarationKind(DeclarationPointer( 0154 *declarationIterator)) + 0155 QLatin1Char(' ')).toHtmlEscaped(); 0156 makeLink((*declarationIterator)->qualifiedIdentifier().toString(), 0157 DeclarationPointer(*declarationIterator), NavigationAction::NavigateDeclaration); 0158 0159 addedDeclarations << id; 0160 } 0161 ++declarationIterator; 0162 } else { 0163 //Eventually Recurse into the context 0164 if ((*childIterator)->type() == DUContext::Global || 0165 (*childIterator)->type() == DUContext::Namespace /*|| (*childIterator)->type() == DUContext::Class*/) 0166 addDeclarationsFromContext(*childIterator, first, addedDeclarations, indent + QLatin1Char(' ')); 0167 ++childIterator; 0168 } 0169 } 0170 //modifyHtml() += "}<br />"; 0171 } 0172 } 0173 0174 #include "moc_abstractincludenavigationcontext.cpp"