AutoTest: Find inherited Qt test methods

Task-number: QTCREATORBUG-17522
Change-Id: Ie7cfed2bd38944c28ea8502552593e0083f9727c
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2017-01-04 12:15:39 +01:00
parent 7d1d4471f0
commit 4a634a23cf
5 changed files with 54 additions and 7 deletions

View File

@@ -109,7 +109,7 @@ static QString testClass(const CppTools::CppModelManager *modelManager,
static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc,
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::Snapshot &snapshot,
const QString &testCaseName, const QString &testCaseName,
unsigned *line, unsigned *column) unsigned *line = 0, unsigned *column = 0)
{ {
CPlusPlus::Document::Ptr declaringDoc = doc; CPlusPlus::Document::Ptr declaringDoc = doc;
CPlusPlus::TypeOfExpression typeOfExpr; CPlusPlus::TypeOfExpression typeOfExpr;
@@ -123,8 +123,10 @@ static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc,
const QString declFileName = QLatin1String(toeClass->fileId()->chars(), const QString declFileName = QLatin1String(toeClass->fileId()->chars(),
toeClass->fileId()->size()); toeClass->fileId()->size());
declaringDoc = snapshot.document(declFileName); declaringDoc = snapshot.document(declFileName);
*line = toeClass->line(); if (line)
*column = toeClass->column() - 1; *line = toeClass->line();
if (column)
*column = toeClass->column() - 1;
} }
} }
} }
@@ -158,6 +160,26 @@ static QMap<QString, QtTestCodeLocationList> checkForDataTags(const QString &fil
return visitor.dataTags(); return visitor.dataTags();
} }
static QMap<QString, QtTestCodeLocationAndType> baseClassTestFunctions(const QSet<QString> &bases,
const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot)
{
QMap<QString, QtTestCodeLocationAndType> testFunctions;
for (const QString &baseClassName : bases) {
TestVisitor baseVisitor(baseClassName, snapshot);
baseVisitor.setInheritedMode(true);
CPlusPlus::Document::Ptr declaringDoc = declaringDocument(doc, snapshot, baseClassName);
if (declaringDoc.isNull())
continue;
baseVisitor.accept(declaringDoc->globalNamespace());
if (baseVisitor.resultValid())
testFunctions.unite(baseVisitor.privateSlots());
const QSet<QString> currentBaseBases = baseVisitor.baseClasses();
// recursively check base classes
testFunctions.unite(baseClassTestFunctions(currentBaseBases, doc, snapshot));
}
return testFunctions;
}
static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document, CPlusPlus::Document::Ptr document,
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::Snapshot &snapshot,
@@ -183,7 +205,9 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
if (!visitor.resultValid()) if (!visitor.resultValid())
return false; return false;
const QMap<QString, QtTestCodeLocationAndType> &testFunctions = visitor.privateSlots(); QMap<QString, QtTestCodeLocationAndType> testFunctions = visitor.privateSlots();
// gather appropriate information of base classes as well
testFunctions.unite(baseClassTestFunctions(visitor.baseClasses(), declaringDoc, snapshot));
const QSet<QString> &files = filesWithDataFunctionDefinitions(testFunctions); const QSet<QString> &files = filesWithDataFunctionDefinitions(testFunctions);
// TODO: change to QHash<> // TODO: change to QHash<>

View File

@@ -251,8 +251,10 @@ TestTreeItem *QtTestTreeItem::find(const TestParseResult *result)
switch (type()) { switch (type()) {
case Root: case Root:
return findChildByFile(result->fileName); return findChildByFile(result->fileName);
case TestCase: case TestCase: {
return findChildByName(result->displayName); const QtTestParseResult *qtResult = static_cast<const QtTestParseResult *>(result);
return findChildByNameAndInheritance(qtResult->displayName, qtResult->inherited());
}
case TestFunctionOrSet: case TestFunctionOrSet:
case TestDataFunction: case TestDataFunction:
case TestSpecialFunction: case TestSpecialFunction:
@@ -280,6 +282,14 @@ bool QtTestTreeItem::modify(const TestParseResult *result)
} }
} }
TestTreeItem *QtTestTreeItem::findChildByNameAndInheritance(const QString &name, bool inherited) const
{
return findChildBy([name, inherited](const TestTreeItem *other) -> bool {
const QtTestTreeItem *qtOther = static_cast<const QtTestTreeItem *>(other);
return qtOther->inherited() == inherited && qtOther->name() == name;
});
}
QString QtTestTreeItem::nameSuffix() const QString QtTestTreeItem::nameSuffix() const
{ {
static QString inheritedSuffix = QLatin1String(" [") static QString inheritedSuffix = QLatin1String(" [")

View File

@@ -51,6 +51,7 @@ public:
void setInherited(bool inherited) { m_inherited = inherited; } void setInherited(bool inherited) { m_inherited = inherited; }
bool inherited() const { return m_inherited; } bool inherited() const { return m_inherited; }
private: private:
TestTreeItem *findChildByNameAndInheritance(const QString &name, bool inherited) const;
QString nameSuffix() const; QString nameSuffix() const;
bool m_inherited = false; bool m_inherited = false;
}; };

View File

@@ -83,10 +83,17 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol)
locationAndType.m_type = TestTreeItem::TestDataFunction; locationAndType.m_type = TestTreeItem::TestDataFunction;
else else
locationAndType.m_type = TestTreeItem::TestFunctionOrSet; locationAndType.m_type = TestTreeItem::TestFunctionOrSet;
locationAndType.m_inherited = false; // for now locationAndType.m_inherited = m_inherited;
m_privSlots.insert(name, locationAndType); m_privSlots.insert(name, locationAndType);
} }
} }
for (unsigned counter = 0, end = symbol->baseClassCount(); counter < end; ++counter) {
if (CPlusPlus::BaseClass *base = symbol->baseClassAt(counter)) {
const QString &baseClassName = o.prettyName(lc.fullyQualifiedName(base));
if (baseClassName != "QObject")
m_baseClasses.insert(baseClassName);
}
}
} }
return true; return true;
} }

View File

@@ -35,6 +35,7 @@
#include <cpptools/symbolfinder.h> #include <cpptools/symbolfinder.h>
#include <QMap> #include <QMap>
#include <QSet>
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
@@ -44,7 +45,9 @@ class TestVisitor : public CPlusPlus::SymbolVisitor
public: public:
explicit TestVisitor(const QString &fullQualifiedClassName, const CPlusPlus::Snapshot &snapshot); explicit TestVisitor(const QString &fullQualifiedClassName, const CPlusPlus::Snapshot &snapshot);
void setInheritedMode(bool inherited) { m_inherited = inherited; }
QMap<QString, QtTestCodeLocationAndType> privateSlots() const { return m_privSlots; } QMap<QString, QtTestCodeLocationAndType> privateSlots() const { return m_privSlots; }
QSet<QString> baseClasses() const { return m_baseClasses; }
bool resultValid() const { return m_valid; } bool resultValid() const { return m_valid; }
bool visit(CPlusPlus::Class *symbol); bool visit(CPlusPlus::Class *symbol);
@@ -55,6 +58,8 @@ private:
CPlusPlus::Snapshot m_snapshot; CPlusPlus::Snapshot m_snapshot;
QMap<QString, QtTestCodeLocationAndType> m_privSlots; QMap<QString, QtTestCodeLocationAndType> m_privSlots;
bool m_valid = false; bool m_valid = false;
bool m_inherited = false;
QSet<QString> m_baseClasses;
}; };
class TestAstVisitor : public CPlusPlus::ASTVisitor class TestAstVisitor : public CPlusPlus::ASTVisitor