diff --git a/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp b/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp
index c9281cfcb..e54eef195 100644
--- a/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp
+++ b/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp
@@ -1,765 +1,769 @@
/*
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 "abstractdeclarationnavigationcontext.h"
#include
#include
#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 "../types/typesystem.h"
#include "../persistentsymboltable.h"
#include "util/debug.h"
#include
#include
#include
#include
#include
namespace KDevelop {
AbstractDeclarationNavigationContext::AbstractDeclarationNavigationContext( DeclarationPointer decl, 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(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)
{
+ DUChainReadLocker lock(DUChain::lock(), 300);
+ if ( !lock.locked() ) {
+ return {};
+ }
clear();
m_shorten = shorten;
modifyHtml() += "" + fontSizePrefix(shorten);
addExternalHtml(m_prefix);
if(!m_declaration.data()) {
modifyHtml() += i18n("
lost declaration
");
return currentHtml();
}
if( m_previousContext ) {
QString link = createLink( m_previousContext->name(), m_previousContext->name(), NavigationAction(m_previousContext) );
modifyHtml() += navigationHighlight(i18n("Back to %1
", link));
}
QExplicitlySharedDataPointer doc;
if( !shorten ) {
doc = ICore::self()->documentationController()->documentationForDeclaration(m_declaration.data());
const AbstractFunctionDeclaration* function = dynamic_cast(m_declaration.data());
if( function ) {
htmlFunction();
} else if( m_declaration->isTypeAlias() || m_declaration->type() || m_declaration->kind() == Declaration::Instance ) {
if( m_declaration->isTypeAlias() )
modifyHtml() += importantHighlight(QStringLiteral("typedef "));
if(m_declaration->type())
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())
useType = useType.cast()->type();
}
eventuallyMakeTypeLinks( useType );
modifyHtml() += ' ' + identifierHighlight(declarationName(m_declaration).toHtmlEscaped(), m_declaration);
if(auto integralType = m_declaration->type()) {
const QString plainValue = integralType->valueAsString();
if (!plainValue.isEmpty()) {
modifyHtml() += QStringLiteral(" = ") + plainValue;
}
}
modifyHtml() += QStringLiteral("
");
}else{
if( m_declaration->kind() == Declaration::Type && m_declaration->abstractType().cast() ) {
htmlClass();
}
if ( m_declaration->kind() == Declaration::Namespace ) {
modifyHtml() += i18n("namespace %1 ", identifierHighlight(m_declaration->qualifiedIdentifier().toString().toHtmlEscaped(), m_declaration));
} else if ( m_declaration->kind() == Declaration::NamespaceAlias ) {
modifyHtml() += identifierHighlight(declarationName(m_declaration).toHtmlEscaped(), m_declaration);
}
if(m_declaration->type()) {
EnumerationType::Ptr enumeration = m_declaration->type();
modifyHtml() += i18n("enumeration %1 ", identifierHighlight(m_declaration->identifier().toString().toHtmlEscaped(), m_declaration));
}
if(m_declaration->isForwardDeclaration()) {
ForwardDeclaration* forwardDec = static_cast(m_declaration.data());
Declaration* resolved = forwardDec->resolve(m_topContext.data());
if(resolved) {
modifyHtml() += i18n("(resolved forward-declaration: ");
makeLink(resolved->identifier().toString(), DeclarationPointer(resolved), NavigationAction::NavigateDeclaration );
modifyHtml() += i18n(") ");
}else{
modifyHtml() += i18n("(unresolved forward-declaration) ");
QualifiedIdentifier id = forwardDec->qualifiedIdentifier();
const auto& forwardDecFile = forwardDec->topContext()->parsingEnvironmentFile();
uint count;
const IndexedDeclaration* decls;
PersistentSymbolTable::self().declarations(id, count, decls);
for(uint a = 0; a < count; ++a) {
auto dec = decls[a].data();
if (!dec || dec->isForwardDeclaration()) {
continue;
}
const auto& decFile = forwardDec->topContext()->parsingEnvironmentFile();
if ((static_cast(decFile) != static_cast(forwardDecFile)) ||
(decFile && forwardDecFile && decFile->language() != forwardDecFile->language()))
{
// the language of the declarations must match
continue;
}
modifyHtml() += QStringLiteral("
");
makeLink(i18n("possible resolution from"), DeclarationPointer(dec), NavigationAction::NavigateDeclaration);
modifyHtml() += ' ' + dec->url().str();
}
}
}
modifyHtml() += QStringLiteral("
");
}
}else{
AbstractType::Ptr showType = m_declaration->abstractType();
if(showType && showType.cast()) {
showType = showType.cast()->returnType();
if(showType)
modifyHtml() += labelHighlight(i18n("Returns: "));
}else if(showType) {
modifyHtml() += labelHighlight(i18n("Type: "));
}
if(showType) {
eventuallyMakeTypeLinks(showType);
modifyHtml() += QStringLiteral(" ");
}
}
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(decl);
if(definition && definition->declaration())
decl = definition->declaration();
if(decl->abstractType().cast())
modifyHtml() += labelHighlight(i18n("Enum: "));
else
modifyHtml() += labelHighlight(i18n("Container: "));
makeLink( declarationName(DeclarationPointer(decl)), DeclarationPointer(decl), NavigationAction::NavigateDeclaration );
modifyHtml() += QStringLiteral(" ");
} else {
QualifiedIdentifier parent = identifier;
parent.pop();
modifyHtml() += labelHighlight(i18n("Scope: %1 ", typeHighlight(parent.toString().toHtmlEscaped())));
}
}
if( shorten && !m_declaration->comment().isEmpty() ) {
QString comment = QString::fromUtf8(m_declaration->comment());
if( comment.length() > 60 ) {
comment.truncate(60);
comment += QLatin1String("...");
}
comment.replace('\n', QLatin1String(" "));
comment.replace(QLatin1String("
"), QLatin1String(" "));
comment.replace(QLatin1String("
"), QLatin1String(" "));
modifyHtml() += commentHighlight(comment.toHtmlEscaped()) + " ";
}
QString access = stringFromAccess(m_declaration);
if( !access.isEmpty() )
modifyHtml() += labelHighlight(i18n("Access: %1 ", propertyHighlight(access.toHtmlEscaped())));
///@todo Enumerations
QString detailsHtml;
QStringList details = declarationDetails(m_declaration);
if( !details.isEmpty() ) {
bool first = true;
foreach( const QString &str, details ) {
if( !first )
detailsHtml += QLatin1String(", ");
first = false;
detailsHtml += propertyHighlight(str);
}
}
QString kind = declarationKind(m_declaration);
if( !kind.isEmpty() ) {
if( !detailsHtml.isEmpty() )
modifyHtml() += labelHighlight(i18n("Kind: %1 %2 ", importantHighlight(kind.toHtmlEscaped()), detailsHtml));
else
modifyHtml() += labelHighlight(i18n("Kind: %1 ", importantHighlight(kind.toHtmlEscaped())));
}
if (m_declaration->isDeprecated()) {
modifyHtml() += labelHighlight(i18n("Status: %1 ", propertyHighlight(i18n("Deprecated"))));
}
modifyHtml() += QStringLiteral("
");
if(!shorten)
htmlAdditionalNavigation();
if( !shorten ) {
if(dynamic_cast(m_declaration.data()))
modifyHtml() += labelHighlight(i18n( "Def.: " ));
else
modifyHtml() += labelHighlight(i18n( "Decl.: " ));
makeLink( QStringLiteral("%1 :%2").arg( m_declaration->url().toUrl().fileName() ).arg( m_declaration->rangeInCurrentRevision().start().line()+1 ), m_declaration, NavigationAction::JumpToSource );
modifyHtml() += QStringLiteral(" ");
//modifyHtml() += "
";
if(!dynamic_cast(m_declaration.data())) {
if( FunctionDefinition* definition = FunctionDefinition::definition(m_declaration.data()) ) {
modifyHtml() += labelHighlight(i18n( " Def.: " ));
makeLink( QStringLiteral("%1 :%2").arg( definition->url().toUrl().fileName() ).arg( definition->rangeInCurrentRevision().start().line()+1 ), DeclarationPointer(definition), NavigationAction::JumpToSource );
}
}
if( FunctionDefinition* definition = dynamic_cast(m_declaration.data()) ) {
if(definition->declaration()) {
modifyHtml() += labelHighlight(i18n( " Decl.: " ));
makeLink( QStringLiteral("%1 :%2").arg( definition->declaration()->url().toUrl().fileName() ).arg( definition->declaration()->rangeInCurrentRevision().start().line()+1 ), DeclarationPointer(definition->declaration()), NavigationAction::JumpToSource );
}
}
modifyHtml() += QStringLiteral(" "); //The action name _must_ stay "show_uses", since that is also used from outside
makeLink(i18n("Show uses"), QStringLiteral("show_uses"), NavigationAction(m_declaration, NavigationAction::NavigateUses));
}
QByteArray declarationComment = m_declaration->comment();
if( !shorten && (!declarationComment.isEmpty() || doc) ) {
modifyHtml() += QStringLiteral("");
if(doc) {
QString comment = doc->description();
connect(doc.data(), &IDocumentation::descriptionChanged, this, &AbstractDeclarationNavigationContext::contentsChanged);
if(!comment.isEmpty()) {
modifyHtml() += "
" + commentHighlight(comment) + "
";
}
}
QString comment = QString::fromUtf8(declarationComment);
if(!comment.isEmpty()) {
// if the first paragraph does not contain a tag, we assume that this is a plain-text comment
if (!Qt::mightBeRichText(comment)) {
// still might contain extra html tags for line breaks (this is the case for doxygen-style comments sometimes)
// let's protect them from being removed completely
comment.replace(QRegExp("
"), QStringLiteral("\n"));
comment = comment.toHtmlEscaped();
comment.replace('\n', QLatin1String("
")); //Replicate newlines in html
}
modifyHtml() += commentHighlight(comment);
modifyHtml() += QStringLiteral("
");
}
}
if(!shorten && doc) {
modifyHtml() += "" + i18n("Show documentation for ");
makeLink(prettyQualifiedName(m_declaration),
m_declaration, NavigationAction::ShowDocumentation);
modifyHtml() += "
";
}
//modifyHtml() += "
";
addExternalHtml(m_suffix);
modifyHtml() += fontSizeSuffix(shorten) + "
";
return currentHtml();
}
AbstractType::Ptr AbstractDeclarationNavigationContext::typeToShow(AbstractType::Ptr type) {
return type;
}
void AbstractDeclarationNavigationContext::htmlFunction()
{
const AbstractFunctionDeclaration* function = dynamic_cast(m_declaration.data());
Q_ASSERT(function);
const ClassFunctionDeclaration* classFunDecl = dynamic_cast(m_declaration.data());
const FunctionType::Ptr type = m_declaration->abstractType().cast();
if( !type ) {
modifyHtml() += errorHighlight(QStringLiteral("Invalid type
"));
return;
}
if( !classFunDecl || (!classFunDecl->isConstructor() && !classFunDecl->isDestructor()) ) {
// only print return type for global functions and non-ctor/dtor methods
eventuallyMakeTypeLinks( type->returnType() );
}
modifyHtml() += ' ' + identifierHighlight(prettyIdentifier(m_declaration).toString().toHtmlEscaped(), m_declaration);
if( type->indexedArgumentsSize() == 0 )
{
modifyHtml() += QStringLiteral("()");
} else {
modifyHtml() += QStringLiteral("( ");
bool first = true;
int firstDefaultParam = type->indexedArgumentsSize() - function->defaultParametersSize();
int currentArgNum = 0;
QVector decls;
if (DUContext* argumentContext = DUChainUtils::getArgumentContext(m_declaration.data())) {
decls = argumentContext->localDeclarations(m_topContext.data());
}
foreach(const AbstractType::Ptr& argType, type->arguments()) {
if( !first )
modifyHtml() += QStringLiteral(", ");
first = false;
eventuallyMakeTypeLinks( argType );
if (currentArgNum < decls.size()) {
modifyHtml() += ' ' + identifierHighlight(decls[currentArgNum]->identifier().toString().toHtmlEscaped(), m_declaration);
}
if( currentArgNum >= firstDefaultParam )
modifyHtml() += " = " + function->defaultParameters()[ currentArgNum - firstDefaultParam ].str().toHtmlEscaped();
++currentArgNum;
}
modifyHtml() += QStringLiteral(" )");
}
modifyHtml() += QStringLiteral("
");
}
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();
}
QString AbstractDeclarationNavigationContext::prettyQualifiedName(DeclarationPointer decl) const
{
const auto qid = prettyQualifiedIdentifier(decl);
if (qid.isEmpty()) {
return i18nc("An anonymous declaration (class, function, etc.)", "");
}
return qid.toString();
}
void AbstractDeclarationNavigationContext::htmlAdditionalNavigation()
{
///Check if the function overrides or hides another one
const ClassFunctionDeclaration* classFunDecl = dynamic_cast(m_declaration.data());
if(classFunDecl) {
Declaration* overridden = DUChainUtils::getOverridden(m_declaration.data());
if(overridden) {
modifyHtml() += i18n("Overrides a ");
makeLink(i18n("function"), QStringLiteral("jump_to_overridden"), NavigationAction(DeclarationPointer(overridden), NavigationAction::NavigateDeclaration));
modifyHtml() += i18n(" from ");
makeLink(prettyQualifiedName(DeclarationPointer(overridden->context()->owner())),
QStringLiteral("jump_to_overridden_container"),
NavigationAction(DeclarationPointer(overridden->context()->owner()),
NavigationAction::NavigateDeclaration));
modifyHtml() += QStringLiteral("
");
}else{
//Check if this declarations hides other declarations
QList 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"), QStringLiteral("jump_to_hide_%1").arg(num),
NavigationAction(DeclarationPointer(decl),
NavigationAction::NavigateDeclaration));
modifyHtml() += i18n(" from ");
makeLink(prettyQualifiedName(DeclarationPointer(decl->context()->owner())),
QStringLiteral("jump_to_hide_container_%1").arg(num),
NavigationAction(DeclarationPointer(decl->context()->owner()),
NavigationAction::NavigateDeclaration));
modifyHtml() += QStringLiteral("
");
++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 overriders = DUChainUtils::getOverriders(classDecl, classFunDecl, maxAllowedSteps);
if(!overriders.isEmpty()) {
modifyHtml() += i18n("Overridden in ");
bool first = true;
foreach(Declaration* overrider, overriders) {
if(!first)
modifyHtml() += QStringLiteral(", ");
first = false;
const auto owner = DeclarationPointer(overrider->context()->owner());
const QString name = prettyQualifiedName(owner);
makeLink(name, name, NavigationAction(DeclarationPointer(overrider), NavigationAction::NavigateDeclaration));
}
modifyHtml() += QStringLiteral("
");
}
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 inheriters = DUChainUtils::getInheriters(m_declaration.data(), maxAllowedSteps);
if(!inheriters.isEmpty()) {
modifyHtml() += i18n("Inherited by ");
bool first = true;
foreach(Declaration* importer, inheriters) {
if(!first)
modifyHtml() += QStringLiteral(", ");
first = false;
const QString importerName = prettyQualifiedName(DeclarationPointer(importer));
makeLink(importerName, importerName,
NavigationAction(DeclarationPointer(importer), NavigationAction::NavigateDeclaration));
}
modifyHtml() += QStringLiteral("
");
}
if(maxAllowedSteps == 0)
createFullBackwardSearchLink(inheriters.isEmpty() ? i18n("Inheriters possible, show all") : i18n("More inheriters possible, show all"));
}
void AbstractDeclarationNavigationContext::createFullBackwardSearchLink(QString string)
{
makeLink(string, QStringLiteral("m_fullBackwardSearch=true"), NavigationAction(QStringLiteral("m_fullBackwardSearch=true")));
modifyHtml() += QStringLiteral("
");
}
NavigationContextPointer AbstractDeclarationNavigationContext::executeKeyAction( QString key )
{
if(key == QLatin1String("m_fullBackwardSearch=true")) {
m_fullBackwardSearch = true;
clear();
}
return NavigationContextPointer(this);
}
void AbstractDeclarationNavigationContext::htmlClass()
{
StructureType::Ptr klass = m_declaration->abstractType().cast();
Q_ASSERT(klass);
ClassDeclaration* classDecl = dynamic_cast(klass->declaration(m_topContext.data()));
if(classDecl) {
switch ( classDecl->classType() ) {
case ClassDeclarationData::Class:
modifyHtml() += QStringLiteral("class ");
break;
case ClassDeclarationData::Struct:
modifyHtml() += QStringLiteral("struct ");
break;
case ClassDeclarationData::Union:
modifyHtml() += QStringLiteral("union ");
break;
case ClassDeclarationData::Interface:
modifyHtml() += QStringLiteral("interface ");
break;
case ClassDeclarationData::Trait:
modifyHtml() += QStringLiteral("trait ");
break;
default:
modifyHtml() += QStringLiteral(" ");
break;
}
eventuallyMakeTypeLinks( klass.cast() );
FOREACH_FUNCTION( const BaseClassInstance& base, classDecl->baseClasses ) {
modifyHtml() += ", " + stringFromAccess(base.access) + " " + (base.virtualInheritance ? QStringLiteral("virtual") : QString()) + " ";
eventuallyMakeTypeLinks(base.baseClass.abstractType());
}
} else {
/// @todo How can we get here? and should this really be a class?
modifyHtml() += QStringLiteral("class ");
eventuallyMakeTypeLinks( klass.cast() );
}
modifyHtml() += QStringLiteral(" ");
}
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(contextType.data());
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() += QStringLiteral("::").toHtmlEscaped();
}
}
//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 {
qCDebug(LANGUAGE) << "could not resolve declaration:" << idType->declarationId().isDirect() << idType->qualifiedIdentifier().toString() << "in top-context" << m_topContext->url().str();
modifyHtml() += typeHighlight(type->toString().toHtmlEscaped());
}
}
void AbstractDeclarationNavigationContext::eventuallyMakeTypeLinks( AbstractType::Ptr type )
{
type = typeToShow(type);
if( !type ) {
modifyHtml() += typeHighlight(QStringLiteral("").toHtmlEscaped());
return;
}
AbstractType::Ptr target = TypeUtils::targetTypeKeepAliases( type, m_topContext.data() );
const IdentifiedType* idType = dynamic_cast( target.data() );
qCDebug(LANGUAGE) << "making type-links for" << type->toString();
if( idType && idType->declaration(m_topContext.data()) ) {
///@todo This is C++ specific, move into subclass
if(target->modifiers() & AbstractType::ConstModifier)
modifyHtml() += typeHighlight(QStringLiteral("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) {
qCDebug(LANGUAGE) << "identified type could not be resolved:" << idType->qualifiedIdentifier() << idType->declarationId().isValid() << idType->declarationId().isDirect();
}
modifyHtml() += typeHighlight(type->toString().toHtmlEscaped());
}
}
DeclarationPointer AbstractDeclarationNavigationContext::declaration() const
{
return m_declaration;
}
QString AbstractDeclarationNavigationContext::identifierHighlight(const QString& identifier, const DeclarationPointer& decl) const
{
QString ret = nameHighlight(identifier);
if (!decl) {
return ret;
}
if (decl->isDeprecated()) {
ret = QStringLiteral("") + ret + QStringLiteral("");
}
return ret;
}
QString AbstractDeclarationNavigationContext::stringFromAccess(Declaration::AccessPolicy access)
{
switch(access) {
case Declaration::Private:
return QStringLiteral("private");
case Declaration::Protected:
return QStringLiteral("protected");
case Declaration::Public:
return QStringLiteral("public");
default:
break;
}
return QString();
}
QString AbstractDeclarationNavigationContext::stringFromAccess(DeclarationPointer decl)
{
const ClassMemberDeclaration* memberDecl = dynamic_cast(decl.data());
if( memberDecl ) {
return stringFromAccess(memberDecl->accessPolicy());
}
return QString();
}
QString AbstractDeclarationNavigationContext::declarationName( DeclarationPointer decl ) const
{
if( NamespaceAliasDeclaration* alias = dynamic_cast(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(decl.data());
const ClassMemberDeclaration* memberDecl = dynamic_cast(decl.data());
if( memberDecl ) {
if( memberDecl->isMutable() )
details << QStringLiteral("mutable");
if( memberDecl->isRegister() )
details << QStringLiteral("register");
if( memberDecl->isStatic() )
details << QStringLiteral("static");
if( memberDecl->isAuto() )
details << QStringLiteral("auto");
if( memberDecl->isExtern() )
details << QStringLiteral("extern");
if( memberDecl->isFriend() )
details << QStringLiteral("friend");
}
if( decl->isDefinition() )
details << i18nc("tells if a declaration is defining the variable's value", "definition");
if( decl->isExplicitlyDeleted() )
details << QStringLiteral("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 << QStringLiteral("volatile");
}
if( function ) {
if( function->isInline() )
details << QStringLiteral("inline");
if( function->isExplicit() )
details << QStringLiteral("explicit");
if( function->isVirtual() )
details << QStringLiteral("virtual");
const ClassFunctionDeclaration* classFunDecl = dynamic_cast(decl.data());
if( classFunDecl ) {
if( classFunDecl->isSignal() )
details << QStringLiteral("signal");
if( classFunDecl->isSlot() )
details << QStringLiteral("slot");
if( classFunDecl->isConstructor() )
details << QStringLiteral("constructor");
if( classFunDecl->isDestructor() )
details << QStringLiteral("destructor");
if( classFunDecl->isConversionFunction() )
details << QStringLiteral("conversion-function");
if( classFunDecl->isAbstract() )
details << QStringLiteral("abstract");
}
}
return details;
}
}