diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h index ad664348166..091ab2b5c06 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h @@ -151,18 +151,24 @@ public: .template valueWithTransaction(&moduleId, exportedTypeName); } - PropertyDeclarationIds propertyIds(TypeId typeId) const + PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const { return selectPropertyDeclarationIdsForTypeStatement .template valuesWithTransaction(32, &typeId); } - PropertyDeclarationIds localPropertyIds(TypeId typeId) const + PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const { return selectLocalPropertyDeclarationIdsForTypeStatement .template valuesWithTransaction(16, &typeId); } + PropertyDeclarationId propertyDeclarationId(TypeId typeId, Utils::SmallStringView propertyName) const + { + return selectPropertyDeclarationIdForTypeAndPropertyNameStatement + .template valueWithTransaction(&typeId, propertyName); + } + Utils::optional propertyName(PropertyDeclarationId propertyDeclarationId) const { return selectPropertyNameStatement.template optionalValueWithTransaction( @@ -2898,6 +2904,16 @@ public: "WHERE typeId=? " "ORDER BY propertyDeclarationId", database}; + mutable ReadStatement<1, 2> selectPropertyDeclarationIdForTypeAndPropertyNameStatement{ + "WITH RECURSIVE " + " typeChain(typeId, level) AS (" + " VALUES(?1, 0)" + " UNION ALL " + " SELECT prototypeId, typeChain.level + 1 FROM types JOIN typeChain " + " USING(typeId) WHERE prototypeId IS NOT NULL)" + "SELECT propertyDeclarationId FROM typeChain JOIN propertyDeclarations " + " USING(typeId) WHERE name=?2 ORDER BY level LIMIT 1", + database}; }; extern template class ProjectStorage; } // namespace QmlDesigner diff --git a/tests/unit/unittest/projectstorage-test.cpp b/tests/unit/unittest/projectstorage-test.cpp index 3956a3e105f..44ff161e70f 100644 --- a/tests/unit/unittest/projectstorage-test.cpp +++ b/tests/unit/unittest/projectstorage-test.cpp @@ -5555,13 +5555,13 @@ TEST_F(ProjectStorage, GetNoTypeIdWithCompleteVersionForWrongMajorVersion) ASSERT_FALSE(typeId); } -TEST_F(ProjectStorage, GetProperties) +TEST_F(ProjectStorage, GetPropertyDeclarationIds) { auto package{createPackageWithProperties()}; storage.synchronize(package); - auto itemTypeId = fetchTypeId(sourceId1, "QObject3"); + auto typeId = fetchTypeId(sourceId1, "QObject3"); - auto propertyIds = storage.propertyIds(itemTypeId); + auto propertyIds = storage.propertyDeclarationIds(typeId); ASSERT_THAT(propertyIds, UnorderedElementsAre(HasName("data"), @@ -5572,24 +5572,24 @@ TEST_F(ProjectStorage, GetProperties) HasName("children3"))); } -TEST_F(ProjectStorage, GetPropertiesAreReturnedSorted) +TEST_F(ProjectStorage, GetPropertyDeclarationIdsAreReturnedSorted) { auto package{createPackageWithProperties()}; storage.synchronize(package); - auto itemTypeId = fetchTypeId(sourceId1, "QObject3"); + auto typeId = fetchTypeId(sourceId1, "QObject3"); - auto propertyIds = storage.propertyIds(itemTypeId); + auto propertyIds = storage.propertyDeclarationIds(typeId); ASSERT_THAT(propertyIds, IsSorted()); } -TEST_F(ProjectStorage, GetNoPropertiesPropertiesFromDerivedTypes) +TEST_F(ProjectStorage, GetNoPropertyDeclarationIdsPropertiesFromDerivedTypes) { auto package{createPackageWithProperties()}; storage.synchronize(package); - auto itemTypeId = fetchTypeId(sourceId1, "QObject2"); + auto typeId = fetchTypeId(sourceId1, "QObject2"); - auto propertyIds = storage.propertyIds(itemTypeId); + auto propertyIds = storage.propertyDeclarationIds(typeId); ASSERT_THAT(propertyIds, UnorderedElementsAre(HasName("data"), @@ -5598,37 +5598,91 @@ TEST_F(ProjectStorage, GetNoPropertiesPropertiesFromDerivedTypes) HasName("children2"))); } -TEST_F(ProjectStorage, GetNoPropertiesForWrongTypeId) +TEST_F(ProjectStorage, GetNoPropertyDeclarationIdsForWrongTypeId) { auto package{createPackageWithProperties()}; storage.synchronize(package); - auto itemTypeId = fetchTypeId(sourceId1, "WrongObject"); + auto typeId = fetchTypeId(sourceId1, "WrongObject"); - auto propertyIds = storage.propertyIds(itemTypeId); + auto propertyIds = storage.propertyDeclarationIds(typeId); ASSERT_THAT(propertyIds, IsEmpty()); } -TEST_F(ProjectStorage, GetLocalProperties) +TEST_F(ProjectStorage, GetLocalPropertyDeclarationIds) { auto package{createPackageWithProperties()}; storage.synchronize(package); - auto itemTypeId = fetchTypeId(sourceId1, "QObject2"); + auto typeId = fetchTypeId(sourceId1, "QObject2"); - auto propertyIds = storage.localPropertyIds(itemTypeId); + auto propertyIds = storage.localPropertyDeclarationIds(typeId); ASSERT_THAT(propertyIds, UnorderedElementsAre(HasName("data2"), HasName("children2"))); } -TEST_F(ProjectStorage, GetLocalPropertiesAreReturnedSorted) +TEST_F(ProjectStorage, GetLocalPropertyDeclarationIdsAreReturnedSorted) { auto package{createPackageWithProperties()}; storage.synchronize(package); - auto itemTypeId = fetchTypeId(sourceId1, "QObject2"); + auto typeId = fetchTypeId(sourceId1, "QObject2"); - auto propertyIds = storage.localPropertyIds(itemTypeId); + auto propertyIds = storage.localPropertyDeclarationIds(typeId); ASSERT_THAT(propertyIds, IsSorted()); } +TEST_F(ProjectStorage, GetPropertyDeclarationId) +{ + auto package{createPackageWithProperties()}; + storage.synchronize(package); + auto typeId = fetchTypeId(sourceId1, "QObject3"); + + auto propertyId = storage.propertyDeclarationId(typeId, "data"); + + ASSERT_THAT(propertyId, HasName("data")); +} + +TEST_F(ProjectStorage, GetLatestPropertyDeclarationId) +{ + auto package{createPackageWithProperties()}; + storage.synchronize(package); + auto typeId = fetchTypeId(sourceId1, "QObject3"); + auto oldPropertyId = storage.propertyDeclarationId(typeId, "data"); + auto found = std::find_if(package.types.begin(), package.types.end(), [](const auto &type) { + return type.typeName == "QObject3"; + }); + found->propertyDeclarations.push_back(Storage::Synchronization::PropertyDeclaration{ + "data", + Storage::Synchronization::ImportedType{"Object"}, + Storage::Synchronization::PropertyDeclarationTraits::IsList}); + storage.synchronize(package); + + auto propertyId = storage.propertyDeclarationId(typeId, "data"); + + ASSERT_THAT(propertyId, AllOf(Not(oldPropertyId), HasName("data"))); + ASSERT_THAT(oldPropertyId, HasName("data")); +} + +TEST_F(ProjectStorage, GetInvalidPropertyDeclarationIdForInvalidTypeId) +{ + auto package{createPackageWithProperties()}; + storage.synchronize(package); + auto typeId = fetchTypeId(sourceId1, "WrongObject"); + + auto propertyId = storage.propertyDeclarationId(typeId, "data"); + + ASSERT_FALSE(propertyId); +} + +TEST_F(ProjectStorage, GetInvalidPropertyDeclarationIdForWrongPropertyName) +{ + auto package{createPackageWithProperties()}; + storage.synchronize(package); + auto typeId = fetchTypeId(sourceId1, "Object3"); + + auto propertyId = storage.propertyDeclarationId(typeId, "wrongName"); + + ASSERT_FALSE(propertyId); +} + } // namespace