From 6b6d9dc21e78d10a4b637e234828e57604ab7fa0 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 1 Sep 2023 12:49:32 +0200 Subject: [PATCH] AutoTest: Speed up Qt Test parser The look up of function definitions is quite costly. Limit it to the test data functions as we need them when looking for data tags. This limitation reduces the time of a full scan here by more than 40% compared to without limitation. Task-number: QTCREATORBUG-29301 Change-Id: Ia692aab8cfcc1c98ca9a2d53c935d7755314f736 Reviewed-by: Marcus Tillmanns Reviewed-by: David Schulz --- src/plugins/autotest/qtest/qttesttreeitem.cpp | 39 ++++++++++++++++--- src/plugins/autotest/qtest/qttesttreeitem.h | 7 ++-- src/plugins/autotest/qtest/qttestvisitors.cpp | 17 ++++---- src/plugins/autotest/qtest/qttestvisitors.h | 6 +-- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index b44c79eed37..0c535fa9f81 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -8,7 +8,9 @@ #include "../autotesttr.h" #include "../itestframework.h" +#include #include +#include #include @@ -16,8 +18,7 @@ using namespace Utils; -namespace Autotest { -namespace Internal { +namespace Autotest::Internal { QtTestTreeItem::QtTestTreeItem(ITestFramework *testFramework, const QString &name, const FilePath &filePath, TestTreeItem::Type type) @@ -49,9 +50,11 @@ QVariant QtTestTreeItem::data(int column, int role) const toolTip.append(Tr::tr("

Multiple testcases inside a single executable are not officially " "supported. Depending on the implementation they might get executed " "or not, but never will be explicitly selectable.

")); + } else if (type() == TestFunction) { + // avoid confusion (displaying header file, but ending up inside source) + toolTip = parentItem()->name() + "::" + name(); } return toolTip; - break; } case Qt::CheckStateRole: switch (type()) { @@ -69,6 +72,13 @@ QVariant QtTestTreeItem::data(int column, int role) const default: return m_multiTest; } + case LinkRole: + if (type() == GroupNode) + return QVariant(); + if (type() == TestDataFunction || type() == TestDataTag) + return TestTreeItem::data(column, role); + // other functions would end up inside declaration - so, find its definition + return linkForTreeItem(); } return TestTreeItem::data(column, role); } @@ -403,6 +413,26 @@ bool QtTestTreeItem::isGroupable() const return type() == TestCase; } +QVariant QtTestTreeItem::linkForTreeItem() const +{ + QVariant itemLink; + using namespace CPlusPlus; + const Snapshot snapshot = CppEditor::CppModelManager::instance()->snapshot(); + const Document::Ptr doc = snapshot.document(filePath()); + Symbol *symbol = doc->lastVisibleSymbolAt(line(), this->column() + 1); + if (auto decl = symbol->asDeclaration()) { + static CppEditor::SymbolFinder symbolFinder; + if (Symbol *definition = symbolFinder.findMatchingDefinition(decl, snapshot, true); + definition && definition->fileId()) { + itemLink.setValue(Link(FilePath::fromUtf8(definition->fileName()), + definition->line(), definition->column() - 1)); + } + } + if (!itemLink.isValid()) // fallback in case we failed to find the definition + itemLink.setValue(Link(filePath(), line(), this->column())); + return itemLink; +} + TestTreeItem *QtTestTreeItem::findChildByFileNameAndType(const FilePath &file, const QString &name, Type type) const { @@ -438,5 +468,4 @@ QString QtTestTreeItem::nameSuffix() const return suffix.isEmpty() ? suffix : QString{" [" + suffix + "]"}; } -} // namespace Internal -} // namespace Autotest +} // namespace Autotest::Internal diff --git a/src/plugins/autotest/qtest/qttesttreeitem.h b/src/plugins/autotest/qtest/qttesttreeitem.h index ebcc8b89dfe..51ad5b97657 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.h +++ b/src/plugins/autotest/qtest/qttesttreeitem.h @@ -5,8 +5,7 @@ #include "../testtreeitem.h" -namespace Autotest { -namespace Internal { +namespace Autotest::Internal { class QtTestTreeItem : public TestTreeItem { @@ -36,6 +35,7 @@ public: TestTreeItem *createParentGroupNode() const override; bool isGroupable() const override; private: + QVariant linkForTreeItem() const; TestTreeItem *findChildByFileNameAndType(const Utils::FilePath &file, const QString &name, Type type) const; TestTreeItem *findChildByNameAndInheritanceAndMultiTest(const QString &name, bool inherited, @@ -53,5 +53,4 @@ public: typedef QVector QtTestCodeLocationList; -} // namespace Internal -} // namespace Autotest +} // namespace Autotest::Internal diff --git a/src/plugins/autotest/qtest/qttestvisitors.cpp b/src/plugins/autotest/qtest/qttestvisitors.cpp index 51f62febb00..f19b855d559 100644 --- a/src/plugins/autotest/qtest/qttestvisitors.cpp +++ b/src/plugins/autotest/qtest/qttestvisitors.cpp @@ -14,8 +14,7 @@ using namespace CPlusPlus; using namespace Utils; -namespace Autotest { -namespace Internal { +namespace Autotest::Internal { static QStringList specialFunctions({"initTestCase", "cleanupTestCase", "init", "cleanup"}); @@ -49,10 +48,13 @@ bool TestVisitor::visit(Class *symbol) const QString name = o.prettyName(func->name()); QtTestCodeLocationAndType locationAndType; - Function *functionDefinition = m_symbolFinder.findMatchingDefinition( - func, m_snapshot, true); - if (functionDefinition && functionDefinition->fileId()) - member = functionDefinition; + if (name.endsWith("_data")) { + // costly.. but we need at least the correct entry for finding data tags + Function *functionDefinition = m_symbolFinder.findMatchingDefinition( + func, m_snapshot, true); + if (functionDefinition && functionDefinition->fileId()) + member = functionDefinition; + } locationAndType.m_filePath = FilePath::fromUtf8(member->fileName()); locationAndType.m_line = member->line(); locationAndType.m_column = member->column() - 1; @@ -281,5 +283,4 @@ bool TestDataFunctionVisitor::newRowCallFound(CallAST *ast, unsigned *firstToken return found; } -} // namespace Internal -} // namespace Autotest +} // namespace Autotest::Internal diff --git a/src/plugins/autotest/qtest/qttestvisitors.h b/src/plugins/autotest/qtest/qttestvisitors.h index dc18914b544..cf1f14642ec 100644 --- a/src/plugins/autotest/qtest/qttestvisitors.h +++ b/src/plugins/autotest/qtest/qttestvisitors.h @@ -16,8 +16,7 @@ #include #include -namespace Autotest { -namespace Internal { +namespace Autotest::Internal { class TestVisitor : public CPlusPlus::SymbolVisitor { @@ -84,5 +83,4 @@ private: bool m_insideUsingQTest = false; }; -} // namespace Internal -} // namespace Autotest +} // namespace Autotest::Internal