Commit ef2f37f6 authored by Christian Stenger's avatar Christian Stenger

AutoTest: Decouple item and model once more

Change-Id: I301f17dd8be7feb9dc61f483277a4835aea937af
Reviewed-by: Christian Stenger's avatarChristian Stenger <christian.stenger@qt.io>
Reviewed-by: default avatarDavid Schulz <david.schulz@theqtcompany.com>
parent e2f5183a
......@@ -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
......@@ -49,6 +49,8 @@ public:
explicit TestParseResult(TestTreeModel::Type t = TestTreeModel::Invalid) : type(t) {}
virtual ~TestParseResult() { qDeleteAll(children); }
virtual TestTreeItem *createTestTreeItem() const = 0;
QVector<TestParseResult *> 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;
......
......@@ -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<TestConfiguration *> 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<TestConfiguration *> 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 (<unnamed>)
......@@ -972,6 +1041,39 @@ QList<TestConfiguration *> GoogleTestTreeItem::getSelectedTestConfigurations() c
return result;
}
TestTreeItem *GoogleTestTreeItem::find(const TestParseResult *result)
{
QTC_ASSERT(result, return 0);
const GoogleTestParseResult *parseResult = static_cast<const GoogleTestParseResult *>(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<const GoogleTestParseResult *>(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<const GoogleTestTreeItem *>(other);
......
......@@ -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<TestConfiguration *> getAllTestConfigurations() const;
virtual QList<TestConfiguration *> 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<bool(const TestTreeItem *)> CompareFunction;
TestTreeItem *findChildBy(CompareFunction compare);
TestTreeItem *findChildBy(CompareFunction compare) const;
private:
void revalidateCheckState();
......@@ -150,6 +149,8 @@ public:
TestConfiguration *testConfiguration() const override;
QList<TestConfiguration *> getAllTestConfigurations() const override;
QList<TestConfiguration *> 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<TestConfiguration *> getAllTestConfigurations() const override;
QList<TestConfiguration *> 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<TestConfiguration *> getAllTestConfigurations() const override;
QList<TestConfiguration *> 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:
......
......@@ -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);
// 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));
// 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);
}
}
}
void TestTreeModel::handleQuickParseResult(const TestParseResultPtr result)
{
if (result->name.isEmpty()) {
handleUnnamedQuickParseResult(result);
// recursively handle children of this item
foreach (const TestParseResult *child, result->children)
handleParseResult(child, toBeModified);
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<const GoogleTestParseResult *>(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<const GoogleTestParseResult *>(setResult);
TestTreeItem *testSetItem = toBeModified->findChildByNameAndFile(testSet->name,
testSet->fileName);
if (!testSetItem) {
toBeModified->appendChild(GoogleTestTreeItem::createTestItem(testSet));
continue;
}
bool changed = static_cast<GoogleTestTreeItem *>(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()
......
......@@ -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);
......
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