forked from qt-creator/qt-creator
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 <marcus.tillmanns@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -8,7 +8,9 @@
|
|||||||
#include "../autotesttr.h"
|
#include "../autotesttr.h"
|
||||||
#include "../itestframework.h"
|
#include "../itestframework.h"
|
||||||
|
|
||||||
|
#include <cplusplus/Symbol.h>
|
||||||
#include <cppeditor/cppmodelmanager.h>
|
#include <cppeditor/cppmodelmanager.h>
|
||||||
|
#include <cppeditor/symbolfinder.h>
|
||||||
|
|
||||||
#include <projectexplorer/projectmanager.h>
|
#include <projectexplorer/projectmanager.h>
|
||||||
|
|
||||||
@@ -16,8 +18,7 @@
|
|||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest::Internal {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
QtTestTreeItem::QtTestTreeItem(ITestFramework *testFramework, const QString &name,
|
QtTestTreeItem::QtTestTreeItem(ITestFramework *testFramework, const QString &name,
|
||||||
const FilePath &filePath, TestTreeItem::Type type)
|
const FilePath &filePath, TestTreeItem::Type type)
|
||||||
@@ -49,9 +50,11 @@ QVariant QtTestTreeItem::data(int column, int role) const
|
|||||||
toolTip.append(Tr::tr("<p>Multiple testcases inside a single executable are not officially "
|
toolTip.append(Tr::tr("<p>Multiple testcases inside a single executable are not officially "
|
||||||
"supported. Depending on the implementation they might get executed "
|
"supported. Depending on the implementation they might get executed "
|
||||||
"or not, but never will be explicitly selectable.</p>"));
|
"or not, but never will be explicitly selectable.</p>"));
|
||||||
|
} else if (type() == TestFunction) {
|
||||||
|
// avoid confusion (displaying header file, but ending up inside source)
|
||||||
|
toolTip = parentItem()->name() + "::" + name();
|
||||||
}
|
}
|
||||||
return toolTip;
|
return toolTip;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Qt::CheckStateRole:
|
case Qt::CheckStateRole:
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
@@ -69,6 +72,13 @@ QVariant QtTestTreeItem::data(int column, int role) const
|
|||||||
default:
|
default:
|
||||||
return m_multiTest;
|
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);
|
return TestTreeItem::data(column, role);
|
||||||
}
|
}
|
||||||
@@ -403,6 +413,26 @@ bool QtTestTreeItem::isGroupable() const
|
|||||||
return type() == TestCase;
|
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,
|
TestTreeItem *QtTestTreeItem::findChildByFileNameAndType(const FilePath &file,
|
||||||
const QString &name, Type type) const
|
const QString &name, Type type) const
|
||||||
{
|
{
|
||||||
@@ -438,5 +468,4 @@ QString QtTestTreeItem::nameSuffix() const
|
|||||||
return suffix.isEmpty() ? suffix : QString{" [" + suffix + "]"};
|
return suffix.isEmpty() ? suffix : QString{" [" + suffix + "]"};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Autotest::Internal
|
||||||
} // namespace Autotest
|
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
|
|
||||||
#include "../testtreeitem.h"
|
#include "../testtreeitem.h"
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest::Internal {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class QtTestTreeItem : public TestTreeItem
|
class QtTestTreeItem : public TestTreeItem
|
||||||
{
|
{
|
||||||
@@ -36,6 +35,7 @@ public:
|
|||||||
TestTreeItem *createParentGroupNode() const override;
|
TestTreeItem *createParentGroupNode() const override;
|
||||||
bool isGroupable() const override;
|
bool isGroupable() const override;
|
||||||
private:
|
private:
|
||||||
|
QVariant linkForTreeItem() const;
|
||||||
TestTreeItem *findChildByFileNameAndType(const Utils::FilePath &file, const QString &name,
|
TestTreeItem *findChildByFileNameAndType(const Utils::FilePath &file, const QString &name,
|
||||||
Type type) const;
|
Type type) const;
|
||||||
TestTreeItem *findChildByNameAndInheritanceAndMultiTest(const QString &name, bool inherited,
|
TestTreeItem *findChildByNameAndInheritanceAndMultiTest(const QString &name, bool inherited,
|
||||||
@@ -53,5 +53,4 @@ public:
|
|||||||
|
|
||||||
typedef QVector<QtTestCodeLocationAndType> QtTestCodeLocationList;
|
typedef QVector<QtTestCodeLocationAndType> QtTestCodeLocationList;
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Autotest::Internal
|
||||||
} // namespace Autotest
|
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest::Internal {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
static QStringList specialFunctions({"initTestCase", "cleanupTestCase", "init", "cleanup"});
|
static QStringList specialFunctions({"initTestCase", "cleanupTestCase", "init", "cleanup"});
|
||||||
|
|
||||||
@@ -49,10 +48,13 @@ bool TestVisitor::visit(Class *symbol)
|
|||||||
const QString name = o.prettyName(func->name());
|
const QString name = o.prettyName(func->name());
|
||||||
QtTestCodeLocationAndType locationAndType;
|
QtTestCodeLocationAndType locationAndType;
|
||||||
|
|
||||||
|
if (name.endsWith("_data")) {
|
||||||
|
// costly.. but we need at least the correct entry for finding data tags
|
||||||
Function *functionDefinition = m_symbolFinder.findMatchingDefinition(
|
Function *functionDefinition = m_symbolFinder.findMatchingDefinition(
|
||||||
func, m_snapshot, true);
|
func, m_snapshot, true);
|
||||||
if (functionDefinition && functionDefinition->fileId())
|
if (functionDefinition && functionDefinition->fileId())
|
||||||
member = functionDefinition;
|
member = functionDefinition;
|
||||||
|
}
|
||||||
locationAndType.m_filePath = FilePath::fromUtf8(member->fileName());
|
locationAndType.m_filePath = FilePath::fromUtf8(member->fileName());
|
||||||
locationAndType.m_line = member->line();
|
locationAndType.m_line = member->line();
|
||||||
locationAndType.m_column = member->column() - 1;
|
locationAndType.m_column = member->column() - 1;
|
||||||
@@ -281,5 +283,4 @@ bool TestDataFunctionVisitor::newRowCallFound(CallAST *ast, unsigned *firstToken
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Autotest::Internal
|
||||||
} // namespace Autotest
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest::Internal {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class TestVisitor : public CPlusPlus::SymbolVisitor
|
class TestVisitor : public CPlusPlus::SymbolVisitor
|
||||||
{
|
{
|
||||||
@@ -84,5 +83,4 @@ private:
|
|||||||
bool m_insideUsingQTest = false;
|
bool m_insideUsingQTest = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Autotest::Internal
|
||||||
} // namespace Autotest
|
|
||||||
|
|||||||
Reference in New Issue
Block a user