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: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
Christian Stenger
2016-04-12 12:44:56 +02:00
committed by Christian Stenger
parent 06c53d8def
commit db71490b1e
4 changed files with 78 additions and 76 deletions

View File

@@ -78,11 +78,11 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent)
this, &TestCodeParser::onTaskStarted); this, &TestCodeParser::onTaskStarted);
connect(progressManager, &Core::ProgressManager::allTasksFinished, connect(progressManager, &Core::ProgressManager::allTasksFinished,
this, &TestCodeParser::onAllTasksFinished); this, &TestCodeParser::onAllTasksFinished);
connect(&m_futureWatcher, &QFutureWatcher<TestParseResult>::started, connect(&m_futureWatcher, &QFutureWatcher<TestParseResultPtr>::started,
this, &TestCodeParser::parsingStarted); this, &TestCodeParser::parsingStarted);
connect(&m_futureWatcher, &QFutureWatcher<TestParseResult>::finished, connect(&m_futureWatcher, &QFutureWatcher<TestParseResultPtr>::finished,
this, &TestCodeParser::onFinished); this, &TestCodeParser::onFinished);
connect(&m_futureWatcher, &QFutureWatcher<TestParseResult>::resultReadyAt, connect(&m_futureWatcher, &QFutureWatcher<TestParseResultPtr>::resultReadyAt,
this, [this] (int index) { this, [this] (int index) {
emit testParseResultReady(m_futureWatcher.resultAt(index)); emit testParseResultReady(m_futureWatcher.resultAt(index));
}); });
@@ -441,7 +441,7 @@ static QMap<QString, TestCodeLocationList> checkForDataTags(const QString &fileN
/****** end of helpers ******/ /****** end of helpers ******/
static bool checkQmlDocumentForTestCode(QFutureInterface<TestParseResult> futureInterface, static bool checkQmlDocumentForTestCode(QFutureInterface<TestParseResultPtr> futureInterface,
const QmlJS::Document::Ptr &qmlJSDoc, const QmlJS::Document::Ptr &qmlJSDoc,
const QString &proFile = QString()) const QString &proFile = QString())
{ {
@@ -456,20 +456,20 @@ static bool checkQmlDocumentForTestCode(QFutureInterface<TestParseResult> future
const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation(); const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation();
const QMap<QString, TestCodeLocationAndType> testFunctions = qmlVisitor.testFunctions(); const QMap<QString, TestCodeLocationAndType> testFunctions = qmlVisitor.testFunctions();
TestParseResult parseResult(TestTreeModel::QuickTest); TestParseResultPtr parseResult(new TestParseResult(TestTreeModel::QuickTest));
parseResult.proFile = proFile; parseResult->proFile = proFile;
parseResult.functions = testFunctions; parseResult->functions = testFunctions;
if (!testCaseName.isEmpty()) { if (!testCaseName.isEmpty()) {
parseResult.fileName = tcLocationAndType.m_name; parseResult->fileName = tcLocationAndType.m_name;
parseResult.testCaseName = testCaseName; parseResult->testCaseName = testCaseName;
parseResult.line = tcLocationAndType.m_line; parseResult->line = tcLocationAndType.m_line;
parseResult.column = tcLocationAndType.m_column; parseResult->column = tcLocationAndType.m_column;
} }
futureInterface.reportResult(parseResult); futureInterface.reportResult(parseResult);
return true; return true;
} }
static bool handleQtTest(QFutureInterface<TestParseResult> futureInterface, static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document, const QString &oldTestCaseName) CPlusPlus::Document::Ptr document, const QString &oldTestCaseName)
{ {
const QString &fileName = document->fileName(); const QString &fileName = document->fileName();
@@ -498,14 +498,14 @@ static bool handleQtTest(QFutureInterface<TestParseResult> futureInterface,
foreach (const QString &file, files) foreach (const QString &file, files)
dataTags.unite(checkForDataTags(file)); dataTags.unite(checkForDataTags(file));
TestParseResult parseResult(TestTreeModel::AutoTest); TestParseResultPtr parseResult(new TestParseResult(TestTreeModel::AutoTest));
parseResult.fileName = declaringDoc->fileName(); parseResult->fileName = declaringDoc->fileName();
parseResult.testCaseName = testCaseName; parseResult->testCaseName = testCaseName;
parseResult.line = line; parseResult->line = line;
parseResult.column = column; parseResult->column = column;
parseResult.functions = testFunctions; parseResult->functions = testFunctions;
parseResult.dataTagsOrTestSets = dataTags; parseResult->dataTagsOrTestSets = dataTags;
parseResult.proFile = modelManager->projectPart(fileName).first()->projectFile; parseResult->proFile = modelManager->projectPart(fileName).first()->projectFile;
futureInterface.reportResult(parseResult); futureInterface.reportResult(parseResult);
return true; return true;
@@ -513,7 +513,7 @@ static bool handleQtTest(QFutureInterface<TestParseResult> futureInterface,
return false; return false;
} }
static bool handleQtQuickTest(QFutureInterface<TestParseResult> futureInterface, static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document) CPlusPlus::Document::Ptr document)
{ {
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
@@ -537,7 +537,7 @@ static bool handleQtQuickTest(QFutureInterface<TestParseResult> futureInterface,
return result; 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 QByteArray &fileContent = getFileContent(filePath);
const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerBase::instance()->snapshot(); const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerBase::instance()->snapshot();
@@ -555,20 +555,20 @@ static bool handleGTest(QFutureInterface<TestParseResult> futureInterface, const
proFile = ppList.first()->projectFile; proFile = ppList.first()->projectFile;
foreach (const GTestCaseSpec &testSpec, result.keys()) { foreach (const GTestCaseSpec &testSpec, result.keys()) {
TestParseResult parseResult(TestTreeModel::GoogleTest); TestParseResultPtr parseResult(new TestParseResult(TestTreeModel::GoogleTest));
parseResult.fileName = filePath; parseResult->fileName = filePath;
parseResult.testCaseName = testSpec.testCaseName; parseResult->testCaseName = testSpec.testCaseName;
parseResult.parameterized = testSpec.parameterized; parseResult->parameterized = testSpec.parameterized;
parseResult.typed = testSpec.typed; parseResult->typed = testSpec.typed;
parseResult.disabled = testSpec.disabled; parseResult->disabled = testSpec.disabled;
parseResult.proFile = proFile; parseResult->proFile = proFile;
parseResult.dataTagsOrTestSets.insert(QString(), result.value(testSpec)); parseResult->dataTagsOrTestSets.insert(QString(), result.value(testSpec));
futureInterface.reportResult(parseResult); futureInterface.reportResult(parseResult);
} }
return !result.keys().isEmpty(); return !result.keys().isEmpty();
} }
static void checkDocumentForTestCode(QFutureInterface<TestParseResult> futureInterface, static void checkDocumentForTestCode(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document, CPlusPlus::Document::Ptr document,
QHash<QString, QString> testCaseNames) QHash<QString, QString> testCaseNames)
{ {
@@ -603,7 +603,7 @@ static void checkDocumentForTestCode(QFutureInterface<TestParseResult> futureInt
// is not (yet) part of the CppModelManager's snapshot // is not (yet) part of the CppModelManager's snapshot
static bool parsingHasFailed; static bool parsingHasFailed;
static void performParse(QFutureInterface<TestParseResult> &futureInterface, static void performParse(QFutureInterface<TestParseResultPtr> &futureInterface,
const QStringList &list, const QHash<QString, QString> testCaseNames) const QStringList &list, const QHash<QString, QString> testCaseNames)
{ {
int progressValue = 0; int progressValue = 0;
@@ -771,7 +771,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
m_model->markForRemoval(filePath); m_model->markForRemoval(filePath);
} }
QFuture<TestParseResult> future = Utils::runAsync(&performParse, list, testCaseNames); QFuture<TestParseResultPtr> future = Utils::runAsync(&performParse, list, testCaseNames);
m_futureWatcher.setFuture(future); m_futureWatcher.setFuture(future);
if (list.size() > 5) { if (list.size() > 5) {
Core::ProgressManager::addTask(future, tr("Scanning for Tests"), Core::ProgressManager::addTask(future, tr("Scanning for Tests"),

View File

@@ -70,7 +70,7 @@ public:
signals: signals:
void aboutToPerformFullParse(); void aboutToPerformFullParse();
void testParseResultReady(TestParseResult result); void testParseResultReady(const TestParseResultPtr result);
void parsingStarted(); void parsingStarted();
void parsingFinished(); void parsingFinished();
void parsingFailed(); void parsingFailed();
@@ -101,7 +101,7 @@ private:
bool m_singleShotScheduled; bool m_singleShotScheduled;
QSet<QString> m_postponedFiles; QSet<QString> m_postponedFiles;
State m_parserState; State m_parserState;
QFutureWatcher<TestParseResult> m_futureWatcher; QFutureWatcher<TestParseResultPtr> m_futureWatcher;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -337,21 +337,21 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item)
return hasChanged; return hasChanged;
} }
void TestTreeModel::onParseResultReady(const TestParseResult &result) void TestTreeModel::onParseResultReady(const TestParseResultPtr result)
{ {
switch (result.type) { switch (result->type) {
case AutoTest: case AutoTest:
handleParseResult(result); handleParseResult(result);
break; break;
case QuickTest: case QuickTest:
if (result.testCaseName.isEmpty()) { if (result->testCaseName.isEmpty()) {
handleUnnamedQuickParseResult(result); handleUnnamedQuickParseResult(result);
break; break;
} }
handleParseResult(result); handleParseResult(result);
break; break;
case GoogleTest: case GoogleTest:
QTC_ASSERT(result.dataTagsOrTestSets.size() == 1, return); QTC_ASSERT(result->dataTagsOrTestSets.size() == 1, return);
handleGTestParseResult(result); handleGTestParseResult(result);
break; break;
case Invalid: 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; TestTreeItem *root;
switch (result.type) { switch (result->type) {
case AutoTest: case AutoTest:
root = m_autoTestRootItem; root = m_autoTestRootItem;
break; break;
@@ -374,46 +374,46 @@ void TestTreeModel::handleParseResult(const TestParseResult &result)
QTC_ASSERT(false, return); // should never happen, just to avoid warning 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 there's no matching item, add the new one
if (!toBeModified) { if (!toBeModified) {
if (result.type == AutoTest) if (result->type == AutoTest)
root->appendChild(AutoTestTreeItem::createTestItem(result)); root->appendChild(AutoTestTreeItem::createTestItem(*result));
else else
root->appendChild(QuickTestTreeItem::createTestItem(result)); root->appendChild(QuickTestTreeItem::createTestItem(*result));
return; return;
} }
// else we have to check level by level.. first the current level... // else we have to check level by level.. first the current level...
bool changed = toBeModified->modifyTestCaseContent(result.testCaseName, result.line, bool changed = toBeModified->modifyTestCaseContent(result->testCaseName, result->line,
result.column); result->column);
toBeModified->markForRemoval(false); toBeModified->markForRemoval(false);
if (changed) if (changed)
emit dataChanged(indexForItem(toBeModified), indexForItem(toBeModified)); emit dataChanged(indexForItem(toBeModified), indexForItem(toBeModified));
// ...now the functions // ...now the functions
foreach (const QString &func, result.functions.keys()) { foreach (const QString &func, result->functions.keys()) {
TestTreeItem *functionItem = toBeModified->findChildByName(func); TestTreeItem *functionItem = toBeModified->findChildByName(func);
// if there's no function matching, add the new one // if there's no function matching, add the new one
if (!functionItem) { if (!functionItem) {
const QString qualifiedName = result.testCaseName + QLatin1String("::") + func; const QString qualifiedName = result->testCaseName + QLatin1String("::") + func;
if (result.type == AutoTest) { if (result->type == AutoTest) {
toBeModified->appendChild(AutoTestTreeItem::createFunctionItem( toBeModified->appendChild(AutoTestTreeItem::createFunctionItem(
func, result.functions.value(func), func, result->functions.value(func),
result.dataTagsOrTestSets.value(qualifiedName))); result->dataTagsOrTestSets.value(qualifiedName)));
} else { } else {
toBeModified->appendChild(QuickTestTreeItem::createFunctionItem( toBeModified->appendChild(QuickTestTreeItem::createFunctionItem(
func, result.functions.value(func))); func, result->functions.value(func)));
} }
continue; continue;
} }
// else we have to check level by level.. first the current level... // 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); functionItem->markForRemoval(false);
if (changed) if (changed)
emit dataChanged(indexForItem(functionItem), indexForItem(functionItem)); emit dataChanged(indexForItem(functionItem), indexForItem(functionItem));
// ...now the data tags - actually these are supported only for AutoTestTreeItem // ...now the data tags - actually these are supported only for AutoTestTreeItem
const QString &funcFileName = result.functions.value(func).m_name; const QString &funcFileName = result->functions.value(func).m_name;
const QString qualifiedFunctionName = result.testCaseName + QLatin1String("::") + func; const QString qualifiedFunctionName = result->testCaseName + QLatin1String("::") + func;
foreach (const TestCodeLocationAndType &location, result.dataTagsOrTestSets.value(qualifiedFunctionName)) { foreach (const TestCodeLocationAndType &location, result->dataTagsOrTestSets.value(qualifiedFunctionName)) {
TestTreeItem *dataTagItem = functionItem->findChildByName(location.m_name); TestTreeItem *dataTagItem = functionItem->findChildByName(location.m_name);
if (!dataTagItem) { if (!dataTagItem) {
functionItem->appendChild(AutoTestTreeItem::createDataTagItem(funcFileName, location)); 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(); TestTreeItem *toBeModified = unnamedQuickTests();
if (!toBeModified) { if (!toBeModified) {
m_quickTestRootItem->appendChild(QuickTestTreeItem::createUnnamedQuickTestItem(result)); m_quickTestRootItem->appendChild(QuickTestTreeItem::createUnnamedQuickTestItem(*result));
return; return;
} }
// if we have already Unnamed Quick tests we might update them.. // if we have already Unnamed Quick tests we might update them..
foreach (const QString &func, result.functions.keys()) { foreach (const QString &func, result->functions.keys()) {
const TestCodeLocationAndType &location = result.functions.value(func); const TestCodeLocationAndType &location = result->functions.value(func);
TestTreeItem *functionItem = toBeModified->findChildByNameAndFile(func, location.m_name); TestTreeItem *functionItem = toBeModified->findChildByNameAndFile(func, location.m_name);
if (!functionItem) { if (!functionItem) {
toBeModified->appendChild(QuickTestTreeItem::createUnnamedQuickFunctionItem( toBeModified->appendChild(QuickTestTreeItem::createUnnamedQuickFunctionItem(
func, result)); func, *result));
continue; continue;
} }
functionItem->modifyLineAndColumn(location); 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; GoogleTestTreeItem::TestStates states = GoogleTestTreeItem::Enabled;
if (result.parameterized) if (result->parameterized)
states |= GoogleTestTreeItem::Parameterized; states |= GoogleTestTreeItem::Parameterized;
if (result.typed) if (result->typed)
states |= GoogleTestTreeItem::Typed; states |= GoogleTestTreeItem::Typed;
TestTreeItem *toBeModified = m_googleTestRootItem->findChildByNameStateAndFile( TestTreeItem *toBeModified = m_googleTestRootItem->findChildByNameStateAndFile(
result.testCaseName, states, result.proFile); result->testCaseName, states, result->proFile);
if (!toBeModified) { if (!toBeModified) {
m_googleTestRootItem->appendChild(GoogleTestTreeItem::createTestItem(result)); m_googleTestRootItem->appendChild(GoogleTestTreeItem::createTestItem(*result));
return; return;
} }
// if found nothing has to be updated as all relevant members are used to find the item // 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, TestTreeItem *testSetItem = toBeModified->findChildByNameAndFile(location.m_name,
result.fileName); result->fileName);
if (!testSetItem) { if (!testSetItem) {
toBeModified->appendChild(GoogleTestTreeItem::createTestSetItem(result, location)); toBeModified->appendChild(GoogleTestTreeItem::createTestSetItem(*result, location));
continue; continue;
} }
bool changed = static_cast<GoogleTestTreeItem *>(testSetItem)->modifyTestSetContent( bool changed = static_cast<GoogleTestTreeItem *>(testSetItem)->modifyTestSetContent(
result.fileName, location); result->fileName, location);
testSetItem->markForRemoval(false); testSetItem->markForRemoval(false);
if (changed) if (changed)
emit dataChanged(indexForItem(testSetItem), indexForItem(testSetItem)); emit dataChanged(indexForItem(testSetItem), indexForItem(testSetItem));

View File

@@ -40,6 +40,8 @@ namespace Internal {
class TestCodeParser; class TestCodeParser;
struct TestParseResult; struct TestParseResult;
using TestParseResultPtr = QSharedPointer<TestParseResult>;
class TestTreeModel : public Utils::TreeModel class TestTreeModel : public Utils::TreeModel
{ {
Q_OBJECT Q_OBJECT
@@ -91,10 +93,10 @@ signals:
public slots: public slots:
private: private:
void onParseResultReady(const TestParseResult &result); void onParseResultReady(const TestParseResultPtr result);
void handleParseResult(const TestParseResult &result); void handleParseResult(const TestParseResultPtr result);
void handleUnnamedQuickParseResult(const TestParseResult &result); void handleUnnamedQuickParseResult(const TestParseResultPtr result);
void handleGTestParseResult(const TestParseResult &result); void handleGTestParseResult(const TestParseResultPtr result);
void removeAllTestItems(); void removeAllTestItems();
void removeFiles(const QStringList &files); void removeFiles(const QStringList &files);
void markForRemoval(const QString &filePath, Type type); void markForRemoval(const QString &filePath, Type type);
@@ -168,4 +170,4 @@ struct TestParseResult
} // namespace Autotest } // namespace Autotest
Q_DECLARE_METATYPE(Autotest::Internal::TestTreeModel::Type) Q_DECLARE_METATYPE(Autotest::Internal::TestTreeModel::Type)
Q_DECLARE_METATYPE(Autotest::Internal::TestParseResult) Q_DECLARE_METATYPE(Autotest::Internal::TestParseResultPtr)