diff --git a/src/libs/cplusplus/TypeHierarchyBuilder.cpp b/src/libs/cplusplus/TypeHierarchyBuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6db175889b62cc4cb71eee50b9fde2d4fee8d334 --- /dev/null +++ b/src/libs/cplusplus/TypeHierarchyBuilder.cpp @@ -0,0 +1,201 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "TypeHierarchyBuilder.h" +#include "FindUsages.h" +#include "Symbols.h" +#include "SymbolVisitor.h" +#include "DependencyTable.h" +#include "CppDocument.h" +#include "Literals.h" +#include "TranslationUnit.h" +#include "CoreTypes.h" + +using namespace CPlusPlus; + +namespace { + +QString unqualifyName(const QString &qualifiedName) +{ + const int index = qualifiedName.lastIndexOf(QLatin1String("::")); + if (index == -1) + return qualifiedName; + return qualifiedName.right(qualifiedName.length() - index - 2); +} + +class DerivedHierarchyVisitor : public SymbolVisitor +{ +public: + DerivedHierarchyVisitor(const QString &qualifiedName) + : _qualifiedName(qualifiedName) + , _unqualifiedName(unqualifyName(qualifiedName)) + {} + + void execute(const Document::Ptr &doc, const Snapshot &snapshot); + + virtual bool visit(Class *); + + const QList<Symbol *> &derived() { return _derived; } + const QStringList otherBases() { return _otherBases; } + +private: + LookupContext _context; + QString _qualifiedName; + QString _unqualifiedName; + Overview _overview; + QHash<Symbol *, QString> _actualBases; + QStringList _otherBases; + QList<Symbol *> _derived; +}; + +void DerivedHierarchyVisitor::execute(const Document::Ptr &doc, const Snapshot &snapshot) +{ + _derived.clear(); + _otherBases.clear(); + _context = LookupContext(doc, snapshot); + + for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) + accept(doc->globalSymbolAt(i)); +} + +bool DerivedHierarchyVisitor::visit(Class *symbol) +{ + for (unsigned i = 0; i < symbol->baseClassCount(); ++i) { + BaseClass *baseSymbol = symbol->baseClassAt(i); + + QString baseName = _actualBases.value(baseSymbol); + if (baseName.isEmpty()) { + QList<LookupItem> items = _context.lookup(baseSymbol->name(), symbol->enclosingScope()); + if (items.isEmpty() || !items.first().declaration()) + continue; + + Symbol *actualBaseSymbol = items.first().declaration(); + if (actualBaseSymbol->isTypedef()) { + NamedType *namedType = actualBaseSymbol->type()->asNamedType(); + const QString &typeName = _overview.prettyName(namedType->name()); + if (namedType && + (typeName == _unqualifiedName || typeName == _qualifiedName)) { + items = _context.lookup(namedType->name(), actualBaseSymbol->enclosingScope()); + if (items.isEmpty() || !items.first().declaration()) + continue; + actualBaseSymbol = items.first().declaration(); + } + } + + const QList<const Name *> &full = LookupContext::fullyQualifiedName(actualBaseSymbol); + baseName = _overview.prettyName(full); + _actualBases.insert(baseSymbol, baseName); + } + + if (_qualifiedName == baseName) + _derived.append(symbol); + else + _otherBases.append(baseName); + } + + return true; +} + +} + +TypeHierarchy::TypeHierarchy() : _symbol(0) +{} + +TypeHierarchy::TypeHierarchy(Symbol *symbol) : _symbol(symbol) +{} + +Symbol *TypeHierarchy::symbol() const +{ + return _symbol; +} + +const QList<TypeHierarchy> &TypeHierarchy::hierarchy() const +{ + return _hierarchy; +} + +TypeHierarchyBuilder::TypeHierarchyBuilder(Symbol *symbol, const Snapshot &snapshot) + : _symbol(symbol) + , _snapshot(snapshot) + , _dependencies(QString::fromUtf8(symbol->fileName(), symbol->fileNameLength())) +{ + DependencyTable dependencyTable; + dependencyTable.build(_snapshot); + _dependencies.append(dependencyTable.filesDependingOn(_dependencies.first())); +} + +void TypeHierarchyBuilder::reset() +{ + _visited.clear(); + _candidates.clear(); +} + +TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy() +{ + reset(); + TypeHierarchy hierarchy(_symbol); + buildDerived(&hierarchy); + return hierarchy; +} + +void TypeHierarchyBuilder::buildDerived(TypeHierarchy *typeHierarchy) +{ + Symbol *symbol = typeHierarchy->_symbol; + if (_visited.contains(symbol)) + return; + + _visited.insert(symbol); + + const QString &symbolName = _overview.prettyName(LookupContext::fullyQualifiedName(symbol)); + DerivedHierarchyVisitor visitor(symbolName); + + foreach (const QString &fileName, _dependencies) { + Document::Ptr doc = _snapshot.document(fileName); + if ((_candidates.contains(fileName) && !_candidates.value(fileName).contains(symbolName)) + || !doc->control()->findIdentifier(symbol->identifier()->chars(), + symbol->identifier()->size())) { + continue; + } + + visitor.execute(doc, _snapshot); + _candidates.insert(fileName, QSet<QString>()); + + foreach (const QString &candidate, visitor.otherBases()) + _candidates[fileName].insert(candidate); + + foreach (Symbol *s, visitor.derived()) { + TypeHierarchy derivedHierarchy(s); + buildDerived(&derivedHierarchy); + typeHierarchy->_hierarchy.append(derivedHierarchy); + } + } +} diff --git a/src/libs/cplusplus/TypeHierarchyBuilder.h b/src/libs/cplusplus/TypeHierarchyBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..f8dceb83bf77f3d5bb4d2db62ee8edfcccc7b130 --- /dev/null +++ b/src/libs/cplusplus/TypeHierarchyBuilder.h @@ -0,0 +1,83 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#ifndef FINDDERIVEDCLASSES_H +#define FINDDERIVEDCLASSES_H + +#include "CppDocument.h" +#include "ModelManagerInterface.h" +#include "Overview.h" + +#include <QtCore/QList> +#include <QtCore/QStringList> +#include <QtCore/QSet> + +namespace CPlusPlus { + +class CPLUSPLUS_EXPORT TypeHierarchy +{ + friend class TypeHierarchyBuilder; + +public: + TypeHierarchy(); + TypeHierarchy(Symbol *symbol); + + Symbol *symbol() const; + const QList<TypeHierarchy> &hierarchy() const; + +private: + Symbol *_symbol; + QList<TypeHierarchy> _hierarchy; +}; + +class CPLUSPLUS_EXPORT TypeHierarchyBuilder +{ +public: + TypeHierarchyBuilder(Symbol *symbol, const Snapshot &snapshot); + + TypeHierarchy buildDerivedTypeHierarchy(); + +private: + void reset(); + void buildDerived(TypeHierarchy *typeHierarchy); + + Symbol *_symbol; + Snapshot _snapshot; + QStringList _dependencies; + QSet<Symbol *> _visited; + QHash<QString, QSet<QString> > _candidates; + Overview _overview; +}; + +} // CPlusPlus + +#endif // FINDDERIVEDCLASSES_H diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri index f2683c7daceda688517d55043d9022b68fa81ec2..d4e12f05999c208d0bdc11c823f753e26d174d6c 100644 --- a/src/libs/cplusplus/cplusplus-lib.pri +++ b/src/libs/cplusplus/cplusplus-lib.pri @@ -52,7 +52,8 @@ HEADERS += \ $$PWD/pp-macro-expander.h \ $$PWD/pp-scanner.h \ $$PWD/ModelManagerInterface.h \ - $$PWD/findcdbbreakpoint.h + $$PWD/findcdbbreakpoint.h \ + $$PWD/TypeHierarchyBuilder.h SOURCES += \ $$PWD/SimpleLexer.cpp \ @@ -80,10 +81,7 @@ SOURCES += \ $$PWD/pp-macro-expander.cpp \ $$PWD/pp-scanner.cpp \ $$PWD/ModelManagerInterface.cpp \ - $$PWD/findcdbbreakpoint.cpp + $$PWD/findcdbbreakpoint.cpp \ + $$PWD/TypeHierarchyBuilder.cpp RESOURCES += $$PWD/cplusplus.qrc - - - - diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp index d3d1b86f7d75fe9f530d3e558e73554f13c1ee26..f4a22e759bd4e73dab4b648e77ddf3096d6d7a3a 100644 --- a/src/plugins/cppeditor/cppelementevaluator.cpp +++ b/src/plugins/cppeditor/cppelementevaluator.cpp @@ -33,6 +33,7 @@ #include "cppelementevaluator.h" #include <coreplugin/ifile.h> +#include <cpptools/cpptoolsreuse.h> #include <FullySpecifiedType.h> #include <Literals.h> @@ -41,6 +42,7 @@ #include <Scope.h> #include <Symbol.h> #include <Symbols.h> +#include <TypeHierarchyBuilder.h> #include <cplusplus/ModelManagerInterface.h> #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/Overview.h> @@ -59,18 +61,6 @@ using namespace Internal; using namespace CPlusPlus; namespace { - void moveCursorToEndOfName(QTextCursor *tc) { - QTextDocument *doc = tc->document(); - if (!doc) - return; - - QChar ch = doc->characterAt(tc->position()); - while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) { - tc->movePosition(QTextCursor::NextCharacter); - ch = doc->characterAt(tc->position()); - } - } - QStringList stripName(const QString &name) { QStringList all; all << name; @@ -88,7 +78,8 @@ CppElementEvaluator::CppElementEvaluator(CPPEditorWidget *editor) : m_editor(editor), m_modelManager(CppModelManagerInterface::instance()), m_tc(editor->textCursor()), - m_lookupBaseClasses(false) + m_lookupBaseClasses(false), + m_lookupDerivedClasses(false) {} void CppElementEvaluator::setTextCursor(const QTextCursor &tc) @@ -97,6 +88,9 @@ void CppElementEvaluator::setTextCursor(const QTextCursor &tc) void CppElementEvaluator::setLookupBaseClasses(const bool lookup) { m_lookupBaseClasses = lookup; } +void CppElementEvaluator::setLookupDerivedClasses(const bool lookup) +{ m_lookupDerivedClasses = lookup; } + // @todo: Consider refactoring code from CPPEditor::findLinkAt into here. void CppElementEvaluator::execute() { @@ -118,7 +112,7 @@ void CppElementEvaluator::execute() checkDiagnosticMessage(doc, line); if (!matchIncludeFile(doc, line) && !matchMacroInUse(doc, pos)) { - moveCursorToEndOfName(&m_tc); + CppTools::moveCursorToEndOfIdentifier(&m_tc); // Fetch the expression's code ExpressionUnderCursor expressionUnderCursor; @@ -185,13 +179,19 @@ void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot, const FullySpecifiedType &type = declaration->type(); if (declaration->isNamespace()) { m_element = QSharedPointer<CppElement>(new CppNamespace(declaration)); - } else if (declaration->isClass() || declaration->isForwardClassDeclaration()) { + } else if (declaration->isClass() + || declaration->isForwardClassDeclaration() + || (declaration->isTemplate() && declaration->asTemplate()->declaration() + && (declaration->asTemplate()->declaration()->isClass() + || declaration->asTemplate()->declaration()->isForwardClassDeclaration()))) { if (declaration->isForwardClassDeclaration()) if (Symbol *classDeclaration = snapshot.findMatchingClassDeclaration(declaration)) declaration = classDeclaration; CppClass *cppClass = new CppClass(declaration); if (m_lookupBaseClasses) cppClass->lookupBases(declaration, context); + if (m_lookupDerivedClasses) + cppClass->lookupDerived(declaration, snapshot); m_element = QSharedPointer<CppElement>(cppClass); } else if (Enum *enumDecl = declaration->asEnum()) { m_element = QSharedPointer<CppElement>(new CppEnum(enumDecl)); @@ -199,13 +199,13 @@ void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot, m_element = QSharedPointer<CppElement>(new CppEnumerator(enumerator)); } else if (declaration->isTypedef()) { m_element = QSharedPointer<CppElement>(new CppTypedef(declaration)); - } else if (declaration->isFunction() || (type.isValid() && type->isFunctionType())) { + } else if (declaration->isFunction() + || (type.isValid() && type->isFunctionType()) + || declaration->isTemplate()) { m_element = QSharedPointer<CppElement>(new CppFunction(declaration)); } else if (declaration->isDeclaration() && type.isValid()) { m_element = QSharedPointer<CppElement>( new CppVariable(declaration, context, lookupItem.scope())); - } else if (declaration->isTemplate() && declaration->asTemplate()->declaration()) { - m_element = QSharedPointer<CppElement>(new CppTemplate(declaration)); } else { m_element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration)); } @@ -327,6 +327,9 @@ CppMacro::~CppMacro() {} // CppDeclarableElement +CppDeclarableElement::CppDeclarableElement() +{} + CppDeclarableElement::CppDeclarableElement(Symbol *declaration) : CppElement() { m_icon = Icons().iconForSymbol(declaration); @@ -388,6 +391,9 @@ CppNamespace::~CppNamespace() {} // CppClass +CppClass::CppClass() +{} + CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration) { setHelpCategory(TextEditor::HelpItem::ClassOrNamespace); @@ -428,9 +434,32 @@ void CppClass::lookupBases(Symbol *declaration, const CPlusPlus::LookupContext & } } +void CppClass::lookupDerived(CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot) +{ + typedef QPair<CppClass *, TypeHierarchy> Data; + + TypeHierarchyBuilder builder(declaration, snapshot); + const TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(); + + QQueue<Data> q; + q.enqueue(qMakePair(this, completeHierarchy)); + while (!q.isEmpty()) { + const Data ¤t = q.dequeue(); + CppClass *clazz = current.first; + const TypeHierarchy &classHierarchy = current.second; + foreach (const TypeHierarchy &derivedHierarchy, classHierarchy.hierarchy()) { + clazz->m_derived.append(CppClass(derivedHierarchy.symbol())); + q.enqueue(qMakePair(&clazz->m_derived.last(), derivedHierarchy)); + } + } +} + const QList<CppClass> &CppClass::bases() const { return m_bases; } +const QList<CppClass> &CppClass::derived() const +{ return m_derived; } + // CppFunction CppFunction::CppFunction(Symbol *declaration) : CppDeclarableElement(declaration) { @@ -515,34 +544,6 @@ CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scop CppVariable::~CppVariable() {} -// CppTemplate -CppTemplate::CppTemplate(CPlusPlus::Symbol *declaration) : CppDeclarableElement(declaration) -{ - Template *templateSymbol = declaration->asTemplate(); - if (templateSymbol->declaration()->isClass() || - templateSymbol->declaration()->isForwardClassDeclaration()) { - m_isClassTemplate = true; - setHelpCategory(TextEditor::HelpItem::ClassOrNamespace); - setTooltip(qualifiedName()); - } else { - m_isClassTemplate = false; - setHelpCategory(TextEditor::HelpItem::Function); - } -} - -CppTemplate::~CppTemplate() -{} - -bool CppTemplate::isClassTemplate() const -{ - return m_isClassTemplate; -} - -bool CppTemplate::isFunctionTemplate() const -{ - return !m_isClassTemplate; -} - CppEnumerator::CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration) : CppDeclarableElement(declaration) { diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cppeditor/cppelementevaluator.h index c20c3c0ff932ed87073a0438342917df77a588a3..ac68784f47874354dd565c9f0b409c169b28721f 100644 --- a/src/plugins/cppeditor/cppelementevaluator.h +++ b/src/plugins/cppeditor/cppelementevaluator.h @@ -68,6 +68,7 @@ public: void setTextCursor(const QTextCursor &tc); void setLookupBaseClasses(const bool lookup); + void setLookupDerivedClasses(const bool lookup); void execute(); bool identifiedCppElement() const; @@ -88,6 +89,7 @@ private: CPlusPlus::CppModelManagerInterface *m_modelManager; QTextCursor m_tc; bool m_lookupBaseClasses; + bool m_lookupDerivedClasses; QSharedPointer<CppElement> m_element; QString m_diagnosis; }; @@ -157,6 +159,7 @@ public: class CppDeclarableElement : public CppElement { public: + CppDeclarableElement(); explicit CppDeclarableElement(CPlusPlus::Symbol *declaration); virtual ~CppDeclarableElement(); @@ -188,15 +191,19 @@ public: class CppClass : public CppDeclarableElement { public: + CppClass(); explicit CppClass(CPlusPlus::Symbol *declaration); virtual ~CppClass(); void lookupBases(CPlusPlus::Symbol *declaration, const CPlusPlus::LookupContext &context); + void lookupDerived(CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot); const QList<CppClass> &bases() const; + const QList<CppClass> &derived() const; private: QList<CppClass> m_bases; + QList<CppClass> m_derived; }; class CppFunction : public CppDeclarableElement @@ -229,19 +236,6 @@ public: virtual ~CppVariable(); }; -class CppTemplate : public CppDeclarableElement -{ -public: - explicit CppTemplate(CPlusPlus::Symbol *declaration); - virtual ~CppTemplate(); - - bool isClassTemplate() const; - bool isFunctionTemplate() const; - -private: - bool m_isClassTemplate; -}; - class CppEnumerator : public CppDeclarableElement { public: diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp index 48fd4de85a9a8d2e5bd59ad7dbccb3da8dfcecb5..aa38b8e64cb5705d4c4ecd5b4b8908935b9b1188 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.cpp +++ b/src/plugins/cppeditor/cpptypehierarchy.cpp @@ -44,6 +44,7 @@ #include <QtCore/QLatin1Char> #include <QtCore/QLatin1String> #include <QtCore/QModelIndex> +#include <QtCore/QVector> #include <QtGui/QVBoxLayout> #include <QtGui/QStandardItemModel> #include <QtGui/QLabel> @@ -52,6 +53,28 @@ using namespace CppEditor; using namespace Internal; using namespace Utils; +namespace { + +enum ItemRole { + AnnotationRole = Qt::UserRole + 1, + LinkRole +}; + +QStandardItem *itemForClass(const CppClass &cppClass) +{ + QStandardItem *item = new QStandardItem; + item->setData(cppClass.name(), Qt::DisplayRole); + if (cppClass.name() != cppClass.qualifiedName()) + item->setData(cppClass.qualifiedName(), AnnotationRole); + item->setData(cppClass.icon(), Qt::DecorationRole); + QVariant link; + link.setValue(CPPEditorWidget::Link(cppClass.link())); + item->setData(link, LinkRole); + return item; +} + +} // Anonymous + // CppTypeHierarchyWidget CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) : QWidget(0), @@ -67,16 +90,18 @@ CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) : if (CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor)) { m_cppEditor = static_cast<CPPEditorWidget *>(cppEditor->widget()); - m_model = new QStandardItemModel; - m_treeView = new Utils::NavigationTreeView; - m_delegate = new AnnotatedItemDelegate; + m_model = new QStandardItemModel(this); + m_treeView = new NavigationTreeView(this); + m_delegate = new AnnotatedItemDelegate(this); m_delegate->setDelimiter(QLatin1String(" ")); m_delegate->setAnnotationRole(AnnotationRole); m_treeView->setModel(m_model); m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_treeView->setItemDelegate(m_delegate); + m_treeView->setRootIsDecorated(false); layout->addWidget(m_treeView); + connect(m_treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onItemClicked(QModelIndex))); connect(m_treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onItemClicked(QModelIndex))); connect(CppPlugin::instance(), SIGNAL(typeHierarchyRequested()), this, SLOT(perform())); } else { @@ -90,10 +115,7 @@ CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) : } CppTypeHierarchyWidget::~CppTypeHierarchyWidget() -{ - delete m_model; - delete m_delegate; -} +{} bool CppTypeHierarchyWidget::handleEditorChange(Core::IEditor *editor) { @@ -117,32 +139,52 @@ void CppTypeHierarchyWidget::perform() CppElementEvaluator evaluator(m_cppEditor); evaluator.setLookupBaseClasses(true); + evaluator.setLookupDerivedClasses(true); evaluator.execute(); if (evaluator.identifiedCppElement()) { const QSharedPointer<CppElement> &cppElement = evaluator.cppElement(); CppElement *element = cppElement.data(); - if (CppClass *cppClass = dynamic_cast<CppClass *>(element)) - buildModel(*cppClass, m_model->invisibleRootItem()); + if (CppClass *cppClass = dynamic_cast<CppClass *>(element)) { + QStandardItem *bases = new QStandardItem(tr("Bases")); + m_model->invisibleRootItem()->appendRow(bases); + QVector<CppClass> v; + v.push_back(*cppClass); + buildBaseHierarchy(&v); + m_treeView->expand(m_model->indexFromItem(bases)); + QStandardItem *derived = new QStandardItem(tr("Derived")); + m_model->invisibleRootItem()->appendRow(derived); + buildDerivedHierarchy(*cppClass, derived); + } } } -void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem *parent) +void CppTypeHierarchyWidget::buildBaseHierarchy(QVector<CppClass> *s) { - QStandardItem *item = new QStandardItem; - parent->appendRow(item); - - m_model->setData(m_model->indexFromItem(item), cppClass.name(), Qt::DisplayRole); - if (cppClass.name() != cppClass.qualifiedName()) - m_model->setData(m_model->indexFromItem(item), cppClass.qualifiedName(), AnnotationRole); - m_model->setData(m_model->indexFromItem(item), cppClass.icon(), Qt::DecorationRole); - QVariant link; - link.setValue(CPPEditorWidget::Link(cppClass.link())); - m_model->setData(m_model->indexFromItem(item), link, LinkRole); - - foreach (const CppClass &cppBase, cppClass.bases()) - buildModel(cppBase, item); + const CppClass ¤t = s->back(); + const QList<CppClass> &bases = current.bases(); + if (!bases.isEmpty()) { + foreach (const CppClass &base, bases) { + s->push_back(base); + buildBaseHierarchy(s); + s->pop_back(); + } + } else { + QStandardItem *parent = m_model->item(0, 0); + for (int i = s->size() - 1; i >= 0; --i) { + QStandardItem *item = itemForClass(s->at(i)); + parent->appendRow(item); + parent = item; + } + } +} - m_treeView->expand(m_model->indexFromItem(item)); +void CppTypeHierarchyWidget::buildDerivedHierarchy(const CppClass &cppClass, QStandardItem *parent) +{ + QStandardItem *item = itemForClass(cppClass); + parent->appendRow(item); + foreach (const CppClass &derived, cppClass.derived()) + buildDerivedHierarchy(derived, item); + m_treeView->expand(m_model->indexFromItem(parent)); } void CppTypeHierarchyWidget::onItemClicked(const QModelIndex &index) diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h index 2685e1f0c5119d85cc916f5e820aa02316108e9b..4be85f3e7319f3a3393f92910cb805a12ab81280 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.h +++ b/src/plugins/cppeditor/cpptypehierarchy.h @@ -33,8 +33,6 @@ #ifndef CPPTYPEHIERARCHY_H #define CPPTYPEHIERARCHY_H -#include "cppelementevaluator.h" - #include <coreplugin/inavigationwidgetfactory.h> #include <QtCore/QString> @@ -45,6 +43,7 @@ QT_BEGIN_NAMESPACE class QStandardItemModel; class QStandardItem; class QModelIndex; +template <class> class QVector; QT_END_NAMESPACE namespace Core { @@ -60,6 +59,7 @@ namespace CppEditor { namespace Internal { class CPPEditorWidget; +class CppClass; class CppTypeHierarchyWidget : public QWidget { @@ -77,12 +77,8 @@ private slots: void onItemClicked(const QModelIndex &index); private: - enum ItemRole { - AnnotationRole = Qt::UserRole + 1, - LinkRole - }; - - void buildModel(const CppClass &cppClass, QStandardItem *item); + void buildDerivedHierarchy(const CppClass &cppClass, QStandardItem *parent); + void buildBaseHierarchy(QVector<CppClass> *s); CPPEditorWidget *m_cppEditor; Utils::NavigationTreeView *m_treeView; diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 2351c5c5ea327803370a0a22f61ec9d430e1d956..2821429df624714cf682d54b679790c836d1464b 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -34,7 +34,8 @@ HEADERS += completionsettingspage.h \ cpptoolssettings.h \ cppcodestylesettings.h \ cppcodestylesettingsfactory.h \ - cppcodestylepreferences.h + cppcodestylepreferences.h \ + cpptoolsreuse.h SOURCES += completionsettingspage.cpp \ cppclassesfilter.cpp \ @@ -60,7 +61,8 @@ SOURCES += completionsettingspage.cpp \ cpptoolssettings.cpp \ cppcodestylesettings.cpp \ cppcodestylesettingsfactory.cpp \ - cppcodestylepreferences.cpp + cppcodestylepreferences.cpp \ + cpptoolsreuse.cpp FORMS += completionsettingspage.ui \ cppfilesettingspage.ui \ diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed97b677392a3aa109d6e52b1cbd1e556da18190 --- /dev/null +++ b/src/plugins/cpptools/cpptoolsreuse.cpp @@ -0,0 +1,52 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "cpptoolsreuse.h" + +#include <QtGui/QTextDocument> +#include <QtGui/QTextCursor> + +namespace CppTools { + +void moveCursorToEndOfIdentifier(QTextCursor *tc) { + QTextDocument *doc = tc->document(); + if (!doc) + return; + + QChar ch = doc->characterAt(tc->position()); + while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) { + tc->movePosition(QTextCursor::NextCharacter); + ch = doc->characterAt(tc->position()); + } +} + +} // CppTools diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h new file mode 100644 index 0000000000000000000000000000000000000000..3be58382fdb473810853394ffd85e495ca5396fb --- /dev/null +++ b/src/plugins/cpptools/cpptoolsreuse.h @@ -0,0 +1,14 @@ +#ifndef CPPTOOLSREUSE_H +#define CPPTOOLSREUSE_H + +#include "cpptools_global.h" + +QT_FORWARD_DECLARE_CLASS(QTextCursor) + +namespace CppTools { + +void CPPTOOLS_EXPORT moveCursorToEndOfIdentifier(QTextCursor *tc); + +} // CppTools + +#endif // CPPTOOLSREUSE_H