summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cppelementevaluator.cpp
diff options
context:
space:
mode:
authorJarek Kobus <jaroslaw.kobus@qt.io>2020-11-30 17:02:33 +0100
committerJarek Kobus <jaroslaw.kobus@qt.io>2020-12-07 14:04:50 +0000
commitc400923308f5c4df4e8d96a04d12dc54322f7ade (patch)
tree472da8291ca7f8bd697f77012b65fb4a7f74b64e /src/plugins/cpptools/cppelementevaluator.cpp
parentf2dd45d8ce93c858b2bc4afccdbf61adadcdc64f (diff)
downloadqt-creator-c400923308f5c4df4e8d96a04d12dc54322f7ade.tar.gz
Modernize Type Hierarchy
Don't freeze UI on request for show Type Hierarchy. Move the lookup code into a separate thread. Don't clear tree hierarchy when waiting for new one. Show progress indicator on top of old hierarchy instead. Add a task to ProgressManager when working on a new hierarchy. Handle canceling the process of showing Type Hierarchy. Implement simple progress reporting for this process. Optimize a bit DerivedHierarchyVisitor. Change-Id: I3894ac6ed3f4834831831f083f718f8385ca346f Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/plugins/cpptools/cppelementevaluator.cpp')
-rw-r--r--src/plugins/cpptools/cppelementevaluator.cpp167
1 files changed, 121 insertions, 46 deletions
diff --git a/src/plugins/cpptools/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp
index b59bf3380d..2d9275ba59 100644
--- a/src/plugins/cpptools/cppelementevaluator.cpp
+++ b/src/plugins/cpptools/cppelementevaluator.cpp
@@ -36,6 +36,8 @@
#include <cplusplus/Icons.h>
#include <cplusplus/TypeOfExpression.h>
+#include <utils/runextensions.h>
+
#include <QDir>
#include <QSet>
#include <QQueue>
@@ -44,6 +46,14 @@ using namespace CPlusPlus;
namespace CppTools {
+static void handleLookupItemMatch(QFutureInterface<QSharedPointer<CppElement>> &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<ClassOrNamespace*, CppClass*>;
@@ -174,6 +185,8 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
QQueue<Data> 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<CppClass*, CppTools::TypeHierarchy>;
CppTools::TypeHierarchyBuilder builder(declaration, snapshot);
- const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy();
+ const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(futureInterface);
QQueue<Data> q;
q.enqueue(qMakePair(this, completeHierarchy));
while (!q.isEmpty()) {
+ if (futureInterface.isCanceled())
+ return;
const Data &current = 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<QSharedPointer<CppElement>> CppElementEvaluator::asyncExecute()
+{
+ return execute(&CppElementEvaluator::asyncExec);
+}
+
+static QFuture<QSharedPointer<CppElement>> createFinishedFuture()
+{
+ QFutureInterface<QSharedPointer<CppElement>> futureInterface;
+ futureInterface.reportStarted();
+ futureInterface.reportFinished();
+ return futureInterface.future();
+}
+
+// @todo: Consider refactoring code from CppEditor::findLinkAt into here.
+QFuture<QSharedPointer<CppElement>> 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<LookupItem> &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<LookupItem> &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<QSharedPointer<CppElement>> CppElementEvaluator::syncExec(
+ const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem,
+ const CPlusPlus::LookupContext &lookupContext)
+{
+ QFutureInterface<QSharedPointer<CppElement>> futureInterface;
+ futureInterface.reportStarted();
+ handleLookupItemMatch(futureInterface, snapshot, lookupItem, lookupContext,
+ *m_modelManager->symbolFinder(),
+ m_lookupBaseClasses, m_lookupDerivedClasses);
+ futureInterface.reportFinished();
+ QFuture<QSharedPointer<CppElement>> future = futureInterface.future();
+ m_element = future.result();
+ return future;
+}
+
+QFuture<QSharedPointer<CppElement>> 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<QSharedPointer<CppElement>> &futureInterface,
+ const Snapshot &snapshot,
+ const LookupItem &lookupItem,
+ const LookupContext &context,
+ CppTools::SymbolFinder symbolFinder,
+ bool lookupBaseClasses,
+ bool lookupDerivedClasses)
{
+ if (futureInterface.isCanceled())
+ return;
+ QSharedPointer<CppElement> 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<CppElement>(new Unknown(type));
+ element = QSharedPointer<CppElement>(new Unknown(type));
} else {
const FullySpecifiedType &type = declaration->type();
if (declaration->isNamespace()) {
- m_element = QSharedPointer<CppElement>(new CppNamespace(declaration));
+ element = QSharedPointer<CppElement>(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<CppElement>(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<CppElement>(cppClass);
} else if (Enum *enumDecl = declaration->asEnum()) {
- m_element = QSharedPointer<CppElement>(new CppEnum(enumDecl));
+ element = QSharedPointer<CppElement>(new CppEnum(enumDecl));
} else if (auto enumerator = dynamic_cast<EnumeratorDeclaration *>(declaration)) {
- m_element = QSharedPointer<CppElement>(new CppEnumerator(enumerator));
+ element = QSharedPointer<CppElement>(new CppEnumerator(enumerator));
} else if (declaration->isTypedef()) {
- m_element = QSharedPointer<CppElement>(new CppTypedef(declaration));
+ element = QSharedPointer<CppElement>(new CppTypedef(declaration));
} else if (declaration->isFunction()
|| (type.isValid() && type->isFunctionType())
|| declaration->isTemplate()) {
- m_element = QSharedPointer<CppElement>(new CppFunction(declaration));
+ element = QSharedPointer<CppElement>(new CppFunction(declaration));
} else if (declaration->isDeclaration() && type.isValid()) {
- m_element = QSharedPointer<CppElement>(
+ element = QSharedPointer<CppElement>(
new CppVariable(declaration, context, lookupItem.scope()));
} else {
- m_element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration));
+ element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration));
}
}
+ futureInterface.reportResult(element);
}
bool CppElementEvaluator::identifiedCppElement() const