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) , column(column)
{} {}
explicit operator bool() const { return statement.fetchIntValue(column); }
operator int() const { return statement.fetchIntValue(column); } operator int() const { return statement.fetchIntValue(column); }
operator long() const { return statement.fetchLongValue(column); } operator long() const { return statement.fetchLongValue(column); }
operator long long() const { return statement.fetchLongLongValue(column); } operator long long() const { return statement.fetchLongLongValue(column); }

View File

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

View File

@@ -6771,8 +6771,7 @@ TEST_F(ProjectStorage, GetPrototypeIdsWithExtension)
auto prototypeIds = storage.prototypeIds(typeId); auto prototypeIds = storage.prototypeIds(typeId);
ASSERT_THAT(prototypeIds, ASSERT_THAT(prototypeIds,
ElementsAre(fetchTypeId(sourceId1, "QObject2"), ElementsAre(fetchTypeId(sourceId1, "QObject2"), fetchTypeId(sourceId1, "QObject")));
fetchTypeId(sourceId1, "QObject")));
} }
TEST_F(ProjectStorage, GetPrototypeAndSelfIds) TEST_F(ProjectStorage, GetPrototypeAndSelfIds)
@@ -6815,4 +6814,91 @@ TEST_F(ProjectStorage, GetPrototypeAndSelfIdsWithExtension)
fetchTypeId(sourceId1, "QObject"))); 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 } // namespace