diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp index c4478f2d521..34025a59bd8 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.cpp +++ b/src/plugins/cppeditor/cpptypehierarchy.cpp @@ -32,11 +32,13 @@ #include #include +#include #include #include #include -#include #include +#include +#include #include #include @@ -107,10 +109,10 @@ CppTypeHierarchyWidget::CppTypeHierarchyWidget() m_treeView->setDefaultDropAction(Qt::MoveAction); connect(m_treeView, &QTreeView::activated, this, &CppTypeHierarchyWidget::onItemActivated); - m_noTypeHierarchyAvailableLabel = new QLabel(tr("No type hierarchy available"), this); - m_noTypeHierarchyAvailableLabel->setAlignment(Qt::AlignCenter); - m_noTypeHierarchyAvailableLabel->setAutoFillBackground(true); - m_noTypeHierarchyAvailableLabel->setBackgroundRole(QPalette::Base); + m_infoLabel = new QLabel(this); + m_infoLabel->setAlignment(Qt::AlignCenter); + m_infoLabel->setAutoFillBackground(true); + m_infoLabel->setBackgroundRole(QPalette::Base); m_hierarchyWidget = new QWidget(this); auto layout = new QVBoxLayout; @@ -122,50 +124,83 @@ CppTypeHierarchyWidget::CppTypeHierarchyWidget() m_stackLayout = new QStackedLayout; m_stackLayout->addWidget(m_hierarchyWidget); - m_stackLayout->addWidget(m_noTypeHierarchyAvailableLabel); - m_stackLayout->setCurrentWidget(m_noTypeHierarchyAvailableLabel); + m_stackLayout->addWidget(m_infoLabel); + showNoTypeHierarchyLabel(); setLayout(m_stackLayout); - connect(CppEditorPlugin::instance(), &CppEditorPlugin::typeHierarchyRequested, this, &CppTypeHierarchyWidget::perform); + connect(CppEditorPlugin::instance(), &CppEditorPlugin::typeHierarchyRequested, + this, &CppTypeHierarchyWidget::perform); + connect(&m_futureWatcher, &QFutureWatcher>::finished, + this, &CppTypeHierarchyWidget::displayHierarchy); } -CppTypeHierarchyWidget::~CppTypeHierarchyWidget() = default; +CppTypeHierarchyWidget::~CppTypeHierarchyWidget() +{ + if (m_future.isRunning()) { + m_future.cancel(); + m_future.waitForFinished(); + } +} void CppTypeHierarchyWidget::perform() { - showNoTypeHierarchyLabel(); + if (m_future.isRunning()) + m_future.cancel(); auto editor = qobject_cast(Core::EditorManager::currentEditor()); - if (!editor) + if (!editor) { + showNoTypeHierarchyLabel(); return; + } auto widget = qobject_cast(editor->widget()); - if (!widget) + if (!widget) { + showNoTypeHierarchyLabel(); return; + } - clearTypeHierarchy(); + showProgress(); CppElementEvaluator evaluator(widget); evaluator.setLookupBaseClasses(true); evaluator.setLookupDerivedClasses(true); - evaluator.execute(); - if (evaluator.identifiedCppElement()) { - const QSharedPointer &cppElement = evaluator.cppElement(); - CppElement *element = cppElement.data(); - if (CppClass *cppClass = element->toCppClass()) { - m_inspectedClass->setText(cppClass->name); - m_inspectedClass->setLink(cppClass->link); - QStandardItem *bases = new QStandardItem(tr("Bases")); - m_model->invisibleRootItem()->appendRow(bases); - buildHierarchy(*cppClass, bases, true, &CppClass::bases); - QStandardItem *derived = new QStandardItem(tr("Derived")); - m_model->invisibleRootItem()->appendRow(derived); - buildHierarchy(*cppClass, derived, true, &CppClass::derived); - m_treeView->expandAll(); + m_future = evaluator.asyncExecute(); + m_futureWatcher.setFuture(m_future); - showTypeHierarchy(); - } + Core::ProgressManager::addTask(m_future, tr("Evaluating Type Hierarchy"), "TypeHierarchy"); +} + +void CppTypeHierarchyWidget::displayHierarchy() +{ + hideProgress(); + clearTypeHierarchy(); + + if (!m_future.resultCount() || m_future.isCanceled()) { + showNoTypeHierarchyLabel(); + return; } + const QSharedPointer &cppElement = m_future.result(); + if (cppElement.isNull()) { + showNoTypeHierarchyLabel(); + return; + } + CppClass *cppClass = cppElement->toCppClass(); + if (!cppClass) { + showNoTypeHierarchyLabel(); + return; + } + + m_inspectedClass->setText(cppClass->name); + m_inspectedClass->setLink(cppClass->link); + QStandardItem *bases = new QStandardItem(tr("Bases")); + m_model->invisibleRootItem()->appendRow(bases); + buildHierarchy(*cppClass, bases, true, &CppClass::bases); + QStandardItem *derived = new QStandardItem(tr("Derived")); + m_model->invisibleRootItem()->appendRow(derived); + buildHierarchy(*cppClass, derived, true, &CppClass::derived); + m_treeView->expandAll(); + + showTypeHierarchy(); } void CppTypeHierarchyWidget::buildHierarchy(const CppClass &cppClass, QStandardItem *parent, @@ -182,7 +217,8 @@ void CppTypeHierarchyWidget::buildHierarchy(const CppClass &cppClass, QStandardI void CppTypeHierarchyWidget::showNoTypeHierarchyLabel() { - m_stackLayout->setCurrentWidget(m_noTypeHierarchyAvailableLabel); + m_infoLabel->setText(tr("No type hierarchy available")); + m_stackLayout->setCurrentWidget(m_infoLabel); } void CppTypeHierarchyWidget::showTypeHierarchy() @@ -190,6 +226,22 @@ void CppTypeHierarchyWidget::showTypeHierarchy() m_stackLayout->setCurrentWidget(m_hierarchyWidget); } +void CppTypeHierarchyWidget::showProgress() +{ + m_infoLabel->setText(tr("Evaluating type hierarchy...")); + if (!m_progressIndicator) { + m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large); + m_progressIndicator->attachToWidget(this); + } + m_progressIndicator->show(); + m_progressIndicator->raise(); +} +void CppTypeHierarchyWidget::hideProgress() +{ + if (m_progressIndicator) + m_progressIndicator->hide(); +} + void CppTypeHierarchyWidget::clearTypeHierarchy() { m_inspectedClass->clear(); diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h index 836f4ba028a..83b1a4d99f3 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.h +++ b/src/plugins/cppeditor/cpptypehierarchy.h @@ -27,11 +27,14 @@ #include +#include +#include #include -#include -#include +#include #include #include +#include +#include QT_BEGIN_NAMESPACE class QLabel; @@ -43,11 +46,12 @@ QT_END_NAMESPACE namespace TextEditor { class TextEditorLinkLabel; } namespace Utils { -class NavigationTreeView; class AnnotatedItemDelegate; +class NavigationTreeView; +class ProgressIndicator; } -namespace CppTools { class CppClass; } +namespace CppTools { class CppClass; class CppElement; } namespace CppEditor { namespace Internal { @@ -75,12 +79,17 @@ public: void perform(); +private slots: + void displayHierarchy(); + private: typedef QList CppTools::CppClass::*HierarchyMember; void buildHierarchy(const CppTools::CppClass &cppClass, QStandardItem *parent, bool isRoot, HierarchyMember member); void showNoTypeHierarchyLabel(); void showTypeHierarchy(); + void showProgress(); + void hideProgress(); void clearTypeHierarchy(); void onItemActivated(const QModelIndex &index); @@ -91,7 +100,10 @@ private: QStandardItemModel *m_model = nullptr; Utils::AnnotatedItemDelegate *m_delegate = nullptr; TextEditor::TextEditorLinkLabel *m_inspectedClass = nullptr; - QLabel *m_noTypeHierarchyAvailableLabel = nullptr; + QLabel *m_infoLabel = nullptr; + QFuture> m_future; + QFutureWatcher> m_futureWatcher; + Utils::ProgressIndicator *m_progressIndicator = nullptr; }; class CppTypeHierarchyFactory : public Core::INavigationWidgetFactory diff --git a/src/plugins/cpptools/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp index b59bf3380d6..2d9275ba595 100644 --- a/src/plugins/cpptools/cppelementevaluator.cpp +++ b/src/plugins/cpptools/cppelementevaluator.cpp @@ -36,6 +36,8 @@ #include #include +#include + #include #include #include @@ -44,6 +46,14 @@ using namespace CPlusPlus; namespace CppTools { +static void handleLookupItemMatch(QFutureInterface> &futureInterface, + const Snapshot &snapshot, + const LookupItem &lookupItem, + const LookupContext &context, + CppTools::SymbolFinder symbolFinder, + bool lookupBaseClasses, + bool lookupDerivedClasses); + static QStringList stripName(const QString &name) { QStringList all; @@ -164,7 +174,8 @@ CppClass *CppClass::toCppClass() return this; } -void CppClass::lookupBases(Symbol *declaration, const LookupContext &context) +void CppClass::lookupBases(QFutureInterfaceBase &futureInterface, + Symbol *declaration, const LookupContext &context) { using Data = QPair; @@ -174,6 +185,8 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context) QQueue q; q.enqueue(qMakePair(clazz, this)); while (!q.isEmpty()) { + if (futureInterface.isCanceled()) + return; Data current = q.dequeue(); clazz = current.first; visited.insert(clazz); @@ -195,16 +208,19 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context) } } -void CppClass::lookupDerived(Symbol *declaration, const Snapshot &snapshot) +void CppClass::lookupDerived(QFutureInterfaceBase &futureInterface, + Symbol *declaration, const Snapshot &snapshot) { using Data = QPair; CppTools::TypeHierarchyBuilder builder(declaration, snapshot); - const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(); + const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(futureInterface); QQueue q; q.enqueue(qMakePair(this, completeHierarchy)); while (!q.isEmpty()) { + if (futureInterface.isCanceled()) + return; const Data ¤t = q.dequeue(); CppClass *clazz = current.first; const CppTools::TypeHierarchy &classHierarchy = current.second; @@ -345,18 +361,43 @@ void CppElementEvaluator::setLookupBaseClasses(const bool lookup) void CppElementEvaluator::setLookupDerivedClasses(const bool lookup) { m_lookupDerivedClasses = lookup; } -// @todo: Consider refactoring code from CppEditor::findLinkAt into here. +// special case for bug QTCREATORBUG-4780 +static bool shouldOmitElement(const LookupItem &lookupItem, const Scope *scope) +{ + return !lookupItem.declaration() && scope && scope->isFunction() + && lookupItem.type().match(scope->asFunction()->returnType()); +} + void CppElementEvaluator::execute() +{ + execute(&CppElementEvaluator::syncExec); +} + +QFuture> CppElementEvaluator::asyncExecute() +{ + return execute(&CppElementEvaluator::asyncExec); +} + +static QFuture> createFinishedFuture() +{ + QFutureInterface> futureInterface; + futureInterface.reportStarted(); + futureInterface.reportFinished(); + return futureInterface.future(); +} + +// @todo: Consider refactoring code from CppEditor::findLinkAt into here. +QFuture> CppElementEvaluator::execute(ExecFunction execFuntion) { clear(); if (!m_modelManager) - return; + return createFinishedFuture(); const Snapshot &snapshot = m_modelManager->snapshot(); Document::Ptr doc = snapshot.document(m_editor->textDocument()->filePath()); if (!doc) - return; + return createFinishedFuture(); int line = 0; int column = 0; @@ -365,25 +406,52 @@ void CppElementEvaluator::execute() checkDiagnosticMessage(pos); - if (!matchIncludeFile(doc, line) && !matchMacroInUse(doc, pos)) { - CppTools::moveCursorToEndOfIdentifier(&m_tc); + if (matchIncludeFile(doc, line) || matchMacroInUse(doc, pos)) + return createFinishedFuture(); - // Fetch the expression's code - ExpressionUnderCursor expressionUnderCursor(doc->languageFeatures()); - const QString &expression = expressionUnderCursor(m_tc); - Scope *scope = doc->scopeAt(line, column - 1); + CppTools::moveCursorToEndOfIdentifier(&m_tc); - TypeOfExpression typeOfExpression; - typeOfExpression.init(doc, snapshot); - // make possible to instantiate templates - typeOfExpression.setExpandTemplates(true); - const QList &lookupItems = typeOfExpression(expression.toUtf8(), scope); - if (lookupItems.isEmpty()) - return; + // Fetch the expression's code + ExpressionUnderCursor expressionUnderCursor(doc->languageFeatures()); + const QString &expression = expressionUnderCursor(m_tc); + Scope *scope = doc->scopeAt(line, column - 1); - const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate. - handleLookupItemMatch(snapshot, lookupItem, typeOfExpression.context(), scope); - } + TypeOfExpression typeOfExpression; + typeOfExpression.init(doc, snapshot); + // make possible to instantiate templates + typeOfExpression.setExpandTemplates(true); + const QList &lookupItems = typeOfExpression(expression.toUtf8(), scope); + if (lookupItems.isEmpty()) + return createFinishedFuture(); + + const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate. + if (shouldOmitElement(lookupItem, scope)) + return createFinishedFuture(); + return std::invoke(execFuntion, this, snapshot, lookupItem, typeOfExpression.context()); +} + +QFuture> CppElementEvaluator::syncExec( + const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem, + const CPlusPlus::LookupContext &lookupContext) +{ + QFutureInterface> futureInterface; + futureInterface.reportStarted(); + handleLookupItemMatch(futureInterface, snapshot, lookupItem, lookupContext, + *m_modelManager->symbolFinder(), + m_lookupBaseClasses, m_lookupDerivedClasses); + futureInterface.reportFinished(); + QFuture> future = futureInterface.future(); + m_element = future.result(); + return future; +} + +QFuture> CppElementEvaluator::asyncExec( + const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem, + const CPlusPlus::LookupContext &lookupContext) +{ + return Utils::runAsync(&handleLookupItemMatch, snapshot, lookupItem, lookupContext, + *m_modelManager->symbolFinder(), + m_lookupBaseClasses, m_lookupDerivedClasses); } void CppElementEvaluator::checkDiagnosticMessage(int pos) @@ -422,24 +490,25 @@ bool CppElementEvaluator::matchMacroInUse(const Document::Ptr &document, int pos return false; } -void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot, - const LookupItem &lookupItem, - const LookupContext &context, - const Scope *scope) +static void handleLookupItemMatch(QFutureInterface> &futureInterface, + const Snapshot &snapshot, + const LookupItem &lookupItem, + const LookupContext &context, + CppTools::SymbolFinder symbolFinder, + bool lookupBaseClasses, + bool lookupDerivedClasses) { + if (futureInterface.isCanceled()) + return; + QSharedPointer element; Symbol *declaration = lookupItem.declaration(); if (!declaration) { const QString &type = Overview().prettyType(lookupItem.type(), QString()); - // special case for bug QTCREATORBUG-4780 - if (scope && scope->isFunction() - && lookupItem.type().match(scope->asFunction()->returnType())) { - return; - } - m_element = QSharedPointer(new Unknown(type)); + element = QSharedPointer(new Unknown(type)); } else { const FullySpecifiedType &type = declaration->type(); if (declaration->isNamespace()) { - m_element = QSharedPointer(new CppNamespace(declaration)); + element = QSharedPointer(new CppNamespace(declaration)); } else if (declaration->isClass() || declaration->isForwardClassDeclaration() || (declaration->isTemplate() && declaration->asTemplate()->declaration() @@ -447,8 +516,7 @@ void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot, || declaration->asTemplate()->declaration()->isForwardClassDeclaration()))) { LookupContext contextToUse = context; if (declaration->isForwardClassDeclaration()) { - const auto symbolFinder = m_modelManager->symbolFinder(); - Symbol *classDeclaration = symbolFinder->findMatchingClassDeclaration(declaration, + Symbol *classDeclaration = symbolFinder.findMatchingClassDeclaration(declaration, snapshot); if (classDeclaration) { declaration = classDeclaration; @@ -460,29 +528,36 @@ void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot, } } + if (futureInterface.isCanceled()) + return; auto cppClass = new CppClass(declaration); - if (m_lookupBaseClasses) - cppClass->lookupBases(declaration, contextToUse); - if (m_lookupDerivedClasses) - cppClass->lookupDerived(declaration, snapshot); - m_element = QSharedPointer(cppClass); + if (lookupBaseClasses) + cppClass->lookupBases(futureInterface, declaration, contextToUse); + if (futureInterface.isCanceled()) + return; + if (lookupDerivedClasses) + cppClass->lookupDerived(futureInterface, declaration, snapshot); + if (futureInterface.isCanceled()) + return; + element = QSharedPointer(cppClass); } else if (Enum *enumDecl = declaration->asEnum()) { - m_element = QSharedPointer(new CppEnum(enumDecl)); + element = QSharedPointer(new CppEnum(enumDecl)); } else if (auto enumerator = dynamic_cast(declaration)) { - m_element = QSharedPointer(new CppEnumerator(enumerator)); + element = QSharedPointer(new CppEnumerator(enumerator)); } else if (declaration->isTypedef()) { - m_element = QSharedPointer(new CppTypedef(declaration)); + element = QSharedPointer(new CppTypedef(declaration)); } else if (declaration->isFunction() || (type.isValid() && type->isFunctionType()) || declaration->isTemplate()) { - m_element = QSharedPointer(new CppFunction(declaration)); + element = QSharedPointer(new CppFunction(declaration)); } else if (declaration->isDeclaration() && type.isValid()) { - m_element = QSharedPointer( + element = QSharedPointer( new CppVariable(declaration, context, lookupItem.scope())); } else { - m_element = QSharedPointer(new CppDeclarableElement(declaration)); + element = QSharedPointer(new CppDeclarableElement(declaration)); } } + futureInterface.reportResult(element); } bool CppElementEvaluator::identifiedCppElement() const diff --git a/src/plugins/cpptools/cppelementevaluator.h b/src/plugins/cpptools/cppelementevaluator.h index 6ce518a2e17..08ded2c6cb3 100644 --- a/src/plugins/cpptools/cppelementevaluator.h +++ b/src/plugins/cpptools/cppelementevaluator.h @@ -32,11 +32,12 @@ #include +#include +#include +#include #include #include -#include #include -#include namespace CPlusPlus { class LookupItem; @@ -57,6 +58,7 @@ public: void setLookupDerivedClasses(const bool lookup); void execute(); + QFuture> asyncExecute(); bool identifiedCppElement() const; const QSharedPointer &cppElement() const; bool hasDiagnosis() const; @@ -64,13 +66,18 @@ public: private: void clear(); + using ExecFunction = QFuture>(CppElementEvaluator::*) + (const CPlusPlus::Snapshot &, const CPlusPlus::LookupItem &, + const CPlusPlus::LookupContext &); + + QFuture> execute(ExecFunction execFuntion); + QFuture> syncExec(const CPlusPlus::Snapshot &, + const CPlusPlus::LookupItem &, const CPlusPlus::LookupContext &); + QFuture> asyncExec(const CPlusPlus::Snapshot &, + const CPlusPlus::LookupItem &, const CPlusPlus::LookupContext &); void checkDiagnosticMessage(int pos); bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, int line); bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, int pos); - void handleLookupItemMatch(const CPlusPlus::Snapshot &snapshot, - const CPlusPlus::LookupItem &lookupItem, - const CPlusPlus::LookupContext &lookupContext, - const CPlusPlus::Scope *scope); TextEditor::TextEditorWidget *m_editor; CppTools::CppModelManager *m_modelManager; @@ -123,8 +130,10 @@ public: CppClass *toCppClass() final; - void lookupBases(CPlusPlus::Symbol *declaration, const CPlusPlus::LookupContext &context); - void lookupDerived(CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot); + void lookupBases(QFutureInterfaceBase &futureInterface, + CPlusPlus::Symbol *declaration, const CPlusPlus::LookupContext &context); + void lookupDerived(QFutureInterfaceBase &futureInterface, + CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot); public: QList bases; diff --git a/src/plugins/cpptools/typehierarchybuilder.cpp b/src/plugins/cpptools/typehierarchybuilder.cpp index b0a31ad62af..a5f05d9042f 100644 --- a/src/plugins/cpptools/typehierarchybuilder.cpp +++ b/src/plugins/cpptools/typehierarchybuilder.cpp @@ -52,7 +52,7 @@ public: bool visit(CPlusPlus::Class *) override; const QList &derived() { return _derived; } - const QStringList otherBases() { return _otherBases; } + const QSet otherBases() { return _otherBases; } private: CPlusPlus::LookupContext _context; @@ -60,7 +60,7 @@ private: QString _unqualifiedName; CPlusPlus::Overview _overview; QHash _actualBases; - QStringList _otherBases; + QSet _otherBases; QList _derived; }; @@ -111,7 +111,7 @@ bool DerivedHierarchyVisitor::visit(CPlusPlus::Class *symbol) if (_qualifiedName == baseName) _derived.append(symbol); else - _otherBases.append(baseName); + _otherBases.insert(baseName); } return true; @@ -146,15 +146,22 @@ void TypeHierarchyBuilder::reset() } TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy() +{ + QFutureInterfaceBase dummy; + return buildDerivedTypeHierarchy(dummy); +} + +TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy(QFutureInterfaceBase &futureInterface) { reset(); TypeHierarchy hierarchy(_symbol); - buildDerived(&hierarchy, filesDependingOn(_symbol)); + buildDerived(futureInterface, &hierarchy, filesDependingOn(_symbol)); return hierarchy; } -void TypeHierarchyBuilder::buildDerived(TypeHierarchy *typeHierarchy, - const QStringList &dependingFiles) +void TypeHierarchyBuilder::buildDerived(QFutureInterfaceBase &futureInterface, + TypeHierarchy *typeHierarchy, + const QStringList &dependingFiles, int depth) { CPlusPlus::Symbol *symbol = typeHierarchy->_symbol; if (_visited.contains(symbol)) @@ -165,7 +172,15 @@ void TypeHierarchyBuilder::buildDerived(TypeHierarchy *typeHierarchy, const QString &symbolName = _overview.prettyName(CPlusPlus::LookupContext::fullyQualifiedName(symbol)); DerivedHierarchyVisitor visitor(symbolName); - foreach (const QString &fileName, dependingFiles) { + if (depth == 0) + futureInterface.setProgressRange(0, dependingFiles.size()); + + int i = -1; + for (const QString &fileName : dependingFiles) { + if (futureInterface.isCanceled()) + return; + if (depth == 0) + futureInterface.setProgressValue(++i); CPlusPlus::Document::Ptr doc = _snapshot.document(fileName); if ((_candidates.contains(fileName) && !_candidates.value(fileName).contains(symbolName)) || !doc->control()->findIdentifier(symbol->identifier()->chars(), @@ -174,14 +189,14 @@ void TypeHierarchyBuilder::buildDerived(TypeHierarchy *typeHierarchy, } visitor.execute(doc, _snapshot); - _candidates.insert(fileName, QSet()); + _candidates.insert(fileName, visitor.otherBases()); - foreach (const QString &candidate, visitor.otherBases()) - _candidates[fileName].insert(candidate); - - foreach (CPlusPlus::Symbol *s, visitor.derived()) { + const QList &derived = visitor.derived(); + for (CPlusPlus::Symbol *s : derived) { TypeHierarchy derivedHierarchy(s); - buildDerived(&derivedHierarchy, filesDependingOn(s)); + buildDerived(futureInterface, &derivedHierarchy, filesDependingOn(s), depth + 1); + if (futureInterface.isCanceled()) + return; typeHierarchy->_hierarchy.append(derivedHierarchy); } } @@ -193,9 +208,10 @@ QStringList TypeHierarchyBuilder::filesDependingOn(CPlusPlus::Symbol *symbol) co if (!symbol) return deps; - Utils::FilePath file = Utils::FilePath::fromUtf8(symbol->fileName(), symbol->fileNameLength()); + const Utils::FilePath file = Utils::FilePath::fromUtf8(symbol->fileName(), symbol->fileNameLength()); deps << file.toString(); - foreach (const Utils::FilePath &fileName, _snapshot.filesDependingOn(file)) + const Utils::FilePaths filePaths = _snapshot.filesDependingOn(file); + for (const Utils::FilePath &fileName : filePaths) deps.append(fileName.toString()); return deps; } diff --git a/src/plugins/cpptools/typehierarchybuilder.h b/src/plugins/cpptools/typehierarchybuilder.h index 4f623d2fdb8..7633b42943e 100644 --- a/src/plugins/cpptools/typehierarchybuilder.h +++ b/src/plugins/cpptools/typehierarchybuilder.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -60,10 +61,12 @@ public: TypeHierarchyBuilder(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot); TypeHierarchy buildDerivedTypeHierarchy(); + TypeHierarchy buildDerivedTypeHierarchy(QFutureInterfaceBase &futureInterface); private: void reset(); - void buildDerived(TypeHierarchy *typeHierarchy, const QStringList &dependencies); + void buildDerived(QFutureInterfaceBase &futureInterface, + TypeHierarchy *typeHierarchy, const QStringList &dependencies, int depth = 0); QStringList filesDependingOn(CPlusPlus::Symbol *symbol) const; CPlusPlus::Symbol *_symbol;