From 0ceea628b083aec16ba4e1dacdaea5c4c8da248f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 4 Jan 2017 13:56:20 +0100 Subject: [PATCH] AutoTest: Do not lose information of base classes In case the base class is defined outside of the file with the derived class we are missing the correct entry point. Work around this by getting alternative entry points beforehand and using them if we cannot find a valid entry point. Task-number: QTCREATORBUG-17522 Change-Id: I07ef87b2fcdac4f78240da9e57eaa518ff0f4d20 Reviewed-by: David Schulz --- src/plugins/autotest/qtest/qttest_utils.cpp | 26 ++++++++++++++++++--- src/plugins/autotest/qtest/qttest_utils.h | 1 + src/plugins/autotest/qtest/qttestparser.cpp | 25 +++++++++++++++++--- src/plugins/autotest/qtest/qttestparser.h | 1 + 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/plugins/autotest/qtest/qttest_utils.cpp b/src/plugins/autotest/qtest/qttest_utils.cpp index bb80570ed12..e596ae71830 100644 --- a/src/plugins/autotest/qtest/qttest_utils.cpp +++ b/src/plugins/autotest/qtest/qttest_utils.cpp @@ -24,8 +24,8 @@ ****************************************************************************/ #include "qttest_utils.h" +#include "qttesttreeitem.h" #include "../testframeworkmanager.h" -#include "../testtreeitem.h" #include @@ -42,8 +42,7 @@ bool isQTestMacro(const QByteArray ¯o) return valid.contains(macro); } -QHash testCaseNamesForFiles(const Core::Id &id, - const QStringList &files) +QHash testCaseNamesForFiles(const Core::Id &id, const QStringList &files) { QHash result; TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); @@ -63,6 +62,27 @@ QHash testCaseNamesForFiles(const Core::Id &id, return result; } +QMultiHash alternativeFiles(const Core::Id &id, const QStringList &files) +{ + QMultiHash result; + TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + QTC_ASSERT(rootNode, return result); + + for (int row = 0, rootCount = rootNode->childCount(); row < rootCount; ++row) { + const TestTreeItem *child = rootNode->childItem(row); + const QString &baseFilePath = child->filePath(); + for (int childRow = 0, count = child->childCount(); childRow < count; ++childRow) { + auto grandChild = static_cast(child->childItem(childRow)); + const QString &filePath = grandChild->filePath(); + if (grandChild->inherited() && baseFilePath != filePath && files.contains(filePath)) { + if (!result.contains(filePath, baseFilePath)) + result.insert(filePath, baseFilePath); + } + } + } + return result; +} + } // namespace QTestUtils } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/qtest/qttest_utils.h b/src/plugins/autotest/qtest/qttest_utils.h index 0d4f661a357..be4fb0a2ca8 100644 --- a/src/plugins/autotest/qtest/qttest_utils.h +++ b/src/plugins/autotest/qtest/qttest_utils.h @@ -35,6 +35,7 @@ namespace QTestUtils { bool isQTestMacro(const QByteArray ¯o); QHash testCaseNamesForFiles(const Core::Id &id, const QStringList &files); +QMultiHash alternativeFiles(const Core::Id &id, const QStringList &files); } // namespace QTestUtils } // namespace Internal diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp index e358a6fcc29..743b7b2e4fa 100644 --- a/src/plugins/autotest/qtest/qttestparser.cpp +++ b/src/plugins/autotest/qtest/qttestparser.cpp @@ -109,14 +109,29 @@ static QString testClass(const CppTools::CppModelManager *modelManager, static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot, const QString &testCaseName, + const QStringList &alternativeFiles = {}, unsigned *line = 0, unsigned *column = 0) { - CPlusPlus::Document::Ptr declaringDoc = doc; + CPlusPlus::Document::Ptr declaringDoc; CPlusPlus::TypeOfExpression typeOfExpr; typeOfExpr.init(doc, snapshot); QList lookupItems = typeOfExpr(testCaseName.toUtf8(), doc->globalNamespace()); + // fallback for inherited functions + if (lookupItems.size() == 0 && !alternativeFiles.isEmpty()) { + for (const QString &alternativeFile : alternativeFiles) { + if (snapshot.contains(alternativeFile)) { + CPlusPlus::Document::Ptr document = snapshot.document(alternativeFile); + CPlusPlus::TypeOfExpression typeOfExpr; // we need a new one with no bindings + typeOfExpr.init(document, snapshot); + lookupItems = typeOfExpr(testCaseName.toUtf8(), document->globalNamespace()); + if (lookupItems.size() != 0) + break; + } + } + } + if (lookupItems.size()) { if (CPlusPlus::Symbol *symbol = lookupItems.first().declaration()) { if (CPlusPlus::Class *toeClass = symbol->asClass()) { @@ -184,6 +199,7 @@ static bool handleQtTest(QFutureInterface futureInterface, CPlusPlus::Document::Ptr document, const CPlusPlus::Snapshot &snapshot, const QString &oldTestCaseName, + const QStringList &alternativeFiles, const Core::Id &id) { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); @@ -196,7 +212,7 @@ static bool handleQtTest(QFutureInterface futureInterface, unsigned line = 0; unsigned column = 0; CPlusPlus::Document::Ptr declaringDoc = declaringDocument(document, snapshot, testCaseName, - &line, &column); + alternativeFiles, &line, &column); if (declaringDoc.isNull()) return false; @@ -263,12 +279,14 @@ static bool handleQtTest(QFutureInterface futureInterface, void QtTestParser::init(const QStringList &filesToParse) { m_testCaseNames = QTestUtils::testCaseNamesForFiles(id(), filesToParse); + m_alternativeFiles = QTestUtils::alternativeFiles(id(), filesToParse); CppParser::init(filesToParse); } void QtTestParser::release() { m_testCaseNames.clear(); + m_alternativeFiles.clear(); CppParser::release(); } @@ -279,10 +297,11 @@ bool QtTestParser::processDocument(QFutureInterface futureIn return false; CPlusPlus::Document::Ptr doc = m_cppSnapshot.find(fileName).value(); const QString &oldName = m_testCaseNames.value(fileName); + const QStringList &alternativeFiles = m_alternativeFiles.values(fileName); if ((!includesQtTest(doc, m_cppSnapshot) || !qtTestLibDefined(fileName)) && oldName.isEmpty()) return false; - return handleQtTest(futureInterface, doc, m_cppSnapshot, oldName, id()); + return handleQtTest(futureInterface, doc, m_cppSnapshot, oldName, alternativeFiles, id()); } } // namespace Internal diff --git a/src/plugins/autotest/qtest/qttestparser.h b/src/plugins/autotest/qtest/qttestparser.h index 4888ed73c09..8b762fe9639 100644 --- a/src/plugins/autotest/qtest/qttestparser.h +++ b/src/plugins/autotest/qtest/qttestparser.h @@ -51,6 +51,7 @@ public: private: QHash m_testCaseNames; + QMultiHash m_alternativeFiles; }; } // namespace Internal