From ef2f37f6d54154deb8f6450dbe3d910ea45fb4ee Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 9 May 2016 10:27:47 +0200 Subject: [PATCH] AutoTest: Decouple item and model once more Change-Id: I301f17dd8be7feb9dc61f483277a4835aea937af Reviewed-by: Christian Stenger Reviewed-by: David Schulz --- src/plugins/autotest/testcodeparser.cpp | 19 +++ src/plugins/autotest/testcodeparser.h | 5 + src/plugins/autotest/testtreeitem.cpp | 106 +++++++++++++++- src/plugins/autotest/testtreeitem.h | 15 ++- src/plugins/autotest/testtreemodel.cpp | 161 ++++-------------------- src/plugins/autotest/testtreemodel.h | 5 +- 6 files changed, 160 insertions(+), 151 deletions(-) diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index a40c366e07c..45acea93910 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -910,5 +910,24 @@ void TestCodeParser::onPartialParsingFinished() } } +TestTreeItem *QtTestParseResult::createTestTreeItem() const +{ + return itemType == TestTreeItem::Root ? 0 : AutoTestTreeItem::createTestItem(this); +} + +TestTreeItem *QuickTestParseResult::createTestTreeItem() const +{ + if (itemType == TestTreeItem::Root || itemType == TestTreeItem::TestDataTag) + return 0; + return QuickTestTreeItem::createTestItem(this); +} + +TestTreeItem *GoogleTestParseResult::createTestTreeItem() const +{ + if (itemType == TestTreeItem::TestCase || itemType == TestTreeItem::TestFunctionOrSet) + return GoogleTestTreeItem::createTestItem(this); + return 0; +} + } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h index a6646a33e39..e666a7eaf0c 100644 --- a/src/plugins/autotest/testcodeparser.h +++ b/src/plugins/autotest/testcodeparser.h @@ -49,6 +49,8 @@ public: explicit TestParseResult(TestTreeModel::Type t = TestTreeModel::Invalid) : type(t) {} virtual ~TestParseResult() { qDeleteAll(children); } + virtual TestTreeItem *createTestTreeItem() const = 0; + QVector children; TestTreeModel::Type type; TestTreeItem::Type itemType = TestTreeItem::Root; @@ -64,18 +66,21 @@ class QtTestParseResult : public TestParseResult { public: explicit QtTestParseResult() : TestParseResult(TestTreeModel::AutoTest) {} + TestTreeItem *createTestTreeItem() const override; }; class QuickTestParseResult : public TestParseResult { public: explicit QuickTestParseResult() : TestParseResult(TestTreeModel::QuickTest) {} + TestTreeItem *createTestTreeItem() const override; }; class GoogleTestParseResult : public TestParseResult { public: explicit GoogleTestParseResult() : TestParseResult(TestTreeModel::GoogleTest) {} + TestTreeItem *createTestTreeItem() const override; bool parameterized = false; bool typed = false; bool disabled = false; diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 7a3d327d2cb..09d1d377e5c 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -326,7 +326,7 @@ inline bool TestTreeItem::modifyName(const QString &name) return false; } -TestTreeItem *TestTreeItem::findChildBy(CompareFunction compare) +TestTreeItem *TestTreeItem::findChildBy(CompareFunction compare) const { for (int row = 0, count = childCount(); row < count; ++row) { TestTreeItem *child = childItem(row); @@ -499,6 +499,42 @@ QList AutoTestTreeItem::getSelectedTestConfigurations() con return result; } +TestTreeItem *AutoTestTreeItem::find(const TestParseResult *result) +{ + QTC_ASSERT(result, return 0); + + switch (type()) { + case Root: + return findChildByFile(result->fileName); + case TestCase: + return findChildByName(result->displayName); + case TestFunctionOrSet: + case TestDataFunction: + case TestSpecialFunction: + return findChildByName(result->name); + default: + return 0; + } +} + +bool AutoTestTreeItem::modify(const TestParseResult *result) +{ + QTC_ASSERT(result, return false); + + switch (type()) { + case TestCase: + return modifyTestCaseContent(result->name, result->line, result->column); + case TestFunctionOrSet: + case TestDataFunction: + case TestSpecialFunction: + return modifyTestFunctionContent(result); + case TestDataTag: + return modifyDataTagContent(result->name, result->fileName, result->line, result->line); + default: + return false; + } +} + QuickTestTreeItem *QuickTestTreeItem::createTestItem(const TestParseResult *result) { QuickTestTreeItem *item = new QuickTestTreeItem(result->name, result->fileName, @@ -740,6 +776,39 @@ QList QuickTestTreeItem::getSelectedTestConfigurations() co return result; } +TestTreeItem *QuickTestTreeItem::find(const TestParseResult *result) +{ + QTC_ASSERT(result, return 0); + + switch (type()) { + case Root: + return result->name.isEmpty() ? unnamedQuickTests() : findChildByFile(result->fileName); + case TestCase: + return name().isEmpty() ? findChildByNameAndFile(result->name, result->fileName) + : findChildByName(result->name); + default: + return 0; + } +} + +bool QuickTestTreeItem::modify(const TestParseResult *result) +{ + QTC_ASSERT(result, return false); + + switch (type()) { + case TestCase: + return result->name.isEmpty() ? false : modifyTestCaseContent(result->name, result->line, + result->column); + case TestFunctionOrSet: + case TestDataFunction: + case TestSpecialFunction: + return name().isEmpty() ? modifyLineAndColumn(result->line, result->column) + : modifyTestFunctionContent(result); + default: + return false; + } +} + bool QuickTestTreeItem::lessThan(const TestTreeItem *other, TestTreeItem::SortMode mode) const { // handle special item () @@ -972,6 +1041,39 @@ QList GoogleTestTreeItem::getSelectedTestConfigurations() c return result; } +TestTreeItem *GoogleTestTreeItem::find(const TestParseResult *result) +{ + QTC_ASSERT(result, return 0); + + const GoogleTestParseResult *parseResult = static_cast(result); + GoogleTestTreeItem::TestStates states = parseResult->disabled ? GoogleTestTreeItem::Disabled + : GoogleTestTreeItem::Enabled; + if (parseResult->parameterized) + states |= GoogleTestTreeItem::Parameterized; + if (parseResult->typed) + states |= GoogleTestTreeItem::Typed; + switch (type()) { + case Root: + return findChildByNameStateAndFile(parseResult->name, states, parseResult->proFile); + case TestCase: + return findChildByNameAndFile(result->name, result->fileName); + default: + return 0; + } +} + +bool GoogleTestTreeItem::modify(const TestParseResult *result) +{ + QTC_ASSERT(result, return false); + + switch (type()) { + case TestFunctionOrSet: + return modifyTestSetContent(static_cast(result)); + default: + return false; + } +} + bool GoogleTestTreeItem::modifyTestSetContent(const GoogleTestParseResult *result) { bool hasBeenModified = modifyLineAndColumn(result->line, result->column); @@ -986,7 +1088,7 @@ bool GoogleTestTreeItem::modifyTestSetContent(const GoogleTestParseResult *resul TestTreeItem *GoogleTestTreeItem::findChildByNameStateAndFile(const QString &name, GoogleTestTreeItem::TestStates state, - const QString &proFile) + const QString &proFile) const { return findChildBy([name, state, proFile](const TestTreeItem *other) -> bool { const GoogleTestTreeItem *gtestItem = static_cast(other); diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index 26e1846b15b..26f204b4d67 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -43,9 +43,6 @@ namespace { namespace Autotest { namespace Internal { -class AutoTestTreeItem; -class QuickTestTreeItem; -class GoogleTestTreeItem; class TestParseResult; class GoogleTestParseResult; class TestConfiguration; @@ -110,11 +107,13 @@ public: virtual QList getAllTestConfigurations() const; virtual QList getSelectedTestConfigurations() const; virtual bool lessThan(const TestTreeItem *other, SortMode mode) const; + virtual TestTreeItem *find(const TestParseResult *result) = 0; + virtual bool modify(const TestParseResult *result) = 0; protected: bool modifyFilePath(const QString &filePath); typedef std::function CompareFunction; - TestTreeItem *findChildBy(CompareFunction compare); + TestTreeItem *findChildBy(CompareFunction compare) const; private: void revalidateCheckState(); @@ -150,6 +149,8 @@ public: TestConfiguration *testConfiguration() const override; QList getAllTestConfigurations() const override; QList getSelectedTestConfigurations() const override; + TestTreeItem *find(const TestParseResult *result) override; + bool modify(const TestParseResult *result) override; }; class QuickTestTreeItem : public TestTreeItem @@ -166,6 +167,8 @@ public: TestConfiguration *testConfiguration() const override; QList getAllTestConfigurations() const override; QList getSelectedTestConfigurations() const override; + TestTreeItem *find(const TestParseResult *result) override; + bool modify(const TestParseResult *result) override; bool lessThan(const TestTreeItem *other, SortMode mode) const override; private: @@ -196,6 +199,8 @@ public: TestConfiguration *testConfiguration() const override; QList getAllTestConfigurations() const override; QList getSelectedTestConfigurations() const override; + TestTreeItem *find(const TestParseResult *result) override; + bool modify(const TestParseResult *result) override; void setStates(TestStates states) { m_state = states; } void setState(TestState state) { m_state |= state; } @@ -203,7 +208,7 @@ public: bool modifyTestSetContent(const GoogleTestParseResult *result); TestTreeItem *findChildByNameStateAndFile(const QString &name, GoogleTestTreeItem::TestStates state, - const QString &proFile); + const QString &proFile) const; QString nameSuffix() const; private: diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index b9194ae0b5d..9517e7339e2 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -311,150 +311,31 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item) void TestTreeModel::onParseResultReady(const TestParseResultPtr result) { - switch (result->type) { - case AutoTest: - handleQtParseResult(result); - break; - case QuickTest: - handleQuickParseResult(result); - break; - case GoogleTest: - handleGTestParseResult(result); - break; - case Invalid: - QTC_ASSERT(false, qWarning("TestParseResult of type Invalid unexpected.")); - break; - } + TestTreeItem *rootNode = rootItemForType(result->type); + QTC_ASSERT(rootNode, return); + handleParseResult(result.data(), rootNode); } -void TestTreeModel::handleQtParseResult(const TestParseResultPtr result) +void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeItem *parentNode) { - TestTreeItem *toBeModified = m_autoTestRootItem->findChildByFile(result->fileName); + // lookup existing items + if (TestTreeItem *toBeModified = parentNode->find(result)) { + // found existing item... Do not remove + toBeModified->markForRemoval(false); + // modify and when content has changed inform ui + if (toBeModified->modify(result)) { + const QModelIndex &idx = indexForItem(toBeModified); + emit dataChanged(idx, idx); + } + // recursively handle children of this item + foreach (const TestParseResult *child, result->children) + handleParseResult(child, toBeModified); + return; + } // if there's no matching item, add the new one - if (!toBeModified) { - m_autoTestRootItem->appendChild(AutoTestTreeItem::createTestItem(result.data())); - return; - } - // else we have to check level by level.. first the current level... - bool changed = toBeModified->modifyTestCaseContent(result->name, result->line, - result->column); - toBeModified->markForRemoval(false); - if (changed) - emit dataChanged(indexForItem(toBeModified), indexForItem(toBeModified)); - // ...now the functions - foreach (const TestParseResult *funcResult, result->children) { - TestTreeItem *functionItem = toBeModified->findChildByName(funcResult->displayName); - if (!functionItem) { - // if there's no function matching, add the new one - toBeModified->appendChild(AutoTestTreeItem::createTestItem(funcResult)); - continue; - } - // else we have to check level by level.. first the current level... - changed = functionItem->modifyTestFunctionContent(funcResult); - functionItem->markForRemoval(false); - if (changed) - emit dataChanged(indexForItem(functionItem), indexForItem(functionItem)); - // ...now the data tags - foreach (const TestParseResult *tag, funcResult->children) { - TestTreeItem *dataTagItem = functionItem->findChildByName(tag->name); - if (!dataTagItem) { - functionItem->appendChild(AutoTestTreeItem::createTestItem(tag)); - continue; - } - changed = dataTagItem->modifyDataTagContent(tag->name, tag->fileName, tag->line, - tag->column); - dataTagItem->markForRemoval(false); - if (changed) - emit dataChanged(indexForItem(dataTagItem), indexForItem(dataTagItem)); - } - } -} - -void TestTreeModel::handleQuickParseResult(const TestParseResultPtr result) -{ - if (result->name.isEmpty()) { - handleUnnamedQuickParseResult(result); - return; - } - - TestTreeItem *toBeModified = m_quickTestRootItem->findChildByFile(result->fileName); - // if there's no matching item, add the new one - if (!toBeModified) { - m_quickTestRootItem->appendChild(QuickTestTreeItem::createTestItem(result.data())); - return; - } - // else we have to check level by level.. first the current level... - bool changed = toBeModified->modifyTestCaseContent(result->name, result->line, - result->column); - toBeModified->markForRemoval(false); - if (changed) - emit dataChanged(indexForItem(toBeModified), indexForItem(toBeModified)); - // ...now the functions - foreach (const TestParseResult *funcResult, result->children) { - TestTreeItem *functionItem = toBeModified->findChildByName(funcResult->name); - if (!functionItem) { - // if there's no matching, add the new one - toBeModified->appendChild(QuickTestTreeItem::createTestItem(funcResult)); - continue; - } - // else we have to modify.. - changed = functionItem->modifyTestFunctionContent(funcResult); - functionItem->markForRemoval(false); - if (changed) - emit dataChanged(indexForItem(functionItem), indexForItem(functionItem)); - } -} - -void TestTreeModel::handleUnnamedQuickParseResult(const TestParseResultPtr result) -{ - TestTreeItem *toBeModified = unnamedQuickTests(); - if (!toBeModified) { - m_quickTestRootItem->appendChild(QuickTestTreeItem::createTestItem(result.data())); - return; - } - // if we have already Unnamed Quick tests we might update them.. - foreach (const TestParseResult *funcResult, result->children) { - TestTreeItem *functionItem = toBeModified->findChildByNameAndFile(funcResult->name, - funcResult->fileName); - if (!functionItem) { - toBeModified->appendChild(QuickTestTreeItem::createTestItem(funcResult)); - continue; - } - functionItem->modifyLineAndColumn(funcResult->line, funcResult->column); - functionItem->markForRemoval(false); - } -} - -void TestTreeModel::handleGTestParseResult(const TestParseResultPtr result) -{ - QTC_ASSERT(!result->children.isEmpty(), return); - const GoogleTestParseResult *parseResult = static_cast(result.data()); - - GoogleTestTreeItem::TestStates states = GoogleTestTreeItem::Enabled; - if (parseResult->parameterized) - states |= GoogleTestTreeItem::Parameterized; - if (parseResult->typed) - states |= GoogleTestTreeItem::Typed; - TestTreeItem *toBeModified = m_googleTestRootItem->findChildByNameStateAndFile( - parseResult->name, states, parseResult->proFile); - if (!toBeModified) { - m_googleTestRootItem->appendChild(GoogleTestTreeItem::createTestItem(parseResult)); - return; - } - // if found nothing has to be updated as all relevant members are used to find the item - foreach (const TestParseResult *setResult, parseResult->children) { - const GoogleTestParseResult *testSet = static_cast(setResult); - TestTreeItem *testSetItem = toBeModified->findChildByNameAndFile(testSet->name, - testSet->fileName); - if (!testSetItem) { - toBeModified->appendChild(GoogleTestTreeItem::createTestItem(testSet)); - continue; - } - bool changed = static_cast(testSetItem)->modifyTestSetContent(testSet); - testSetItem->markForRemoval(false); - if (changed) - emit dataChanged(indexForItem(testSetItem), indexForItem(testSetItem)); - } + TestTreeItem *newItem = result->createTestTreeItem(); + QTC_ASSERT(newItem, return); + parentNode->appendChild(newItem); } void TestTreeModel::removeAllTestItems() diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h index a87fd78f567..e07a06321e3 100644 --- a/src/plugins/autotest/testtreemodel.h +++ b/src/plugins/autotest/testtreemodel.h @@ -94,10 +94,7 @@ public slots: private: void onParseResultReady(const TestParseResultPtr result); - void handleQtParseResult(const TestParseResultPtr result); - void handleQuickParseResult(const TestParseResultPtr result); - void handleUnnamedQuickParseResult(const TestParseResultPtr result); - void handleGTestParseResult(const TestParseResultPtr result); + void handleParseResult(const TestParseResult *result, TestTreeItem *rootNode); void removeAllTestItems(); void removeFiles(const QStringList &files); bool sweepChildren(TestTreeItem *item);