forked from qt-creator/qt-creator
Show type hierarchy also for typedefs
Make it possible to show type hierarchy for typedefs and unsings. Before, no type hierarchy was shown. Change-Id: I63ffa9c544072d66c42de8edf306c898d2fa90cb Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -471,9 +471,19 @@ QFuture<QSharedPointer<CppElement>> CppElementEvaluator::execute(SourceFunction
|
|||||||
Symbol *symbol = item.declaration();
|
Symbol *symbol = item.declaration();
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
continue;
|
continue;
|
||||||
if (!symbol->isClass() && !symbol->isTemplate() && !symbol->isForwardClassDeclaration())
|
if (!symbol->isClass() && !symbol->isTemplate() && !symbol->isForwardClassDeclaration() && !symbol->isTypedef())
|
||||||
continue;
|
continue;
|
||||||
|
if (symbol->isTypedef()) {
|
||||||
|
CPlusPlus::NamedType *namedType = symbol->type()->asNamedType();
|
||||||
|
if (!namedType) {
|
||||||
|
// Anonymous aggregate such as: typedef struct {} Empty;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lookupItem = TypeHierarchyBuilder::followTypedef(typeOfExpression.context(),
|
||||||
|
namedType->name(), symbol->enclosingScope());
|
||||||
|
} else {
|
||||||
lookupItem = item;
|
lookupItem = item;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <cplusplus/FindUsages.h>
|
#include <cplusplus/FindUsages.h>
|
||||||
|
|
||||||
|
using namespace CPlusPlus;
|
||||||
using namespace CppTools;
|
using namespace CppTools;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -39,7 +40,7 @@ QString unqualifyName(const QString &qualifiedName)
|
|||||||
return qualifiedName.right(qualifiedName.length() - index - 2);
|
return qualifiedName.right(qualifiedName.length() - index - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
class DerivedHierarchyVisitor : public CPlusPlus::SymbolVisitor
|
class DerivedHierarchyVisitor : public SymbolVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit DerivedHierarchyVisitor(const QString &qualifiedName, QHash<QString, QHash<QString, QString>> &cache)
|
explicit DerivedHierarchyVisitor(const QString &qualifiedName, QHash<QString, QHash<QString, QString>> &cache)
|
||||||
@@ -48,86 +49,56 @@ public:
|
|||||||
, _cache(cache)
|
, _cache(cache)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void execute(const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot);
|
void execute(const Document::Ptr &doc, const Snapshot &snapshot);
|
||||||
|
|
||||||
bool visit(CPlusPlus::Class *) override;
|
bool visit(Class *) override;
|
||||||
|
|
||||||
const QList<CPlusPlus::Symbol *> &derived() { return _derived; }
|
const QList<Symbol *> &derived() { return _derived; }
|
||||||
const QSet<QString> otherBases() { return _otherBases; }
|
const QSet<QString> otherBases() { return _otherBases; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CPlusPlus::Symbol *lookup(const CPlusPlus::Name *symbolName, CPlusPlus::Scope *enclosingScope);
|
Symbol *lookup(const Name *symbolName, Scope *enclosingScope);
|
||||||
|
|
||||||
CPlusPlus::LookupContext _context;
|
LookupContext _context;
|
||||||
QString _qualifiedName;
|
QString _qualifiedName;
|
||||||
QString _unqualifiedName;
|
QString _unqualifiedName;
|
||||||
CPlusPlus::Overview _overview;
|
Overview _overview;
|
||||||
// full scope name to base symbol name to fully qualified base symbol name
|
// full scope name to base symbol name to fully qualified base symbol name
|
||||||
QHash<QString, QHash<QString, QString>> &_cache;
|
QHash<QString, QHash<QString, QString>> &_cache;
|
||||||
QSet<QString> _otherBases;
|
QSet<QString> _otherBases;
|
||||||
QList<CPlusPlus::Symbol *> _derived;
|
QList<Symbol *> _derived;
|
||||||
};
|
};
|
||||||
|
|
||||||
void DerivedHierarchyVisitor::execute(const CPlusPlus::Document::Ptr &doc,
|
void DerivedHierarchyVisitor::execute(const Document::Ptr &doc,
|
||||||
const CPlusPlus::Snapshot &snapshot)
|
const Snapshot &snapshot)
|
||||||
{
|
{
|
||||||
_derived.clear();
|
_derived.clear();
|
||||||
_otherBases.clear();
|
_otherBases.clear();
|
||||||
_context = CPlusPlus::LookupContext(doc, snapshot);
|
_context = LookupContext(doc, snapshot);
|
||||||
|
|
||||||
for (int i = 0; i < doc->globalSymbolCount(); ++i)
|
for (int i = 0; i < doc->globalSymbolCount(); ++i)
|
||||||
accept(doc->globalSymbolAt(i));
|
accept(doc->globalSymbolAt(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
CPlusPlus::Symbol *DerivedHierarchyVisitor::lookup(const CPlusPlus::Name *symbolName, CPlusPlus::Scope *enclosingScope)
|
bool DerivedHierarchyVisitor::visit(Class *symbol)
|
||||||
{
|
{
|
||||||
QList<CPlusPlus::LookupItem> items = _context.lookup(symbolName, enclosingScope);
|
const QList<const Name *> &fullScope
|
||||||
|
= LookupContext::fullyQualifiedName(symbol->enclosingScope());
|
||||||
CPlusPlus::Symbol *actualBaseSymbol = nullptr;
|
|
||||||
|
|
||||||
for (const CPlusPlus::LookupItem &item : items) {
|
|
||||||
CPlusPlus::Symbol *s = item.declaration();
|
|
||||||
if (!s)
|
|
||||||
continue;
|
|
||||||
if (!s->isClass() && !s->isTemplate() && !s->isTypedef())
|
|
||||||
continue;
|
|
||||||
actualBaseSymbol = s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!actualBaseSymbol)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (actualBaseSymbol->isTypedef()) {
|
|
||||||
CPlusPlus::NamedType *namedType = actualBaseSymbol->type()->asNamedType();
|
|
||||||
if (!namedType) {
|
|
||||||
// Anonymous aggregate such as: typedef struct {} Empty;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
actualBaseSymbol = lookup(namedType->name(), actualBaseSymbol->enclosingScope());
|
|
||||||
}
|
|
||||||
|
|
||||||
return actualBaseSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DerivedHierarchyVisitor::visit(CPlusPlus::Class *symbol)
|
|
||||||
{
|
|
||||||
const QList<const CPlusPlus::Name *> &fullScope
|
|
||||||
= CPlusPlus::LookupContext::fullyQualifiedName(symbol->enclosingScope());
|
|
||||||
const QString fullScopeName = _overview.prettyName(fullScope);
|
const QString fullScopeName = _overview.prettyName(fullScope);
|
||||||
|
|
||||||
for (int i = 0; i < symbol->baseClassCount(); ++i) {
|
for (int i = 0; i < symbol->baseClassCount(); ++i) {
|
||||||
CPlusPlus::BaseClass *baseSymbol = symbol->baseClassAt(i);
|
BaseClass *baseSymbol = symbol->baseClassAt(i);
|
||||||
|
|
||||||
const QString &baseName = _overview.prettyName(baseSymbol->name());
|
const QString &baseName = _overview.prettyName(baseSymbol->name());
|
||||||
QString fullBaseName = _cache.value(fullScopeName).value(baseName);
|
QString fullBaseName = _cache.value(fullScopeName).value(baseName);
|
||||||
if (fullBaseName.isEmpty()) {
|
if (fullBaseName.isEmpty()) {
|
||||||
CPlusPlus::Symbol *actualBaseSymbol = lookup(baseSymbol->name(), symbol->enclosingScope());
|
Symbol *actualBaseSymbol = TypeHierarchyBuilder::followTypedef(_context,
|
||||||
|
baseSymbol->name(), symbol->enclosingScope()).declaration();
|
||||||
if (!actualBaseSymbol)
|
if (!actualBaseSymbol)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const QList<const CPlusPlus::Name *> &full
|
const QList<const Name *> &full
|
||||||
= CPlusPlus::LookupContext::fullyQualifiedName(actualBaseSymbol);
|
= LookupContext::fullyQualifiedName(actualBaseSymbol);
|
||||||
fullBaseName = _overview.prettyName(full);
|
fullBaseName = _overview.prettyName(full);
|
||||||
_cache[fullScopeName].insert(baseName, fullBaseName);
|
_cache[fullScopeName].insert(baseName, fullBaseName);
|
||||||
}
|
}
|
||||||
@@ -144,10 +115,10 @@ bool DerivedHierarchyVisitor::visit(CPlusPlus::Class *symbol)
|
|||||||
|
|
||||||
TypeHierarchy::TypeHierarchy() = default;
|
TypeHierarchy::TypeHierarchy() = default;
|
||||||
|
|
||||||
TypeHierarchy::TypeHierarchy(CPlusPlus::Symbol *symbol) : _symbol(symbol)
|
TypeHierarchy::TypeHierarchy(Symbol *symbol) : _symbol(symbol)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CPlusPlus::Symbol *TypeHierarchy::symbol() const
|
Symbol *TypeHierarchy::symbol() const
|
||||||
{
|
{
|
||||||
return _symbol;
|
return _symbol;
|
||||||
}
|
}
|
||||||
@@ -157,16 +128,16 @@ const QList<TypeHierarchy> &TypeHierarchy::hierarchy() const
|
|||||||
return _hierarchy;
|
return _hierarchy;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy(CPlusPlus::Symbol *symbol,
|
TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy(Symbol *symbol,
|
||||||
const CPlusPlus::Snapshot &snapshot)
|
const Snapshot &snapshot)
|
||||||
{
|
{
|
||||||
QFutureInterfaceBase dummy;
|
QFutureInterfaceBase dummy;
|
||||||
return TypeHierarchyBuilder::buildDerivedTypeHierarchy(dummy, symbol, snapshot);
|
return TypeHierarchyBuilder::buildDerivedTypeHierarchy(dummy, symbol, snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy(QFutureInterfaceBase &futureInterface,
|
TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy(QFutureInterfaceBase &futureInterface,
|
||||||
CPlusPlus::Symbol *symbol,
|
Symbol *symbol,
|
||||||
const CPlusPlus::Snapshot &snapshot)
|
const Snapshot &snapshot)
|
||||||
{
|
{
|
||||||
TypeHierarchy hierarchy(symbol);
|
TypeHierarchy hierarchy(symbol);
|
||||||
TypeHierarchyBuilder builder;
|
TypeHierarchyBuilder builder;
|
||||||
@@ -175,8 +146,41 @@ TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy(QFutureInterfaceBa
|
|||||||
return hierarchy;
|
return hierarchy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Utils::FilePaths filesDependingOn(const CPlusPlus::Snapshot &snapshot,
|
LookupItem TypeHierarchyBuilder::followTypedef(const LookupContext &context, const Name *symbolName, Scope *enclosingScope)
|
||||||
CPlusPlus::Symbol *symbol)
|
{
|
||||||
|
QList<LookupItem> items = context.lookup(symbolName, enclosingScope);
|
||||||
|
|
||||||
|
Symbol *actualBaseSymbol = nullptr;
|
||||||
|
LookupItem matchingItem;
|
||||||
|
|
||||||
|
for (const LookupItem &item : items) {
|
||||||
|
Symbol *s = item.declaration();
|
||||||
|
if (!s)
|
||||||
|
continue;
|
||||||
|
if (!s->isClass() && !s->isTemplate() && !s->isTypedef())
|
||||||
|
continue;
|
||||||
|
actualBaseSymbol = s;
|
||||||
|
matchingItem = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!actualBaseSymbol)
|
||||||
|
return LookupItem();
|
||||||
|
|
||||||
|
if (actualBaseSymbol->isTypedef()) {
|
||||||
|
NamedType *namedType = actualBaseSymbol->type()->asNamedType();
|
||||||
|
if (!namedType) {
|
||||||
|
// Anonymous aggregate such as: typedef struct {} Empty;
|
||||||
|
return LookupItem();
|
||||||
|
}
|
||||||
|
return followTypedef(context, namedType->name(), actualBaseSymbol->enclosingScope());
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Utils::FilePaths filesDependingOn(const Snapshot &snapshot,
|
||||||
|
Symbol *symbol)
|
||||||
{
|
{
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
return Utils::FilePaths();
|
return Utils::FilePaths();
|
||||||
@@ -187,17 +191,17 @@ static Utils::FilePaths filesDependingOn(const CPlusPlus::Snapshot &snapshot,
|
|||||||
|
|
||||||
void TypeHierarchyBuilder::buildDerived(QFutureInterfaceBase &futureInterface,
|
void TypeHierarchyBuilder::buildDerived(QFutureInterfaceBase &futureInterface,
|
||||||
TypeHierarchy *typeHierarchy,
|
TypeHierarchy *typeHierarchy,
|
||||||
const CPlusPlus::Snapshot &snapshot,
|
const Snapshot &snapshot,
|
||||||
QHash<QString, QHash<QString, QString>> &cache,
|
QHash<QString, QHash<QString, QString>> &cache,
|
||||||
int depth)
|
int depth)
|
||||||
{
|
{
|
||||||
CPlusPlus::Symbol *symbol = typeHierarchy->_symbol;
|
Symbol *symbol = typeHierarchy->_symbol;
|
||||||
if (_visited.contains(symbol))
|
if (_visited.contains(symbol))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_visited.insert(symbol);
|
_visited.insert(symbol);
|
||||||
|
|
||||||
const QString &symbolName = _overview.prettyName(CPlusPlus::LookupContext::fullyQualifiedName(symbol));
|
const QString &symbolName = _overview.prettyName(LookupContext::fullyQualifiedName(symbol));
|
||||||
DerivedHierarchyVisitor visitor(symbolName, cache);
|
DerivedHierarchyVisitor visitor(symbolName, cache);
|
||||||
|
|
||||||
const Utils::FilePaths &dependingFiles = filesDependingOn(snapshot, symbol);
|
const Utils::FilePaths &dependingFiles = filesDependingOn(snapshot, symbol);
|
||||||
@@ -210,7 +214,7 @@ void TypeHierarchyBuilder::buildDerived(QFutureInterfaceBase &futureInterface,
|
|||||||
return;
|
return;
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
futureInterface.setProgressValue(++i);
|
futureInterface.setProgressValue(++i);
|
||||||
CPlusPlus::Document::Ptr doc = snapshot.document(fileName);
|
Document::Ptr doc = snapshot.document(fileName);
|
||||||
if ((_candidates.contains(fileName) && !_candidates.value(fileName).contains(symbolName))
|
if ((_candidates.contains(fileName) && !_candidates.value(fileName).contains(symbolName))
|
||||||
|| !doc->control()->findIdentifier(symbol->identifier()->chars(),
|
|| !doc->control()->findIdentifier(symbol->identifier()->chars(),
|
||||||
symbol->identifier()->size())) {
|
symbol->identifier()->size())) {
|
||||||
@@ -220,8 +224,8 @@ void TypeHierarchyBuilder::buildDerived(QFutureInterfaceBase &futureInterface,
|
|||||||
visitor.execute(doc, snapshot);
|
visitor.execute(doc, snapshot);
|
||||||
_candidates.insert(fileName, visitor.otherBases());
|
_candidates.insert(fileName, visitor.otherBases());
|
||||||
|
|
||||||
const QList<CPlusPlus::Symbol *> &derived = visitor.derived();
|
const QList<Symbol *> &derived = visitor.derived();
|
||||||
for (CPlusPlus::Symbol *s : derived) {
|
for (Symbol *s : derived) {
|
||||||
TypeHierarchy derivedHierarchy(s);
|
TypeHierarchy derivedHierarchy(s);
|
||||||
buildDerived(futureInterface, &derivedHierarchy, snapshot, cache, depth + 1);
|
buildDerived(futureInterface, &derivedHierarchy, snapshot, cache, depth + 1);
|
||||||
if (futureInterface.isCanceled())
|
if (futureInterface.isCanceled())
|
||||||
|
|||||||
@@ -34,6 +34,13 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
|
namespace CPlusPlus {
|
||||||
|
class LookupContext;
|
||||||
|
class LookupItem;
|
||||||
|
class Name;
|
||||||
|
class Scope;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
|
|
||||||
class CPPTOOLS_EXPORT TypeHierarchy
|
class CPPTOOLS_EXPORT TypeHierarchy
|
||||||
@@ -63,7 +70,9 @@ public:
|
|||||||
static TypeHierarchy buildDerivedTypeHierarchy(QFutureInterfaceBase &futureInterface,
|
static TypeHierarchy buildDerivedTypeHierarchy(QFutureInterfaceBase &futureInterface,
|
||||||
CPlusPlus::Symbol *symbol,
|
CPlusPlus::Symbol *symbol,
|
||||||
const CPlusPlus::Snapshot &snapshot);
|
const CPlusPlus::Snapshot &snapshot);
|
||||||
|
static CPlusPlus::LookupItem followTypedef(const CPlusPlus::LookupContext &context,
|
||||||
|
const CPlusPlus::Name *symbolName,
|
||||||
|
CPlusPlus::Scope *enclosingScope);
|
||||||
private:
|
private:
|
||||||
TypeHierarchyBuilder() = default;
|
TypeHierarchyBuilder() = default;
|
||||||
void buildDerived(QFutureInterfaceBase &futureInterface, TypeHierarchy *typeHierarchy,
|
void buildDerived(QFutureInterfaceBase &futureInterface, TypeHierarchy *typeHierarchy,
|
||||||
|
|||||||
Reference in New Issue
Block a user