QmlDesigner: Add isBaseOf to project storage

It return true if it is the same or a derived type. You can use multiple
base types.

Task-number: QDS-7424
Change-Id: I965a7c5b87ef0eb0183be1c705ebc18dee1943c3
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2022-08-15 15:21:23 +02:00
committed by Thomas Hartmann
parent 8a29c7da2f
commit 0982e668e7
3 changed files with 112 additions and 7 deletions

View File

@@ -469,6 +469,7 @@ private:
, column(column)
{}
explicit operator bool() const { return statement.fetchIntValue(column); }
operator int() const { return statement.fetchIntValue(column); }
operator long() const { return statement.fetchLongValue(column); }
operator long long() const { return statement.fetchLongLongValue(column); }

View File

@@ -245,11 +245,17 @@ public:
.template valuesWithTransaction<TypeId>(16, type);
}
PropertyDeclarationId fetchPropertyDeclarationByTypeIdAndName(TypeId typeId,
Utils::SmallStringView name)
template<typename... TypeIds>
bool isBasedOn(TypeId typeId, TypeIds... baseTypeIds) const
{
return selectPropertyDeclarationIdByTypeIdAndNameStatement
.template valueWithTransaction<PropertyDeclarationId>(typeId, name);
auto range = selectPrototypeAndSelfIdsStatement.template rangeWithTransaction<TypeId>(typeId);
for (TypeId currentTypeId : range) {
if (((currentTypeId == baseTypeIds) || ...))
return true;
}
return false;
}
TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const
@@ -2635,7 +2641,6 @@ public:
"ORDER BY minorVersion DESC "
"LIMIT 1",
database};
mutable ReadStatement<1, 2> selectPrototypeIdStatement{
"WITH RECURSIVE "
" all_prototype_and_extension(typeId, prototypeId) AS ("
@@ -3259,6 +3264,19 @@ public:
" typeChain AS tc USING(typeId)) "
"SELECT typeId FROM typeChain ORDER BY level",
database};
mutable ReadStatement<1, 1> selectPrototypeAndSelfIdsStatement{
"WITH RECURSIVE "
" all_prototype_and_extension(typeId, prototypeId) AS ("
" SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
" UNION ALL "
" SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
" typeSelection(typeId) AS ("
" VALUES(?1) "
" UNION ALL "
" SELECT prototypeId FROM all_prototype_and_extension JOIN typeSelection "
" USING(typeId))"
"SELECT typeId FROM typeSelection",
database};
};
extern template class ProjectStorage<Sqlite::Database>;
} // namespace QmlDesigner

View File

@@ -6771,8 +6771,7 @@ TEST_F(ProjectStorage, GetPrototypeIdsWithExtension)
auto prototypeIds = storage.prototypeIds(typeId);
ASSERT_THAT(prototypeIds,
ElementsAre(fetchTypeId(sourceId1, "QObject2"),
fetchTypeId(sourceId1, "QObject")));
ElementsAre(fetchTypeId(sourceId1, "QObject2"), fetchTypeId(sourceId1, "QObject")));
}
TEST_F(ProjectStorage, GetPrototypeAndSelfIds)
@@ -6815,4 +6814,91 @@ TEST_F(ProjectStorage, GetPrototypeAndSelfIdsWithExtension)
fetchTypeId(sourceId1, "QObject")));
}
TEST_F(ProjectStorage, IsBaseOfForDirectPrototype)
{
auto package{createPackageWithProperties()};
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject2");
auto baseTypeId = fetchTypeId(sourceId1, "QObject");
auto baseTypeId2 = fetchTypeId(sourceId1, "QObject3");
bool isBasedOn = storage.isBasedOn(typeId, baseTypeId, baseTypeId2, TypeId{});
ASSERT_TRUE(isBasedOn);
}
TEST_F(ProjectStorage, IsBaseOfForIndirectPrototype)
{
auto package{createPackageWithProperties()};
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject3");
auto baseTypeId = fetchTypeId(sourceId1, "QObject");
bool isBasedOn = storage.isBasedOn(typeId, baseTypeId);
ASSERT_TRUE(isBasedOn);
}
TEST_F(ProjectStorage, IsBaseOfForDirectExtension)
{
auto package{createPackageWithProperties()};
std::swap(package.types[1].extension, package.types[1].prototype);
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject2");
auto baseTypeId = fetchTypeId(sourceId1, "QObject");
bool isBasedOn = storage.isBasedOn(typeId, baseTypeId);
ASSERT_TRUE(isBasedOn);
}
TEST_F(ProjectStorage, IsBaseOfForIndirectExtension)
{
auto package{createPackageWithProperties()};
std::swap(package.types[1].extension, package.types[1].prototype);
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject3");
auto baseTypeId = fetchTypeId(sourceId1, "QObject");
bool isBasedOn = storage.isBasedOn(typeId, baseTypeId);
ASSERT_TRUE(isBasedOn);
}
TEST_F(ProjectStorage, IsBaseOfForSelf)
{
auto package{createPackageWithProperties()};
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject2");
auto baseTypeId = fetchTypeId(sourceId1, "QObject2");
bool isBasedOn = storage.isBasedOn(typeId, baseTypeId);
ASSERT_TRUE(isBasedOn);
}
TEST_F(ProjectStorage, IsNotBaseOf)
{
auto package{createPackageWithProperties()};
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject");
auto baseTypeId = fetchTypeId(sourceId1, "QObject2");
auto baseTypeId2 = fetchTypeId(sourceId1, "QObject3");
bool isBasedOn = storage.isBasedOn(typeId, baseTypeId, baseTypeId2, TypeId{});
ASSERT_FALSE(isBasedOn);
}
TEST_F(ProjectStorage, IsNotBaseOfIfNoBaseTypeIsGiven)
{
auto package{createPackageWithProperties()};
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QObject");
bool isBasedOn = storage.isBasedOn(typeId);
ASSERT_FALSE(isBasedOn);
}
} // namespace