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"