QmlDesigner: Add singletons to project storage

Task-number: QDS-13601
Change-Id: I6a39c5a4ddc267f6fabebcaa411ae61635e4e311
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2024-09-10 15:56:36 +02:00
parent e91fe4dea7
commit fae113f5f8
5 changed files with 107 additions and 6 deletions

View File

@@ -18,6 +18,7 @@ enum class SpecialIdState { Unresolved = -1 };
constexpr TypeId unresolvedTypeId = TypeId::createSpecialState(SpecialIdState::Unresolved);
namespace {
class UnresolvedTypeId : public TypeId
{
public:
@@ -33,6 +34,25 @@ public:
}
};
auto createSingletonTypeTraitMask()
{
Storage::TypeTraits traits;
traits.type = 0;
traits.isSingleton = true;
return traits.type;
}
auto createSingletonTraitsExpression()
{
Utils::SmallString traitsExpression = "traits & ";
traitsExpression.append(Utils::SmallString::number(createSingletonTypeTraitMask()));
return traitsExpression;
}
} // namespace
struct ProjectStorage::Statements
{
Statements(Sqlite::Database &database)
@@ -874,6 +894,14 @@ struct ProjectStorage::Statements
" propertyImportedTypeNameId IS NULL "
"LIMIT 1",
database};
mutable Sqlite::ReadStatement<1, 1> selectSingletonTypeIdsBySourceIdStatement{
"SELECT DISTINCT typeId "
"FROM types "
" JOIN exportedTypeNames USING (typeId) "
" JOIN documentImports AS di USING(moduleId) "
"WHERE di.sourceId=?1 AND "
+ createSingletonTraitsExpression(),
database};
};
class ProjectStorage::Initializer
@@ -909,7 +937,7 @@ public:
typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text);
typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer);
auto &traitsColumn = typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer);
auto &prototypeIdColumn = typesTable.addColumn("prototypeId",
Sqlite::StrictColumnType::Integer);
auto &prototypeNameIdColumn = typesTable.addColumn("prototypeNameId",
@@ -927,6 +955,9 @@ public:
typesTable.addIndex({extensionIdColumn, sourceIdColumn});
typesTable.addIndex({prototypeNameIdColumn});
typesTable.addIndex({extensionNameIdColumn});
Utils::SmallString traitsExpression = "traits & ";
traitsExpression.append(Utils::SmallString::number(createSingletonTypeTraitMask()));
typesTable.addIndex({traitsColumn}, traitsExpression);
typesTable.initialize(database);
@@ -1453,8 +1484,23 @@ QVarLengthArray<TypeId, 256> ProjectStorage::typeIds(ModuleId moduleId) const
projectStorageCategory(),
keyValue("module id", moduleId)};
auto typeIds = s->selectTypeIdsByModuleIdStatement
.valuesWithTransaction<QVarLengthArray<TypeId, 256>>(moduleId);
auto typeIds = s->selectTypeIdsByModuleIdStatement.valuesWithTransaction<SmallTypeIds<256>>(
moduleId);
tracer.end(keyValue("type ids", typeIds));
return typeIds;
}
SmallTypeIds<256> ProjectStorage::singletonTypeIds(SourceId sourceId) const
{
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"get singleton type ids by source id",
projectStorageCategory(),
keyValue("source id", sourceId)};
auto typeIds = s->selectSingletonTypeIdsBySourceIdStatement.valuesWithTransaction<SmallTypeIds<256>>(
sourceId);
tracer.end(keyValue("type ids", typeIds));

View File

@@ -70,7 +70,9 @@ public:
TypeId typeId(ImportedTypeNameId typeNameId) const override;
QVarLengthArray<TypeId, 256> typeIds(ModuleId moduleId) const override;
SmallTypeIds<256> typeIds(ModuleId moduleId) const override;
SmallTypeIds<256> singletonTypeIds(SourceId sourceId) const override;
Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override;

View File

@@ -40,7 +40,8 @@ public:
Storage::Version version) const
= 0;
virtual TypeId typeId(ImportedTypeNameId typeNameId) const = 0;
virtual QVarLengthArray<TypeId, 256> typeIds(ModuleId moduleId) const = 0;
virtual SmallTypeIds<256> typeIds(ModuleId moduleId) const = 0;
virtual SmallTypeIds<256> singletonTypeIds(SourceId sourceId) const = 0;
virtual Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const = 0;
virtual Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
SourceId sourceId) const

View File

@@ -153,10 +153,14 @@ public:
::Utils::SmallStringView exportedTypeName,
QmlDesigner::Storage::Version version),
(const, override));
MOCK_METHOD((QVarLengthArray<QmlDesigner::TypeId, 256>),
MOCK_METHOD((QmlDesigner::SmallTypeIds<256>),
typeIds,
(QmlDesigner::ModuleId moduleId),
(const, override));
MOCK_METHOD((QmlDesigner::SmallTypeIds<256>),
singletonTypeIds,
(QmlDesigner::SourceId sourceId),
(const, override));
MOCK_METHOD(QmlDesigner::Storage::Info::ExportedTypeNames,
exportedTypeNames,
(QmlDesigner::TypeId),

View File

@@ -8835,4 +8835,52 @@ TEST_F(ProjectStorage, changed_export_is_notifing_changed_exported_types)
storage.synchronize(std::move(package));
}
TEST_F(ProjectStorage, get_unqiue_singleton_type_ids)
{
auto package{createSimpleSynchronizationPackage()};
package.types.back().traits.isSingleton = true;
Storage::Imports imports;
imports.emplace_back(qmlModuleId, Storage::Version{}, sourceId5);
imports.emplace_back(qtQuickModuleId, Storage::Version{}, sourceId5);
storage.synchronizeDocumentImports(imports, sourceId5);
storage.synchronize(package);
auto singletonTypeIds = storage.singletonTypeIds(sourceId5);
ASSERT_THAT(singletonTypeIds, ElementsAre(fetchTypeId(sourceId2, "QObject")));
}
TEST_F(ProjectStorage, get_only_singleton_type_ids_for_document_imports)
{
auto package{createSimpleSynchronizationPackage()};
package.types.back().traits.isSingleton = true;
package.types.front().traits.isSingleton = true;
Storage::Imports imports;
imports.emplace_back(qtQuickModuleId, Storage::Version{}, sourceId5);
storage.synchronizeDocumentImports(imports, sourceId5);
storage.synchronize(package);
auto singletonTypeIds = storage.singletonTypeIds(sourceId5);
ASSERT_THAT(singletonTypeIds, ElementsAre(fetchTypeId(sourceId1, "QQuickItem")));
}
TEST_F(ProjectStorage, get_only_singleton_type_ids_exported_types)
{
auto package{createSimpleSynchronizationPackage()};
package.types.back().traits.isSingleton = true;
package.types.back().exportedTypes.clear();
package.types.front().traits.isSingleton = true;
Storage::Imports imports;
imports.emplace_back(qmlModuleId, Storage::Version{}, sourceId5);
imports.emplace_back(qtQuickModuleId, Storage::Version{}, sourceId5);
storage.synchronizeDocumentImports(imports, sourceId5);
storage.synchronize(package);
auto singletonTypeIds = storage.singletonTypeIds(sourceId5);
ASSERT_THAT(singletonTypeIds, ElementsAre(fetchTypeId(sourceId1, "QQuickItem")));
}
} // namespace