mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 19:32:54 +00:00
694 lines
26 KiB
C++
694 lines
26 KiB
C++
/*
|
|
Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
|
|
|
|
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 "abstractdeclarationnavigationcontext.h"
|
|
|
|
#include <QtGui/QTextDocument>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include "../functiondeclaration.h"
|
|
#include "../functiondefinition.h"
|
|
#include "../classfunctiondeclaration.h"
|
|
#include "../namespacealiasdeclaration.h"
|
|
#include "../forwarddeclaration.h"
|
|
#include "../types/enumeratortype.h"
|
|
#include "../types/enumerationtype.h"
|
|
#include "../types/functiontype.h"
|
|
#include "../duchainutils.h"
|
|
#include "../types/pointertype.h"
|
|
#include "../types/referencetype.h"
|
|
#include "../types/typeutils.h"
|
|
#include "../persistentsymboltable.h"
|
|
#include <interfaces/icore.h>
|
|
#include <interfaces/idocumentationcontroller.h>
|
|
#include <duchain/types/typealiastype.h>
|
|
#include <duchain/types/structuretype.h>
|
|
#include <duchain/classdeclaration.h>
|
|
#include <typeinfo>
|
|
|
|
namespace KDevelop {
|
|
AbstractDeclarationNavigationContext::AbstractDeclarationNavigationContext( DeclarationPointer decl, KDevelop::TopDUContextPointer topContext, AbstractNavigationContext* previousContext)
|
|
: AbstractNavigationContext((topContext ? topContext : TopDUContextPointer(decl ? decl->topContext() : 0)), previousContext), m_declaration(decl), m_fullBackwardSearch(false)
|
|
{
|
|
//Jump from definition to declaration if possible
|
|
FunctionDefinition* definition = dynamic_cast<FunctionDefinition*>(m_declaration.data());
|
|
if(definition && definition->declaration())
|
|
m_declaration = DeclarationPointer(definition->declaration());
|
|
}
|
|
|
|
QString AbstractDeclarationNavigationContext::name() const
|
|
{
|
|
if(m_declaration.data())
|
|
return prettyQualifiedIdentifier(m_declaration).toString();
|
|
else
|
|
return declarationName(m_declaration);
|
|
}
|
|
|
|
QString AbstractDeclarationNavigationContext::html(bool shorten)
|
|
{
|
|
clear();
|
|
m_shorten = shorten;
|
|
modifyHtml() += "<html><body><p>" + fontSizePrefix(shorten);
|
|
|
|
addExternalHtml(m_prefix);
|
|
|
|
if(!m_declaration.data()) {
|
|
modifyHtml() += i18n("<br /> lost declaration <br />");
|
|
return currentHtml();
|
|
}
|
|
|
|
if( m_previousContext ) {
|
|
QString link = createLink( m_previousContext->name(), m_previousContext->name(), NavigationAction(m_previousContext) );
|
|
modifyHtml() += navigationHighlight(i18n("Back to %1<br />", link));
|
|
}
|
|
|
|
KSharedPtr<IDocumentation> doc;
|
|
|
|
if( !shorten ) {
|
|
doc = ICore::self()->documentationController()->documentationForDeclaration(m_declaration.data());
|
|
|
|
const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(m_declaration.data());
|
|
if( function ) {
|
|
htmlFunction();
|
|
} else if( m_declaration->isTypeAlias() || m_declaration->kind() == Declaration::Instance ) {
|
|
if( m_declaration->isTypeAlias() )
|
|
modifyHtml() += importantHighlight("typedef ");
|
|
|
|
if(m_declaration->type<EnumeratorType>())
|
|
modifyHtml() += i18n("enumerator ");
|
|
|
|
AbstractType::Ptr useType = m_declaration->abstractType();
|
|
if(m_declaration->isTypeAlias()) {
|
|
//Do not show the own name as type of typedefs
|
|
if(useType.cast<TypeAliasType>())
|
|
useType = useType.cast<TypeAliasType>()->type();
|
|
}
|
|
|
|
eventuallyMakeTypeLinks( useType );
|
|
|
|
modifyHtml() += ' ' + nameHighlight(Qt::escape(declarationName(m_declaration))) + "<br>";
|
|
}else{
|
|
if( m_declaration->kind() == Declaration::Type && m_declaration->abstractType().cast<StructureType>() ) {
|
|
htmlClass();
|
|
}
|
|
if ( m_declaration->kind() == Declaration::Namespace ) {
|
|
modifyHtml() += i18n("namespace %1 ", nameHighlight(Qt::escape(m_declaration->qualifiedIdentifier().toString())));
|
|
}
|
|
|
|
if(m_declaration->type<EnumerationType>()) {
|
|
EnumerationType::Ptr enumeration = m_declaration->type<EnumerationType>();
|
|
modifyHtml() += i18n("enumeration %1 ", Qt::escape(m_declaration->identifier().toString()) );
|
|
}
|
|
|
|
if(m_declaration->isForwardDeclaration()) {
|
|
ForwardDeclaration* forwardDec = static_cast<ForwardDeclaration*>(m_declaration.data());
|
|
Declaration* resolved = forwardDec->resolve(m_topContext.data());
|
|
if(resolved) {
|
|
modifyHtml() += i18n("( resolved forward-declaration: ");
|
|
makeLink(resolved->identifier().toString(), KDevelop::DeclarationPointer(resolved), NavigationAction::NavigateDeclaration );
|
|
modifyHtml() += i18n(") ");
|
|
}else{
|
|
modifyHtml() += i18n("(unresolved forward-declaration) ");
|
|
QualifiedIdentifier id = forwardDec->qualifiedIdentifier();
|
|
uint count;
|
|
const IndexedDeclaration* decls;
|
|
PersistentSymbolTable::self().declarations(id, count, decls);
|
|
for(uint a = 0; a < count; ++a) {
|
|
if(decls[a].isValid() && !decls[a].data()->isForwardDeclaration()) {
|
|
modifyHtml() += "<br />";
|
|
makeLink(i18n("possible resolution from"), KDevelop::DeclarationPointer(decls[a].data()), NavigationAction::NavigateDeclaration);
|
|
modifyHtml() += ' ' + decls[a].data()->url().str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
modifyHtml() += "<br />";
|
|
}
|
|
}else{
|
|
AbstractType::Ptr showType = m_declaration->abstractType();
|
|
if(showType && showType.cast<FunctionType>()) {
|
|
showType = showType.cast<FunctionType>()->returnType();
|
|
if(showType)
|
|
modifyHtml() += labelHighlight(i18n("Returns: "));
|
|
}else if(showType) {
|
|
modifyHtml() += labelHighlight(i18n("Type: "));
|
|
}
|
|
|
|
if(showType) {
|
|
eventuallyMakeTypeLinks(showType);
|
|
modifyHtml() += " ";
|
|
}
|
|
}
|
|
|
|
QualifiedIdentifier identifier = m_declaration->qualifiedIdentifier();
|
|
if( identifier.count() > 1 ) {
|
|
if( m_declaration->context() && m_declaration->context()->owner() )
|
|
{
|
|
Declaration* decl = m_declaration->context()->owner();
|
|
|
|
FunctionDefinition* definition = dynamic_cast<FunctionDefinition*>(decl);
|
|
if(definition && definition->declaration())
|
|
decl = definition->declaration();
|
|
|
|
if(decl->abstractType().cast<EnumerationType>())
|
|
modifyHtml() += labelHighlight(i18n("Enum: "));
|
|
else
|
|
modifyHtml() += labelHighlight(i18n("Container: "));
|
|
|
|
makeLink( declarationName(DeclarationPointer(decl)), DeclarationPointer(decl), NavigationAction::NavigateDeclaration );
|
|
modifyHtml() += " ";
|
|
} else {
|
|
QualifiedIdentifier parent = identifier;
|
|
parent.pop();
|
|
modifyHtml() += labelHighlight(i18n("Scope: %1 ", typeHighlight(Qt::escape(parent.toString()))));
|
|
}
|
|
}
|
|
|
|
if( shorten && !m_declaration->comment().isEmpty() ) {
|
|
QString comment = QString::fromUtf8(m_declaration->comment());
|
|
if( comment.length() > 60 ) {
|
|
comment.truncate(60);
|
|
comment += "...";
|
|
}
|
|
comment.replace('\n', " ");
|
|
comment.replace("<br />", " ");
|
|
comment.replace("<br/>", " ");
|
|
modifyHtml() += commentHighlight(Qt::escape(comment)) + " ";
|
|
}
|
|
|
|
|
|
QString access = stringFromAccess(m_declaration);
|
|
if( !access.isEmpty() )
|
|
modifyHtml() += labelHighlight(i18n("Access: %1 ", propertyHighlight(Qt::escape(access))));
|
|
|
|
|
|
///@todo Enumerations
|
|
|
|
QString detailsHtml;
|
|
QStringList details = declarationDetails(m_declaration);
|
|
if( !details.isEmpty() ) {
|
|
bool first = true;
|
|
foreach( const QString &str, details ) {
|
|
if( !first )
|
|
detailsHtml += ", ";
|
|
first = false;
|
|
detailsHtml += propertyHighlight(str);
|
|
}
|
|
}
|
|
|
|
QString kind = declarationKind(m_declaration);
|
|
if( !kind.isEmpty() ) {
|
|
if( !detailsHtml.isEmpty() )
|
|
modifyHtml() += labelHighlight(i18n("Kind: %1 %2 ", importantHighlight(Qt::escape(kind)), detailsHtml));
|
|
else
|
|
modifyHtml() += labelHighlight(i18n("Kind: %1 ", importantHighlight(Qt::escape(kind))));
|
|
} else if( !detailsHtml.isEmpty() ) {
|
|
modifyHtml() += labelHighlight(i18n("Modifiers: %1 ", importantHighlight(Qt::escape(kind))));
|
|
}
|
|
|
|
modifyHtml() += "<br />";
|
|
|
|
if(!shorten)
|
|
htmlAdditionalNavigation();
|
|
|
|
if( !shorten ) {
|
|
if(dynamic_cast<FunctionDefinition*>(m_declaration.data()))
|
|
modifyHtml() += labelHighlight(i18n( "Def.: " ));
|
|
else
|
|
modifyHtml() += labelHighlight(i18n( "Decl.: " ));
|
|
|
|
makeLink( QString("%1 :%2").arg( KUrl(m_declaration->url().str()).fileName() ).arg( m_declaration->rangeInCurrentRevision().textRange().start().line()+1 ), m_declaration, NavigationAction::JumpToSource );
|
|
modifyHtml() += " ";
|
|
//modifyHtml() += "<br />";
|
|
if(!dynamic_cast<FunctionDefinition*>(m_declaration.data())) {
|
|
if( FunctionDefinition* definition = FunctionDefinition::definition(m_declaration.data()) ) {
|
|
modifyHtml() += labelHighlight(i18n( " Def.: " ));
|
|
makeLink( QString("%1 :%2").arg( KUrl(definition->url().str()).fileName() ).arg( definition->rangeInCurrentRevision().textRange().start().line()+1 ), DeclarationPointer(definition), NavigationAction::JumpToSource );
|
|
}
|
|
}
|
|
|
|
if( FunctionDefinition* definition = dynamic_cast<FunctionDefinition*>(m_declaration.data()) ) {
|
|
if(definition->declaration()) {
|
|
modifyHtml() += labelHighlight(i18n( " Decl.: " ));
|
|
makeLink( QString("%1 :%2").arg( KUrl(definition->declaration()->url().str()).fileName() ).arg( definition->declaration()->rangeInCurrentRevision().textRange().start().line()+1 ), DeclarationPointer(definition->declaration()), NavigationAction::JumpToSource );
|
|
}
|
|
}
|
|
|
|
modifyHtml() += " "; //The action name _must_ stay "show_uses", since that is also used from outside
|
|
makeLink(i18n("Show uses"), "show_uses", NavigationAction(m_declaration, NavigationAction::NavigateUses));
|
|
}
|
|
|
|
if( !shorten && (!m_declaration->comment().isEmpty() || doc) ) {
|
|
modifyHtml() += "<br />";
|
|
QString comment = QString::fromUtf8(m_declaration->comment());
|
|
if(comment.isEmpty() && doc) {
|
|
comment = doc->description();
|
|
if(!comment.isEmpty()) {
|
|
connect(doc.data(), SIGNAL(descriptionChanged()), this, SIGNAL(contentsChanged()));
|
|
modifyHtml() += "<br />" + commentHighlight(comment);
|
|
}
|
|
} else if(!comment.isEmpty()) {
|
|
comment.replace(QRegExp("<br */>"), "\n"); //do not escape html newlines within the comment
|
|
comment = Qt::escape(comment);
|
|
comment.replace('\n', "<br />"); //Replicate newlines in html
|
|
modifyHtml() += commentHighlight(comment);
|
|
modifyHtml() += "<br />";
|
|
}
|
|
}
|
|
|
|
if(!shorten && doc) {
|
|
modifyHtml() += "<br />" + i18n("Show documentation for ");
|
|
makeLink( prettyQualifiedIdentifier(m_declaration).toString(), m_declaration, NavigationAction::ShowDocumentation );
|
|
}
|
|
|
|
|
|
//modifyHtml() += "<br />";
|
|
|
|
addExternalHtml(m_suffix);
|
|
|
|
modifyHtml() += fontSizeSuffix(shorten) + "</p></body></html>";
|
|
|
|
return currentHtml();
|
|
}
|
|
|
|
KDevelop::AbstractType::Ptr AbstractDeclarationNavigationContext::typeToShow(KDevelop::AbstractType::Ptr type) {
|
|
return type;
|
|
}
|
|
|
|
void AbstractDeclarationNavigationContext::htmlFunction()
|
|
{
|
|
const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(m_declaration.data());
|
|
Q_ASSERT(function);
|
|
|
|
const ClassFunctionDeclaration* classFunDecl = dynamic_cast<const ClassFunctionDeclaration*>(m_declaration.data());
|
|
const FunctionType::Ptr type = m_declaration->abstractType().cast<FunctionType>();
|
|
if( !type ) {
|
|
modifyHtml() += errorHighlight("Invalid type<br />");
|
|
return;
|
|
}
|
|
|
|
if( !classFunDecl || (!classFunDecl->isConstructor() && !classFunDecl->isDestructor()) ) {
|
|
// only print return type for global functions and non-ctor/dtor methods
|
|
eventuallyMakeTypeLinks( type->returnType() );
|
|
}
|
|
|
|
modifyHtml() += ' ' + nameHighlight(Qt::escape(prettyIdentifier(m_declaration).toString()));
|
|
|
|
if( type->indexedArgumentsSize() == 0 )
|
|
{
|
|
modifyHtml() += "()";
|
|
} else {
|
|
modifyHtml() += "( ";
|
|
|
|
bool first = true;
|
|
int firstDefaultParam = type->indexedArgumentsSize() - function->defaultParametersSize();
|
|
int currentArgNum = 0;
|
|
|
|
QVector<Declaration*> decls;
|
|
if (KDevelop::DUContext* argumentContext = DUChainUtils::getArgumentContext(m_declaration.data())) {
|
|
decls = argumentContext->localDeclarations(m_topContext.data());
|
|
}
|
|
foreach(const AbstractType::Ptr& argType, type->arguments()) {
|
|
if( !first )
|
|
modifyHtml() += ", ";
|
|
first = false;
|
|
|
|
eventuallyMakeTypeLinks( argType );
|
|
if (currentArgNum < decls.size()) {
|
|
modifyHtml() += ' ' + nameHighlight(Qt::escape(decls[currentArgNum]->identifier().toString()));
|
|
}
|
|
|
|
if( currentArgNum >= firstDefaultParam )
|
|
modifyHtml() += " = " + Qt::escape(function->defaultParameters()[ currentArgNum - firstDefaultParam ].str());
|
|
|
|
++currentArgNum;
|
|
}
|
|
|
|
modifyHtml() += " )";
|
|
}
|
|
modifyHtml() += "<br />";
|
|
}
|
|
|
|
|
|
Identifier AbstractDeclarationNavigationContext::prettyIdentifier(DeclarationPointer decl) const
|
|
{
|
|
Identifier ret;
|
|
QualifiedIdentifier q = prettyQualifiedIdentifier(decl);
|
|
if(!q.isEmpty())
|
|
ret = q.last();
|
|
|
|
return ret;
|
|
}
|
|
|
|
QualifiedIdentifier AbstractDeclarationNavigationContext::prettyQualifiedIdentifier(DeclarationPointer decl) const
|
|
{
|
|
if(decl)
|
|
return decl->qualifiedIdentifier();
|
|
else
|
|
return QualifiedIdentifier();
|
|
}
|
|
|
|
void AbstractDeclarationNavigationContext::htmlAdditionalNavigation()
|
|
{
|
|
///Check if the function overrides or hides another one
|
|
const ClassFunctionDeclaration* classFunDecl = dynamic_cast<const ClassFunctionDeclaration*>(m_declaration.data());
|
|
if(classFunDecl) {
|
|
|
|
Declaration* overridden = DUChainUtils::getOverridden(m_declaration.data());
|
|
|
|
if(overridden) {
|
|
modifyHtml() += i18n("Overrides a ");
|
|
makeLink(i18n("function"), QString("jump_to_overridden"), NavigationAction(DeclarationPointer(overridden), KDevelop::NavigationAction::NavigateDeclaration));
|
|
modifyHtml() += i18n(" from ");
|
|
makeLink(prettyQualifiedIdentifier(DeclarationPointer(overridden->context()->owner())).toString(), QString("jump_to_overridden_container"), NavigationAction(DeclarationPointer(overridden->context()->owner()), KDevelop::NavigationAction::NavigateDeclaration));
|
|
|
|
modifyHtml() += "<br />";
|
|
}else{
|
|
//Check if this declarations hides other declarations
|
|
QList<Declaration*> decls;
|
|
foreach(const DUContext::Import &import, m_declaration->context()->importedParentContexts())
|
|
if(import.context(m_topContext.data()))
|
|
decls += import.context(m_topContext.data())->findDeclarations(QualifiedIdentifier(m_declaration->identifier()),
|
|
CursorInRevision::invalid(), AbstractType::Ptr(), m_topContext.data(), DUContext::DontSearchInParent);
|
|
uint num = 0;
|
|
foreach(Declaration* decl, decls) {
|
|
modifyHtml() += i18n("Hides a ");
|
|
makeLink(i18n("function"), QString("jump_to_hide_%1").arg(num), NavigationAction(DeclarationPointer(decl), KDevelop::NavigationAction::NavigateDeclaration));
|
|
modifyHtml() += i18n(" from ");
|
|
makeLink(prettyQualifiedIdentifier(DeclarationPointer(decl->context()->owner())).toString(), QString("jump_to_hide_container_%1").arg(num), NavigationAction(DeclarationPointer(decl->context()->owner()), KDevelop::NavigationAction::NavigateDeclaration));
|
|
|
|
modifyHtml() += "<br />";
|
|
++num;
|
|
}
|
|
}
|
|
|
|
///Show all places where this function is overridden
|
|
if(classFunDecl->isVirtual()) {
|
|
Declaration* classDecl = m_declaration->context()->owner();
|
|
if(classDecl) {
|
|
uint maxAllowedSteps = m_fullBackwardSearch ? (uint)-1 : 10;
|
|
QList<Declaration*> overriders = DUChainUtils::getOverriders(classDecl, classFunDecl, maxAllowedSteps);
|
|
|
|
if(!overriders.isEmpty()) {
|
|
modifyHtml() += i18n("Overridden in ");
|
|
bool first = true;
|
|
foreach(Declaration* overrider, overriders) {
|
|
if(!first)
|
|
modifyHtml() += ", ";
|
|
first = false;
|
|
|
|
QString name = prettyQualifiedIdentifier(DeclarationPointer(overrider->context()->owner())).toString();
|
|
makeLink(name, name, NavigationAction(DeclarationPointer(overrider), NavigationAction::NavigateDeclaration));
|
|
}
|
|
modifyHtml() += "<br />";
|
|
}
|
|
if(maxAllowedSteps == 0)
|
|
createFullBackwardSearchLink(overriders.isEmpty() ? i18n("Overriders possible, show all") : i18n("More overriders possible, show all"));
|
|
}
|
|
}
|
|
}
|
|
|
|
///Show all classes that inherit this one
|
|
uint maxAllowedSteps = m_fullBackwardSearch ? (uint)-1 : 10;
|
|
QList<Declaration*> inheriters = DUChainUtils::getInheriters(m_declaration.data(), maxAllowedSteps);
|
|
|
|
if(!inheriters.isEmpty()) {
|
|
modifyHtml() += i18n("Inherited by ");
|
|
bool first = true;
|
|
foreach(Declaration* importer, inheriters) {
|
|
if(!first)
|
|
modifyHtml() += ", ";
|
|
first = false;
|
|
|
|
QString importerName = prettyQualifiedIdentifier(DeclarationPointer(importer)).toString();
|
|
makeLink(importerName, importerName, NavigationAction(DeclarationPointer(importer), KDevelop::NavigationAction::NavigateDeclaration));
|
|
}
|
|
modifyHtml() += "<br />";
|
|
}
|
|
if(maxAllowedSteps == 0)
|
|
createFullBackwardSearchLink(inheriters.isEmpty() ? i18n("Inheriters possible, show all") : i18n("More inheriters possible, show all"));
|
|
}
|
|
|
|
void AbstractDeclarationNavigationContext::createFullBackwardSearchLink(QString string)
|
|
{
|
|
makeLink(string, "m_fullBackwardSearch=true", NavigationAction("m_fullBackwardSearch=true"));
|
|
modifyHtml() += "<br />";
|
|
}
|
|
|
|
NavigationContextPointer AbstractDeclarationNavigationContext::executeKeyAction( QString key )
|
|
{
|
|
if(key == "m_fullBackwardSearch=true") {
|
|
m_fullBackwardSearch = true;
|
|
clear();
|
|
}
|
|
return NavigationContextPointer(this);
|
|
}
|
|
|
|
void AbstractDeclarationNavigationContext::htmlClass()
|
|
{
|
|
StructureType::Ptr klass = m_declaration->abstractType().cast<StructureType>();
|
|
Q_ASSERT(klass);
|
|
|
|
ClassDeclaration* classDecl = dynamic_cast<ClassDeclaration*>(klass->declaration(m_topContext.data()));
|
|
if(classDecl) {
|
|
switch ( classDecl->classType() ) {
|
|
case ClassDeclarationData::Class:
|
|
modifyHtml() += "class ";
|
|
break;
|
|
case ClassDeclarationData::Struct:
|
|
modifyHtml() += "struct ";
|
|
break;
|
|
case ClassDeclarationData::Union:
|
|
modifyHtml() += "union ";
|
|
break;
|
|
case ClassDeclarationData::Interface:
|
|
modifyHtml() += "interface ";
|
|
break;
|
|
case ClassDeclarationData::Trait:
|
|
modifyHtml() += "trait ";
|
|
break;
|
|
default:
|
|
modifyHtml() += "<unknown type> ";
|
|
break;
|
|
}
|
|
eventuallyMakeTypeLinks( klass.cast<AbstractType>() );
|
|
|
|
FOREACH_FUNCTION( const KDevelop::BaseClassInstance& base, classDecl->baseClasses ) {
|
|
modifyHtml() += ", " + stringFromAccess(base.access) + " " + (base.virtualInheritance ? QString("virtual") : QString()) + " ";
|
|
eventuallyMakeTypeLinks(base.baseClass.abstractType());
|
|
}
|
|
} else {
|
|
/// @todo How can we get here? and should this really be a class?
|
|
modifyHtml() += "class ";
|
|
eventuallyMakeTypeLinks( klass.cast<AbstractType>() );
|
|
}
|
|
modifyHtml() += " ";
|
|
}
|
|
|
|
void AbstractDeclarationNavigationContext::htmlIdentifiedType(AbstractType::Ptr type, const IdentifiedType* idType)
|
|
{
|
|
Q_ASSERT(type);
|
|
Q_ASSERT(idType);
|
|
|
|
if( Declaration* decl = idType->declaration(m_topContext.data()) ) {
|
|
|
|
//Remove the last template-identifiers, because we create those directly
|
|
QualifiedIdentifier id = prettyQualifiedIdentifier(DeclarationPointer(decl));
|
|
Identifier lastId = id.last();
|
|
id.pop();
|
|
lastId.clearTemplateIdentifiers();
|
|
id.push(lastId);
|
|
|
|
if(decl->context() && decl->context()->owner()) {
|
|
|
|
//Also create full type-links for the context around
|
|
AbstractType::Ptr contextType = decl->context()->owner()->abstractType();
|
|
IdentifiedType* contextIdType = dynamic_cast<IdentifiedType*>(contextType.unsafeData());
|
|
if(contextIdType && !contextIdType->equals(idType)) {
|
|
//Create full type information for the context
|
|
if(!id.isEmpty())
|
|
id = id.mid(id.count()-1);
|
|
htmlIdentifiedType(contextType, contextIdType);
|
|
modifyHtml() += Qt::escape("::");
|
|
}
|
|
}
|
|
|
|
//We leave out the * and & reference and pointer signs, those are added to the end
|
|
makeLink(id.toString() , DeclarationPointer(idType->declaration(m_topContext.data())), NavigationAction::NavigateDeclaration );
|
|
} else {
|
|
kDebug() << "could not resolve declaration:" << idType->declarationId().isDirect() << idType->qualifiedIdentifier().toString() << "in top-context" << m_topContext->url().str();
|
|
modifyHtml() += typeHighlight(Qt::escape(type->toString()));
|
|
}
|
|
}
|
|
|
|
void AbstractDeclarationNavigationContext::eventuallyMakeTypeLinks( AbstractType::Ptr type )
|
|
{
|
|
type = typeToShow(type);
|
|
|
|
if( !type ) {
|
|
modifyHtml() += typeHighlight(Qt::escape("<no type>"));
|
|
return;
|
|
}
|
|
|
|
AbstractType::Ptr target = TypeUtils::targetTypeKeepAliases( type, m_topContext.data() );
|
|
const IdentifiedType* idType = dynamic_cast<const IdentifiedType*>( target.unsafeData() );
|
|
|
|
kDebug() << "making type-links for" << type->toString() << typeid(*type).name();
|
|
|
|
if( idType && idType->declaration(m_topContext.data()) ) {
|
|
///@todo This is C++ specific, move into subclass
|
|
|
|
if(target->modifiers() & AbstractType::ConstModifier)
|
|
modifyHtml() += typeHighlight("const ");
|
|
|
|
htmlIdentifiedType(target, idType);
|
|
|
|
//We need to exchange the target type, else template-parameters may confuse this
|
|
SimpleTypeExchanger exchangeTarget(target, AbstractType::Ptr());
|
|
|
|
AbstractType::Ptr exchanged = exchangeTarget.exchange(type);
|
|
|
|
if(exchanged) {
|
|
QString typeSuffixString = exchanged->toString();
|
|
QRegExp suffixExp("\\&|\\*");
|
|
int suffixPos = typeSuffixString.indexOf(suffixExp);
|
|
if(suffixPos != -1)
|
|
modifyHtml() += typeHighlight(typeSuffixString.mid(suffixPos));
|
|
}
|
|
|
|
} else {
|
|
if(idType) {
|
|
kDebug() << "identified type could not be resolved:" << idType->qualifiedIdentifier() << idType->declarationId().isValid() << idType->declarationId().isDirect();
|
|
}
|
|
modifyHtml() += typeHighlight(Qt::escape(type->toString()));
|
|
}
|
|
}
|
|
|
|
DeclarationPointer AbstractDeclarationNavigationContext::declaration() const
|
|
{
|
|
return m_declaration;
|
|
}
|
|
|
|
QString AbstractDeclarationNavigationContext::stringFromAccess(Declaration::AccessPolicy access)
|
|
{
|
|
switch(access) {
|
|
case Declaration::Private:
|
|
return "private";
|
|
case Declaration::Protected:
|
|
return "protected";
|
|
case Declaration::Public:
|
|
return "public";
|
|
default:
|
|
break;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString AbstractDeclarationNavigationContext::stringFromAccess(DeclarationPointer decl)
|
|
{
|
|
const ClassMemberDeclaration* memberDecl = dynamic_cast<const ClassMemberDeclaration*>(decl.data());
|
|
if( memberDecl ) {
|
|
return stringFromAccess(memberDecl->accessPolicy());
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
QString AbstractDeclarationNavigationContext::declarationName( DeclarationPointer decl ) const
|
|
{
|
|
if( NamespaceAliasDeclaration* alias = dynamic_cast<NamespaceAliasDeclaration*>(decl.data()) ) {
|
|
if( alias->identifier().isEmpty() )
|
|
return "using namespace " + alias->importIdentifier().toString();
|
|
else
|
|
return "namespace " + alias->identifier().toString() + " = " + alias->importIdentifier().toString();
|
|
}
|
|
|
|
if( !decl )
|
|
return i18nc("A declaration that is unknown", "Unknown");
|
|
else
|
|
return prettyIdentifier(decl).toString();
|
|
}
|
|
|
|
QStringList AbstractDeclarationNavigationContext::declarationDetails(DeclarationPointer decl)
|
|
{
|
|
QStringList details;
|
|
const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(decl.data());
|
|
const ClassMemberDeclaration* memberDecl = dynamic_cast<const ClassMemberDeclaration*>(decl.data());
|
|
if( memberDecl ) {
|
|
if( memberDecl->isMutable() )
|
|
details << "mutable";
|
|
if( memberDecl->isRegister() )
|
|
details << "register";
|
|
if( memberDecl->isStatic() )
|
|
details << "static";
|
|
if( memberDecl->isAuto() )
|
|
details << "auto";
|
|
if( memberDecl->isExtern() )
|
|
details << "extern";
|
|
if( memberDecl->isFriend() )
|
|
details << "friend";
|
|
}
|
|
|
|
if( decl->isDefinition() )
|
|
details << i18nc("tells if a declaration is defining the variable's value", "definition");
|
|
if( decl->isExplicitlyDeleted() )
|
|
details << "deleted";
|
|
|
|
if( memberDecl && memberDecl->isForwardDeclaration() )
|
|
details << i18nc("as in c++ forward declaration", "forward");
|
|
|
|
AbstractType::Ptr t(decl->abstractType());
|
|
if( t ) {
|
|
if( t->modifiers() & AbstractType::ConstModifier )
|
|
details << i18nc("a variable that won't change, const", "constant");
|
|
if( t->modifiers() & AbstractType::VolatileModifier )
|
|
details << "volatile";
|
|
}
|
|
if( function ) {
|
|
|
|
if( function->isInline() )
|
|
details << "inline";
|
|
|
|
if( function->isExplicit() )
|
|
details << "explicit";
|
|
|
|
if( function->isVirtual() )
|
|
details << "virtual";
|
|
|
|
const ClassFunctionDeclaration* classFunDecl = dynamic_cast<const ClassFunctionDeclaration*>(decl.data());
|
|
|
|
if( classFunDecl ) {
|
|
if( classFunDecl->isSignal() )
|
|
details << "signal";
|
|
if( classFunDecl->isSlot() )
|
|
details << "slot";
|
|
if( classFunDecl->isConstructor() )
|
|
details << "constructor";
|
|
if( classFunDecl->isDestructor() )
|
|
details << "destructor";
|
|
if( classFunDecl->isConversionFunction() )
|
|
details << "conversion-function";
|
|
if( classFunDecl->isAbstract() )
|
|
details << "abstract";
|
|
}
|
|
}
|
|
|
|
return details;
|
|
}
|
|
|
|
}
|