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