Commit db71490b authored by Christian Stenger's avatar Christian Stenger Committed by Christian Stenger

AutoTest: Use (shared) pointer for parse results

This is necessary later on as we will need different sub-classes of
TestParseResult to support different test frameworks.
This avoids the necessarity to put all information inside a single
object even if it is not used.

Change-Id: I39c74ba06b9337608ece8b113b0993c0934b24b9
Reviewed-by: default avatarDavid Schulz <david.schulz@theqtcompany.com>
parent 06c53d8d
......@@ -78,11 +78,11 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent)
this, &TestCodeParser::onTaskStarted);
connect(progressManager, &Core::ProgressManager::allTasksFinished,
this, &TestCodeParser::onAllTasksFinished);
connect(&m_futureWatcher, &QFutureWatcher<TestParseResult>::started,
connect(&m_futureWatcher, &QFutureWatcher<TestParseResultPtr>::started,
this, &TestCodeParser::parsingStarted);
connect(&m_futureWatcher, &QFutureWatcher<TestParseResult>::finished,
connect(&m_futureWatcher, &QFutureWatcher<TestParseResultPtr>::finished,
this, &TestCodeParser::onFinished);
connect(&m_futureWatcher, &QFutureWatcher<TestParseResult>::resultReadyAt,
connect(&m_futureWatcher, &QFutureWatcher<TestParseResultPtr>::resultReadyAt,
this, [this] (int index) {
emit testParseResultReady(m_futureWatcher.resultAt(index));
});
......@@ -441,7 +441,7 @@ static QMap<QString, TestCodeLocationList> checkForDataTags(const QString &fileN
/****** end of helpers ******/
static bool checkQmlDocumentForTestCode(QFutureInterface<TestParseResult> futureInterface,
static bool checkQmlDocumentForTestCode(QFutureInterface<TestParseResultPtr> futureInterface,
const QmlJS::Document::Ptr &qmlJSDoc,
const QString &proFile = QString())
{
......@@ -456,20 +456,20 @@ static bool checkQmlDocumentForTestCode(QFutureInterface<TestParseResult> future
const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation();
const QMap<QString, TestCodeLocationAndType> testFunctions = qmlVisitor.testFunctions();
TestParseResult parseResult(TestTreeModel::QuickTest);
parseResult.proFile = proFile;
parseResult.functions = testFunctions;
TestParseResultPtr parseResult(new TestParseResult(TestTreeModel::QuickTest));
parseResult->proFile = proFile;
parseResult->functions = testFunctions;
if (!testCaseName.isEmpty()) {
parseResult.fileName = tcLocationAndType.m_name;
parseResult.testCaseName = testCaseName;
parseResult.line = tcLocationAndType.m_line;
parseResult.column = tcLocationAndType.m_column;
parseResult->fileName = tcLocationAndType.m_name;
parseResult->testCaseName = testCaseName;
parseResult->line = tcLocationAndType.m_line;
parseResult->column = tcLocationAndType.m_column;
}
futureInterface.reportResult(parseResult);
return true;
}
static bool handleQtTest(QFutureInterface<TestParseResult> futureInterface,
static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document, const QString &oldTestCaseName)
{
const QString &fileName = document->fileName();
......@@ -498,14 +498,14 @@ static bool handleQtTest(QFutureInterface<TestParseResult> futureInterface,
foreach (const QString &file, files)
dataTags.unite(checkForDataTags(file));
TestParseResult parseResult(TestTreeModel::AutoTest);
parseResult.fileName = declaringDoc->fileName();
parseResult.testCaseName = testCaseName;
parseResult.line = line;
parseResult.column = column;
parseResult.functions = testFunctions;
parseResult.dataTagsOrTestSets = dataTags;
parseResult.proFile = modelManager->projectPart(fileName).first()->projectFile;
TestParseResultPtr parseResult(new TestParseResult(TestTreeModel::AutoTest));
parseResult->fileName = declaringDoc->fileName();
parseResult->testCaseName = testCaseName;
parseResult->line = line;
parseResult->column = column;
parseResult->functions = testFunctions;
parseResult->dataTagsOrTestSets = dataTags;
parseResult->proFile = modelManager->projectPart(fileName).first()->projectFile;
futureInterface.reportResult(parseResult);
return true;
......@@ -513,7 +513,7 @@ static bool handleQtTest(QFutureInterface<TestParseResult> futureInterface,
return false;
}
static bool handleQtQuickTest(QFutureInterface<TestParseResult> futureInterface,
static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document)
{
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
......@@ -537,7 +537,7 @@ static bool handleQtQuickTest(QFutureInterface<TestParseResult> futureInterface,
return result;
}
static bool handleGTest(QFutureInterface<TestParseResult> futureInterface, const QString &filePath)
static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface, const QString &filePath)
{
const QByteArray &fileContent = getFileContent(filePath);
const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerBase::instance()->snapshot();
......@@ -555,20 +555,20 @@ static bool handleGTest(QFutureInterface<TestParseResult> futureInterface, const
proFile = ppList.first()->projectFile;
foreach (const GTestCaseSpec &testSpec, result.keys()) {
TestParseResult parseResult(TestTreeModel::GoogleTest);
parseResult.fileName = filePath;
parseResult.testCaseName = testSpec.testCaseName;
parseResult.parameterized = testSpec.parameterized;
parseResult.typed = testSpec.typed;
parseResult.disabled = testSpec.disabled;
parseResult.proFile = proFile;
parseResult.dataTagsOrTestSets.insert(QString(), result.value(testSpec));
TestParseResultPtr parseResult(new TestParseResult(TestTreeModel::GoogleTest));
parseResult->fileName = filePath;
parseResult->testCaseName = testSpec.testCaseName;
parseResult->parameterized = testSpec.parameterized;
parseResult->typed = testSpec.typed;
parseResult->disabled = testSpec.disabled;
parseResult->proFile = proFile;
parseResult->dataTagsOrTestSets.insert(QString(), result.value(testSpec));
futureInterface.reportResult(parseResult);
}
return !result.keys().isEmpty();
}
static void checkDocumentForTestCode(QFutureInterface<TestParseResult> futureInterface,
static void checkDocumentForTestCode(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document,
QHash<QString, QString> testCaseNames)
{
......@@ -603,7 +603,7 @@ static void checkDocumentForTestCode(QFutureInterface<TestParseResult> futureInt
// is not (yet) part of the CppModelManager's snapshot
static bool parsingHasFailed;
static void performParse(QFutureInterface<TestParseResult> &futureInterface,
static void performParse(QFutureInterface<TestParseResultPtr> &futureInterface,
const QStringList &list, const QHash<QString, QString> testCaseNames)
{
int progressValue = 0;
......@@ -771,7 +771,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
m_model->markForRemoval(filePath);
}
QFuture<TestParseResult> future = Utils::runAsync(&performParse, list, testCaseNames);
QFuture<TestParseResultPtr> future = Utils::runAsync(&performParse, list, testCaseNames);
m_futureWatcher.setFuture(future);
if (list.size() > 5) {
Core::ProgressManager::addTask(future, tr("Scanning for Tests"),
......
......@@ -70,7 +70,7 @@ public:
signals:
void aboutToPerformFullParse();
void testParseResultReady(TestParseResult result);
void testParseResultReady(const TestParseResultPtr result);
void parsingStarted();
void parsingFinished();
void parsingFailed();
......@@ -101,7 +101,7 @@ private:
bool m_singleShotScheduled;
QSet<QString> m_postponedFiles;
State m_parserState;
QFutureWatcher<TestParseResult> m_futureWatcher;
QFutureWatcher<TestParseResultPtr> m_futureWatcher;
};
} // namespace Internal
......
......@@ -337,21 +337,21 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item)
return hasChanged;
}
void TestTreeModel::onParseResultReady(const TestParseResult &result)
void TestTreeModel::onParseResultReady(const TestParseResultPtr result)
{
switch (result.type) {
switch (result->type) {
case AutoTest:
handleParseResult(result);
break;
case QuickTest:
if (result.testCaseName.isEmpty()) {
if (result->testCaseName.isEmpty()) {
handleUnnamedQuickParseResult(result);
break;
}
handleParseResult(result);
break;
case GoogleTest:
QTC_ASSERT(result.dataTagsOrTestSets.size() == 1, return);
QTC_ASSERT(result->dataTagsOrTestSets.size() == 1, return);
handleGTestParseResult(result);
break;
case Invalid:
......@@ -360,10 +360,10 @@ void TestTreeModel::onParseResultReady(const TestParseResult &result)
}
}
void TestTreeModel::handleParseResult(const TestParseResult &result)
void TestTreeModel::handleParseResult(const TestParseResultPtr result)
{
TestTreeItem *root;
switch (result.type) {
switch (result->type) {
case AutoTest:
root = m_autoTestRootItem;
break;
......@@ -374,46 +374,46 @@ void TestTreeModel::handleParseResult(const TestParseResult &result)
QTC_ASSERT(false, return); // should never happen, just to avoid warning
}
TestTreeItem *toBeModified = root->findChildByFile(result.fileName);
TestTreeItem *toBeModified = root->findChildByFile(result->fileName);
// if there's no matching item, add the new one
if (!toBeModified) {
if (result.type == AutoTest)
root->appendChild(AutoTestTreeItem::createTestItem(result));
if (result->type == AutoTest)
root->appendChild(AutoTestTreeItem::createTestItem(*result));
else
root->appendChild(QuickTestTreeItem::createTestItem(result));
root->appendChild(QuickTestTreeItem::createTestItem(*result));
return;
}
// else we have to check level by level.. first the current level...
bool changed = toBeModified->modifyTestCaseContent(result.testCaseName, result.line,
result.column);
bool changed = toBeModified->modifyTestCaseContent(result->testCaseName, result->line,
result->column);
toBeModified->markForRemoval(false);
if (changed)
emit dataChanged(indexForItem(toBeModified), indexForItem(toBeModified));
// ...now the functions
foreach (const QString &func, result.functions.keys()) {
foreach (const QString &func, result->functions.keys()) {
TestTreeItem *functionItem = toBeModified->findChildByName(func);
// if there's no function matching, add the new one
if (!functionItem) {
const QString qualifiedName = result.testCaseName + QLatin1String("::") + func;
if (result.type == AutoTest) {
const QString qualifiedName = result->testCaseName + QLatin1String("::") + func;
if (result->type == AutoTest) {
toBeModified->appendChild(AutoTestTreeItem::createFunctionItem(
func, result.functions.value(func),
result.dataTagsOrTestSets.value(qualifiedName)));
func, result->functions.value(func),
result->dataTagsOrTestSets.value(qualifiedName)));
} else {
toBeModified->appendChild(QuickTestTreeItem::createFunctionItem(
func, result.functions.value(func)));
func, result->functions.value(func)));
}
continue;
}
// else we have to check level by level.. first the current level...
changed = functionItem->modifyTestFunctionContent(result.functions.value(func));
changed = functionItem->modifyTestFunctionContent(result->functions.value(func));
functionItem->markForRemoval(false);
if (changed)
emit dataChanged(indexForItem(functionItem), indexForItem(functionItem));
// ...now the data tags - actually these are supported only for AutoTestTreeItem
const QString &funcFileName = result.functions.value(func).m_name;
const QString qualifiedFunctionName = result.testCaseName + QLatin1String("::") + func;
foreach (const TestCodeLocationAndType &location, result.dataTagsOrTestSets.value(qualifiedFunctionName)) {
const QString &funcFileName = result->functions.value(func).m_name;
const QString qualifiedFunctionName = result->testCaseName + QLatin1String("::") + func;
foreach (const TestCodeLocationAndType &location, result->dataTagsOrTestSets.value(qualifiedFunctionName)) {
TestTreeItem *dataTagItem = functionItem->findChildByName(location.m_name);
if (!dataTagItem) {
functionItem->appendChild(AutoTestTreeItem::createDataTagItem(funcFileName, location));
......@@ -427,20 +427,20 @@ void TestTreeModel::handleParseResult(const TestParseResult &result)
}
}
void TestTreeModel::handleUnnamedQuickParseResult(const TestParseResult &result)
void TestTreeModel::handleUnnamedQuickParseResult(const TestParseResultPtr result)
{
TestTreeItem *toBeModified = unnamedQuickTests();
if (!toBeModified) {
m_quickTestRootItem->appendChild(QuickTestTreeItem::createUnnamedQuickTestItem(result));
m_quickTestRootItem->appendChild(QuickTestTreeItem::createUnnamedQuickTestItem(*result));
return;
}
// if we have already Unnamed Quick tests we might update them..
foreach (const QString &func, result.functions.keys()) {
const TestCodeLocationAndType &location = result.functions.value(func);
foreach (const QString &func, result->functions.keys()) {
const TestCodeLocationAndType &location = result->functions.value(func);
TestTreeItem *functionItem = toBeModified->findChildByNameAndFile(func, location.m_name);
if (!functionItem) {
toBeModified->appendChild(QuickTestTreeItem::createUnnamedQuickFunctionItem(
func, result));
func, *result));
continue;
}
functionItem->modifyLineAndColumn(location);
......@@ -448,29 +448,29 @@ void TestTreeModel::handleUnnamedQuickParseResult(const TestParseResult &result)
}
}
void TestTreeModel::handleGTestParseResult(const TestParseResult &result)
void TestTreeModel::handleGTestParseResult(const TestParseResultPtr result)
{
GoogleTestTreeItem::TestStates states = GoogleTestTreeItem::Enabled;
if (result.parameterized)
if (result->parameterized)
states |= GoogleTestTreeItem::Parameterized;
if (result.typed)
if (result->typed)
states |= GoogleTestTreeItem::Typed;
TestTreeItem *toBeModified = m_googleTestRootItem->findChildByNameStateAndFile(
result.testCaseName, states, result.proFile);
result->testCaseName, states, result->proFile);
if (!toBeModified) {
m_googleTestRootItem->appendChild(GoogleTestTreeItem::createTestItem(result));
m_googleTestRootItem->appendChild(GoogleTestTreeItem::createTestItem(*result));
return;
}
// if found nothing has to be updated as all relevant members are used to find the item
foreach (const TestCodeLocationAndType &location , result.dataTagsOrTestSets.first()) {
foreach (const TestCodeLocationAndType &location , result->dataTagsOrTestSets.first()) {
TestTreeItem *testSetItem = toBeModified->findChildByNameAndFile(location.m_name,
result.fileName);
result->fileName);
if (!testSetItem) {
toBeModified->appendChild(GoogleTestTreeItem::createTestSetItem(result, location));
toBeModified->appendChild(GoogleTestTreeItem::createTestSetItem(*result, location));
continue;
}
bool changed = static_cast<GoogleTestTreeItem *>(testSetItem)->modifyTestSetContent(
result.fileName, location);
result->fileName, location);
testSetItem->markForRemoval(false);
if (changed)
emit dataChanged(indexForItem(testSetItem), indexForItem(testSetItem));
......
......@@ -40,6 +40,8 @@ namespace Internal {
class TestCodeParser;
struct TestParseResult;
using TestParseResultPtr = QSharedPointer<TestParseResult>;
class TestTreeModel : public Utils::TreeModel
{
Q_OBJECT
......@@ -91,10 +93,10 @@ signals:
public slots:
private:
void onParseResultReady(const TestParseResult &result);
void handleParseResult(const TestParseResult &result);
void handleUnnamedQuickParseResult(const TestParseResult &result);
void handleGTestParseResult(const TestParseResult &result);
void onParseResultReady(const TestParseResultPtr result);
void handleParseResult(const TestParseResultPtr result);
void handleUnnamedQuickParseResult(const TestParseResultPtr result);
void handleGTestParseResult(const TestParseResultPtr result);
void removeAllTestItems();
void removeFiles(const QStringList &files);
void markForRemoval(const QString &filePath, Type type);
......@@ -168,4 +170,4 @@ struct TestParseResult
} // namespace Autotest
Q_DECLARE_METATYPE(Autotest::Internal::TestTreeModel::Type)
Q_DECLARE_METATYPE(Autotest::Internal::TestParseResult)
Q_DECLARE_METATYPE(Autotest::Internal::TestParseResultPtr)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment