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); constexpr TypeId unresolvedTypeId = TypeId::createSpecialState(SpecialIdState::Unresolved);
namespace {
class UnresolvedTypeId : public TypeId class UnresolvedTypeId : public TypeId
{ {
public: 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 struct ProjectStorage::Statements
{ {
Statements(Sqlite::Database &database) Statements(Sqlite::Database &database)
@@ -874,6 +894,14 @@ struct ProjectStorage::Statements
" propertyImportedTypeNameId IS NULL " " propertyImportedTypeNameId IS NULL "
"LIMIT 1", "LIMIT 1",
database}; 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 class ProjectStorage::Initializer
@@ -909,7 +937,7 @@ public:
typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}}); typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer); auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text); 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", auto &prototypeIdColumn = typesTable.addColumn("prototypeId",
Sqlite::StrictColumnType::Integer); Sqlite::StrictColumnType::Integer);
auto &prototypeNameIdColumn = typesTable.addColumn("prototypeNameId", auto &prototypeNameIdColumn = typesTable.addColumn("prototypeNameId",
@@ -927,6 +955,9 @@ public:
typesTable.addIndex({extensionIdColumn, sourceIdColumn}); typesTable.addIndex({extensionIdColumn, sourceIdColumn});
typesTable.addIndex({prototypeNameIdColumn}); typesTable.addIndex({prototypeNameIdColumn});
typesTable.addIndex({extensionNameIdColumn}); typesTable.addIndex({extensionNameIdColumn});
Utils::SmallString traitsExpression = "traits & ";
traitsExpression.append(Utils::SmallString::number(createSingletonTypeTraitMask()));
typesTable.addIndex({traitsColumn}, traitsExpression);
typesTable.initialize(database); typesTable.initialize(database);
@@ -1453,8 +1484,23 @@ QVarLengthArray<TypeId, 256> ProjectStorage::typeIds(ModuleId moduleId) const
projectStorageCategory(), projectStorageCategory(),
keyValue("module id", moduleId)}; keyValue("module id", moduleId)};
auto typeIds = s->selectTypeIdsByModuleIdStatement auto typeIds = s->selectTypeIdsByModuleIdStatement.valuesWithTransaction<SmallTypeIds<256>>(
.valuesWithTransaction<QVarLengthArray<TypeId, 256>>(moduleId); 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)); tracer.end(keyValue("type ids", typeIds));

View File

@@ -70,7 +70,9 @@ public:
TypeId typeId(ImportedTypeNameId typeNameId) const override; 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; Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override;

View File

@@ -40,7 +40,8 @@ public:
Storage::Version version) const Storage::Version version) const
= 0; = 0;
virtual TypeId typeId(ImportedTypeNameId typeNameId) 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) const = 0;
virtual Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId, virtual Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
SourceId sourceId) const SourceId sourceId) const

View File

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

View File

@@ -8835,4 +8835,52 @@ TEST_F(ProjectStorage, changed_export_is_notifing_changed_exported_types)
storage.synchronize(std::move(package)); 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 } // namespace