From 4a634a23cf2b7dca51f321a4affd61300a3c6b81 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 4 Jan 2017 12:15:39 +0100 Subject: [PATCH] AutoTest: Find inherited Qt test methods Task-number: QTCREATORBUG-17522 Change-Id: Ie7cfed2bd38944c28ea8502552593e0083f9727c Reviewed-by: David Schulz --- src/plugins/autotest/qtest/qttestparser.cpp | 32 ++++++++++++++++--- src/plugins/autotest/qtest/qttesttreeitem.cpp | 14 ++++++-- src/plugins/autotest/qtest/qttesttreeitem.h | 1 + src/plugins/autotest/qtest/qttestvisitors.cpp | 9 +++++- src/plugins/autotest/qtest/qttestvisitors.h | 5 +++ 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp index 3a0f90f82ef..e358a6fcc29 100644 --- a/src/plugins/autotest/qtest/qttestparser.cpp +++ b/src/plugins/autotest/qtest/qttestparser.cpp @@ -109,7 +109,7 @@ static QString testClass(const CppTools::CppModelManager *modelManager, static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot, const QString &testCaseName, - unsigned *line, unsigned *column) + unsigned *line = 0, unsigned *column = 0) { CPlusPlus::Document::Ptr declaringDoc = doc; CPlusPlus::TypeOfExpression typeOfExpr; @@ -123,8 +123,10 @@ static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, const QString declFileName = QLatin1String(toeClass->fileId()->chars(), toeClass->fileId()->size()); declaringDoc = snapshot.document(declFileName); - *line = toeClass->line(); - *column = toeClass->column() - 1; + if (line) + *line = toeClass->line(); + if (column) + *column = toeClass->column() - 1; } } } @@ -158,6 +160,26 @@ static QMap checkForDataTags(const QString &fil return visitor.dataTags(); } +static QMap baseClassTestFunctions(const QSet &bases, + const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot) +{ + QMap 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 currentBaseBases = baseVisitor.baseClasses(); + // recursively check base classes + testFunctions.unite(baseClassTestFunctions(currentBaseBases, doc, snapshot)); + } + return testFunctions; +} + static bool handleQtTest(QFutureInterface futureInterface, CPlusPlus::Document::Ptr document, const CPlusPlus::Snapshot &snapshot, @@ -183,7 +205,9 @@ static bool handleQtTest(QFutureInterface futureInterface, if (!visitor.resultValid()) return false; - const QMap &testFunctions = visitor.privateSlots(); + QMap testFunctions = visitor.privateSlots(); + // gather appropriate information of base classes as well + testFunctions.unite(baseClassTestFunctions(visitor.baseClasses(), declaringDoc, snapshot)); const QSet &files = filesWithDataFunctionDefinitions(testFunctions); // TODO: change to QHash<> diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index 4ebb4ee6250..9f7ba29edcd 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -251,8 +251,10 @@ TestTreeItem *QtTestTreeItem::find(const TestParseResult *result) switch (type()) { case Root: return findChildByFile(result->fileName); - case TestCase: - return findChildByName(result->displayName); + case TestCase: { + const QtTestParseResult *qtResult = static_cast(result); + return findChildByNameAndInheritance(qtResult->displayName, qtResult->inherited()); + } case TestFunctionOrSet: case TestDataFunction: 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(other); + return qtOther->inherited() == inherited && qtOther->name() == name; + }); +} + QString QtTestTreeItem::nameSuffix() const { static QString inheritedSuffix = QLatin1String(" [") diff --git a/src/plugins/autotest/qtest/qttesttreeitem.h b/src/plugins/autotest/qtest/qttesttreeitem.h index 9c9d35f6f78..42b1efddbd0 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.h +++ b/src/plugins/autotest/qtest/qttesttreeitem.h @@ -51,6 +51,7 @@ public: void setInherited(bool inherited) { m_inherited = inherited; } bool inherited() const { return m_inherited; } private: + TestTreeItem *findChildByNameAndInheritance(const QString &name, bool inherited) const; QString nameSuffix() const; bool m_inherited = false; }; diff --git a/src/plugins/autotest/qtest/qttestvisitors.cpp b/src/plugins/autotest/qtest/qttestvisitors.cpp index b420f0f92ec..4b6b53b3dae 100644 --- a/src/plugins/autotest/qtest/qttestvisitors.cpp +++ b/src/plugins/autotest/qtest/qttestvisitors.cpp @@ -83,10 +83,17 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) locationAndType.m_type = TestTreeItem::TestDataFunction; else locationAndType.m_type = TestTreeItem::TestFunctionOrSet; - locationAndType.m_inherited = false; // for now + locationAndType.m_inherited = m_inherited; 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; } diff --git a/src/plugins/autotest/qtest/qttestvisitors.h b/src/plugins/autotest/qtest/qttestvisitors.h index adbb906c8eb..8f8bd273990 100644 --- a/src/plugins/autotest/qtest/qttestvisitors.h +++ b/src/plugins/autotest/qtest/qttestvisitors.h @@ -35,6 +35,7 @@ #include #include +#include namespace Autotest { namespace Internal { @@ -44,7 +45,9 @@ class TestVisitor : public CPlusPlus::SymbolVisitor public: explicit TestVisitor(const QString &fullQualifiedClassName, const CPlusPlus::Snapshot &snapshot); + void setInheritedMode(bool inherited) { m_inherited = inherited; } QMap privateSlots() const { return m_privSlots; } + QSet baseClasses() const { return m_baseClasses; } bool resultValid() const { return m_valid; } bool visit(CPlusPlus::Class *symbol); @@ -55,6 +58,8 @@ private: CPlusPlus::Snapshot m_snapshot; QMap m_privSlots; bool m_valid = false; + bool m_inherited = false; + QSet m_baseClasses; }; class TestAstVisitor : public CPlusPlus::ASTVisitor