/* Copyright 2007 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "abstractincludenavigationcontext.h" #include #include #include #include #include namespace KDevelop { AbstractIncludeNavigationContext::AbstractIncludeNavigationContext(const IncludeItem& item, TopDUContextPointer topContext, const ParsingEnvironmentType& type) : AbstractNavigationContext(topContext), m_type(type), m_item(item) {} TopDUContext* pickContextWithData(QList duchains, uint maxDepth, const ParsingEnvironmentType& type, bool forcePick = true) { TopDUContext* duchain = 0; foreach(TopDUContext* ctx, duchains) { if(!ctx->parsingEnvironmentFile() || ctx->parsingEnvironmentFile()->type() != type) continue; if(ctx->childContexts().count() != 0 && (duchain == 0 || ctx->childContexts().count() > duchain->childContexts().count())) { duchain = ctx; } if(ctx->localDeclarations().count() != 0 && (duchain == 0 || ctx->localDeclarations().count() > duchain->localDeclarations().count())) { duchain = ctx; } } if(!duchain && maxDepth != 0) { if(maxDepth != 0) { foreach(TopDUContext* ctx, duchains) { QList children; foreach(const DUContext::Import &import, ctx->importedParentContexts()) if(import.context(0)) children << import.context(0)->topContext(); duchain = pickContextWithData(children, maxDepth-1, type, false); if(duchain) break; } } } if(!duchain && !duchains.isEmpty() && forcePick) duchain = duchains.first(); return duchain; } QString AbstractIncludeNavigationContext::html(bool shorten) { clear(); modifyHtml() += "

" + fontSizePrefix(shorten); addExternalHtml(m_prefix); KUrl u(m_item.url()); NavigationAction action(u, KTextEditor::Cursor(0,0)); makeLink(u.pathOrUrl(), u.pathOrUrl(), action); modifyHtml() += "
"; QList duchains = DUChain::self()->chainsForDocument(u); //Pick the one duchain for this document that has the most child-contexts/declarations. //This prevents picking a context that is empty due to header-guards. TopDUContext* duchain = pickContextWithData(duchains, 2, m_type); if(duchain) { getFileInfo(duchain); if(!shorten) { modifyHtml() += labelHighlight(i18n("Declarations:")) + "
"; bool first = true; QList decs; addDeclarationsFromContext(duchain, first, decs); } }else if(duchains.isEmpty()) { modifyHtml() += i18n("not parsed yet"); } addExternalHtml(m_suffix); modifyHtml() += fontSizeSuffix(shorten) + "

"; return currentHtml(); } void AbstractIncludeNavigationContext::getFileInfo(TopDUContext* duchain) { modifyHtml() += QString("%1: %2 %3: %4").arg(labelHighlight(i18nc("Files included into this file", "Includes"))).arg(duchain->importedParentContexts().count()).arg(labelHighlight(i18nc("Count of files this file was included into", "Included by"))).arg(duchain->importers().count()); modifyHtml() += "
"; } QString AbstractIncludeNavigationContext::name() const { return m_item.name; } bool AbstractIncludeNavigationContext::filterDeclaration(Declaration* /*decl*/) { return true; } void AbstractIncludeNavigationContext::addDeclarationsFromContext(KDevelop::DUContext* ctx, bool& first, QList< IdentifierPair > &addedDeclarations, const QString& indent ) { //modifyHtml() += indent + ctx->localScopeIdentifier().toString() + "{
"; QVector children = ctx->childContexts(); QVector declarations = ctx->localDeclarations(); QVector::const_iterator childIterator = children.constBegin(); QVector::const_iterator declarationIterator = declarations.constBegin(); while(childIterator != children.constEnd() || declarationIterator != declarations.constEnd()) { //Show declarations/contexts in the order they appear in the file int currentDeclarationLine = -1; int currentContextLine = -1; if(declarationIterator != declarations.constEnd()) currentDeclarationLine = (*declarationIterator)->rangeInCurrentRevision().textRange().start().line(); if(childIterator != children.constEnd()) currentDeclarationLine = (*childIterator)->rangeInCurrentRevision().textRange().start().line(); if((currentDeclarationLine <= currentContextLine || currentContextLine == -1 || childIterator == children.constEnd()) && declarationIterator != declarations.constEnd() ) { IdentifierPair id = qMakePair(static_cast((*declarationIterator)->kind()), (*declarationIterator)->qualifiedIdentifier().index()); if(!addedDeclarations.contains(id) && filterDeclaration(*declarationIterator) ) { //Show the declaration if(!first) modifyHtml() += Qt::escape(", "); else first = false; modifyHtml() += Qt::escape(indent + declarationKind(DeclarationPointer(*declarationIterator)) + " "); makeLink((*declarationIterator)->qualifiedIdentifier().toString(), DeclarationPointer(*declarationIterator), NavigationAction::NavigateDeclaration); addedDeclarations << id; } ++declarationIterator; } else { //Eventually Recurse into the context if((*childIterator)->type() == DUContext::Global || (*childIterator)->type() == DUContext::Namespace /*|| (*childIterator)->type() == DUContext::Class*/) addDeclarationsFromContext(*childIterator, first, addedDeclarations, indent + ' '); ++childIterator; } } //modifyHtml() += "}
"; } }