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 <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2017-01-04 13:56:20 +01:00
parent 4a634a23cf
commit 0ceea628b0
4 changed files with 47 additions and 6 deletions

View File

@@ -24,8 +24,8 @@
****************************************************************************/
#include "qttest_utils.h"
#include "qttesttreeitem.h"
#include "../testframeworkmanager.h"
#include "../testtreeitem.h"
#include <utils/qtcassert.h>
@@ -42,8 +42,7 @@ bool isQTestMacro(const QByteArray &macro)
return valid.contains(macro);
}
QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id,
const QStringList &files)
QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringList &files)
{
QHash<QString, QString> result;
TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id);
@@ -63,6 +62,27 @@ QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id,
return result;
}
QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringList &files)
{
QMultiHash<QString, QString> 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<const QtTestTreeItem *>(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

View File

@@ -35,6 +35,7 @@ namespace QTestUtils {
bool isQTestMacro(const QByteArray &macro);
QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringList &files);
QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringList &files);
} // namespace QTestUtils
} // namespace Internal

View File

@@ -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<CPlusPlus::LookupItem> 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<TestParseResultPtr> 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<TestParseResultPtr> 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<TestParseResultPtr> 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<TestParseResultPtr> 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

View File

@@ -51,6 +51,7 @@ public:
private:
QHash<QString, QString> m_testCaseNames;
QMultiHash<QString, QString> m_alternativeFiles;
};
} // namespace Internal