forked from qt-creator/qt-creator
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:
@@ -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);
|
||||||
|
@@ -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();
|
||||||
|
Reference in New Issue
Block a user