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{ Sqlite::WriteStatement<2> updateTypeTraitStatement{
"UPDATE types SET traits = ?2 WHERE typeId=?1", database}; "UPDATE types SET traits = ?2 WHERE typeId=?1", database};
Sqlite::WriteStatement<2> updateTypeAnnotationTraitStatement{ 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{ Sqlite::ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{
"SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN " "SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN "
"carray(?2))", "carray(?2))",
@@ -601,6 +613,11 @@ struct ProjectStorage::Statements
"UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database}; "UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
mutable Sqlite::ReadStatement<3, 1> selectInfoTypeByTypeIdStatement{ mutable Sqlite::ReadStatement<3, 1> selectInfoTypeByTypeIdStatement{
"SELECT sourceId, traits, annotationTraits FROM types WHERE typeId=?", database}; "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{ mutable Sqlite::ReadStatement<1, 1> selectDefaultPropertyDeclarationIdStatement{
"SELECT defaultPropertyId FROM types WHERE typeId=?", database}; "SELECT defaultPropertyId FROM types WHERE typeId=?", database};
mutable Sqlite::ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{ mutable Sqlite::ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
@@ -2316,7 +2333,6 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
if (!annotation.sourceId) if (!annotation.sourceId)
throw TypeAnnotationHasInvalidSourceId{}; throw TypeAnnotationHasInvalidSourceId{};
synchronizeTypeTraits(annotation.typeId, annotation.traits);
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"insert type annotations"_t, NanotraceHR::Tracer tracer{"insert type annotations"_t,
@@ -2330,11 +2346,12 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
annotation.iconPath, annotation.iconPath,
createEmptyAsNull(annotation.itemLibraryJson), createEmptyAsNull(annotation.itemLibraryJson),
createEmptyAsNull(annotation.hintsJson)); createEmptyAsNull(annotation.hintsJson));
synchronizeTypeTraits(annotation.typeId, annotation.traits);
}; };
auto update = [&](const TypeAnnotationView &annotationFromDatabase, auto update = [&](const TypeAnnotationView &annotationFromDatabase,
const TypeAnnotation &annotation) { const TypeAnnotation &annotation) {
synchronizeTypeTraits(annotation.typeId, annotation.traits);
if (annotationFromDatabase.typeName != annotation.typeName if (annotationFromDatabase.typeName != annotation.typeName
|| annotationFromDatabase.iconPath != annotation.iconPath || annotationFromDatabase.iconPath != annotation.iconPath
@@ -2352,21 +2369,29 @@ void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAn
annotation.iconPath, annotation.iconPath,
createEmptyAsNull(annotation.itemLibraryJson), createEmptyAsNull(annotation.itemLibraryJson),
createEmptyAsNull(annotation.hintsJson)); createEmptyAsNull(annotation.hintsJson));
synchronizeTypeTraits(annotation.typeId, annotation.traits);
return Sqlite::UpdateChange::Update; return Sqlite::UpdateChange::Update;
} }
synchronizeTypeTraits(annotation.typeId, annotation.traits);
return Sqlite::UpdateChange::No; return Sqlite::UpdateChange::No;
}; };
auto remove = [&](const TypeAnnotationView &annotationFromDatabase) { auto remove = [&](const TypeAnnotationView &annotationFromDatabase) {
synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{});
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"remove type annotations"_t, NanotraceHR::Tracer tracer{"remove type annotations"_t,
projectStorageCategory(), projectStorageCategory(),
keyValue("type annotation", annotationFromDatabase)}; keyValue("type annotation", annotationFromDatabase)};
auto prototypeAnnotationTraits = s->selectPrototypeAnnotationTraitsByTypeIdStatement
.value<long long>(annotationFromDatabase.typeId);
s->deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId); s->deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId);
s->updateTypeAnnotationTraitStatement.write(annotationFromDatabase.typeId,
prototypeAnnotationTraits);
}; };
Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove); 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.typeAnnotations = createTypeAnnotions();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds( package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations); package.typeAnnotations);
TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True;
traits.visibleInLibrary = FlagIs::True;
storage.synchronize(package); storage.synchronize(package);
@@ -7382,13 +7379,29 @@ TEST_F(ProjectStorage, synchronize_type_annotation_type_traits)
ASSERT_THAT(storage.type(fetchTypeId(sourceId2, "QObject"))->traits, 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) TEST_F(ProjectStorage, synchronize_updates_type_annotation_type_traits)
{ {
auto package{createSimpleSynchronizationPackage()}; auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package); storage.synchronize(package);
SynchronizationPackage annotationPackage; SynchronizationPackage annotationPackage;
annotationPackage.typeAnnotations = createTypeAnnotions(); annotationPackage.typeAnnotations = createTypeAnnotions();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds( annotationPackage.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations); package.typeAnnotations);
TypeTraits traits{TypeTraitsKind::Reference}; TypeTraits traits{TypeTraitsKind::Reference};
traits.canBeContainer = FlagIs::True; 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); 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)
{
}
TEST_F(ProjectStorage,
synchronize_clears_annotation_type_traits_if_annotation_was_removed_for_prototype_heirs)
{ {
auto package{createSimpleSynchronizationPackage()}; auto package{createSimpleSynchronizationPackage()};
package.typeAnnotations = createTypeAnnotions(); package.typeAnnotations = createTypeAnnotions();
package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds( package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
package.typeAnnotations); package.typeAnnotations);
storage.synchronize(package);
package.typeAnnotations[0].traits.isStackedContainer = FlagIs::True; package.typeAnnotations[0].traits.isStackedContainer = FlagIs::True;
TypeTraits traits{TypeTraitsKind::Reference}; storage.synchronize(package);
traits.canBeContainer = FlagIs::True; package.typeAnnotations.pop_back();
traits.visibleInLibrary = FlagIs::True;
traits.isStackedContainer = FlagIs::True;
storage.synchronize(package); 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()}; auto package{createSimpleSynchronizationPackage()};
package.typeAnnotations = createTypeAnnotions(); package.typeAnnotations = createTypeAnnotions();