QmlDesigner: Propagate annotation type traits recursivly

Task-number: QDS-12661
Change-Id: I593eeaaa3800c450a0c2b9f08ae1993ddc29cd8f
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2024-05-02 11:32:37 +02:00
parent d877e1bb1f
commit 522805629a
2 changed files with 76 additions and 16 deletions

View File

@@ -90,7 +90,19 @@ struct ProjectStorage::Statements
Sqlite::WriteStatement<2> updateTypeTraitStatement{
"UPDATE types SET traits = ?2 WHERE typeId=?1", database};
Sqlite::WriteStatement<2> updateTypeAnnotationTraitStatement{
"UPDATE types SET annotationTraits = ?2 WHERE typeId=?1", database};
"WITH RECURSIVE "
" typeSelection(typeId) AS ("
" VALUES(?1) "
" UNION ALL "
" SELECT t.typeId "
" FROM types AS t JOIN typeSelection AS ts "
" WHERE prototypeId=ts.typeId "
" AND t.typeId NOT IN (SELECT typeId FROM typeAnnotations)) "
"UPDATE types AS t "
"SET annotationTraits = ?2 "
"FROM typeSelection ts "
"WHERE t.typeId=ts.typeId",
database};
Sqlite::ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{
"SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN "
"carray(?2))",
@@ -601,6 +613,11 @@ struct ProjectStorage::Statements
"UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
mutable Sqlite::ReadStatement<3, 1> selectInfoTypeByTypeIdStatement{
"SELECT sourceId, traits, annotationTraits FROM types WHERE typeId=?", database};
mutable Sqlite::ReadStatement<1, 1> selectPrototypeAnnotationTraitsByTypeIdStatement{
"SELECT annotationTraits "
"FROM types "
"WHERE typeId=(SELECT prototypeId FROM types WHERE typeId=?)",
database};
mutable Sqlite::ReadStatement<1, 1> selectDefaultPropertyDeclarationIdStatement{
"SELECT defaultPropertyId FROM types WHERE typeId=?", database};
mutable Sqlite::ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
@@ -2316,7 +2333,6 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
if (!annotation.sourceId)
throw TypeAnnotationHasInvalidSourceId{};
synchronizeTypeTraits(annotation.typeId, annotation.traits);
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"insert type annotations"_t,
@@ -2330,11 +2346,12 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
annotation.iconPath,
createEmptyAsNull(annotation.itemLibraryJson),
createEmptyAsNull(annotation.hintsJson));
synchronizeTypeTraits(annotation.typeId, annotation.traits);
};
auto update = [&](const TypeAnnotationView &annotationFromDatabase,
const TypeAnnotation &annotation) {
synchronizeTypeTraits(annotation.typeId, annotation.traits);
if (annotationFromDatabase.typeName != annotation.typeName
|| annotationFromDatabase.iconPath != annotation.iconPath
@@ -2352,21 +2369,29 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
annotation.iconPath,
createEmptyAsNull(annotation.itemLibraryJson),
createEmptyAsNull(annotation.hintsJson));
synchronizeTypeTraits(annotation.typeId, annotation.traits);
return Sqlite::UpdateChange::Update;
}
synchronizeTypeTraits(annotation.typeId, annotation.traits);
return Sqlite::UpdateChange::No;
};
auto remove = [&](const TypeAnnotationView &annotationFromDatabase) {
synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{});
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"remove type annotations"_t,
projectStorageCategory(),
keyValue("type annotation", annotationFromDatabase)};
auto prototypeAnnotationTraits = s->selectPrototypeAnnotationTraitsByTypeIdStatement
.value<long long>(annotationFromDatabase.typeId);
s->deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId);
s->updateTypeAnnotationTraitStatement.write(annotationFromDatabase.typeId,
prototypeAnnotationTraits);
};
Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove);

View File

@@ -7358,9 +7358,6 @@ TEST_F(ProjectStorage, do_not_synchronize_type_annotations_without_type)
package.typeAnnotations = createTypeAnnotions();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations);
TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True;
traits.visibleInLibrary = FlagIs::True;
storage.synchronize(package);
@@ -7382,13 +7379,29 @@ TEST_F(ProjectStorage, synchronize_type_annotation_type_traits)
ASSERT_THAT(storage.type(fetchTypeId(sourceId2, "QObject"))->traits, traits);
}
TEST_F(ProjectStorage, synchronize_type_annotation_type_traits_for_prototype_heirs)
{
auto package{createSimpleSynchronizationPackage()};
package.typeAnnotations = createTypeAnnotions();
package.typeAnnotations.pop_back();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations);
TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True;
traits.visibleInLibrary = FlagIs::True;
storage.synchronize(package);
ASSERT_THAT(storage.type(fetchTypeId(sourceId1, "QQuickItem"))->traits, traits);
}
TEST_F(ProjectStorage, synchronize_updates_type_annotation_type_traits)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
SynchronizationPackage annotationPackage;
annotationPackage.typeAnnotations = createTypeAnnotions();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
annotationPackage.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations);
TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True;
@@ -7399,25 +7412,47 @@ TEST_F(ProjectStorage, synchronize_updates_type_annotation_type_traits)
ASSERT_THAT(storage.type(fetchTypeId(sourceId2, "QObject"))->traits, traits);
}
TEST_F(ProjectStorage, synchronize_updates_type_annotation_type_traits_for_prototype_heirs)
{
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
SynchronizationPackage annotationPackage;
annotationPackage.typeAnnotations = createTypeAnnotions();
annotationPackage.typeAnnotations.pop_back();
annotationPackage.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations);
TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True;
traits.visibleInLibrary = FlagIs::True;
storage.synchronize(annotationPackage);
ASSERT_THAT(storage.type(fetchTypeId(sourceId1, "QQuickItem"))->traits, traits);
}
TEST_F(ProjectStorage, synchronize_clears_annotation_type_traits_if_annotation_was_removed)
{
}
TEST_F(ProjectStorage,
synchronize_clears_annotation_type_traits_if_annotation_was_removed_for_prototype_heirs)
{
auto package{createSimpleSynchronizationPackage()};
package.typeAnnotations = createTypeAnnotions();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations);
storage.synchronize(package);
package.typeAnnotations[0].traits.isStackedContainer = FlagIs::True;
TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True;
traits.visibleInLibrary = FlagIs::True;
traits.isStackedContainer = FlagIs::True;
storage.synchronize(package);
package.typeAnnotations.pop_back();
storage.synchronize(package);
ASSERT_THAT(storage.type(fetchTypeId(sourceId2, "QObject"))->traits, traits);
ASSERT_THAT(storage.type(fetchTypeId(sourceId1, "QQuickItem"))->traits,
package.typeAnnotations[0].traits);
}
TEST_F(ProjectStorage, synchronize_updatesannotation_type_traits)
TEST_F(ProjectStorage, synchronize_updates_annotation_type_traits)
{
auto package{createSimpleSynchronizationPackage()};
package.typeAnnotations = createTypeAnnotions();