From 728be609864ee0870bb331663587af3de5dfee7b Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 24 Aug 2021 16:49:42 +0200 Subject: [PATCH] QmlDesigner: Change import export architecture The new architecture should be a better abstractions for qml. ImportedTypeNames are introduced. ModuleDependencies are now taken over by document imports. Modules lost their version and ExportedTypeNames gained it. Task-number: QDS-4938 Task-number: QDS-4933 Task-number: QDS-5009 Task-number: QDS-5032 Change-Id: Ia86921c5be9107fe7d5bfd28f12bf8453769dc10 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- .../designercore/include/projectstorageids.h | 24 +- .../projectstorage/projectstorage.h | 1027 +++--- .../projectstorage/projectstorageinterface.h | 4 +- .../projectstorage/projectstoragetypes.h | 261 +- .../projectstorage/projectstorageupdater.cpp | 29 +- .../projectstorage/projectstorageupdater.h | 8 +- .../projectstorage/qmltypesparserinterface.h | 2 +- .../unit/unittest/gtest-creator-printing.cpp | 46 +- tests/unit/unittest/gtest-creator-printing.h | 12 +- tests/unit/unittest/projectstorage-test.cpp | 2777 +++++++++++------ tests/unit/unittest/projectstoragemock.h | 4 +- .../unittest/projectstorageupdater-test.cpp | 17 +- tests/unit/unittest/qmltypesparsermock.h | 2 +- 13 files changed, 2576 insertions(+), 1637 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/projectstorageids.h b/src/plugins/qmldesigner/designercore/include/projectstorageids.h index d3701c6a6b4..5bb03b90109 100644 --- a/src/plugins/qmldesigner/designercore/include/projectstorageids.h +++ b/src/plugins/qmldesigner/designercore/include/projectstorageids.h @@ -77,15 +77,16 @@ enum class BasicIdType { Type, PropertyType, PropertyDeclaration, - SourceId, - SourceContextId, + Source, + SourceContext, StorageCacheIndex, FunctionDeclaration, SignalDeclaration, EnumerationDeclaration, Module, - TypeName, - ProjectPartId + ProjectPartId, + Import, + ImportedTypeName }; using TypeId = BasicId; @@ -103,19 +104,22 @@ using SignalDeclarationIds = std::vector; using EnumerationDeclarationId = BasicId; using EnumerationDeclarationIds = std::vector; -using SourceContextId = BasicId; +using SourceContextId = BasicId; using SourceContextIds = std::vector; -using SourceId = BasicId; +using SourceId = BasicId; using SourceIds = std::vector; -using ModuleId = BasicId; +using ModuleId = BasicId; using ModuleIds = std::vector; -using TypeNameId = BasicId; -using TypeNameIds = std::vector; - using ProjectPartId = BasicId; using ProjectPartIds = std::vector; +using ImportId = BasicId; +using ImportIds = std::vector; + +using ImportedTypeNameId = BasicId; +using ImportedTypeNameIds = std::vector; + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h index cdf02674658..a3b46b301c2 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h @@ -55,8 +55,8 @@ public: , initializer{database, isInitialized} {} - void synchronize(Storage::ModuleDependencies moduleDependencies, - Storage::Documents documents, + void synchronize(Storage::Modules modules, + Storage::Imports imports, Storage::Types types, SourceIds sourceIds, FileStatuses fileStatuses) override @@ -69,27 +69,40 @@ public: TypeIds updatedTypeIds; updatedTypeIds.reserve(types.size()); - TypeIds deletedTypeIds; + TypeIds typeIdsToBeDeleted; auto sourceIdValues = Utils::transform(sourceIds, [](SourceId sourceId) { return &sourceId; }); + std::sort(sourceIdValues.begin(), sourceIdValues.end()); + synchronizeFileStatuses(fileStatuses, sourceIdValues); - synchronizeModules(moduleDependencies, deletedTypeIds, sourceIdValues); - synchronizeDocuments(documents, sourceIdValues); + synchronizeModules(modules, typeIdsToBeDeleted, sourceIdValues); + synchronizeImports(imports, sourceIdValues); synchronizeTypes(types, updatedTypeIds, insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations); - deleteNotUpdatedTypes(updatedTypeIds, sourceIdValues, deletedTypeIds); + deleteNotUpdatedTypes(updatedTypeIds, sourceIdValues, typeIdsToBeDeleted); linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations); transaction.commit(); } + ModuleId fetchModuleId(Utils::SmallStringView moduleName) + { + Sqlite::DeferredTransaction transaction{database}; + + ModuleId moduleId = fetchModuleIdUnguarded(moduleName); + + transaction.commit(); + + return moduleId; + } + ModuleIds fetchModuleIds(const Storage::Modules &modules) { Sqlite::DeferredTransaction transaction{database}; @@ -101,17 +114,6 @@ public: return moduleIds; } - ModuleIds fetchModuleIds(SourceId sourceId) - { - return selectModuleIdsForSourceIdStatement.template valeWithTransaction(16, &sourceId); - } - - ModuleIds fetchModuleDependencyIds(ModuleIds moduleIds) const - { - return fetchModuleDependencyIdsStatement.template valuesWithTransaction( - 16, static_cast(moduleIds.data()), static_cast(moduleIds.size())); - } - PropertyDeclarationId fetchPropertyDeclarationByTypeIdAndName(TypeId typeId, Utils::SmallStringView name) { @@ -245,6 +247,16 @@ public: return value; } + void clearSources() + { + Sqlite::ImmediateTransaction transaction{database}; + + deleteAllSourceContextsStatement.execute(); + deleteAllSourcesStatement.execute(); + + transaction.commit(); + } + SourceContextId fetchSourceContextId(SourceId sourceId) const { auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement @@ -273,23 +285,7 @@ public: auto fetchAllModules() const { - Storage::ModuleDependencies modules; - modules.reserve(128); - - auto callback = [&](Utils::SmallStringView name, int version, int moduleId) { - auto &lastModule = modules.emplace_back(name, - Storage::VersionNumber{version}, - SourceId{moduleId}); - - lastModule.dependencies = selectModulesForThatDependentOnThisModuleIdStatement - .template values(6, moduleId); - - return Sqlite::CallbackControl::Continue; - }; - - selectAllModulesStatement.readCallbackWithTransaction(callback); - - return modules; + return selectAllModulesStatement.template valuesWithTransaction(128); } auto fetchAllFileStatuses() const @@ -310,106 +306,62 @@ private: { public: explicit AliasPropertyDeclaration( + TypeId typeId, PropertyDeclarationId propertyDeclarationId, - Storage::TypeName aliasTypeName, + ImportedTypeNameId aliasImportedTypeNameId, Utils::SmallString aliasPropertyName, - SourceId sourceId, PropertyDeclarationId aliasPropertyDeclarationId = PropertyDeclarationId{}) - : propertyDeclarationId{propertyDeclarationId} - , aliasTypeName{std::move(aliasTypeName)} + : typeId{typeId} + , propertyDeclarationId{propertyDeclarationId} + , aliasImportedTypeNameId{aliasImportedTypeNameId} , aliasPropertyName{std::move(aliasPropertyName)} - , sourceId{sourceId} , aliasPropertyDeclarationId{aliasPropertyDeclarationId} {} public: + TypeId typeId; PropertyDeclarationId propertyDeclarationId; - Storage::TypeName aliasTypeName; + ImportedTypeNameId aliasImportedTypeNameId; Utils::SmallString aliasPropertyName; - SourceId sourceId; PropertyDeclarationId aliasPropertyDeclarationId; }; class PropertyDeclaration { public: - explicit PropertyDeclaration(PropertyDeclarationId propertyDeclarationId, - Storage::TypeName typeName, - SourceId sourceId) - : propertyDeclarationId{propertyDeclarationId} - , typeName{std::move(typeName)} - , sourceId{sourceId} + explicit PropertyDeclaration(TypeId typeId, + PropertyDeclarationId propertyDeclarationId, + ImportedTypeNameId importedTypeNameId) + : typeId{typeId} + , propertyDeclarationId{propertyDeclarationId} + , importedTypeNameId{std::move(importedTypeNameId)} + {} + + explicit PropertyDeclaration(long long typeId, + long long propertyDeclarationId, + long long importedTypeNameId) + : typeId{typeId} + , propertyDeclarationId{propertyDeclarationId} + , importedTypeNameId{importedTypeNameId} {} public: + TypeId typeId; PropertyDeclarationId propertyDeclarationId; - Storage::TypeName typeName; - SourceId sourceId; + ImportedTypeNameId importedTypeNameId; }; class Prototype { public: - explicit Prototype(TypeId typeId, Storage::TypeName prototypeName, SourceId sourceId) + explicit Prototype(TypeId typeId, ImportedTypeNameId prototypeNameId) : typeId{typeId} - , typeName{std::move(prototypeName)} - , sourceId{sourceId} + , prototypeNameId{std::move(prototypeNameId)} {} public: TypeId typeId; - Storage::TypeName typeName; - SourceId sourceId; - }; - - Storage::TypeName fetchTypeName(long long typeNameIdValue) - { - TypeNameId typeNameId{std::abs(typeNameIdValue)}; - Storage::TypeName typeName; - bool isExplicitTypeName = typeNameIdValue < 0; - - if (isExplicitTypeName) { - auto callback = [&](Utils::SmallStringView type, Utils::SmallStringView module, int version) { - typeName = Storage::ExplicitExportedType{type, Storage::Module{module, version}}; - return Sqlite::CallbackControl::Abort; - }; - - selectExplicitTypeNameStatement.readCallback(callback, &typeNameId); - } else { - auto callback = [&](Utils::SmallStringView name, long long kind) { - typeName = createTypeName(kind, name); - return Sqlite::CallbackControl::Abort; - }; - - selectTypeNameStatement.readCallback(callback, &typeNameId); - } - return typeName; - } - - struct ModuleDependency - { - ModuleDependency(ModuleId id, ModuleId dependencyId) - : id{id} - , dependencyId{dependencyId} - {} - - ModuleDependency(long long id, long long dependencyId) - : id{id} - , dependencyId{dependencyId} - {} - - ModuleId id; - ModuleId dependencyId; - - friend bool operator<(ModuleDependency first, ModuleDependency second) - { - return std::tie(first.id, first.dependencyId) < std::tie(second.id, second.dependencyId); - } - - friend bool operator==(ModuleDependency first, ModuleDependency second) - { - return first.id == second.id && first.dependencyId == second.dependencyId; - } + ImportedTypeNameId prototypeNameId; }; void synchronizeTypes(Storage::Types &types, @@ -470,41 +422,67 @@ private: Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove); } - void synchronizeModules(Storage::ModuleDependencies &modules, - TypeIds &deletedTypeIds, + void synchronizeModules(Storage::Modules &modules, + TypeIds &typeIdsToBeDeleted, const std::vector &moduleIdValues) { - synchronizeModulesAndUpdatesModuleIds(modules, deletedTypeIds, moduleIdValues); - synchronizeModuleDependencies(createSortedModuleDependecies(modules), moduleIdValues); + auto compareKey = [](auto &&first, auto &&second) { + return first.sourceId.id - second.sourceId.id; + }; + + std::sort(modules.begin(), modules.end(), [&](auto &&first, auto &&second) { + return compareKey(first, second) < 0; + }); + + auto range = selectModulesForIdsStatement.template range( + Utils::span(moduleIdValues)); + + auto insert = [&](Storage::Module &module) { + insertModuleStatement.write(module.name, &module.sourceId); + }; + + auto update = [&](const Storage::ModuleView &moduleView, Storage::Module &module) { + if (moduleView.name != module.name) + updateModuleStatement.write(&moduleView.sourceId, module.name); + }; + + auto remove = [&](const Storage::ModuleView &moduleView) { + deleteModuleStatement.write(&moduleView.sourceId); + selectTypeIdsForModuleIdStatement.readTo(typeIdsToBeDeleted, &moduleView.sourceId); + }; + + Sqlite::insertUpdateDelete(range, modules, compareKey, insert, update, remove); } - void synchronizeDocuments(Storage::Documents &documents, std::vector &sourceIdValues) + void synchronizeImports(Storage::Imports &imports, std::vector &sourceIdValues) { - deleteDocumentModulesForDeletedDocuments(documents, sourceIdValues); + deleteDocumentImportsForDeletedDocuments(imports, sourceIdValues); - for (auto &&document : documents) - synchronizeDocumentModules(document.sourceId, document.modules); + addModuleIdToImports(imports); + synchronizeDocumentImports(imports, sourceIdValues); } - void deleteDocumentModulesForDeletedDocuments(Storage::Documents &documents, + void deleteDocumentImportsForDeletedDocuments(Storage::Imports &imports, const std::vector &sourceIdValues) { - const std::vector documentSourceIds = Utils::transform>( - documents, [](const auto &document) { return &document.sourceId; }); + std::vector importSourceIds = Utils::transform>( + imports, [](const Storage::Import &import) { return &import.sourceId; }); + + std::sort(importSourceIds.begin(), importSourceIds.end()); std::vector documentSourceIdsToBeDeleted; std::set_difference(sourceIdValues.begin(), sourceIdValues.end(), - documentSourceIds.begin(), - documentSourceIds.end(), + importSourceIds.begin(), + importSourceIds.end(), std::back_inserter(documentSourceIdsToBeDeleted)); - deleteDocumentModulesWithSourceIdsStatement.write(Utils::span{documentSourceIdsToBeDeleted}); + deleteDocumentImportsWithSourceIdsStatement.write(Utils::span{documentSourceIdsToBeDeleted}); } - void synchronizeModulesAndUpdatesModuleIds(Storage::ModuleDependencies &modules, - TypeIds &deletedTypeIds, + void synchronizeModulesAndUpdatesModuleIds(Storage::Modules &modules, + TypeIds &typeIdsToBeDeleted, const std::vector &moduleIds) { auto compareKey = [](auto &&first, auto &&second) { @@ -518,103 +496,48 @@ private: auto range = selectModulesForIdsStatement.template range( Utils::span(moduleIds)); - auto insert = [&](Storage::ModuleDependency &module) { - insertModuleStatement.write(module.name, module.version.version, &module.sourceId); + auto insert = [&](Storage::Module &module) { + insertModuleStatement.write(module.name, &module.sourceId); }; - auto update = [&](const Storage::ModuleView &moduleView, Storage::ModuleDependency &module) { - if (moduleView.name != module.name || moduleView.version != module.version) - updateModuleStatement.write(&moduleView.sourceId, module.name, module.version.version); + auto update = [&](const Storage::ModuleView &moduleView, Storage::Module &module) { + if (moduleView.name != module.name) + updateModuleStatement.write(&moduleView.sourceId, module.name); }; auto remove = [&](const Storage::ModuleView &moduleView) { deleteModuleStatement.write(&moduleView.sourceId); - selectTypeIdsForModuleIdStatement.readTo(deletedTypeIds, &moduleView.sourceId); + selectTypeIdsForModuleIdStatement.readTo(typeIdsToBeDeleted, &moduleView.sourceId); }; Sqlite::insertUpdateDelete(range, modules, compareKey, insert, update, remove); } - std::vector createSortedModuleDependecies( - const Storage::ModuleDependencies &moduleDependencies) const + ModuleId fetchModuleIdUnguarded(const Storage::Module &module) const { - std::vector moduleDependecies; - moduleDependecies.reserve(moduleDependencies.size() * 5); - - for (const Storage::ModuleDependency &moduleDependency : moduleDependencies) { - for (const Storage::Module &dependency : moduleDependency.dependencies) { - auto moduleIdForDependency = fetchModuleId(dependency); - - if (!moduleIdForDependency) - throw ModuleDoesNotExists{}; - - moduleDependecies.emplace_back(ModuleId{&moduleDependency.sourceId}, - moduleIdForDependency); - } - } - - std::sort(moduleDependecies.begin(), moduleDependecies.end()); - moduleDependecies.erase(std::unique(moduleDependecies.begin(), moduleDependecies.end()), - moduleDependecies.end()); - - return moduleDependecies; + return fetchModuleIdUnguarded(module.name); } - void synchronizeModuleDependencies(const std::vector &moduleDependecies, - const std::vector &moduleIds) + ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const { - auto compareKey = [](ModuleDependency first, ModuleDependency second) { - auto idCompare = first.id.id - second.id.id; - - if (idCompare != 0) - return idCompare; - - return first.dependencyId.id - second.dependencyId.id; - }; - - auto range = selectModuleDependenciesForIdsStatement.template range( - Utils::span(moduleIds)); - - auto insert = [&](ModuleDependency dependency) { - insertModuleDependencyStatement.write(&dependency.id, &dependency.dependencyId); - }; - - auto update = [](ModuleDependency, ModuleDependency) {}; - - auto remove = [&](ModuleDependency dependency) { - deleteModuleDependencyStatement.write(&dependency.id, &dependency.dependencyId); - }; - - Sqlite::insertUpdateDelete(range, moduleDependecies, compareKey, insert, update, remove); - } - - ModuleId fetchModuleId(const Storage::Module &module) const - { - if (module.version) { - return selectModuleIdByNameAndVersionStatement - .template value(module.name, module.version.version); - } - - return selectModuleIdByNameStatement.template value(module.name); + return selectModuleIdByNameStatement.template value(name); } void handleAliasPropertyDeclarationsWithPropertyType( TypeId typeId, std::vector &relinkableAliasPropertyDeclarations) { - auto callback = [&](long long propertyDeclarationId, - long long propertyTypeNameId, - long long typeIdFromProperty, + auto callback = [&](long long typeId, + long long propertyDeclarationId, + long long propertyImportedTypeNameId, long long aliasPropertyDeclarationId) { - auto sourceId = selectSourceIdForTypeIdStatement.template value( - typeIdFromProperty); - auto aliasPropertyName = selectPropertyNameStatement.template value( aliasPropertyDeclarationId); - relinkableAliasPropertyDeclarations.emplace_back(PropertyDeclarationId{propertyDeclarationId}, - fetchTypeName(propertyTypeNameId), - std::move(aliasPropertyName), - sourceId); + relinkableAliasPropertyDeclarations + .emplace_back(TypeId{typeId}, + PropertyDeclarationId{propertyDeclarationId}, + ImportedTypeNameId{propertyImportedTypeNameId}, + std::move(aliasPropertyName)); updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId); @@ -630,19 +553,15 @@ private: std::vector &relinkableAliasPropertyDeclarations) { auto callback = [&](long long propertyDeclarationId, - long long propertyTypeNameId, - long long typeIdFromProperty, + long long propertyImportedTypeNameId, long long aliasPropertyDeclarationId) { - auto sourceId = selectSourceIdForTypeIdStatement.template value( - typeIdFromProperty); - auto aliasPropertyName = selectPropertyNameStatement.template value( aliasPropertyDeclarationId); - relinkableAliasPropertyDeclarations.emplace_back(PropertyDeclarationId{propertyDeclarationId}, - fetchTypeName(propertyTypeNameId), - std::move(aliasPropertyName), - sourceId); + relinkableAliasPropertyDeclarations + .emplace_back(PropertyDeclarationId{propertyDeclarationId}, + ImportedTypeNameId{propertyImportedTypeNameId}, + std::move(aliasPropertyName)); updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId); @@ -656,25 +575,14 @@ private: void handlePropertyDeclarationWithPropertyType( TypeId typeId, std::vector &relinkablePropertyDeclarations) { - auto callback = [&](long long propertyDeclarationId, long long propertyTypeNameId) { - auto sourceId = selectSourceIdForTypeIdStatement.template value(&typeId); - - relinkablePropertyDeclarations.emplace_back(PropertyDeclarationId{propertyDeclarationId}, - fetchTypeName(propertyTypeNameId), - sourceId); - - return Sqlite::CallbackControl::Continue; - }; - - updatesPropertyDeclarationPropertyTypeToNullStatement.readCallback(callback, &typeId); + updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations, + &typeId); } void handlePrototypes(TypeId prototypeId, std::vector &relinkablePrototypes) { - auto callback = [&](long long typeId, long long prototypeNameId, int sourceId) { - relinkablePrototypes.emplace_back(TypeId{typeId}, - fetchTypeName(prototypeNameId), - SourceId{sourceId}); + auto callback = [&](long long typeId, long long prototypeNameId) { + relinkablePrototypes.emplace_back(TypeId{typeId}, ImportedTypeNameId{prototypeNameId}); return Sqlite::CallbackControl::Continue; }; @@ -699,21 +607,17 @@ private: } void relinkAliasPropertyDeclarations( - const std::vector &aliasPropertyDeclarations) + const std::vector &aliasPropertyDeclarations, + const TypeIds &deletedTypeIds) { for (const AliasPropertyDeclaration &alias : aliasPropertyDeclarations) { - auto [typeId, aliasTypeNameId] = fetchTypeIdByNameUngarded(alias.aliasTypeName, - alias.sourceId); - - if (!typeId) { - auto hasPropertyDeclaration = selectPropertyDeclarationIdStatement - .template optionalValue( - &alias.propertyDeclarationId); - if (hasPropertyDeclaration) - throw TypeNameDoesNotExists{}; - + if (std::binary_search(deletedTypeIds.begin(), deletedTypeIds.end(), alias.typeId)) continue; - } + + auto typeId = fetchTypeId(alias.aliasImportedTypeNameId); + + if (!typeId) + throw TypeNameDoesNotExists{}; auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded( typeId, alias.aliasPropertyName); @@ -721,66 +625,59 @@ private: updatePropertyDeclarationWithAliasAndTypeStatement.write(&alias.propertyDeclarationId, &propertyTypeId, propertyTraits, - &aliasTypeNameId, + &alias.aliasImportedTypeNameId, &aliasId); } } - void relinkPropertyDeclarations(const std::vector &relinkablePropertyDeclaration) + void relinkPropertyDeclarations(const std::vector &relinkablePropertyDeclaration, + const TypeIds &deletedTypeIds) { for (const PropertyDeclaration &property : relinkablePropertyDeclaration) { - auto [propertyTypeId, propertyTypeNameId] = fetchTypeIdByNameUngarded(property.typeName, - property.sourceId); - - if (!propertyTypeId) { - auto hasPropertyDeclaration = selectPropertyDeclarationIdStatement - .template optionalValue( - &property.propertyDeclarationId); - if (hasPropertyDeclaration) - throw TypeNameDoesNotExists{}; - + if (std::binary_search(deletedTypeIds.begin(), deletedTypeIds.end(), property.typeId)) continue; - } + + TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId); + + if (!propertyTypeId) + throw TypeNameDoesNotExists{}; updatePropertyDeclarationTypeStatement.write(&property.propertyDeclarationId, - &propertyTypeId, - &propertyTypeNameId); + &propertyTypeId); } } - void relinkPrototypes(std::vector relinkablePrototypes) + void relinkPrototypes(std::vector relinkablePrototypes, const TypeIds &deletedTypeIds) { for (const Prototype &prototype : relinkablePrototypes) { - auto [prototypeId, prototypeNameId] = fetchTypeIdByNameUngarded(prototype.typeName, - prototype.sourceId); - - if (!prototypeId) { - auto hasTypeId = selectPropertyDeclarationIdStatement.template optionalValue( - &prototype.typeId); - if (hasTypeId) - throw TypeNameDoesNotExists{}; - + if (std::binary_search(deletedTypeIds.begin(), deletedTypeIds.end(), prototype.typeId)) continue; - } - updateTypePrototypeStatement.write(&prototype.typeId, &prototypeId, &prototypeNameId); + TypeId prototypeId = fetchTypeId(prototype.prototypeNameId); + + if (!prototypeId) + throw TypeNameDoesNotExists{}; + + updateTypePrototypeStatement.write(&prototype.typeId, &prototypeId); checkForPrototypeChainCycle(prototype.typeId); } } void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds, const std::vector &sourceIdValues, - const TypeIds &deletedTypeIds) + const TypeIds &typeIdsToBeDeleted) { std::vector relinkableAliasPropertyDeclarations; std::vector relinkablePropertyDeclarations; std::vector relinkablePrototypes; + TypeIds deletedTypeIds; auto updatedTypeIdValues = Utils::transform(updatedTypeIds, [](TypeId typeId) { return &typeId; }); auto callback = [&](long long typeId) { + deletedTypeIds.push_back(TypeId{typeId}); deleteType(TypeId{typeId}, relinkableAliasPropertyDeclarations, relinkablePropertyDeclarations, @@ -791,19 +688,20 @@ private: selectNotUpdatedTypesInSourcesStatement.readCallback(callback, Utils::span(sourceIdValues), Utils::span(updatedTypeIdValues)); - for (TypeId deletedTypeId : deletedTypeIds) - callback(&deletedTypeId); + for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted) + callback(&typeIdToBeDeleted); - relinkPrototypes(relinkablePrototypes); - relinkPropertyDeclarations(relinkablePropertyDeclarations); - relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations); + std::sort(deletedTypeIds.begin(), deletedTypeIds.end()); + + relinkPrototypes(relinkablePrototypes, deletedTypeIds); + relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds); + relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds); } void linkAliasPropertyDeclarationAliasIds(const std::vector &aliasDeclarations) { for (const auto &aliasDeclaration : aliasDeclarations) { - auto [aliasTypeId, aliasTypeNameId] = fetchTypeIdByNameUngarded(aliasDeclaration.aliasTypeName, - aliasDeclaration.sourceId); + auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId); if (!aliasTypeId) throw TypeNameDoesNotExists{}; @@ -812,7 +710,9 @@ private: aliasTypeId, aliasDeclaration.aliasPropertyName); updatePropertyDeclarationAliasIdAndTypeNameIdStatement - .write(&aliasDeclaration.propertyDeclarationId, &aliasId, &aliasTypeNameId); + .write(&aliasDeclaration.propertyDeclarationId, + &aliasId, + &aliasDeclaration.aliasImportedTypeNameId); } } @@ -845,20 +745,37 @@ private: updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations); } - void upsertExportedType(ModuleId moduleId, Utils::SmallStringView name, TypeId typeId) + void upsertExportedType(ModuleId moduleId, + Utils::SmallStringView name, + TypeId typeId, + Storage::Version version) { - upsertTypeNamesStatement.write(&moduleId, - name, - static_cast(Storage::TypeNameKind::Exported), - -1, - -1, - &typeId); + if (version) { + upsertTypeNamesWithVersionStatement.write(&moduleId, + name, + static_cast( + Storage::TypeNameKind::Exported), + version.major.value, + version.minor.value, + &typeId); + + } else if (version.major) { + upsertTypeNamesWithMajorVersionStatement.write(&moduleId, + name, + static_cast( + Storage::TypeNameKind::Exported), + version.major.value, + &typeId); + } else { + upsertTypeNamesWithoutVersionStatement.write( + &moduleId, name, static_cast(Storage::TypeNameKind::Exported), &typeId); + } } void upsertNativeType(ModuleId moduleId, Utils::SmallStringView name, TypeId typeId) { - upsertTypeNamesStatement.write( - &moduleId, name, static_cast(Storage::TypeNameKind::Native), -1, -1, &typeId); + upsertTypeNamesWithoutVersionStatement + .write(&moduleId, name, static_cast(Storage::TypeNameKind::Native), &typeId); } void synchronizePropertyDeclarationsInsertAlias( @@ -868,10 +785,11 @@ private: TypeId typeId) { auto callback = [&](long long propertyDeclarationId) { - insertedAliasPropertyDeclarations.emplace_back(PropertyDeclarationId{propertyDeclarationId}, - std::move(value.typeName), - std::move(value.aliasPropertyName), - sourceId); + insertedAliasPropertyDeclarations.emplace_back(typeId, + PropertyDeclarationId{propertyDeclarationId}, + fetchImportedTypeNameId(value.typeName, + sourceId), + std::move(value.aliasPropertyName)); return Sqlite::CallbackControl::Abort; }; @@ -882,14 +800,18 @@ private: SourceId sourceId, TypeId typeId) { - auto [propertyTypeId, propertyTypeNameId] = fetchTypeIdByNameUngarded(value.typeName, - sourceId); + auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId); + auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId); if (!propertyTypeId) throw TypeNameDoesNotExists{}; - auto propertyDeclarationId = insertPropertyDeclarationStatement.template value( - &typeId, value.name, &propertyTypeId, static_cast(value.traits), &propertyTypeNameId); + auto propertyDeclarationId = insertPropertyDeclarationStatement.template value< + PropertyDeclarationId>(&typeId, + value.name, + &propertyTypeId, + static_cast(value.traits), + &propertyImportedTypeNameId); auto nextPropertyDeclarationId = selectPropertyDeclarationIdPrototypeChainDownStatement .template value(&typeId, @@ -908,10 +830,11 @@ private: const Storage::PropertyDeclaration &value, SourceId sourceId) { - auto last = updatedAliasPropertyDeclarations.emplace_back(view.id, - value.typeName, + auto last = updatedAliasPropertyDeclarations.emplace_back(view.typeId, + view.id, + fetchImportedTypeNameId(value.typeName, + sourceId), value.aliasPropertyName, - sourceId, view.aliasId); } @@ -919,20 +842,21 @@ private: const Storage::PropertyDeclaration &value, SourceId sourceId) { - auto [propertyTypeId, propertyTypeNameId] = fetchTypeIdByNameUngarded(value.typeName, - sourceId); + auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId); + + auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId); if (!propertyTypeId) throw TypeNameDoesNotExists{}; if (view.traits == value.traits && propertyTypeId == view.typeId - && propertyTypeNameId == view.typeNameId) + && propertyImportedTypeNameId == view.typeNameId) return; updatePropertyDeclarationStatement.write(&view.id, &propertyTypeId, static_cast(value.traits), - &propertyTypeNameId); + &propertyImportedTypeNameId); updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement .write(&view.id, &propertyTypeId, static_cast(value.traits)); } @@ -1046,32 +970,69 @@ private: moduleIds.reserve(moduleIds.size()); for (auto &&module : modules) - moduleIds.push_back(fetchModuleId(module)); + moduleIds.push_back(fetchModuleIdUnguarded(module)); return moduleIds; } - void synchronizeDocumentModules(SourceId sourceId, const Storage::Modules &modules) + void addModuleIdToImports(Storage::Imports &imports) { - ModuleIds moduleIds = fetchModuleIdsUnguarded(modules); + for (Storage::Import &import : imports) { + import.moduleId = fetchModuleIdUnguarded(import.name); + if (!import.moduleId) + throw ModuleDoesNotExists{}; + } + } - std::sort(moduleIds.begin(), moduleIds.end()); + void synchronizeDocumentImports(Storage::Imports &imports, const std::vector &sourceIdValues) + { + std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) { + return std::tie(first.sourceId, first.moduleId, first.version) + < std::tie(second.sourceId, second.moduleId, second.version); + }); - auto range = selectModuleIdsForSourceIdStatement.template range(&sourceId); + auto range = selectDocumentImportForSourceIdStatement.template range( + Utils::span{sourceIdValues}); - auto compareKey = [](ModuleId first, ModuleId second) { return first.id - second.id; }; + auto compareKey = [](const Storage::ImportView &view, + const Storage::Import &import) -> long long { + auto sourceIdDifference = view.sourceId.id - import.sourceId.id; + if (sourceIdDifference != 0) + return sourceIdDifference; - auto insert = [&](ModuleId moduleId) { - insertModuleIdForSourceIdStatement.write(&sourceId, &moduleId); + auto moduleIdDifference = view.moduleId.id - import.moduleId.id; + if (moduleIdDifference != 0) + return moduleIdDifference; + + auto versionDifference = view.version.major.value - import.version.major.value; + if (versionDifference != 0) + return versionDifference; + + return view.version.minor.value - import.version.minor.value; }; - auto update = [](ModuleId, ModuleId) {}; - - auto remove = [&](ModuleId moduleId) { - deleteModuleIdForSourceIdStatement.write(&sourceId, &moduleId); + auto insert = [&](const Storage::Import &import) { + if (import.version.minor) { + insertDocumentImportWithVersionStatement.write(&import.sourceId, + &import.moduleId, + import.version.major.value, + import.version.minor.value); + } else if (import.version.major) { + insertDocumentImportWithMajorVersionStatement.write(&import.sourceId, + &import.moduleId, + import.version.major.value); + } else { + insertDocumentImportWithoutVersionStatement.write(&import.sourceId, &import.moduleId); + } }; - Sqlite::insertUpdateDelete(range, moduleIds, compareKey, insert, update, remove); + auto update = [](const Storage::ImportView &, const Storage::Import &) {}; + + auto remove = [&](const Storage::ImportView &view) { + deleteDocumentImportStatement.write(&view.importId); + }; + + Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove); } Utils::PathString createJson(const Storage::ParameterDeclarations ¶meters) @@ -1251,7 +1212,7 @@ private: return type.typeId; } - ModuleId moduleId = fetchModuleId(type.module); + ModuleId moduleId = fetchModuleIdUnguarded(type.module); if (!moduleId) throw ModuleDoesNotExists{}; @@ -1267,7 +1228,7 @@ private: upsertNativeType(moduleId, type.typeName, type.typeId); for (const auto &exportedType : type.exportedTypes) - upsertExportedType(moduleId, exportedType.name, type.typeId); + upsertExportedType(moduleId, exportedType.name, type.typeId, exportedType.version); return type.typeId; } @@ -1318,8 +1279,10 @@ private: type.prototype)) { updatePrototypeStatement.write(&type.typeId, Sqlite::NullValue{}, Sqlite::NullValue{}); } else { - auto [prototypeId, prototypeTypeNameId] = fetchTypeIdByNameUngarded(type.prototype, - type.sourceId); + ImportedTypeNameId prototypeTypeNameId = fetchImportedTypeNameId(type.prototype, + type.sourceId); + + TypeId prototypeId = fetchTypeId(prototypeTypeNameId); if (!prototypeId) throw TypeNameDoesNotExists{}; @@ -1329,65 +1292,47 @@ private: } } - Utils::SmallStringView extractTypeName(const Storage::TypeName &name) const + ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const { - return Utils::visit([](auto &&typeName) -> Utils::SmallStringView { return typeName.name; }, - name); - } - - Storage::TypeName createTypeName(long long typeIndex, Utils::SmallStringView name) const - { - switch (typeIndex) { - case 0: - return Utils::variant_alternative_t<0, Storage::TypeName>(name); - case 1: - return Utils::variant_alternative_t<1, Storage::TypeName>(name); + if (import.version) { + return selectImportIdBySourceIdAndImportNameAndVersionStatement.template value( + &sourceId, import.name, import.version.major.value, import.version.minor.value); } - return {}; + if (import.version.major) { + return selectImportIdBySourceIdAndImportNameAndMajorVersionStatement + .template value(&sourceId, import.name, import.version.major.value); + } + + return selectImportIdBySourceIdAndImportNameStatement.template value(&sourceId, + import.name); } - class TypeIdAndTypeNameId - { - public: - TypeIdAndTypeNameId() = default; - TypeIdAndTypeNameId(long long typeId, long long typeNameId) - : typeId{typeId} - , typeNameId{typeNameId} - {} - - public: - TypeId typeId; - TypeNameId typeNameId; - }; - - TypeIdAndTypeNameId fetchTypeIdByNameUngarded(const Storage::TypeName &name, SourceId sourceId) + ImportedTypeNameId fetchImportedTypeNameId(const Storage::ImportedTypeName &name, SourceId sourceId) { struct Inspect { auto operator()(const Storage::NativeType &nativeType) { - return storage.selectTypeIdByModuleIdsFromSourceIdAndNameStatement - .template value(&sourceId, nativeType.name); + return storage.fetchImportedTypeNameId(Storage::TypeNameKind::Native, + &sourceId, + nativeType.name); } - auto operator()(const Storage::ExportedType &exportedType) + auto operator()(const Storage::ImportedType &importedType) { - return storage.selectTypeIdByModuleIdsFromSourceIdAndExportedNameStatement - .template value(&sourceId, exportedType.name); + return storage.fetchImportedTypeNameId(Storage::TypeNameKind::Exported, + &sourceId, + importedType.name); } - auto operator()(const Storage::ExplicitExportedType &exportedType) + auto operator()(const Storage::QualifiedImportedType &importedType) { - if (exportedType.module.version) { - return storage.selectTypeIdByModuleNameAndVersionAndExportedNameStatement - .template value(exportedType.module.name, - exportedType.module.version.version, - exportedType.name); - } + ImportId importId = storage.fetchImportId(sourceId, importedType.import); - return storage.selectTypeIdByModuleNameAndExportedNameStatement - .template value(exportedType.module.name, exportedType.name); + return storage.fetchImportedTypeNameId(Storage::TypeNameKind::QualifiedExported, + &importId, + importedType.name); } ProjectStorage &storage; @@ -1397,6 +1342,42 @@ private: return Utils::visit(Inspect{*this, sourceId}, name); } + ImportedTypeNameId fetchImportedTypeNameId(Storage::TypeNameKind kind, + long long id, + Utils::SmallStringView typeName) + { + auto importedTypeNameId = selectImportedTypeNameIdStatement.template value( + static_cast(kind), id, typeName); + + if (importedTypeNameId) + return importedTypeNameId; + + return insertImportedTypeNameIdStatement + .template value(static_cast(kind), id, typeName); + } + + TypeId fetchTypeId(ImportedTypeNameId typeNameId) const + { + auto kindValue = selectKindFromImportedTypeNamesStatement.template optionalValue( + &typeNameId); + auto kind = static_cast(*kindValue); + + return fetchTypeId(typeNameId, kind); + } + + TypeId fetchTypeId(ImportedTypeNameId typeNameId, Storage::TypeNameKind kind) const + { + if (kind == Storage::TypeNameKind::QualifiedExported) { + return selectTypeIdForQualifiedImportedTypeNameNamesStatement.template value( + &typeNameId); + } + + if (kind == Storage::TypeNameKind::Native) + return selectTypeIdForNativeTypeNameNamesStatement.template value(&typeNameId); + + return selectTypeIdForImportedTypeNameNamesStatement.template value(&typeNameId); + } + class FetchPropertyDeclarationResult { public: @@ -1542,16 +1523,16 @@ private: if (!isInitialized) { Sqlite::ExclusiveTransaction transaction{database}; - createModulesTable(database); - createModuleDependeciesTable(database); + auto moduleIdColumn = createModulesTable(database); createSourceContextsTable(database); createSourcesTable(database); - createTypesAndePropertyDeclarationsTables(database); - createTypeNamesTable(database); + createTypesAndePropertyDeclarationsTables(database, moduleIdColumn); + createExportedTypeNamesTable(database, moduleIdColumn); + createImportedTypeNamesTable(database); createEnumerationsTable(database); createFunctionsTable(database); createSignalsTable(database); - createSourceModulesTable(database); + createDocumentImportsTable(database, moduleIdColumn); createFileStatusesTable(database); transaction.commit(); @@ -1593,13 +1574,18 @@ private: table.initialize(database); } - void createTypesAndePropertyDeclarationsTables(Database &database) + void createTypesAndePropertyDeclarationsTables(Database &database, + const Sqlite::Column &foreignModuleIdColumn) { Sqlite::Table typesTable; typesTable.setUseIfNotExists(true); typesTable.setName("types"); typesTable.addColumn("typeId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); - auto &moduleIdColumn = typesTable.addColumn("moduleId"); + auto &moduleIdColumn = typesTable.addForeignKeyColumn("moduleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::Enforment::Deferred); auto &typesNameColumn = typesTable.addColumn("name"); typesTable.addColumn("accessSemantics"); typesTable.addColumn("sourceId"); @@ -1627,7 +1613,7 @@ private: Sqlite::ForeignKeyAction::NoAction, Sqlite::ForeignKeyAction::Restrict); propertyDeclarationTable.addColumn("propertyTraits"); - propertyDeclarationTable.addColumn("propertyTypeNameId"); + propertyDeclarationTable.addColumn("propertyImportedTypeNameId"); auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn( "aliasPropertyDeclarationId", propertyDeclarationTable, @@ -1642,20 +1628,46 @@ private: } } - void createTypeNamesTable(Database &database) + void createExportedTypeNamesTable(Database &database, + const Sqlite::Column &foreignModuleIdColumn) { Sqlite::Table table; table.setUseIfNotExists(true); - table.setName("typeNames"); - table.addColumn("typeNameId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); - auto &moduleIdColumn = table.addColumn("moduleId"); + table.setName("exportedTypeNames"); + table.addColumn("exportedTypeNameId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); + auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::Enforment::Deferred); auto &nameColumn = table.addColumn("name"); auto &kindColumn = table.addColumn("kind"); - table.addColumn("majorVersion"); - table.addColumn("minorVersion"); table.addColumn("typeId"); + auto &majorVersionColumn = table.addColumn("majorVersion"); + auto &minorVersionColumn = table.addColumn("minorVersion"); - table.addUniqueIndex({moduleIdColumn, nameColumn, kindColumn}); + table.addUniqueIndex({moduleIdColumn, nameColumn, kindColumn}, + "majorVersion IS NULL AND minorVersion IS NULL"); + table.addUniqueIndex({moduleIdColumn, nameColumn, kindColumn, majorVersionColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NULL"); + table.addUniqueIndex( + {moduleIdColumn, nameColumn, kindColumn, majorVersionColumn, minorVersionColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NOT NULL"); + + table.initialize(database); + } + + void createImportedTypeNamesTable(Database &database) + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("importedTypeNames"); + table.addColumn("importedTypeNameId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); + auto &importOrSourceIdColumn = table.addColumn("importOrSourceId"); + auto &nameColumn = table.addColumn("name"); + auto &kindColumn = table.addColumn("kind"); + + table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn}); table.initialize(database); } @@ -1710,44 +1722,44 @@ private: table.initialize(database); } - void createModulesTable(Database &database) + Sqlite::Column createModulesTable(Database &database) { Sqlite::Table table; table.setUseIfNotExists(true); table.setName("modules"); - table.addColumn("moduleId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); + auto &modelIdColumn = table.addColumn("moduleId", + Sqlite::ColumnType::Integer, + {Sqlite::PrimaryKey{}}); auto &nameColumn = table.addColumn("name"); - auto &versionColumn = table.addColumn("version"); - table.addUniqueIndex({nameColumn, versionColumn}); + table.addUniqueIndex({nameColumn}); table.initialize(database); + + return std::move(modelIdColumn); } - void createModuleDependeciesTable(Database &database) + void createDocumentImportsTable(Database &database, const Sqlite::Column &foreignModuleIdColumn) { Sqlite::Table table; table.setUseIfNotExists(true); - table.setUseWithoutRowId(true); - table.setName("moduleDependencies"); - auto &moduleIdColumn = table.addColumn("moduleId"); - auto &parentModuleIdColumn = table.addColumn("parentModuleId"); - - table.addPrimaryKeyContraint({moduleIdColumn, parentModuleIdColumn}); - - table.initialize(database); - } - - void createSourceModulesTable(Database &database) - { - Sqlite::Table table; - table.setUseIfNotExists(true); - table.setUseWithoutRowId(true); - table.setName("documentModules"); + table.setName("documentImports"); + table.addColumn("importId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); auto &sourceIdColumn = table.addColumn("sourceId"); - auto &moduleIdColumn = table.addColumn("moduleId"); + auto &moduleIdColumn = table.addForeignKeyColumn("moduleId", + foreignModuleIdColumn, + Sqlite::ForeignKeyAction::NoAction, + Sqlite::ForeignKeyAction::Cascade, + Sqlite::Enforment::Deferred); + auto &majorVersionColumn = table.addColumn("majorVersion"); + auto &minorVersionColumn = table.addColumn("minorVersion"); - table.addPrimaryKeyContraint({sourceIdColumn, moduleIdColumn}); + table.addUniqueIndex({sourceIdColumn, moduleIdColumn}, + "majorVersion IS NULL AND minorVersion IS NULL"); + table.addUniqueIndex({sourceIdColumn, moduleIdColumn, majorVersionColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NULL"); + table.addUniqueIndex({sourceIdColumn, moduleIdColumn, majorVersionColumn, minorVersionColumn}, + "majorVersion IS NOT NULL AND minorVersion IS NOT NULL"); table.initialize(database); } @@ -1785,13 +1797,14 @@ public: "NOT ?2 OR prototypeNameId IS NOT ?3)", database}; mutable ReadStatement<1> selectTypeIdByExportedNameStatement{ - "SELECT typeId FROM typeNames WHERE name=?1 AND kind=1", database}; + "SELECT typeId FROM exportedTypeNames WHERE name=?1 AND kind=1", database}; mutable ReadStatement<1> selectPrototypeIdStatement{ "WITH RECURSIVE " " typeSelection(typeId) AS (" " VALUES(?1) " " UNION ALL " - " SELECT prototypeId FROM types JOIN typeSelection USING(typeId)) " + " SELECT prototypeId FROM types JOIN typeSelection USING(typeId) WHERE prototypeId " + " IS NOT NULL)" "SELECT typeId FROM typeSelection WHERE typeId=?2 LIMIT 1", database}; mutable ReadStatement<1> selectPropertyDeclarationIdByTypeIdAndNameStatement{ @@ -1800,7 +1813,7 @@ public: " VALUES(?1, 0) " " UNION ALL " " SELECT prototypeId, typeSelection.level+1 FROM types JOIN typeSelection " - " USING(typeId)) " + " USING(typeId) WHERE prototypeId IS NOT NULL) " "SELECT propertyDeclarationId FROM propertyDeclarations JOIN typeSelection USING(typeId) " " WHERE name=?2 ORDER BY level LIMIT 1", database}; @@ -1810,25 +1823,35 @@ public: " VALUES(?1, 0) " " UNION ALL " " SELECT prototypeId, typeSelection.level+1 FROM types JOIN typeSelection " - " USING(typeId)) " - "SELECT propertyTypeId, propertyDeclarationId, propertyTraits " + " USING(typeId) WHERE prototypeId IS NOT NULL)" + "SELECT nullif(propertyTypeId, -1), propertyDeclarationId, propertyTraits " " FROM propertyDeclarations JOIN typeSelection USING(typeId) " " WHERE name=?2 ORDER BY level LIMIT 1", database}; - WriteStatement upsertTypeNamesStatement{ - "INSERT INTO typeNames(moduleId, name, kind, majorVersion, minorVersion, typeId) " + WriteStatement upsertTypeNamesWithVersionStatement{ + "INSERT INTO exportedTypeNames(moduleId, name, kind, majorVersion, minorVersion, typeId) " "VALUES(?1, ?2, ?3, ?4, ?5, ?6) ON CONFLICT DO UPDATE SET typeId=excluded.typeId, " "majorVersion=excluded.majorVersion, minorVersion=excluded.minorVersion WHERE typeId IS " "NOT excluded.typeId OR majorVersion IS NOT excluded.majorVersion OR minorVersion IS NOT " "excluded.minorVersion", database}; + WriteStatement upsertTypeNamesWithMajorVersionStatement{ + "INSERT INTO exportedTypeNames(moduleId, name, kind, majorVersion, typeId) " + "VALUES(?1, ?2, ?3, ?4, ?5) ON CONFLICT DO UPDATE SET typeId=excluded.typeId, " + "majorVersion=excluded.majorVersion WHERE typeId IS NOT excluded.typeId OR majorVersion IS " + "NOT excluded.majorVersion", + database}; + WriteStatement upsertTypeNamesWithoutVersionStatement{ + "INSERT INTO exportedTypeNames(moduleId, name, kind, typeId) VALUES(?1, ?2, ?3, ?4) ON " + "CONFLICT DO UPDATE SET typeId=excluded.typeId WHERE typeId IS NOT excluded.typeId", + database}; mutable ReadStatement<1> selectPrototypeIdsStatement{ "WITH RECURSIVE " " typeSelection(typeId, level) AS (" " VALUES(?1, 0) " " UNION ALL " " SELECT prototypeId, typeSelection.level+1 FROM types JOIN typeSelection " - " USING(typeId)) " + " USING(typeId) WHERE prototypeId IS NOT NULL) " "SELECT typeId FROM typeSelection ORDER BY level DESC", database}; mutable ReadStatement<1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{ @@ -1849,27 +1872,24 @@ public: "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database}; mutable ReadStatement<3> selectAllSourcesStatement{ "SELECT sourceName, sourceContextId, sourceId FROM sources", database}; - mutable ReadStatement<1> selectTypeIdByModuleIdsAndNameStatement{ - "SELECT typeId FROM types WHERE moduleId IN carray(?1, ?2, 'int64') AND name=?3", database}; - mutable ReadStatement<2> selectTypeIdByModuleIdsFromSourceIdAndNameStatement{ - "SELECT typeId, typeNameId FROM typeNames JOIN documentModules AS di USING(moduleId) WHERE " - " name=?2 AND kind=0 AND di.sourceId=?1 LIMIT 1", - database}; mutable ReadStatement<5> selectTypeByTypeIdStatement{ "SELECT moduleId, name, (SELECT name FROM types WHERE typeId=outerTypes.prototypeId), " "accessSemantics, ifnull(sourceId, -1) FROM types AS outerTypes WHERE typeId=?", database}; - mutable ReadStatement<1> selectExportedTypesByTypeIdStatement{ - "SELECT name FROM typeNames WHERE typeId=? AND kind=1", database}; + mutable ReadStatement<3> selectExportedTypesByTypeIdStatement{ + "SELECT name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM exportedTypeNames " + "WHERE typeId=? AND kind=1", + database}; mutable ReadStatement<7> selectTypesStatement{ - "SELECT i.name, i.version, t.name, typeId, (SELECT name FROM types WHERE " + "SELECT m.name, m.moduleId, t.name, typeId, (SELECT name FROM types WHERE " "typeId=t.prototypeId), accessSemantics, ifnull(sourceId, -1) FROM types AS " - "t JOIN modules AS i USING (moduleId)", + "t JOIN modules AS m USING (moduleId)", database}; ReadStatement<1> selectNotUpdatedTypesInSourcesStatement{ "SELECT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN carray(?2))", database}; - WriteStatement deleteTypeNamesByTypeIdStatement{"DELETE FROM typeNames WHERE typeId=?", database}; + WriteStatement deleteTypeNamesByTypeIdStatement{"DELETE FROM exportedTypeNames WHERE typeId=?", + database}; WriteStatement deleteEnumerationDeclarationByTypeIdStatement{ "DELETE FROM enumerationDeclarations WHERE typeId=?", database}; WriteStatement deletePropertyDeclarationByTypeIdStatement{ @@ -1886,18 +1906,19 @@ public: "WHERE typeId=?", database}; ReadStatement<6> selectPropertyDeclarationsForTypeIdStatement{ - "SELECT name, propertyTraits, propertyTypeId, propertyTypeNameId, propertyDeclarationId, " - "ifnull(aliasPropertyDeclarationId, -1) FROM propertyDeclarations WHERE typeId=? ORDER BY " - "name", + "SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, " + "propertyDeclarationId, ifnull(aliasPropertyDeclarationId, -1) FROM propertyDeclarations " + "WHERE typeId=? ORDER BY name", database}; ReadWriteStatement<1> insertPropertyDeclarationStatement{ "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, " - "propertyTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) " + "propertyImportedTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) " "RETURNING propertyDeclarationId", database}; WriteStatement updatePropertyDeclarationStatement{ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, " - "propertyTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE propertyDeclarationId=?1", + "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE " + "propertyDeclarationId=?1", database}; WriteStatement updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{ "WITH RECURSIVE " @@ -1936,10 +1957,7 @@ public: database}; WriteStatement updatePropertyDeclarationWithAliasAndTypeStatement{ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, " - "propertyTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE propertyDeclarationId=?1", - database}; - WriteStatement updatePropertyDeclarationWithAliasStatement{ - "UPDATE propertyDeclarations SET propertyTypeId=?2, aliasPropertyDeclarationId=?3 WHERE " + "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE " "propertyDeclarationId=?1", database}; ReadWriteStatement<1> insertAliasPropertyDeclarationStatement{ @@ -2010,76 +2028,47 @@ public: database}; WriteStatement deleteEnumerationDeclarationStatement{ "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database}; - WriteStatement insertModuleStatement{ - "INSERT INTO modules(name, version, moduleId) VALUES(?1, ?2, ?3)", database}; - WriteStatement updateModuleStatement{"UPDATE modules SET name=?2, version=?3 WHERE moduleId=?1", + WriteStatement insertModuleStatement{"INSERT INTO modules(name, moduleId) VALUES(?1, ?2)", database}; + WriteStatement updateModuleStatement{"UPDATE modules SET name=?2 WHERE moduleId=?1", database}; WriteStatement deleteModuleStatement{"DELETE FROM modules WHERE moduleId=?", database}; mutable ReadStatement<1> selectModuleIdByNameStatement{ - "SELECT moduleId FROM modules WHERE name=? ORDER BY version DESC LIMIT 1", database}; - mutable ReadStatement<1> selectModuleIdByNameAndVersionStatement{ - "SELECT moduleId FROM modules WHERE name=? AND version=?", database}; - mutable ReadStatement<3> selectModulesForIdsStatement{ - "SELECT name, version, moduleId FROM modules WHERE moduleId IN carray(?1) ORDER BY " + "SELECT moduleId FROM modules WHERE name=? LIMIT 1", database}; + mutable ReadStatement<2> selectModulesForIdsStatement{ + "SELECT name, moduleId FROM modules WHERE moduleId IN carray(?1) ORDER BY " "moduleId", database}; - mutable ReadStatement<3> selectAllModulesStatement{ - "SELECT name, version, moduleId FROM modules ORDER BY moduleId", database}; - WriteStatement insertModuleDependencyStatement{ - "INSERT INTO moduleDependencies(moduleId, parentModuleId) VALUES(?1, ?2)", database}; - WriteStatement deleteModuleDependencyStatement{ - "DELETE FROM moduleDependencies WHERE moduleId=?1 AND parentModuleId=?2", database}; - mutable ReadStatement<2> selectModuleDependenciesForIdsStatement{ - "SELECT moduleId, parentModuleId FROM moduleDependencies WHERE moduleId IN carray(?1) " - "ORDER BY moduleId, parentModuleId", - database}; - mutable ReadStatement<2> selectModulesForThatDependentOnThisModuleIdStatement{ - "SELECT name, version FROM moduleDependencies JOIN modules ON " - "moduleDependencies.parentModuleId = modules.moduleId WHERE moduleDependencies.moduleId=?", - database}; + mutable ReadStatement<2> selectAllModulesStatement{ + "SELECT name, moduleId FROM modules ORDER BY moduleId", database}; mutable ReadStatement<1> selectTypeIdsForModuleIdStatement{ "SELECT typeId FROM types WHERE moduleId=?", database}; mutable ReadStatement<1> selectTypeIdByModuleIdAndNameStatement{ "SELECT typeId FROM types WHERE moduleId=?1 and name=?2", database}; mutable ReadStatement<1> selectTypeIdByModuleIdsAndExportedNameStatement{ - "SELECT typeId FROM typeNames WHERE moduleId IN carray(?1, ?2, 'int64') AND name=?3 AND " - "kind=1", + "SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND " + "name=?3 AND kind=1", database}; - mutable ReadStatement<2> selectTypeIdByModuleIdsFromSourceIdAndExportedNameStatement{ - "SELECT typeId, typeNameId FROM typeNames JOIN documentModules AS di USING(moduleId) WHERE " - "name=?2 AND kind=1 AND di.sourceId=?1 LIMIT 1", + mutable ReadStatement<5> selectDocumentImportForSourceIdStatement{ + "SELECT importId, sourceId, moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) " + "FROM documentImports WHERE sourceId IN carray(?1) ORDER BY sourceId, moduleId, " + "majorVersion, minorVersion", database}; - mutable ReadStatement<2> selectTypeIdByModuleNameAndExportedNameStatement{ - "WITH RECURSIVE " - " highestModule(moduleId) AS ( " - " SELECT moduleId FROM modules WHERE name=?1 ORDER BY version DESC LIMIT 1) " - "SELECT typeId, -typeNameId FROM typeNames JOIN highestModule USING(moduleId) WHERE " - " name=?2 AND kind=1 LIMIT 1", + WriteStatement insertDocumentImportWithoutVersionStatement{ + "INSERT INTO documentImports(sourceId, moduleId) " + "VALUES (?1, ?2)", database}; - mutable ReadStatement<2> selectTypeIdByModuleNameAndVersionAndExportedNameStatement{ - "WITH RECURSIVE " - " highestModule(moduleId) AS ( " - " SELECT moduleId FROM modules WHERE name=?1 AND version=?2 ORDER BY version DESC LIMIT " - " 1) " - "SELECT typeId, -typeNameId FROM typeNames JOIN highestModule USING(moduleId) WHERE " - " name=?3 AND kind=1 LIMIT 1", + WriteStatement insertDocumentImportWithMajorVersionStatement{ + "INSERT INTO documentImports(sourceId, moduleId, majorVersion) " + "VALUES (?1, ?2, ?3)", database}; - mutable ReadStatement<1> fetchModuleDependencyIdsStatement{ - "WITH RECURSIVE " - " moduleIds(moduleId) AS (" - " SELECT value FROM carray(?1, ?2, 'int64') " - " UNION " - " SELECT parentModuleId FROM moduleDependencies JOIN moduleIds USING(moduleId)) " - "SELECT moduleId FROM moduleIds", + WriteStatement insertDocumentImportWithVersionStatement{ + "INSERT INTO documentImports(sourceId, moduleId, majorVersion, minorVersion) " + "VALUES (?1, ?2, ?3, ?4)", database}; - mutable ReadStatement<1> selectModuleIdsForSourceIdStatement{ - "SELECT moduleId FROM documentModules WHERE sourceId=? ORDER BY moduleId", database}; - WriteStatement insertModuleIdForSourceIdStatement{ - "INSERT INTO documentModules(sourceId, moduleId) VALUES (?1, ?2)", database}; - WriteStatement deleteModuleIdForSourceIdStatement{ - "DELETE FROM documentModules WHERE sourceId=?1 AND moduleId=?2", database}; - WriteStatement deleteDocumentModulesWithSourceIdsStatement{ - "DELETE FROM documentModules WHERE sourceId=?1 IN carray(?1)", database}; + WriteStatement deleteDocumentImportStatement{"DELETE FROM documentImports WHERE importId=?1", + database}; + WriteStatement deleteDocumentImportsWithSourceIdsStatement{ + "DELETE FROM documentImports WHERE sourceId IN carray(?1)", database}; ReadStatement<1> selectPropertyDeclarationIdPrototypeChainDownStatement{ "WITH RECURSIVE " " typeSelection(typeId, level) AS (" @@ -2106,66 +2095,55 @@ public: "NULL OR propertyTypeId IS NOT NULL OR propertyTraits IS NOT NULL)", database}; ReadStatement<4> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{ - "SELECT alias.propertyDeclarationId, alias.propertyTypeNameId, alias.typeId, " + "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, " "target.propertyDeclarationId FROM propertyDeclarations AS alias JOIN propertyDeclarations " "AS target ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId WHERE " - "alias.propertyTypeId=?1 OR alias.propertyTypeNameId IN (SELECT typeNameId FROM typeNames " + "alias.propertyTypeId=?1 OR target.typeId=?1 OR alias.propertyImportedTypeNameId IN " + "(SELECT importedTypeNameId FROM exportedTypeNames JOIN importedTypeNames USING(name) " "WHERE typeId=?1)", database}; - ReadStatement<4> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{ + ReadStatement<3> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{ "WITH RECURSIVE " - " properties(propertyDeclarationId, propertyTypeNameId, typeId, " + " properties(propertyDeclarationId, propertyImportedTypeNameId, typeId, " " aliasPropertyDeclarationId) AS (" - " SELECT propertyDeclarationId, propertyTypeNameId, typeId, " + " SELECT propertyDeclarationId, propertyImportedTypeNameId, typeId, " " aliasPropertyDeclarationId FROM propertyDeclarations WHERE " " aliasPropertyDeclarationId=?1" " UNION ALL " - " SELECT pd.propertyDeclarationId, pd.propertyTypeNameId, pd.typeId, " + " SELECT pd.propertyDeclarationId, pd.propertyImportedTypeNameId, pd.typeId, " " pd.aliasPropertyDeclarationId FROM propertyDeclarations AS pd JOIN properties AS " " p ON pd.aliasPropertyDeclarationId=p.propertyDeclarationId)" - "SELECT propertyDeclarationId, propertyTypeNameId, typeId, aliasPropertyDeclarationId " + "SELECT propertyDeclarationId, propertyImportedTypeNameId, aliasPropertyDeclarationId " " FROM properties", database}; - ReadWriteStatement<2> updatesPropertyDeclarationPropertyTypeToNullStatement{ + ReadWriteStatement<3> updatesPropertyDeclarationPropertyTypeToNullStatement{ "UPDATE propertyDeclarations SET propertyTypeId=NULL WHERE propertyTypeId=?1 AND " - "aliasPropertyDeclarationId IS NULL RETURNING propertyDeclarationId, propertyTypeNameId", - database}; - ReadStatement<1> selectSourceIdForTypeIdStatement{"SELECT sourceId FROM types WHERE typeId=?", - database}; - ReadStatement<2> selectTypeNameStatement{"SELECT name, kind FROM typeNames WHERE typeNameId=?", - database}; - ReadStatement<3> selectExplicitTypeNameStatement{ - "SELECT tn.name, i.name, i.version FROM typeNames AS tn JOIN modules AS i USING(moduleId) " - "WHERE typeNameId=? AND kind=1", + "aliasPropertyDeclarationId IS NULL RETURNING typeId, propertyDeclarationId, " + "propertyImportedTypeNameId", database}; ReadStatement<1> selectPropertyNameStatement{ "SELECT name FROM propertyDeclarations WHERE propertyDeclarationId=?", database}; WriteStatement updatePropertyDeclarationTypeStatement{ - "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTypeNameId=?3 WHERE " - "propertyDeclarationId=?1", - database}; - ReadStatement<1> selectPropertyDeclarationIdStatement{ - "SELECT propertyDeclarationId FROM propertyDeclarations WHERE propertyDeclarationId=?", - database}; - ReadWriteStatement<3> updatePrototypeIdToNullStatement{ + "UPDATE propertyDeclarations SET propertyTypeId=?2 WHERE propertyDeclarationId=?1", database}; + ReadWriteStatement<2> updatePrototypeIdToNullStatement{ "UPDATE types SET prototypeId=NULL WHERE prototypeId=?1 RETURNING " - "typeId, prototypeNameId, sourceId", + "typeId, prototypeNameId", database}; - ReadStatement<1> selectTypeIdStatement{"SELECT typeId FROM types WHERE typeId=?", database}; - WriteStatement updateTypePrototypeStatement{ - "UPDATE types SET prototypeId=?2, prototypeNameId=?3 WHERE typeId=?1", database}; + WriteStatement updateTypePrototypeStatement{"UPDATE types SET prototypeId=?2 WHERE typeId=?1", + database}; mutable ReadStatement<1> selectTypeIdsForPrototypeChainIdStatement{ "WITH RECURSIVE " " prototypes(typeId) AS (" - " SELECT prototypeId FROM types WHERE typeId=? " + " SELECT prototypeId FROM types WHERE typeId=? AND prototypeId IS NOT NULL" " UNION ALL " - " SELECT prototypeId FROM types JOIN prototypes USING(typeId)) " + " SELECT prototypeId FROM types JOIN prototypes USING(typeId) WHERE prototypeId " + " IS NOT NULL)" "SELECT typeId FROM prototypes", database}; WriteStatement updatePropertyDeclarationAliasIdAndTypeNameIdStatement{ - "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, propertyTypeNameId=?3 " - "WHERE propertyDeclarationId=?1 AND (aliasPropertyDeclarationId IS NOT ?2 OR " - "propertyTypeNameId IS NOT ?3)", + "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, " + "propertyImportedTypeNameId=?3 WHERE propertyDeclarationId=?1 AND " + "(aliasPropertyDeclarationId IS NOT ?2 OR propertyImportedTypeNameId IS NOT ?3)", database}; WriteStatement updatetPropertiesDeclarationValuesOfAliasStatement{ "WITH RECURSIVE " @@ -2212,6 +2190,51 @@ public: "UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database}; ReadStatement<1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?", database}; + mutable ReadStatement<1> selectImportedTypeNameIdStatement{ + "SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 " + "AND name=?3 LIMIT 1", + database}; + mutable ReadWriteStatement<1> insertImportedTypeNameIdStatement{ + "INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) " + "RETURNING importedTypeNameId", + database}; + mutable ReadStatement<1> selectImportIdBySourceIdAndImportNameStatement{ + "SELECT importId FROM documentImports JOIN modules AS m USING(moduleId) WHERE sourceId=?1 " + "AND m.name=?2 AND majorVersion IS NULL AND minorVersion IS NULL LIMIT 1", + database}; + mutable ReadStatement<1> selectImportIdBySourceIdAndImportNameAndMajorVersionStatement{ + "SELECT importId FROM documentImports JOIN modules AS m USING(moduleId) WHERE sourceId=?1 " + "AND m.name=?2 AND majorVersion=?3 AND minorVersion IS NULL LIMIT 1", + database}; + mutable ReadStatement<1> selectImportIdBySourceIdAndImportNameAndVersionStatement{ + "SELECT importId FROM documentImports JOIN modules AS m USING(moduleId) WHERE sourceId=?1 " + "AND m.name=?2 AND majorVersion=?3 AND minorVersion=?4 LIMIT 1", + database}; + mutable ReadStatement<1> selectKindFromImportedTypeNamesStatement{ + "SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database}; + mutable ReadStatement<1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{ + "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON " + "importOrSourceId=importId JOIN exportedTypeNames AS etn USING(moduleId) WHERE " + "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND etn.kind=1 AND " + "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS " + "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, " + "etn.minorVersion DESC NULLS FIRST LIMIT 1", + database}; + mutable ReadStatement<1> selectTypeIdForImportedTypeNameNamesStatement{ + "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON " + "importOrSourceId=sourceId JOIN exportedTypeNames AS etn USING(moduleId) WHERE " + "itn.kind=1 AND importedTypeNameId=?1 AND itn.name=etn.name AND etn.kind=1 AND " + "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS " + "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, " + "etn.minorVersion DESC NULLS FIRST LIMIT 1", + database}; + mutable ReadStatement<1> selectTypeIdForNativeTypeNameNamesStatement{ + "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON " + "importOrSourceId=sourceId JOIN exportedTypeNames AS etn USING(moduleId) WHERE itn.kind=0 " + "AND importedTypeNameId=?1 AND itn.name=etn.name AND etn.kind=0 LIMIT 1", + database}; + WriteStatement deleteAllSourcesStatement{"DELETE FROM sources", database}; + WriteStatement deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database}; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h index 713a1f727c6..302a1801a2d 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h @@ -33,8 +33,8 @@ namespace QmlDesigner { class ProjectStorageInterface { public: - virtual void synchronize(Storage::ModuleDependencies moduleDependencies, - Storage::Documents documents, + virtual void synchronize(Storage::Modules modules, + Storage::Imports imports, Storage::Types types, SourceIds sourceIds, FileStatuses fileStatuses) diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h index 1303af720c7..e65f91276dd 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h @@ -43,7 +43,7 @@ enum class PropertyDeclarationTraits : unsigned int { IsList = 1 << 2 }; -enum class TypeNameKind { Native = 0, Exported = 1 }; +enum class TypeNameKind { Native = 0, Exported = 1, QualifiedExported = 2 }; constexpr PropertyDeclarationTraits operator|(PropertyDeclarationTraits first, PropertyDeclarationTraits second) @@ -60,15 +60,15 @@ class VersionNumber { public: explicit VersionNumber() = default; - explicit VersionNumber(int version) - : version{version} + explicit VersionNumber(int value) + : value{value} {} - explicit operator bool() const { return version >= 0; } + explicit operator bool() const { return value >= 0; } friend bool operator==(VersionNumber first, VersionNumber second) noexcept { - return first.version == second.version; + return first.value == second.value; } friend bool operator!=(VersionNumber first, VersionNumber second) noexcept @@ -76,8 +76,13 @@ public: return !(first == second); } + friend bool operator<(VersionNumber first, VersionNumber second) noexcept + { + return first.value < second.value; + } + public: - int version = -1; + int value = -1; }; class Version @@ -103,7 +108,12 @@ public: return first.major == second.major && first.minor == second.minor; } - explicit operator bool() { return major && minor; } + friend bool operator<(Version first, Version second) noexcept + { + return std::tie(first.major, first.minor) < std::tie(second.major, second.minor); + } + + explicit operator bool() const { return major && minor; } public: VersionNumber major; @@ -115,34 +125,147 @@ class Module public: explicit Module() = default; - explicit Module(Utils::SmallStringView name, VersionNumber version = VersionNumber{}) + explicit Module(Utils::SmallStringView name, SourceId sourceId = SourceId{}) : name{name} - , version{version} + , sourceId{sourceId} {} - explicit Module(Utils::SmallStringView name, int version) + explicit Module(Utils::SmallStringView name, int sourceId) : name{name} - , version{version} + , sourceId{sourceId} {} friend bool operator==(const Module &first, const Module &second) { - return first.name == second.name && first.version == second.version; + return first.name == second.name; } public: Utils::PathString name; - VersionNumber version; + SourceId sourceId; }; using Modules = std::vector; +enum class IsQualified : int { No, Yes }; + +inline int operator-(IsQualified first, IsQualified second) +{ + return static_cast(first) - static_cast(second); +} + +inline int operator<(IsQualified first, IsQualified second) +{ + return static_cast(first) < static_cast(second); +} + +class Import +{ +public: + explicit Import() = default; + + explicit Import(Utils::SmallStringView name, Version version, SourceId sourceId) + : name{name} + , version{version} + , sourceId{sourceId} + {} + + explicit Import(Utils::SmallStringView name, int majorVersion, int minorVersion, int sourceId) + : name{name} + , version{majorVersion, minorVersion} + , sourceId{sourceId} + {} + + friend bool operator==(const Import &first, const Import &second) + { + return first.name == second.name && first.version == second.version + && first.sourceId == second.sourceId; + } + +public: + Utils::PathString name; + Version version; + ModuleId moduleId; + SourceId sourceId; +}; + +using Imports = std::vector; + +class ImportView +{ +public: + explicit ImportView() = default; + + explicit ImportView(long long importId, int sourceId, int moduleId, int majorVersion, int minorVersion) + : importId{importId} + , sourceId{sourceId} + , moduleId{moduleId} + , version{majorVersion, minorVersion} + {} + + friend bool operator==(const ImportView &first, const ImportView &second) + { + return first.sourceId == second.sourceId && first.moduleId == second.moduleId + && first.version == second.version; + } + +public: + ImportId importId; + SourceId sourceId; + ModuleId moduleId; + Version version; +}; + +class ImportedType +{ +public: + explicit ImportedType() = default; + explicit ImportedType(Utils::SmallStringView name) + : name{name} + {} + + friend bool operator==(const ImportedType &first, const ImportedType &second) + { + return first.name == second.name; + } + +public: + Utils::SmallString name; +}; + +class QualifiedImportedType +{ +public: + explicit QualifiedImportedType() = default; + explicit QualifiedImportedType(Utils::SmallStringView name, Import import) + : name{name} + , import{std::move(import)} + {} + + friend bool operator==(const QualifiedImportedType &first, const QualifiedImportedType &second) + { + return first.name == second.name && first.import == second.import; + } + +public: + Utils::SmallString name; + Import import; +}; + +using ImportedTypes = std::vector; + class ExportedType { public: explicit ExportedType() = default; - explicit ExportedType(Utils::SmallStringView name) + explicit ExportedType(Utils::SmallStringView name, Version version = Version{}) : name{name} + , version{version} + {} + + explicit ExportedType(Utils::SmallStringView name, int majorVersion, int minorVersion) + : name{name} + , version{majorVersion, minorVersion} {} friend bool operator==(const ExportedType &first, const ExportedType &second) @@ -152,25 +275,7 @@ public: public: Utils::SmallString name; -}; - -class ExplicitExportedType -{ -public: - explicit ExplicitExportedType() = default; - explicit ExplicitExportedType(Utils::SmallStringView name, Module module) - : name{name} - , module{std::move(module)} - {} - - friend bool operator==(const ExplicitExportedType &first, const ExplicitExportedType &second) - { - return first.name == second.name && first.module == second.module; - } - -public: - Utils::SmallString name; - Module module; + Storage::Version version; }; using ExportedTypes = std::vector; @@ -192,7 +297,7 @@ public: Utils::SmallString name; }; -using TypeName = Utils::variant; +using ImportedTypeName = Utils::variant; class EnumeratorDeclaration { @@ -398,7 +503,7 @@ class PropertyDeclaration public: explicit PropertyDeclaration() = default; explicit PropertyDeclaration(Utils::SmallStringView name, - TypeName typeName, + ImportedTypeName typeName, PropertyDeclarationTraits traits) : name{name} , typeName{std::move(typeName)} @@ -407,7 +512,7 @@ public: {} explicit PropertyDeclaration(Utils::SmallStringView name, - TypeName typeName, + ImportedTypeName typeName, PropertyDeclarationTraits traits, Utils::SmallStringView aliasPropertyName) : name{name} @@ -429,7 +534,7 @@ public: {} explicit PropertyDeclaration(Utils::SmallStringView name, - TypeName aliasTypeName, + ImportedTypeName aliasTypeName, Utils::SmallStringView aliasPropertyName) : name{name} , typeName{std::move(aliasTypeName)} @@ -446,7 +551,7 @@ public: public: Utils::SmallString name; - TypeName typeName; + ImportedTypeName typeName; Utils::SmallString aliasPropertyName; PropertyDeclarationTraits traits = {}; TypeId typeId; @@ -476,7 +581,7 @@ public: Utils::SmallStringView name; PropertyDeclarationTraits traits = {}; TypeId typeId; - TypeNameId typeNameId; + ImportedTypeNameId typeNameId; PropertyDeclarationId id; PropertyDeclarationId aliasId; }; @@ -487,7 +592,7 @@ public: explicit Type() = default; explicit Type(Module module, Utils::SmallStringView typeName, - TypeName prototype, + ImportedTypeName prototype, TypeAccessSemantics accessSemantics, SourceId sourceId, ExportedTypes exportedTypes = {}, @@ -510,21 +615,19 @@ public: {} explicit Type(Utils::SmallStringView moduleName, - int moduleVersion, Utils::SmallStringView typeName, Utils::SmallStringView prototype, int accessSemantics, int sourceId) : typeName{typeName} , prototype{NativeType{prototype}} - , module{moduleName, moduleVersion} + , module{moduleName} , accessSemantics{static_cast(accessSemantics)} , sourceId{sourceId} {} explicit Type(Utils::SmallStringView moduleName, - int moduleVersion, Utils::SmallStringView typeName, long long typeId, Utils::SmallStringView prototype, @@ -532,7 +635,22 @@ public: int sourceId) : typeName{typeName} , prototype{NativeType{prototype}} - , module{moduleName, moduleVersion} + , module{moduleName} + , accessSemantics{static_cast(accessSemantics)} + , sourceId{sourceId} + , typeId{typeId} + {} + + explicit Type(Utils::SmallStringView moduleName, + int moduleId, + Utils::SmallStringView typeName, + long long typeId, + Utils::SmallStringView prototype, + int accessSemantics, + int sourceId) + : typeName{typeName} + , prototype{NativeType{prototype}} + , module{moduleName, moduleId} , accessSemantics{static_cast(accessSemantics)} , sourceId{sourceId} , typeId{typeId} @@ -551,7 +669,7 @@ public: public: Utils::SmallString typeName; - TypeName prototype; + ImportedTypeName prototype; ExportedTypes exportedTypes; PropertyDeclarations propertyDeclarations; FunctionDeclarations functionDeclarations; @@ -565,70 +683,21 @@ public: using Types = std::vector; -class Document -{ -public: - explicit Document() = default; - explicit Document(SourceId sourceId, Modules modules) - : modules{std::move(modules)} - , sourceId{sourceId} - {} - -public: - Modules modules; - SourceId sourceId; -}; - -using Documents = std::vector; - -class ModuleDependency : public Module -{ -public: - explicit ModuleDependency(Utils::SmallStringView name, - VersionNumber version, - SourceId sourceId, - Modules moduleDependencies = {}) - : Module(name, version) - , dependencies{std::move(moduleDependencies)} - , sourceId{sourceId} - {} - - explicit ModuleDependency(Utils::SmallStringView name, int version, int sourceId) - : Module(name, version) - , sourceId{sourceId} - {} - - friend bool operator==(const ModuleDependency &first, const ModuleDependency &second) - { - return static_cast(first) == static_cast(second) - && first.sourceId == second.sourceId && first.dependencies == second.dependencies; - } - -public: - Modules dependencies; - SourceId sourceId; -}; - -using ModuleDependencies = std::vector; - class ModuleView { public: - explicit ModuleView(Utils::SmallStringView name, int version, int sourceId) + explicit ModuleView(Utils::SmallStringView name, int sourceId) : name{name} - , version{version} , sourceId{sourceId} {} friend bool operator==(const ModuleView &first, const ModuleView &second) { - return first.name == second.name && first.version == second.version - && first.sourceId == second.sourceId; + return first.name == second.name && first.sourceId == second.sourceId; } public: Utils::SmallStringView name; - VersionNumber version; SourceId sourceId; }; diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp index da056777879..ee8e0c8fed1 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp @@ -52,8 +52,8 @@ ComponentReferences createComponentReferences(const QMultiHash(first) & static_cast(second); } -} // namespace - -static const char *typeAccessSemanticsFlagsToString(TypeAccessSemantics accessSemantics) +const char *typeAccessSemanticsFlagsToString(TypeAccessSemantics accessSemantics) { if (accessSemantics & TypeAccessSemantics::IsEnum) return "(IsEnum)"; @@ -1045,15 +1043,34 @@ static const char *typeAccessSemanticsFlagsToString(TypeAccessSemantics accessSe return ""; } +const char *isQualifiedToString(IsQualified isQualified) +{ + switch (isQualified) { + case IsQualified::No: + return "no"; + case IsQualified::Yes: + return "yes"; + } + + return ""; +} + +} // namespace + std::ostream &operator<<(std::ostream &out, TypeAccessSemantics accessSemantics) { return out << typeAccessSemanticsToString(accessSemantics) << typeAccessSemanticsFlagsToString(accessSemantics); } +std::ostream &operator<<(std::ostream &out, IsQualified isQualified) +{ + return out << isQualifiedToString(isQualified); +} + std::ostream &operator<<(std::ostream &out, VersionNumber versionNumber) { - return out << versionNumber.version; + return out << versionNumber.value; } std::ostream &operator<<(std::ostream &out, Version version) @@ -1066,16 +1083,20 @@ std::ostream &operator<<(std::ostream &out, const ExportedType &exportedType) return out << "(\"" << exportedType.name << "\")"; } -std::ostream &operator<<(std::ostream &out, const ExplicitExportedType &exportedType) -{ - return out << "(\"" << exportedType.name << "\", " << exportedType.module << ")"; -} - std::ostream &operator<<(std::ostream &out, const NativeType &nativeType) { return out << "(\"" << nativeType.name << "\")"; } +std::ostream &operator<<(std::ostream &out, const ImportedType &importedType) +{ + return out << "(\"" << importedType.name << ")"; +} +std::ostream &operator<<(std::ostream &out, const QualifiedImportedType &importedType) +{ + return out << "(\"" << importedType.name << "\", " << importedType.import << ")"; +} + std::ostream &operator<<(std::ostream &out, const Type &type) { using Utils::operator<<; @@ -1151,13 +1172,12 @@ std::ostream &operator<<(std::ostream &out, const EnumerationDeclaration &enumer std::ostream &operator<<(std::ostream &out, const Module &module) { - return out << "(" << module.name << ", " << module.version << ")"; + return out << "(" << module.name << ", " << module.sourceId << ")"; } -std::ostream &operator<<(std::ostream &out, const ModuleDependency &module) +std::ostream &operator<<(std::ostream &out, const Import &import) { - return out << "(" << module.name << ", " << module.version << ", " << module.sourceId << ", " - << module.dependencies << ")"; + return out << "(" << import.name << ", " << import.version << ", " << import.sourceId << ")"; } } // namespace Storage diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index 26ff0ec8c75..d2c20d92b5f 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -247,8 +247,9 @@ namespace Storage { class Type; class ExportedType; class NativeType; -class ExplicitExportedType; -using TypeName = Utils::variant; +class ImportedType; +class QualifiedImportedType; +using TypeName = Utils::variant; class Version; class VersionNumber; enum class TypeAccessSemantics : int; @@ -261,6 +262,8 @@ class EnumerationDeclaration; class EnumeratorDeclaration; class Module; class ModuleDependency; +class Import; +enum class IsQualified : int; std::ostream &operator<<(std::ostream &out, TypeAccessSemantics accessSemantics); std::ostream &operator<<(std::ostream &out, VersionNumber versionNumber); @@ -268,7 +271,8 @@ std::ostream &operator<<(std::ostream &out, Version version); std::ostream &operator<<(std::ostream &out, const Type &type); std::ostream &operator<<(std::ostream &out, const ExportedType &exportedType); std::ostream &operator<<(std::ostream &out, const NativeType &nativeType); -std::ostream &operator<<(std::ostream &out, const ExplicitExportedType &exportedType); +std::ostream &operator<<(std::ostream &out, const ImportedType &importedType); +std::ostream &operator<<(std::ostream &out, const QualifiedImportedType &importedType); std::ostream &operator<<(std::ostream &out, const PropertyDeclaration &propertyDeclaration); std::ostream &operator<<(std::ostream &out, PropertyDeclarationTraits traits); std::ostream &operator<<(std::ostream &out, const FunctionDeclaration &functionDeclaration); @@ -278,6 +282,8 @@ std::ostream &operator<<(std::ostream &out, const EnumerationDeclaration &enumer std::ostream &operator<<(std::ostream &out, const EnumeratorDeclaration &enumeratorDeclaration); std::ostream &operator<<(std::ostream &out, const Module &module); std::ostream &operator<<(std::ostream &out, const ModuleDependency &module); +std::ostream &operator<<(std::ostream &out, const Import &import); +std::ostream &operator<<(std::ostream &out, IsQualified isQualified); } // namespace Storage diff --git a/tests/unit/unittest/projectstorage-test.cpp b/tests/unit/unittest/projectstorage-test.cpp index 3a08fa4c3eb..dd570f4c4b6 100644 --- a/tests/unit/unittest/projectstorage-test.cpp +++ b/tests/unit/unittest/projectstorage-test.cpp @@ -42,6 +42,7 @@ using QmlDesigner::ModuleId; using QmlDesigner::PropertyDeclarationId; using QmlDesigner::SourceContextId; using QmlDesigner::SourceId; +using QmlDesigner::SourceIds; using QmlDesigner::TypeId; using QmlDesigner::Cache::Source; using QmlDesigner::Cache::SourceContext; @@ -49,6 +50,17 @@ using QmlDesigner::Storage::TypeAccessSemantics; namespace Storage = QmlDesigner::Storage; +Storage::Imports operator+(const Storage::Imports &first, const Storage::Imports &second) +{ + Storage::Imports imports; + imports.reserve(first.size() + second.size()); + + imports.insert(imports.end(), first.begin(), first.end()); + imports.insert(imports.end(), second.begin(), second.end()); + + return imports; +} + MATCHER_P2(IsSourceContext, id, value, @@ -84,7 +96,7 @@ MATCHER_P5(IsStorageType, return type.module == module && type.typeName == typeName && type.accessSemantics == accessSemantics && type.sourceId == sourceId - && Storage::TypeName{prototype} == type.prototype; + && Storage::ImportedTypeName{prototype} == type.prototype; } MATCHER_P4(IsStorageTypeWithInvalidSourceId, @@ -120,7 +132,7 @@ MATCHER_P3(IsPropertyDeclaration, const Storage::PropertyDeclaration &propertyDeclaration = arg; return propertyDeclaration.name == name - && Storage::TypeName{typeName} == propertyDeclaration.typeName + && Storage::ImportedTypeName{typeName} == propertyDeclaration.typeName && propertyDeclaration.traits == traits; } @@ -141,26 +153,23 @@ MATCHER_P4(IsPropertyDeclaration, && propertyDeclaration.traits == traits; } -MATCHER_P2(IsModule, - name, - version, - std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Module{name, version})) +MATCHER_P(IsModule, + name, + std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Module{name})) { const Storage::Module &module = arg; - return module.name == name && module.version == version; + return module.name == name; } -MATCHER_P3(IsModuleDependency, +MATCHER_P2(IsModule, name, - version, sourceId, - std::string(negation ? "isn't " : "is ") - + PrintToString(Storage::ModuleDependency{name, version, sourceId})) + std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Module{name, sourceId})) { - const Storage::ModuleDependency &module = arg; + const Storage::Module &module = arg; - return module.name == name && module.version == version && &module.sourceId == &sourceId; + return module.name == name; } class ProjectStorage : public testing::Test @@ -192,7 +201,14 @@ protected: auto createTypes() { - setUpModuleDependenciesAndDocuments(); + imports.emplace_back("Qml", Storage::Version{}, sourceId1); + imports.emplace_back("Qml", Storage::Version{}, sourceId2); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId1); + + importsSourceId1.emplace_back("Qml", Storage::Version{}, sourceId1); + importsSourceId1.emplace_back("QtQuick", Storage::Version{}, sourceId1); + + importsSourceId2.emplace_back("Qml", Storage::Version{}, sourceId2); return Storage::Types{ Storage::Type{ @@ -206,7 +222,7 @@ protected: Storage::NativeType{"QObject"}, Storage::PropertyDeclarationTraits::IsList}, Storage::PropertyDeclaration{"children", - Storage::ExportedType{"Item"}, + Storage::ImportedType{"Item"}, Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}}, {Storage::FunctionDeclaration{"execute", "", {Storage::ParameterDeclaration{"arg", ""}}}, @@ -220,7 +236,7 @@ protected: Storage::ParameterDeclaration{"arg3", "string"}}}}, {Storage::SignalDeclaration{"execute", {Storage::ParameterDeclaration{"arg", ""}}}, Storage::SignalDeclaration{ - "values", + "value0s", {Storage::ParameterDeclaration{"arg1", "int"}, Storage::ParameterDeclaration{"arg2", "QObject", @@ -232,20 +248,56 @@ protected: Storage::EnumerationDeclaration{"Type", {Storage::EnumeratorDeclaration{"Foo"}, Storage::EnumeratorDeclaration{"Poo", 12}}}}}, - Storage::Type{Storage::Module{"Qml", 2}, + Storage::Type{Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, sourceId2, - {Storage::ExportedType{"Object"}, Storage::ExportedType{"Obj"}}}}; + {Storage::ExportedType{"Object", Storage::Version{2}}, + Storage::ExportedType{"Obj", Storage::Version{2}}}}}; + } + + auto createVersionedTypes() + { + return Storage::Types{Storage::Type{Storage::Module{"Qml"}, + "QObject", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId1, + {Storage::ExportedType{"Object", Storage::Version{1}}, + Storage::ExportedType{"Obj", Storage::Version{1, 2}}, + Storage::ExportedType{"BuiltInObj", Storage::Version{}}}}, + Storage::Type{Storage::Module{"Qml"}, + "QObject2", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId1, + {Storage::ExportedType{"Object", Storage::Version{2, 0}}, + Storage::ExportedType{"Obj", Storage::Version{2, 3}}}}, + Storage::Type{Storage::Module{"Qml"}, + "QObject3", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId1, + {Storage::ExportedType{"Object", Storage::Version{2, 11}}, + Storage::ExportedType{"Obj", Storage::Version{2, 11}}}}, + Storage::Type{Storage::Module{"Qml"}, + "QObject4", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId1, + {Storage::ExportedType{"Object", Storage::Version{3, 4}}, + Storage::ExportedType{"Obj", Storage::Version{3, 4}}, + Storage::ExportedType{"BuiltInObj", + Storage::Version{3, 4}}}}}; } auto createTypesWithExportedTypeNamesOnly() { auto types = createTypes(); - types[0].prototype = Storage::ExportedType{"Object"}; - types[0].propertyDeclarations[0].typeName = Storage::ExportedType{"Object"}; + types[0].prototype = Storage::ImportedType{"Object"}; + types[0].propertyDeclarations[0].typeName = Storage::ImportedType{"Object"}; return types; } @@ -254,6 +306,18 @@ protected: { auto types = createTypes(); + imports.emplace_back("Qml", Storage::Version{}, sourceId3); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); + + imports.emplace_back("Qml", Storage::Version{}, sourceId4); + imports.emplace_back("/path/to", Storage::Version{}, sourceId4); + + importsSourceId3.emplace_back("Qml", Storage::Version{}, sourceId3); + importsSourceId3.emplace_back("QtQuick", Storage::Version{}, sourceId3); + + importsSourceId4.emplace_back("Qml", Storage::Version{}, sourceId4); + importsSourceId4.emplace_back("/path/to", Storage::Version{}, sourceId4); + types[1].propertyDeclarations.push_back( Storage::PropertyDeclaration{"objects", Storage::NativeType{"QObject"}, @@ -261,7 +325,7 @@ protected: types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QAliasItem", - Storage::ExportedType{"Item"}, + Storage::ImportedType{"Item"}, TypeAccessSemantics::Reference, sourceId3, {Storage::ExportedType{"AliasItem"}}}); @@ -270,9 +334,9 @@ protected: Storage::NativeType{"QObject"}, Storage::PropertyDeclarationTraits::IsList}); types.back().propertyDeclarations.push_back( - Storage::PropertyDeclaration{"items", Storage::ExportedType{"Item"}, "children"}); + Storage::PropertyDeclaration{"items", Storage::ImportedType{"Item"}, "children"}); types.back().propertyDeclarations.push_back( - Storage::PropertyDeclaration{"objects", Storage::ExportedType{"Item"}, "objects"}); + Storage::PropertyDeclaration{"objects", Storage::ImportedType{"Item"}, "objects"}); types.push_back( Storage::Type{Storage::Module{"/path/to"}, @@ -291,16 +355,19 @@ protected: auto createTypesWithRecursiveAliases() { + imports.emplace_back("Qml", Storage::Version{}, sourceId5); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId5); + auto types = createTypesWithAliases(); types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QAliasItem2", - Storage::ExportedType{"Object"}, + Storage::ImportedType{"Object"}, TypeAccessSemantics::Reference, sourceId5, {Storage::ExportedType{"AliasItem2"}}}); types.back().propertyDeclarations.push_back( - Storage::PropertyDeclaration{"objects", Storage::ExportedType{"AliasItem"}, "objects"}); + Storage::PropertyDeclaration{"objects", Storage::ImportedType{"AliasItem"}, "objects"}); return types; } @@ -314,86 +381,34 @@ protected: return types; } - auto createModuleDependencies() - { - moduleSourceId1 = sourcePathCache.sourceId(modulePath1); - moduleSourceId2 = sourcePathCache.sourceId(modulePath2); - moduleSourceId3 = sourcePathCache.sourceId(modulePath3); - moduleSourceId5 = sourcePathCache.sourceId("/path/to/."); - - return Storage::ModuleDependencies{ - Storage::ModuleDependency{"Qml", Storage::VersionNumber{2}, moduleSourceId1, {}}, - Storage::ModuleDependency{"QtQuick", - Storage::VersionNumber{}, - moduleSourceId2, - {Storage::Module{"Qml", Storage::VersionNumber{2}}}}, - Storage::ModuleDependency{"/path/to", - Storage::VersionNumber{}, - moduleSourceId5, - {Storage::Module{"QtQuick"}, - Storage::Module{"Qml", Storage::VersionNumber{2}}}}}; - } - Storage::Modules createModules() { - return Storage::Modules{Storage::Module{"Qml", Storage::VersionNumber{2}}, - Storage::Module{"QtQuick", Storage::VersionNumber{}}, - Storage::Module{"/path/to", Storage::VersionNumber{}}}; + return Storage::Modules{Storage::Module{"Qml", moduleSourceId1}, + Storage::Module{"QtQuick", moduleSourceId2}, + Storage::Module{"/path/to", moduleSourceId3}}; } - auto createModuleDependencies2() + Storage::Imports createImports(SourceId sourceId) { - moduleSourceId4 = sourcePathCache.sourceId(modulePath4); - - auto newModuleDependencies = createModuleDependencies(); - newModuleDependencies.push_back( - Storage::ModuleDependency{"Qml2", Storage::VersionNumber{3}, moduleSourceId4, {}}); - - return newModuleDependencies; + return Storage::Imports{Storage::Import{"Qml", Storage::Version{2}, sourceId}, + Storage::Import{"QtQuick", Storage::Version{}, sourceId}, + Storage::Import{"/path/to", Storage::Version{}, sourceId}}; } - void setUpSourceIds() + static Storage::Imports createImports(const SourceIds &sourceIds) { - sourceId1 = sourcePathCache.sourceId(path1); - sourceId2 = sourcePathCache.sourceId(path2); - sourceId3 = sourcePathCache.sourceId(path3); - sourceId4 = sourcePathCache.sourceId(path4); - sourceId5 = sourcePathCache.sourceId(path5); + Storage::Imports imports; + imports.reserve(3 * sourceIds.size()); + + for (SourceId sourceId : sourceIds) { + imports.emplace_back("Qml", Storage::Version{2}, sourceId); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId); + imports.emplace_back("/path/to", Storage::Version{}, sourceId); + } + + return imports; } - void setUpModuleDependenciesAndDocuments() - { - setUpModules(); - setUpSourceIds(); - - moduleDependencies = createModuleDependencies(); - - documents = {Storage::Document{sourceId1, modules}, - Storage::Document{sourceId2, modules}, - Storage::Document{sourceId3, modules}, - Storage::Document{sourceId4, modules}, - Storage::Document{sourceId5, modules}}; - - storage.synchronize(moduleDependencies, - documents, - {}, - {sourceId1, - sourceId2, - sourceId3, - sourceId4, - sourceId5, - moduleSourceId1, - moduleSourceId2, - moduleSourceId5}, - {}); - moduleIds = storage.fetchModuleIds(modules); - moduleId1 = moduleIds[0]; - moduleId2 = moduleIds[1]; - moduleId3 = moduleIds[2]; - } - - void setUpModules() { modules = createModules(); } - template static FileStatuses convert(const Range &range) { @@ -410,27 +425,32 @@ protected: QmlDesigner::SourcePathView path3{"/path3/to"}; QmlDesigner::SourcePathView path4{"/path4/to"}; QmlDesigner::SourcePathView path5{"/path5/to"}; - SourceId sourceId1; - SourceId sourceId2; - SourceId sourceId3; - SourceId sourceId4; - SourceId sourceId5; QmlDesigner::SourcePathView modulePath1{"/module/path1/to"}; QmlDesigner::SourcePathView modulePath2{"/module/path2/to"}; QmlDesigner::SourcePathView modulePath3{"/module/aaaa/to"}; QmlDesigner::SourcePathView modulePath4{"/module/ooo/to"}; - SourceId moduleSourceId1; - SourceId moduleSourceId2; - SourceId moduleSourceId3; - SourceId moduleSourceId4; - SourceId moduleSourceId5; - Storage::Modules modules; - ModuleId moduleId1; - ModuleId moduleId2; - ModuleId moduleId3; - Storage::ModuleDependencies moduleDependencies; - Storage::Documents documents; - QmlDesigner::ModuleIds moduleIds; + QmlDesigner::SourcePathView modulePath5{"/module/xxx/to"}; + SourceId sourceId1{sourcePathCache.sourceId(path1)}; + SourceId sourceId2{sourcePathCache.sourceId(path2)}; + SourceId sourceId3{sourcePathCache.sourceId(path3)}; + SourceId sourceId4{sourcePathCache.sourceId(path4)}; + SourceId sourceId5{sourcePathCache.sourceId(path5)}; + SourceIds sourceIds{sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}; + SourceId moduleSourceId1{sourcePathCache.sourceId(modulePath1)}; + SourceId moduleSourceId2{sourcePathCache.sourceId(modulePath2)}; + SourceId moduleSourceId3{sourcePathCache.sourceId(modulePath3)}; + SourceId moduleSourceId4{sourcePathCache.sourceId(modulePath4)}; + SourceId moduleSourceId5{sourcePathCache.sourceId(modulePath5)}; + Storage::Modules modules{createModules()}; + QmlDesigner::ModuleIds moduleIds{storage.fetchModuleIds(modules)}; + ModuleId moduleId1{moduleIds[0]}; + ModuleId moduleId2{moduleIds[1]}; + ModuleId moduleId3{moduleIds[2]}; + Storage::Imports imports; + Storage::Imports importsSourceId1; + Storage::Imports importsSourceId2; + Storage::Imports importsSourceId3; + Storage::Imports importsSourceId4; }; TEST_F(ProjectStorage, FetchSourceContextIdReturnsAlwaysTheSameIdForTheSamePath) @@ -468,6 +488,8 @@ TEST_F(ProjectStorage, FetchUnknownSourceContextPathThrows) TEST_F(ProjectStorage, FetchAllSourceContextsAreEmptyIfNoSourceContextsExists) { + storage.clearSources(); + auto sourceContexts = storage.fetchAllSourceContexts(); ASSERT_THAT(toValues(sourceContexts), IsEmpty()); @@ -475,6 +497,7 @@ TEST_F(ProjectStorage, FetchAllSourceContextsAreEmptyIfNoSourceContextsExists) TEST_F(ProjectStorage, FetchAllSourceContexts) { + storage.clearSources(); auto sourceContextId = storage.fetchSourceContextId("/path/to"); auto sourceContextId2 = storage.fetchSourceContextId("/path/to2"); @@ -570,6 +593,8 @@ TEST_F(ProjectStorage, FetchSourceContextIdForExistingSourceId) TEST_F(ProjectStorage, FetchAllSources) { + storage.clearSources(); + auto sources = storage.fetchAllSources(); ASSERT_THAT(toValues(sources), IsEmpty()); @@ -635,10 +660,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypes) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -658,12 +687,16 @@ TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypes) TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesWithExportedPrototypeName) { Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExportedType{"Object"}; + types[0].prototype = Storage::ImportedType{"Object"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + importsSourceId1, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -680,38 +713,54 @@ TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesWithExportedPrototypeName) UnorderedElementsAre(IsExportedType("Item")))))); } -TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesThrowsWithWrongExportedPrototypeName) +TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesThrowsWithWrongPrototypeName) { Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExportedType{"Objec"}; + types[0].prototype = Storage::ImportedType{"Objec"}; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesWithMissingModuleAndExportedPrototypeName) +TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesWithMissingModuleAndPrototypeName) { Storage::Types types{createTypes()}; types.push_back(Storage::Type{Storage::Module{"/path/to"}, "QObject2", Storage::NativeType{}, TypeAccessSemantics::Reference, - sourceId4, + sourceId3, {Storage::ExportedType{"Object2"}, Storage::ExportedType{"Obj2"}}}); - storage.synchronize({}, {Storage::Document{sourceId1, {modules[0]}}}, {}, {sourceId1}, {}); - types[1].prototype = Storage::ExportedType{"Object2"}; + storage.synchronize(modules, + imports, + {}, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[1].prototype = Storage::ImportedType{"Object2"}; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesWithMissingModule) { Storage::Types types{createTypes()}; - storage.synchronize({}, {Storage::Document{sourceId1, {modules[0]}}}, {}, {sourceId1}, {}); + storage.synchronize(modules, + imports, + {}, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), - QmlDesigner::TypeNameDoesNotExists); + ASSERT_THROW(storage.synchronize({}, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), + QmlDesigner::ModuleDoesNotExists); } TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesReverseOrder) @@ -719,10 +768,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesReverseOrder) Storage::Types types{createTypes()}; std::reverse(types.begin(), types.end()); - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -742,14 +795,18 @@ TEST_F(ProjectStorage, SynchronizeTypesAddsNewTypesReverseOrder) TEST_F(ProjectStorage, SynchronizeTypesOverwritesTypeAccessSemantics) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].accessSemantics = TypeAccessSemantics::Value; types[1].accessSemantics = TypeAccessSemantics::Value; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize({}, imports, types, {sourceId1, sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Value, @@ -769,14 +826,22 @@ TEST_F(ProjectStorage, SynchronizeTypesOverwritesTypeAccessSemantics) TEST_F(ProjectStorage, SynchronizeTypesOverwritesSources) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].sourceId = sourceId3; types[1].sourceId = sourceId4; + Storage::Imports newImports; + newImports.emplace_back("Qml", Storage::Version{}, sourceId3); + newImports.emplace_back("Qml", Storage::Version{}, sourceId4); + newImports.emplace_back("QtQuick", Storage::Version{}, sourceId3); - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize({}, newImports, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -796,7 +861,11 @@ TEST_F(ProjectStorage, SynchronizeTypesOverwritesSources) TEST_F(ProjectStorage, SynchronizeTypesInsertTypeIntoPrototypeChain) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].prototype = Storage::NativeType{"QQuickObject"}; types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QQuickObject", @@ -805,10 +874,10 @@ TEST_F(ProjectStorage, SynchronizeTypesInsertTypeIntoPrototypeChain) sourceId1, {Storage::ExportedType{"Object"}}}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize({}, importsSourceId1, {types[0], types[2]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -832,10 +901,13 @@ TEST_F(ProjectStorage, SynchronizeTypesInsertTypeIntoPrototypeChain) UnorderedElementsAre(IsExportedType("Item")))))); } -TEST_F(ProjectStorage, SynchronizeTypesAddExplicitPrototype) +TEST_F(ProjectStorage, SynchronizeTypesAddQualifiedPrototype) { Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"QtQuick"}}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"QtQuick", + Storage::Version{}, + sourceId1}}; types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QQuickObject", Storage::NativeType{"QObject"}, @@ -843,10 +915,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddExplicitPrototype) sourceId1, {Storage::ExportedType{"Object"}}}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -872,7 +948,6 @@ TEST_F(ProjectStorage, SynchronizeTypesAddExplicitPrototype) TEST_F(ProjectStorage, SynchronizeTypesThrowsForMissingPrototype) { - setUpModuleDependenciesAndDocuments(); sourceId1 = sourcePathCache.sourceId(path1); Storage::Types types{Storage::Type{Storage::Module{"QtQuick"}, "QQuickItem", @@ -881,7 +956,11 @@ TEST_F(ProjectStorage, SynchronizeTypesThrowsForMissingPrototype) sourceId1, {Storage::ExportedType{"Item"}}}}; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1}, {}), + ASSERT_THROW(storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } @@ -895,7 +974,7 @@ TEST_F(ProjectStorage, SynchronizeTypesThrowsForMissingModule) sourceId1, {Storage::ExportedType{"Item"}}}}; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1}, {}), + ASSERT_THROW(storage.synchronize({}, imports, types, {sourceId1}, {}), QmlDesigner::ModuleDoesNotExists); } @@ -908,19 +987,28 @@ TEST_F(ProjectStorage, TypeWithInvalidSourceIdThrows) SourceId{}, {Storage::ExportedType{"Item"}}}}; - ASSERT_THROW(storage.synchronize({}, {}, types, {}, {}), QmlDesigner::TypeHasInvalidSourceId); + ASSERT_THROW(storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), + QmlDesigner::TypeHasInvalidSourceId); } TEST_F(ProjectStorage, DeleteTypeIfSourceIdIsSynchronized) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types.erase(types.begin()); - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize({}, importsSourceId2, types, {sourceId1, sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -933,13 +1021,17 @@ TEST_F(ProjectStorage, DeleteTypeIfSourceIdIsSynchronized) TEST_F(ProjectStorage, DontDeleteTypeIfSourceIdIsNotSynchronized) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types.pop_back(); - storage.synchronize({}, {}, types, {sourceId1}, {}); + storage.synchronize({}, importsSourceId1, types, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -959,13 +1051,17 @@ TEST_F(ProjectStorage, DontDeleteTypeIfSourceIdIsNotSynchronized) TEST_F(ProjectStorage, UpdateExportedTypesIfTypeNameChanges) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].typeName = "QQuickItem2"; - storage.synchronize({}, {}, {types[0]}, {sourceId1}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, + UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, TypeAccessSemantics::Reference, @@ -985,10 +1081,14 @@ TEST_F(ProjectStorage, UpdateExportedTypesIfTypeNameChanges) TEST_F(ProjectStorage, BreakingPrototypeChainByDeletingBaseComponentThrows) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId1, types, {sourceId1, sourceId2}, {}), QmlDesigner::TypeNameDoesNotExists); } @@ -996,7 +1096,11 @@ TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarations) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -1017,30 +1121,38 @@ TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarations) | Storage::PropertyDeclarationTraits::IsReadOnly)))))); } -TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationsWithMissingModuleIdsForNativeTypes) +TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationsWithMissingImportsForNativeTypes) { Storage::Types types{createTypes()}; - storage.synchronize({}, {Storage::Document{sourceId1, {}}}, {}, {sourceId1}, {}); types[0].propertyDeclarations.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {}, {}), QmlDesigner::TypeNameDoesNotExists); + ASSERT_THROW(storage.synchronize(modules, + {}, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), + QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationsWithMissingModuleIdsForExportedTypes) +TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationsWithMissingImportsForExportedTypes) { Storage::Types types{createTypes()}; - storage.synchronize({}, {Storage::Document{sourceId1, {modules[0]}}}, {}, {sourceId1}, {}); - types[0].propertyDeclarations[0].typeName = Storage::ExportedType{"Obj"}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[0].propertyDeclarations[0].typeName = Storage::ImportedType{"Obj"}; - ASSERT_THROW(storage.synchronize({}, {}, types, {}, {}), QmlDesigner::TypeNameDoesNotExists); + ASSERT_THROW(storage.synchronize({}, {}, {types[0]}, {sourceId1}, {}), + QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationExplicitType) +TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationQualifiedType) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "QtQuick"}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"QtQuick", Storage::Version{}, sourceId1}}; types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QQuickObject", Storage::NativeType{"QObject"}, @@ -1048,7 +1160,11 @@ TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationExplicitType) sourceId1, {Storage::ExportedType{"Object"}}}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -1072,11 +1188,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddPropertyDeclarationExplicitType) TEST_F(ProjectStorage, SynchronizeTypesChangesPropertyDeclarationType) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations[0].typeName = Storage::NativeType{"QQuickItem"}; - storage.synchronize({}, {}, types, {}, {}); - + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains( AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1099,10 +1218,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesPropertyDeclarationType) TEST_F(ProjectStorage, SynchronizeTypesChangesDeclarationTraits) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsPointer; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -1126,11 +1249,15 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesDeclarationTraits) TEST_F(ProjectStorage, SynchronizeTypesChangesDeclarationTraitsAndType) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsPointer; types[0].propertyDeclarations[0].typeName = Storage::NativeType{"QQuickItem"}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -1154,10 +1281,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesDeclarationTraitsAndType) TEST_F(ProjectStorage, SynchronizeTypesRemovesAPropertyDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1175,13 +1306,17 @@ TEST_F(ProjectStorage, SynchronizeTypesRemovesAPropertyDeclaration) TEST_F(ProjectStorage, SynchronizeTypesAddsAPropertyDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations.push_back( Storage::PropertyDeclaration{"object", Storage::NativeType{"QObject"}, Storage::PropertyDeclarationTraits::IsPointer}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT( storage.fetchTypes(), @@ -1208,10 +1343,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddsAPropertyDeclaration) TEST_F(ProjectStorage, SynchronizeTypesRenameAPropertyDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations[1].name = "objects"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -1238,52 +1377,74 @@ TEST_F(ProjectStorage, UsingNonExistingNativePropertyTypeThrows) types[0].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; types.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + importsSourceId1, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, UsingNonExistingExportedPropertyTypeThrows) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExportedType{"QObject2"}; + types[0].propertyDeclarations[0].typeName = Storage::ImportedType{"QObject2"}; types.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + importsSourceId1, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, UsingNonExistingExplicitExportedPropertyTypeWithWrongNameThrows) +TEST_F(ProjectStorage, UsingNonExistingQualifiedExportedPropertyTypeWithWrongNameThrows) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"QObject2", - Storage::Module{ - "Qml"}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "QObject2", Storage::Import{"Qml", Storage::Version{}, sourceId1}}; types.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + importsSourceId1, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, UsingNonExistingExplicitExportedPropertyTypeWithWrongModuleThrows) +TEST_F(ProjectStorage, UsingNonExistingQualifiedExportedPropertyTypeWithWrongModuleThrows) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"QObject", - Storage::Module{ - "QtQuick"}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "QObject", Storage::Import{"QtQuick", Storage::Version{}, sourceId1}}; types.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + importsSourceId1, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, BreakingPropertyDeclarationTypeDependencyByDeletingTypeThrows) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].prototype = Storage::NativeType{}; types.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + importsSourceId1, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } @@ -1291,7 +1452,11 @@ TEST_F(ProjectStorage, SynchronizeTypesAddFunctionDeclarations) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1307,10 +1472,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddFunctionDeclarations) TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationReturnType) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].returnTypeName = "item"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1326,10 +1495,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationReturnType) TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].name = "name"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1345,10 +1518,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationName) TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationPopParameters) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].parameters.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1364,10 +1541,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationPopParameters) TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationAppendParameters) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].parameters.push_back(Storage::ParameterDeclaration{"arg4", "int"}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1383,10 +1564,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationAppendParameter TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationChangeParameterName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].parameters[0].name = "other"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1402,10 +1587,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationChangeParameter TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationChangeParameterTypeName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].parameters[0].name = "long long"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1421,10 +1610,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationChangeParameter TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationChangeParameterTraits) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations[1].parameters[0].traits = QmlDesigner::Storage::PropertyDeclarationTraits::IsList; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1440,10 +1633,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesFunctionDeclarationChangeParameter TEST_F(ProjectStorage, SynchronizeTypesRemovesFunctionDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1458,11 +1655,15 @@ TEST_F(ProjectStorage, SynchronizeTypesRemovesFunctionDeclaration) TEST_F(ProjectStorage, SynchronizeTypesAddFunctionDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].functionDeclarations.push_back( Storage::FunctionDeclaration{"name", "string", {Storage::ParameterDeclaration{"arg", "int"}}}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1480,7 +1681,11 @@ TEST_F(ProjectStorage, SynchronizeTypesAddSignalDeclarations) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1496,10 +1701,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddSignalDeclarations) TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations[1].name = "name"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1515,10 +1724,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationName) TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationPopParameters) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations[1].parameters.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1534,10 +1747,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationPopParameters) TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationAppendParameters) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations[1].parameters.push_back(Storage::ParameterDeclaration{"arg4", "int"}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1553,10 +1770,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationAppendParameters) TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationChangeParameterName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations[1].parameters[0].name = "other"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1572,10 +1793,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationChangeParameterNa TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationChangeParameterTypeName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations[1].parameters[0].typeName = "long long"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1591,10 +1816,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationChangeParameterTy TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationChangeParameterTraits) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations[1].parameters[0].traits = QmlDesigner::Storage::PropertyDeclarationTraits::IsList; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1610,10 +1839,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesSignalDeclarationChangeParameterTr TEST_F(ProjectStorage, SynchronizeTypesRemovesSignalDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1628,11 +1861,15 @@ TEST_F(ProjectStorage, SynchronizeTypesRemovesSignalDeclaration) TEST_F(ProjectStorage, SynchronizeTypesAddSignalDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].signalDeclarations.push_back( Storage::SignalDeclaration{"name", {Storage::ParameterDeclaration{"arg", "int"}}}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1650,7 +1887,11 @@ TEST_F(ProjectStorage, SynchronizeTypesAddEnumerationDeclarations) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1666,10 +1907,14 @@ TEST_F(ProjectStorage, SynchronizeTypesAddEnumerationDeclarations) TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].name = "Name"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1685,10 +1930,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationName) TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationPopEnumeratorDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].enumeratorDeclarations.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1704,11 +1953,15 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationPopEnumerato TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationAppendEnumeratorDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].enumeratorDeclarations.push_back( Storage::EnumeratorDeclaration{"Haa", 54}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1724,10 +1977,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationAppendEnumer TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationChangeEnumeratorDeclarationName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].enumeratorDeclarations[0].name = "Hoo"; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1743,10 +2000,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationChangeEnumer TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationChangeEnumeratorDeclarationValue) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].enumeratorDeclarations[1].value = 11; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1763,11 +2024,15 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationAddThatEnumeratorDeclarationHasValue) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].enumeratorDeclarations[0].value = 11; types[0].enumerationDeclarations[1].enumeratorDeclarations[0].hasValue = true; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1784,10 +2049,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangesEnumerationDeclarationRemoveThatEnumeratorDeclarationHasValue) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations[1].enumeratorDeclarations[0].hasValue = false; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1803,10 +2072,14 @@ TEST_F(ProjectStorage, TEST_F(ProjectStorage, SynchronizeTypesRemovesEnumerationDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations.pop_back(); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1821,11 +2094,15 @@ TEST_F(ProjectStorage, SynchronizeTypesRemovesEnumerationDeclaration) TEST_F(ProjectStorage, SynchronizeTypesAddEnumerationDeclaration) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].enumerationDeclarations.push_back( Storage::EnumerationDeclaration{"name", {Storage::EnumeratorDeclaration{"Foo", 98, true}}}); - storage.synchronize({}, {}, types, {}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -1841,470 +2118,152 @@ TEST_F(ProjectStorage, SynchronizeTypesAddEnumerationDeclaration) TEST_F(ProjectStorage, SynchronizeModulesAddModules) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; + Storage::Modules modules{createModules()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId5}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5))); + UnorderedElementsAre(IsModule("Qml", moduleSourceId1), + IsModule("QtQuick", moduleSourceId2), + IsModule("/path/to", moduleSourceId3))); } TEST_F(ProjectStorage, SynchronizeModulesAddModulesAgain) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); + Storage::Modules modules{createModules()}; + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5))); + UnorderedElementsAre(IsModule("Qml", moduleSourceId1), + IsModule("QtQuick", moduleSourceId2), + IsModule("/path/to", moduleSourceId3))); } TEST_F(ProjectStorage, SynchronizeModulesUpdateToMoreModules) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - moduleDependencies.push_back( - Storage::ModuleDependency{"QtQuick.Foo", Storage::VersionNumber{1}, moduleSourceId3}); + Storage::Modules modules{createModules()}; + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); + modules.push_back(Storage::Module{"QtQuick.Foo", moduleSourceId4}); - storage.synchronize(moduleDependencies, + storage.synchronize(modules, {}, {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId3, moduleSourceId5}, + {moduleSourceId1, moduleSourceId2, moduleSourceId3, moduleSourceId4}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - IsModuleDependency("QtQuick.Foo", Storage::VersionNumber{1}, moduleSourceId3))); + UnorderedElementsAre(IsModule("Qml", moduleSourceId1), + IsModule("QtQuick", moduleSourceId2), + IsModule("/path/to", moduleSourceId3), + IsModule("QtQuick.Foo", moduleSourceId4))); } TEST_F(ProjectStorage, SynchronizeModulesAddOneMoreModules) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto newModuleDependency = Storage::ModuleDependency{"QtQuick.Foo", - Storage::VersionNumber{1}, - moduleSourceId3}; + Storage::Modules modules{createModules()}; + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); + auto newModule = Storage::Module{"QtQuick.Foo", moduleSourceId4}; - storage.synchronize({newModuleDependency}, {}, {}, {moduleSourceId3}, {}); + storage.synchronize({newModule}, {}, {}, {moduleSourceId4}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - IsModuleDependency("QtQuick.Foo", Storage::VersionNumber{1}, moduleSourceId3))); -} - -TEST_F(ProjectStorage, SynchronizeModulesAddSameModuleNameButDifferentVersion) -{ - auto moduleSourceIdQml4 = sourcePathCache.sourceId("/path/Qml.4"); - auto moduleSourceIdQml3 = sourcePathCache.sourceId("/path/Qml.3"); - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - moduleDependencies.push_back( - Storage::ModuleDependency{"Qml", Storage::VersionNumber{4}, moduleSourceIdQml4}); - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto newModuleDependency = Storage::ModuleDependency{"Qml", - Storage::VersionNumber{3}, - moduleSourceIdQml3}; - - storage.synchronize({newModuleDependency}, {}, {}, {moduleSourceIdQml4, moduleSourceIdQml3}, {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("Qml", Storage::VersionNumber{3}, moduleSourceIdQml3), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5))); + UnorderedElementsAre(IsModule("Qml", moduleSourceId1), + IsModule("QtQuick", moduleSourceId2), + IsModule("/path/to", moduleSourceId3), + IsModule("QtQuick.Foo", moduleSourceId4))); } TEST_F(ProjectStorage, SynchronizeModulesRemoveModule) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); + Storage::Modules modules{createModules()}; + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); - storage.synchronize({}, {}, {}, {moduleSourceId5}, {}); + storage.synchronize({}, {}, {}, {moduleSourceId3}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2))); + UnorderedElementsAre(IsModule("Qml", moduleSourceId1), + IsModule("QtQuick", moduleSourceId2))); } TEST_F(ProjectStorage, SynchronizeModulesChangeSourceId) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - moduleDependencies[1].sourceId = moduleSourceId3; + Storage::Modules modules{createModules()}; + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); + modules[1].sourceId = moduleSourceId4; - storage.synchronize({moduleDependencies[1]}, {}, {}, {moduleSourceId2, moduleSourceId3}, {}); + storage.synchronize({modules[1]}, {}, {}, {moduleSourceId2, moduleSourceId4}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId3), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5))); + UnorderedElementsAre(IsModule("Qml", moduleSourceId1), + IsModule("QtQuick", moduleSourceId4), + IsModule("/path/to", moduleSourceId3))); } TEST_F(ProjectStorage, SynchronizeModulesChangeName) { - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - moduleDependencies[0].name = "Qml2"; - moduleDependencies[1].dependencies[0].name = "Qml2"; - moduleDependencies[2].dependencies[1].name = "Qml2"; + Storage::Modules modules{createModules()}; + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); + modules[0].name = "Qml2"; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); + storage.synchronize(modules, {}, {}, {moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml2", Storage::VersionNumber{2}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5))); -} - -TEST_F(ProjectStorage, SynchronizeModulesChangeVersion) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - moduleDependencies[0].version = Storage::VersionNumber{3}; - moduleDependencies[1].dependencies[0].version = Storage::VersionNumber{3}; - moduleDependencies[2].dependencies[1].version = Storage::VersionNumber{3}; - - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - IsModuleDependency("Qml", Storage::VersionNumber{3}, moduleSourceId1), - IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5))); -} - -TEST_F(ProjectStorage, SynchronizeModulesAddModuleDependecies) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - ElementsAre(IsModule("Qml", Storage::VersionNumber{2})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("QtQuick", Storage::VersionNumber{})))))); -} - -TEST_F(ProjectStorage, SynchronizeModulesAddModuleDependeciesWhichDoesNotExitsThrows) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - moduleDependencies[1].dependencies.push_back(Storage::Module{"QmlBase", Storage::VersionNumber{2}}); - - ASSERT_THROW(storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}), - QmlDesigner::ModuleDoesNotExists); -} - -TEST_F(ProjectStorage, SynchronizeModulesRemovesDependeciesForRemovedModules) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto last = moduleDependencies.back(); - moduleDependencies.pop_back(); - storage.synchronize({}, {}, {}, {moduleSourceId5}, {}); - last.dependencies.pop_back(); - moduleDependencies.push_back(last); - - storage.synchronize({moduleDependencies[2]}, {}, {}, {moduleSourceId5}, {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - ElementsAre(IsModule("Qml", Storage::VersionNumber{2})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("QtQuick", Storage::VersionNumber{})))))); -} - -TEST_F(ProjectStorage, SynchronizeModulesAddMoreModuleDependecies) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto moduleSourceIdQmlBase = sourcePathCache.sourceId("/path/QmlBase"); - moduleDependencies.push_back( - Storage::ModuleDependency{"QmlBase", Storage::VersionNumber{2}, moduleSourceIdQmlBase}); - moduleDependencies[1].dependencies.push_back(Storage::Module{"QmlBase", Storage::VersionNumber{2}}); - - storage.synchronize({moduleDependencies[1], moduleDependencies[3]}, - {}, - {}, - {moduleSourceId2, moduleSourceIdQmlBase}, - {}); - - ASSERT_THAT( - storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QmlBase", Storage::VersionNumber{2}, moduleSourceIdQmlBase), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("QmlBase", Storage::VersionNumber{2})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("QtQuick", Storage::VersionNumber{})))))); -} - -TEST_F(ProjectStorage, SynchronizeModulesAddMoreModuleDependeciesWithDifferentVersionNumber) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto moduleSourceIdQml3 = sourcePathCache.sourceId("/path/Qml.3"); - moduleDependencies.push_back( - Storage::ModuleDependency{"Qml", Storage::VersionNumber{3}, moduleSourceIdQml3, {}}); - moduleDependencies[1].dependencies.push_back(Storage::Module{"Qml", Storage::VersionNumber{3}}); - - storage.synchronize({moduleDependencies[1], moduleDependencies[3]}, - {}, - {}, - {moduleSourceId2, moduleSourceIdQml3}, - {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{3}, moduleSourceIdQml3), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("Qml", Storage::VersionNumber{3})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("QtQuick", Storage::VersionNumber{})))))); -} - -TEST_F(ProjectStorage, SynchronizeModulesDependencyGetsHighestVersionIfNoVersionIsSupplied) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto moduleSourceIdQml3 = sourcePathCache.sourceId("/path/Qml.3"); - moduleDependencies.push_back( - Storage::ModuleDependency{"Qml", Storage::VersionNumber{3}, moduleSourceIdQml3, {}}); - moduleDependencies[1].dependencies.push_back(Storage::Module{"Qml"}); - - storage.synchronize({moduleDependencies[1], moduleDependencies[3]}, - {}, - {}, - {moduleSourceId2, moduleSourceIdQml3}, - {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{3}, moduleSourceIdQml3), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("Qml", Storage::VersionNumber{3})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("QtQuick", Storage::VersionNumber{})))))); -} - -TEST_F(ProjectStorage, SynchronizeModulesDependencyGetsOnlyTheHighestDependency) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto moduleSourceIdQml1 = sourcePathCache.sourceId("/path/Qml.1"); - moduleDependencies.push_back( - Storage::ModuleDependency{"Qml", Storage::VersionNumber{1}, moduleSourceIdQml1, {}}); - moduleDependencies[1].dependencies.push_back(Storage::Module{"Qml"}); - - storage.synchronize({moduleDependencies[1], moduleDependencies[3]}, - {}, - {}, - {moduleSourceId2, moduleSourceIdQml1}, - {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{1}, moduleSourceIdQml1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("QtQuick", Storage::VersionNumber{})))))); -} - -TEST_F(ProjectStorage, SynchronizeModulesDependencyRemoveDuplicateDependencies) -{ - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - storage.synchronize(moduleDependencies, - {}, - {}, - {moduleSourceId1, moduleSourceId2, moduleSourceId5}, - {}); - auto moduleSourceIdQml3 = sourcePathCache.sourceId("/path/Qml.3"); - moduleDependencies.push_back( - Storage::ModuleDependency{"Qml", Storage::VersionNumber{3}, moduleSourceIdQml3}); - moduleDependencies[2].dependencies.push_back(Storage::Module{"Qml", Storage::VersionNumber{3}}); - moduleDependencies[2].dependencies.push_back(Storage::Module{"Qml", Storage::VersionNumber{2}}); - moduleDependencies[2].dependencies.push_back(Storage::Module{"Qml", Storage::VersionNumber{3}}); - moduleDependencies[2].dependencies.push_back(Storage::Module{"Qml", Storage::VersionNumber{2}}); - - storage.synchronize({moduleDependencies[2], moduleDependencies[3]}, - {}, - {}, - {moduleSourceId5, moduleSourceIdQml3}, - {}); - - ASSERT_THAT(storage.fetchAllModules(), - UnorderedElementsAre( - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{2}, moduleSourceId1), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("Qml", Storage::VersionNumber{3}, moduleSourceIdQml3), - Field(&Storage::ModuleDependency::dependencies, IsEmpty())), - AllOf(IsModuleDependency("QtQuick", Storage::VersionNumber{}, moduleSourceId2), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2})))), - AllOf(IsModuleDependency("/path/to", Storage::VersionNumber{}, moduleSourceId5), - Field(&Storage::ModuleDependency::dependencies, - UnorderedElementsAre(IsModule("Qml", Storage::VersionNumber{2}), - IsModule("Qml", Storage::VersionNumber{3}), - IsModule("QtQuick", Storage::VersionNumber{})))))); + UnorderedElementsAre(IsModule("Qml2", moduleSourceId1), + IsModule("QtQuick", moduleSourceId2), + IsModule("/path/to", moduleSourceId3))); } TEST_F(ProjectStorage, RemovingModuleRemovesDependentTypesToo) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - Storage::ModuleDependencies moduleDependencies{createModuleDependencies()}; - moduleDependencies.pop_back(); - moduleDependencies.pop_back(); - storage.synchronize({}, {}, {}, {moduleSourceId2, moduleSourceId5}, {}); + types[0].prototype = Storage::NativeType{""}; + types[0].propertyDeclarations.clear(); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + storage.synchronize({}, {}, {}, {moduleSourceId2, moduleSourceId3}, {}); ASSERT_THAT(storage.fetchTypes(), - UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Qml", 2}, - "QObject", - Storage::NativeType{}, - TypeAccessSemantics::Reference, - sourceId2), - Field(&Storage::Type::exportedTypes, - UnorderedElementsAre(IsExportedType("Object"), - IsExportedType("Obj")))))); + UnorderedElementsAre(IsStorageType(Storage::Module{"Qml"}, + "QObject", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, RemovingModuleThrowsForMissingType) +{ + Storage::Types types{createTypes()}; + imports.emplace_back("QtQuick", Storage::Version{}, sourceId2); + types[0].prototype = Storage::NativeType{""}; + types[0].propertyDeclarations.clear(); + types[1].prototype = Storage::ImportedType{"Item"}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + ASSERT_THROW(storage.synchronize({}, {}, {}, {moduleSourceId2, moduleSourceId3}, {}), + QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, FetchTypeIdByModuleIdAndName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + auto qmlModuleId = storage.fetchModuleId("Qml"); - auto typeId = storage.fetchTypeIdByName(moduleId1, "QObject"); + auto typeId = storage.fetchTypeIdByName(qmlModuleId, "QObject"); ASSERT_THAT(storage.fetchTypeIdByExportedName("Object"), Eq(typeId)); } @@ -2312,28 +2271,43 @@ TEST_F(ProjectStorage, FetchTypeIdByModuleIdAndName) TEST_F(ProjectStorage, FetchTypeIdByExportedName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + auto qmlModuleId = storage.fetchModuleId("Qml"); auto typeId = storage.fetchTypeIdByExportedName("Object"); - ASSERT_THAT(storage.fetchTypeIdByName(moduleId1, "QObject"), Eq(typeId)); + ASSERT_THAT(storage.fetchTypeIdByName(qmlModuleId, "QObject"), Eq(typeId)); } TEST_F(ProjectStorage, FetchTypeIdByImporIdsAndExportedName) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + auto qmlModuleId = storage.fetchModuleId("Qml"); + auto qtQuickModuleId = storage.fetchModuleId("QtQuick"); - auto typeId = storage.fetchTypeIdByModuleIdsAndExportedName({moduleId1, moduleId2}, "Object"); + auto typeId = storage.fetchTypeIdByModuleIdsAndExportedName({qmlModuleId, qtQuickModuleId}, + "Object"); - ASSERT_THAT(storage.fetchTypeIdByName(moduleId1, "QObject"), Eq(typeId)); + ASSERT_THAT(storage.fetchTypeIdByName(qmlModuleId, "QObject"), Eq(typeId)); } TEST_F(ProjectStorage, FetchInvalidTypeIdByImporIdsAndExportedNameIfModuleIdsAreEmpty) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); auto typeId = storage.fetchTypeIdByModuleIdsAndExportedName({}, "Object"); ASSERT_FALSE(typeId.isValid()); @@ -2342,8 +2316,11 @@ TEST_F(ProjectStorage, FetchInvalidTypeIdByImporIdsAndExportedNameIfModuleIdsAre TEST_F(ProjectStorage, FetchInvalidTypeIdByImporIdsAndExportedNameIfModuleIdsAreInvalid) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); auto typeId = storage.fetchTypeIdByModuleIdsAndExportedName({ModuleId{}}, "Object"); ASSERT_FALSE(typeId.isValid()); @@ -2352,38 +2329,27 @@ TEST_F(ProjectStorage, FetchInvalidTypeIdByImporIdsAndExportedNameIfModuleIdsAre TEST_F(ProjectStorage, FetchInvalidTypeIdByImporIdsAndExportedNameIfNotInModule) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - - auto typeId = storage.fetchTypeIdByModuleIdsAndExportedName({moduleId2, moduleId3}, "Object"); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + auto qtQuickModuleId = storage.fetchModuleId("QtQuick"); + auto typeId = storage.fetchTypeIdByModuleIdsAndExportedName({qtQuickModuleId}, "Object"); ASSERT_FALSE(typeId.isValid()); } -TEST_F(ProjectStorage, FetchModuleDepencencyIds) -{ - Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - - auto moduleIds = storage.fetchModuleDependencyIds({moduleId3}); - - ASSERT_THAT(moduleIds, UnorderedElementsAre(moduleId1, moduleId2, moduleId3)); -} - -TEST_F(ProjectStorage, FetchModuleDepencencyIdsForRootDepencency) -{ - Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - - auto moduleIds = storage.fetchModuleDependencyIds({moduleId1}); - - ASSERT_THAT(moduleIds, ElementsAre(moduleId1)); -} - TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarations) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2409,9 +2375,19 @@ TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarations) TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarationsAgain) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2437,10 +2413,15 @@ TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarationsAgain) TEST_F(ProjectStorage, SynchronizeTypesRemoveAliasDeclarations) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[2].propertyDeclarations.pop_back(); - storage.synchronize({}, {}, {types[2]}, {sourceId3}, {}); + storage.synchronize({}, importsSourceId3, {types[2]}, {sourceId3}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2465,7 +2446,7 @@ TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarationsThrowsForWrongTypeNam Storage::Types types{createTypesWithAliases()}; types[2].propertyDeclarations[1].typeName = Storage::NativeType{"QQuickItemWrong"}; - ASSERT_THROW(storage.synchronize({}, {}, {types[2]}, {sourceId4}, {}), + ASSERT_THROW(storage.synchronize(modules, importsSourceId4, {types[2]}, {sourceId4}, {}), QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarationsThrowsForWrongPropertyName) @@ -2473,17 +2454,23 @@ TEST_F(ProjectStorage, SynchronizeTypesAddAliasDeclarationsThrowsForWrongPropert Storage::Types types{createTypesWithAliases()}; types[2].propertyDeclarations[1].aliasPropertyName = "childrenWrong"; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId4}, {}), + ASSERT_THROW(storage.synchronize(modules, imports, types, {sourceId4}, {}), QmlDesigner::PropertyNameDoesNotExists); } TEST_F(ProjectStorage, SynchronizeTypesChangeAliasDeclarationsTypeName) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); - types[2].propertyDeclarations[2].typeName = Storage::ExportedType{"Obj2"}; + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[2].propertyDeclarations[2].typeName = Storage::ImportedType{"Obj2"}; + importsSourceId3.emplace_back("/path/to", Storage::Version{}, sourceId3); - storage.synchronize({}, {}, {types[2]}, {sourceId3}, {}); + storage.synchronize({}, importsSourceId3, {types[2]}, {sourceId3}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2509,10 +2496,15 @@ TEST_F(ProjectStorage, SynchronizeTypesChangeAliasDeclarationsTypeName) TEST_F(ProjectStorage, SynchronizeTypesChangeAliasDeclarationsPropertyName) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[2].propertyDeclarations[2].aliasPropertyName = "children"; - storage.synchronize({}, {}, {types[2]}, {sourceId3}, {}); + storage.synchronize({}, importsSourceId3, {types[2]}, {sourceId3}, {}); ASSERT_THAT( storage.fetchTypes(), @@ -2540,7 +2532,12 @@ TEST_F(ProjectStorage, SynchronizeTypesChangeAliasDeclarationsPropertyName) TEST_F(ProjectStorage, SynchronizeTypesChangeAliasDeclarationsToPropertyDeclaration) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[2].propertyDeclarations.pop_back(); types[2].propertyDeclarations.push_back( Storage::PropertyDeclaration{"objects", @@ -2548,7 +2545,7 @@ TEST_F(ProjectStorage, SynchronizeTypesChangeAliasDeclarationsToPropertyDeclarat Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, {types[2]}, {sourceId3}, {}); + storage.synchronize({}, importsSourceId3, {types[2]}, {sourceId3}, {}); ASSERT_THAT( storage.fetchTypes(), @@ -2583,9 +2580,14 @@ TEST_F(ProjectStorage, SynchronizeTypesChangePropertyDeclarationsToAliasDeclarat Storage::NativeType{"QQuickItem"}, Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, typesChanged, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + typesChanged, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize({}, imports, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2611,11 +2613,16 @@ TEST_F(ProjectStorage, SynchronizeTypesChangePropertyDeclarationsToAliasDeclarat TEST_F(ProjectStorage, SynchronizeTypesChangeAliasTargetPropertyDeclarationTraits) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly; - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT( storage.fetchTypes(), @@ -2643,10 +2650,16 @@ TEST_F(ProjectStorage, SynchronizeTypesChangeAliasTargetPropertyDeclarationTrait TEST_F(ProjectStorage, SynchronizeTypesChangeAliasTargetPropertyDeclarationTypeName) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); - types[1].propertyDeclarations[0].typeName = Storage::ExportedType{"Item"}; + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[1].propertyDeclarations[0].typeName = Storage::ImportedType{"Item"}; + importsSourceId2.emplace_back("QtQuick", Storage::Version{}, sourceId2); - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2672,21 +2685,35 @@ TEST_F(ProjectStorage, SynchronizeTypesChangeAliasTargetPropertyDeclarationTypeN TEST_F(ProjectStorage, SynchronizeTypesRemovePropertyDeclarationWithAnAliasThrows) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].propertyDeclarations.pop_back(); - ASSERT_THROW(storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), Sqlite::ConstraintPreventsModification); } TEST_F(ProjectStorage, SynchronizeTypesRemovePropertyDeclarationAndAlias) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].propertyDeclarations.pop_back(); types[2].propertyDeclarations.pop_back(); - storage.synchronize({}, {}, {types[1], types[2]}, {sourceId2, sourceId3}, {}); + storage.synchronize({}, + importsSourceId2 + importsSourceId3, + {types[1], types[2]}, + {sourceId2, sourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2709,8 +2736,14 @@ TEST_F(ProjectStorage, SynchronizeTypesRemovePropertyDeclarationAndAlias) TEST_F(ProjectStorage, SynchronizeTypesRemoveTypeWithAliasTargetPropertyDeclarationThrows) { Storage::Types types{createTypesWithAliases()}; - types[2].propertyDeclarations[2].typeName = Storage::ExportedType{"Object2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + types[2].propertyDeclarations[2].typeName = Storage::ImportedType{"Object2"}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId3); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THROW(storage.synchronize({}, {}, {}, {sourceId4}, {}), QmlDesigner::TypeNameDoesNotExists); } @@ -2718,11 +2751,21 @@ TEST_F(ProjectStorage, SynchronizeTypesRemoveTypeWithAliasTargetPropertyDeclarat TEST_F(ProjectStorage, SynchronizeTypesRemoveTypeAndAliasPropertyDeclaration) { Storage::Types types{createTypesWithAliases()}; - types[2].propertyDeclarations[2].typeName = Storage::ExportedType{"Object2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + types[2].propertyDeclarations[2].typeName = Storage::ImportedType{"Object2"}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId3); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[2].propertyDeclarations.pop_back(); - storage.synchronize({}, {}, {types[0], types[2]}, {sourceId1, sourceId3}, {}); + storage.synchronize({}, + importsSourceId1 + importsSourceId3, + {types[0], types[2]}, + {sourceId1, sourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2745,14 +2788,19 @@ TEST_F(ProjectStorage, SynchronizeTypesRemoveTypeAndAliasPropertyDeclaration) TEST_F(ProjectStorage, UpdateAliasPropertyIfPropertyIsOverloaded) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations.push_back( Storage::PropertyDeclaration{"objects", Storage::NativeType{"QQuickItem"}, Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, {types[0]}, {sourceId1}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT( storage.fetchTypes(), @@ -2786,7 +2834,12 @@ TEST_F(ProjectStorage, AliasPropertyIsOverloaded) Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT( storage.fetchTypes(), @@ -2819,10 +2872,15 @@ TEST_F(ProjectStorage, UpdateAliasPropertyIfOverloadedPropertyIsRemoved) Storage::NativeType{"QQuickItem"}, Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].propertyDeclarations.pop_back(); - storage.synchronize({}, {}, {types[0]}, {sourceId1}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2849,10 +2907,17 @@ TEST_F(ProjectStorage, RelinkAliasProperty) { Storage::Types types{createTypesWithAliases()}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId2); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[3].module = Storage::Module{"QtQuick"}; - storage.synchronize({}, {}, {types[3]}, {sourceId4}, {}); + storage.synchronize({}, importsSourceId4, {types[3]}, {sourceId4}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2875,26 +2940,32 @@ TEST_F(ProjectStorage, RelinkAliasProperty) Storage::PropertyDeclarationTraits::IsList)))))); } -TEST_F(ProjectStorage, DoNotRelinkAliasPropertyForExplicitExportedTypeName) +TEST_F(ProjectStorage, DoNotRelinkAliasPropertyForQualifiedImportedTypeName) { Storage::Types types{createTypesWithAliases()}; - types[1].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object2", - Storage::Module{ - "/path/to"}}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + types[1].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object2", Storage::Import{"/path/to", Storage::Version{}, sourceId2}}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[3].module = Storage::Module{"QtQuick"}; + importsSourceId4.emplace_back("QtQuick", Storage::Version{}, sourceId4); - ASSERT_THROW(storage.synchronize({}, {}, {types[3]}, {sourceId4}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId4, {types[3]}, {sourceId4}, {}), QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, - DoRelinkAliasPropertyForExplicitExportedTypeNameEvenIfAnOtherSimilarTimeNameExists) + DoRelinkAliasPropertyForQualifiedImportedTypeNameEvenIfAnOtherSimilarTimeNameExists) { Storage::Types types{createTypesWithAliases()}; - types[1].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object2", - Storage::Module{ - "/path/to"}}; + types[1].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object2", Storage::Import{"/path/to", Storage::Version{}, sourceId2}}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QObject2", Storage::NativeType{}, @@ -2902,7 +2973,18 @@ TEST_F(ProjectStorage, sourceId5, {Storage::ExportedType{"Object2"}, Storage::ExportedType{"Obj2"}}}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2929,11 +3011,16 @@ TEST_F(ProjectStorage, RelinkAliasPropertyReactToTypeNameChange) { Storage::Types types{createTypesWithAliases2()}; types[2].propertyDeclarations.push_back( - Storage::PropertyDeclaration{"items", Storage::ExportedType{"Item"}, "children"}); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + Storage::PropertyDeclaration{"items", Storage::ImportedType{"Item"}, "children"}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[0].typeName = "QQuickItem2"; - storage.synchronize({}, {}, {types[0]}, {sourceId1}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf( @@ -2960,11 +3047,18 @@ TEST_F(ProjectStorage, DoNotRelinkAliasPropertyForDeletedType) { Storage::Types types{createTypesWithAliases()}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); - types.erase(std::next(types.begin(), 2)); - types[2].module = Storage::Module{"QtQuick"}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId2); - storage.synchronize({}, {}, {types[2]}, {sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[3].module = Storage::Module{"QtQuick"}; + + storage.synchronize({}, importsSourceId4, {types[3]}, {sourceId3, sourceId4}, {}); ASSERT_THAT(storage.fetchTypes(), Not(Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -2978,12 +3072,24 @@ TEST_F(ProjectStorage, DoNotRelinkAliasPropertyForDeletedTypeAndPropertyType) { Storage::Types types{createTypesWithAliases()}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); - types.pop_back(); - types.pop_back(); - types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject"}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[0].prototype = Storage::NativeType{}; + importsSourceId1.emplace_back("/path/to", Storage::Version{}, sourceId1); + importsSourceId4.emplace_back("QtQuick", Storage::Version{}, sourceId4); + types[0].propertyDeclarations[0].typeName = Storage::ImportedType{"Object2"}; + types[3].propertyDeclarations[0].typeName = Storage::ImportedType{"Item"}; - storage.synchronize({}, {}, {types[1]}, {sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize({}, + importsSourceId1 + importsSourceId4, + {types[0], types[3]}, + {sourceId1, sourceId2, sourceId3, sourceId4}, + {}); ASSERT_THAT(storage.fetchTypes(), SizeIs(2)); } @@ -2992,26 +3098,43 @@ TEST_F(ProjectStorage, DoNotRelinkAliasPropertyForDeletedTypeAndPropertyTypeName { Storage::Types types{createTypesWithAliases()}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); - types.erase(std::next(types.begin(), 2)); - types[2].module = Storage::Module{"QtQuick"}; + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[3].module = Storage::Module{"QtQuick"}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject"}; + importsSourceId4.emplace_back("QtQuick", Storage::Version{}, sourceId4); - storage.synchronize({}, {}, {types[2]}, {sourceId3, sourceId4}, {}); + storage.synchronize({}, + importsSourceId2 + importsSourceId4, + {types[1], types[3]}, + {sourceId2, sourceId3, sourceId4}, + {}); ASSERT_THAT(storage.fetchTypes(), - Not(Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, - "QAliasItem", - Storage::NativeType{"QQuickItem"}, - TypeAccessSemantics::Reference, - sourceId3))))); + Not(Contains(IsStorageType(Storage::Module{"QtQuick"}, + "QAliasItem", + Storage::NativeType{"QQuickItem"}, + TypeAccessSemantics::Reference, + sourceId3)))); } TEST_F(ProjectStorage, DoNotRelinkPropertyTypeDoesNotExists) { Storage::Types types{createTypesWithAliases()}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId2); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types.pop_back(); ASSERT_THROW(storage.synchronize({}, {}, {}, {sourceId4}, {}), QmlDesigner::TypeNameDoesNotExists); @@ -3021,8 +3144,13 @@ TEST_F(ProjectStorage, DoNotRelinkAliasPropertyTypeDoesNotExists) { Storage::Types types{createTypesWithAliases2()}; types[1].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); - types.erase(types.begin()); + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THROW(storage.synchronize({}, {}, {}, {sourceId1}, {}), QmlDesigner::TypeNameDoesNotExists); } @@ -3030,10 +3158,14 @@ TEST_F(ProjectStorage, DoNotRelinkAliasPropertyTypeDoesNotExists) TEST_F(ProjectStorage, ChangePrototypeTypeName) { Storage::Types types{createTypesWithExportedTypeNamesOnly()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].typeName = "QObject3"; - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(IsStorageType(Storage::Module{"QtQuick"}, @@ -3046,10 +3178,14 @@ TEST_F(ProjectStorage, ChangePrototypeTypeName) TEST_F(ProjectStorage, ChangePrototypeTypeModuleId) { Storage::Types types{createTypes()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].module = Storage::Module{"QtQuick"}; - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(IsStorageType(Storage::Module{"QtQuick"}, @@ -3059,26 +3195,47 @@ TEST_F(ProjectStorage, ChangePrototypeTypeModuleId) sourceId1))); } -TEST_F(ProjectStorage, ChangeExplicitPrototypeTypeModuleIdThows) +TEST_F(ProjectStorage, ChangeQualifiedPrototypeTypeModuleIdThows) { Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"Qml"}}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"Qml", + Storage::Version{}, + sourceId1}}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].module = Storage::Module{"QtQuick"}; - ASSERT_THROW(storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, ChangeExplicitPrototypeTypeModuleId) +TEST_F(ProjectStorage, ChangeQualifiedPrototypeTypeModuleId) { Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"Qml"}}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"Qml", + Storage::Version{}, + sourceId1}}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].module = Storage::Module{"QtQuick"}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"QtQuick"}}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"QtQuick", + Storage::Version{}, + sourceId1}}; - storage.synchronize({}, {}, {types[0], types[1]}, {sourceId1, sourceId2}, {}); + storage.synchronize({}, + importsSourceId1 + importsSourceId2, + {types[0], types[1]}, + {sourceId1, sourceId2}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(IsStorageType(Storage::Module{"QtQuick"}, @@ -3091,11 +3248,15 @@ TEST_F(ProjectStorage, ChangeExplicitPrototypeTypeModuleId) TEST_F(ProjectStorage, ChangePrototypeTypeNameAndModuleId) { Storage::Types types{createTypesWithExportedTypeNamesOnly()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].module = Storage::Module{"QtQuick"}; types[1].typeName = "QObject3"; - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(IsStorageType(Storage::Module{"QtQuick"}, @@ -3108,46 +3269,67 @@ TEST_F(ProjectStorage, ChangePrototypeTypeNameAndModuleId) TEST_F(ProjectStorage, ChangePrototypeTypeNameThrowsForWrongNativePrototupeTypeName) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExportedType{"Object"}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + types[0].propertyDeclarations[0].typeName = Storage::ImportedType{"Object"}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[1].typeName = "QObject3"; - ASSERT_THROW(storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), QmlDesigner::TypeNameDoesNotExists); } TEST_F(ProjectStorage, ThrowForPrototypeChainCycles) { Storage::Types types{createTypes()}; - types[1].prototype = Storage::ExportedType{"Object2"}; + types[1].prototype = Storage::ImportedType{"Object2"}; types.push_back(Storage::Type{Storage::Module{"/path/to"}, "QObject2", - Storage::ExportedType{"Item"}, + Storage::ImportedType{"Item"}, TypeAccessSemantics::Reference, sourceId3, {Storage::ExportedType{"Object2"}, Storage::ExportedType{"Obj2"}}}); + imports.emplace_back("/path/to", Storage::Version{}, sourceId2); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); + imports.emplace_back("/path/to", Storage::Version{}, sourceId3); - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}), + ASSERT_THROW(storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::PrototypeChainCycle); } TEST_F(ProjectStorage, ThrowForTypeIdAndPrototypeIdAreTheSame) { Storage::Types types{createTypes()}; - types[1].prototype = Storage::ExportedType{"Object"}; + types[1].prototype = Storage::ImportedType{"Object"}; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}), + ASSERT_THROW(storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::PrototypeChainCycle); } TEST_F(ProjectStorage, ThrowForTypeIdAndPrototypeIdAreTheSameForRelinking) { Storage::Types types{createTypesWithExportedTypeNamesOnly()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - types[1].prototype = Storage::ExportedType{"Item"}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[1].prototype = Storage::ImportedType{"Item"}; types[1].typeName = "QObject2"; + importsSourceId2.emplace_back("QtQuick", Storage::Version{}, sourceId2); - ASSERT_THROW(storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), QmlDesigner::PrototypeChainCycle); } @@ -3155,7 +3337,18 @@ TEST_F(ProjectStorage, RecursiveAliases) { Storage::Types types{createTypesWithRecursiveAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -3173,10 +3366,22 @@ TEST_F(ProjectStorage, RecursiveAliases) TEST_F(ProjectStorage, RecursiveAliasesChangePropertyType) { Storage::Types types{createTypesWithRecursiveAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); - types[1].propertyDeclarations[0].typeName = Storage::ExportedType{"Object2"}; + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); + types[1].propertyDeclarations[0].typeName = Storage::ImportedType{"Object2"}; + importsSourceId2.emplace_back("/path/to", Storage::Version{}, sourceId2); - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -3194,14 +3399,25 @@ TEST_F(ProjectStorage, RecursiveAliasesChangePropertyType) TEST_F(ProjectStorage, UpdateAliasesAfterInjectingProperty) { Storage::Types types{createTypesWithRecursiveAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); types[0].propertyDeclarations.push_back( Storage::PropertyDeclaration{"objects", - Storage::ExportedType{"Item"}, + Storage::ImportedType{"Item"}, Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, {types[0]}, {sourceId1}, {}); + storage.synchronize({}, importsSourceId1, {types[0]}, {sourceId1}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -3220,15 +3436,26 @@ TEST_F(ProjectStorage, UpdateAliasesAfterInjectingProperty) TEST_F(ProjectStorage, UpdateAliasesAfterChangeAliasToProperty) { Storage::Types types{createTypesWithRecursiveAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); types[2].propertyDeclarations.clear(); types[2].propertyDeclarations.push_back( Storage::PropertyDeclaration{"objects", - Storage::ExportedType{"Item"}, + Storage::ImportedType{"Item"}, Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly}); - storage.synchronize({}, {}, {types[2]}, {sourceId3}, {}); + storage.synchronize({}, importsSourceId3, {types[2]}, {sourceId3}, {}); ASSERT_THAT(storage.fetchTypes(), AllOf(Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -3262,12 +3489,24 @@ TEST_F(ProjectStorage, UpdateAliasesAfterChangePropertyToAlias) Storage::Types types{createTypesWithRecursiveAliases()}; types[3].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsList | Storage::PropertyDeclarationTraits::IsReadOnly; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); types[1].propertyDeclarations.clear(); types[1].propertyDeclarations.push_back( - Storage::PropertyDeclaration{"objects", Storage::ExportedType{"Object2"}, "objects"}); + Storage::PropertyDeclaration{"objects", Storage::ImportedType{"Object2"}, "objects"}); + importsSourceId2.emplace_back("/path/to", Storage::Version{}, sourceId2); - storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}); + storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -3289,174 +3528,236 @@ TEST_F(ProjectStorage, CheckForProtoTypeCycleThrows) Storage::Types types{createTypesWithRecursiveAliases()}; types[1].propertyDeclarations.clear(); types[1].propertyDeclarations.push_back( - Storage::PropertyDeclaration{"objects", Storage::ExportedType{"AliasItem2"}, "objects"}); + Storage::PropertyDeclaration{"objects", Storage::ImportedType{"AliasItem2"}, "objects"}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId2); - ASSERT_THROW(storage.synchronize( - {}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}), + ASSERT_THROW(storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}), QmlDesigner::AliasChainCycle); } TEST_F(ProjectStorage, CheckForProtoTypeCycleAfterUpdateThrows) { Storage::Types types{createTypesWithRecursiveAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4, sourceId5}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, + sourceId2, + sourceId3, + sourceId4, + sourceId5, + moduleSourceId1, + moduleSourceId2, + moduleSourceId3}, + {}); types[1].propertyDeclarations.clear(); types[1].propertyDeclarations.push_back( - Storage::PropertyDeclaration{"objects", Storage::ExportedType{"AliasItem2"}, "objects"}); + Storage::PropertyDeclaration{"objects", Storage::ImportedType{"AliasItem2"}, "objects"}); + importsSourceId2.emplace_back("QtQuick", Storage::Version{}, sourceId2); - ASSERT_THROW(storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), QmlDesigner::AliasChainCycle); } -TEST_F(ProjectStorage, ExplicitPrototype) +TEST_F(ProjectStorage, QualifiedPrototype) { Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"Qml"}}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"Qml", + Storage::Version{}, + sourceId1}}; types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QQuickObject", Storage::NativeType{}, TypeAccessSemantics::Reference, sourceId3, {Storage::ExportedType{"Object"}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}); - - ASSERT_THAT(storage.fetchTypes(), - Contains(IsStorageType(Storage::Module{"QtQuick"}, - "QQuickItem", - Storage::NativeType{"QObject"}, - TypeAccessSemantics::Reference, - sourceId1))); -} - -TEST_F(ProjectStorage, ExplicitPrototypeUpperDownTheModuleChainThrows) -{ - Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"QtQuick"}}; - - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}), - QmlDesigner::TypeNameDoesNotExists); -} - -TEST_F(ProjectStorage, ExplicitPrototypeUpperInTheModuleChain) -{ - Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"QtQuick"}}; - types.push_back(Storage::Type{Storage::Module{"QtQuick"}, - "QQuickObject", - Storage::NativeType{}, - TypeAccessSemantics::Reference, - sourceId3, - {Storage::ExportedType{"Object"}}}); - - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}); - - ASSERT_THAT(storage.fetchTypes(), - Contains(IsStorageType(Storage::Module{"QtQuick"}, - "QQuickItem", - Storage::NativeType{"QQuickObject"}, - TypeAccessSemantics::Reference, - sourceId1))); -} - -TEST_F(ProjectStorage, ExplicitPrototypeWithWrongVersionThrows) -{ - Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"Qml", 4}}; - types.push_back(Storage::Type{Storage::Module{"QtQuick"}, - "QQuickObject", - Storage::NativeType{}, - TypeAccessSemantics::Reference, - sourceId3, - {Storage::ExportedType{"Object"}}}); - - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}), - QmlDesigner::TypeNameDoesNotExists); -} - -TEST_F(ProjectStorage, ExplicitPrototypeWithVersion) -{ - Storage::Types types{createTypes()}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"Qml", 2}}; - types.push_back(Storage::Type{Storage::Module{"QtQuick"}, - "QQuickObject", - Storage::NativeType{}, - TypeAccessSemantics::Reference, - sourceId3, - {Storage::ExportedType{"Object"}}}); - - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}); - - ASSERT_THAT(storage.fetchTypes(), - Contains(IsStorageType(Storage::Module{"QtQuick"}, - "QQuickItem", - Storage::NativeType{"QObject"}, - TypeAccessSemantics::Reference, - sourceId1))); -} - -TEST_F(ProjectStorage, ExplicitPrototypeWithVersionInTheProtoTypeChain) -{ - Storage::Types types{createTypes()}; - auto moduleDependencyQtQuick2 = Storage::ModuleDependency{ - "QtQuick", - Storage::VersionNumber{2}, - moduleSourceId2, - {Storage::Module{"Qml", Storage::VersionNumber{2}}}}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"QtQuick", 2}}; - types.push_back(Storage::Type{Storage::Module{"QtQuick"}, - "QQuickObject", - Storage::NativeType{}, - TypeAccessSemantics::Reference, - sourceId3, - {Storage::ExportedType{"Object"}}}); - - storage.synchronize({moduleDependencyQtQuick2}, - {}, + storage.synchronize(modules, + imports, types, - {sourceId1, sourceId2, sourceId3, moduleSourceId2}, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}); ASSERT_THAT(storage.fetchTypes(), - Contains(IsStorageType(Storage::Module{"QtQuick", 2}, + Contains(IsStorageType(Storage::Module{"QtQuick"}, "QQuickItem", - Storage::NativeType{"QQuickObject"}, + Storage::NativeType{"QObject"}, TypeAccessSemantics::Reference, sourceId1))); } -TEST_F(ProjectStorage, ExplicitPrototypeWithVersionDownTheProtoTypeChainThrows) +TEST_F(ProjectStorage, QualifiedPrototypeUpperDownTheModuleChainThrows) { Storage::Types types{createTypes()}; - auto moduleDependencyQtQuick2 = Storage::ModuleDependency{ - "QtQuick", - Storage::VersionNumber{2}, - moduleSourceId2, - {Storage::Module{"Qml", Storage::VersionNumber{2}}}}; - types[0].prototype = Storage::ExplicitExportedType{"Object", Storage::Module{"QtQuick", 2}}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"QtQuick", + Storage::Version{}, + sourceId1}}; - ASSERT_THROW(storage.synchronize({moduleDependencyQtQuick2}, - {}, + ASSERT_THROW(storage.synchronize(modules, + imports, types, - {sourceId1, sourceId2, sourceId3, moduleSourceId2}, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeName) +TEST_F(ProjectStorage, QualifiedPrototypeUpperInTheModuleChain) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "Qml"}}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"QtQuick", + Storage::Version{}, + sourceId1}}; types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QQuickObject", Storage::NativeType{}, TypeAccessSemantics::Reference, sourceId3, {Storage::ExportedType{"Object"}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "QQuickItem", + Storage::NativeType{"QQuickObject"}, + TypeAccessSemantics::Reference, + sourceId1))); +} + +TEST_F(ProjectStorage, QualifiedPrototypeWithWrongVersionThrows) +{ + Storage::Types types{createTypes()}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"Qml", + Storage::Version{4}, + sourceId1}}; + types.push_back(Storage::Type{Storage::Module{"QtQuick"}, + "QQuickObject", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId3, + {Storage::ExportedType{"Object"}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); + + ASSERT_THROW(storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, QualifiedPrototypeWithVersion) +{ + Storage::Types types{createTypes()}; + imports[0].version = Storage::Version{2}; + types[0].prototype = Storage::QualifiedImportedType{"Object", imports[0]}; + types.push_back(Storage::Type{Storage::Module{"QtQuick"}, + "QQuickObject", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId3, + {Storage::ExportedType{"Object"}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); + + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "QQuickItem", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId1))); +} + +TEST_F(ProjectStorage, QualifiedPrototypeWithVersionInTheProtoTypeChain) +{ + Storage::Types types{createTypes()}; + imports[2].version = Storage::Version{2}; + types[0].prototype = Storage::QualifiedImportedType{"Object", imports[2]}; + types[0].exportedTypes[0].version = Storage::Version{2}; + types.push_back(Storage::Type{Storage::Module{"QtQuick"}, + "QQuickObject", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId3, + {Storage::ExportedType{"Object", Storage::Version{2}}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); + + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "QQuickItem", + Storage::NativeType{"QQuickObject"}, + TypeAccessSemantics::Reference, + sourceId1))); +} + +TEST_F(ProjectStorage, QualifiedPrototypeWithVersionDownTheProtoTypeChainThrows) +{ + Storage::Types types{createTypes()}; + types[0].prototype = Storage::QualifiedImportedType{"Object", + Storage::Import{"QtQuick", + Storage::Version{2}, + sourceId1}}; + + ASSERT_THROW(storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, QualifiedPropertyDeclarationTypeName) +{ + Storage::Types types{createTypes()}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"Qml", Storage::Version{}, sourceId1}}; + types.push_back(Storage::Type{Storage::Module{"QtQuick"}, + "QQuickObject", + Storage::NativeType{}, + TypeAccessSemantics::Reference, + sourceId3, + {Storage::ExportedType{"Object"}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); + + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -3466,31 +3767,39 @@ TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeName) Storage::PropertyDeclarationTraits::IsList))))); } -TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeNameDownTheModuleChainThrows) +TEST_F(ProjectStorage, QualifiedPropertyDeclarationTypeNameDownTheModuleChainThrows) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "QtQuick"}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"QtQuick", Storage::Version{}, sourceId1}}; - ASSERT_THROW(storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}), + ASSERT_THROW(storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeNameInTheModuleChain) +TEST_F(ProjectStorage, QualifiedPropertyDeclarationTypeNameInTheModuleChain) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "QtQuick"}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"QtQuick", Storage::Version{}, sourceId1}}; types.push_back(Storage::Type{Storage::Module{"QtQuick"}, "QQuickObject", Storage::NativeType{}, TypeAccessSemantics::Reference, sourceId3, {Storage::ExportedType{"Object"}}}); + imports.emplace_back("QtQuick", Storage::Version{}, sourceId3); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -3500,14 +3809,18 @@ TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeNameInTheModuleChain) Storage::PropertyDeclarationTraits::IsList))))); } -TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeNameWithVersion) +TEST_F(ProjectStorage, QualifiedPropertyDeclarationTypeNameWithVersion) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{"Qml", - 2}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"Qml", Storage::Version{2}, sourceId1}}; + imports.emplace_back("Qml", Storage::Version{2}, sourceId1); - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3}, {}); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); ASSERT_THAT(storage.fetchTypes(), Contains( @@ -3517,51 +3830,38 @@ TEST_F(ProjectStorage, ExplicitPropertyDeclarationTypeNameWithVersion) Storage::PropertyDeclarationTraits::IsList))))); } -TEST_F(ProjectStorage, PrototypeWithVersionDownTheProtoTypeChainThrows) +TEST_F(ProjectStorage, ChangePropertyTypeModuleIdWithQualifiedTypeThrows) { Storage::Types types{createTypes()}; - auto moduleDependencyQtQuick2 = Storage::ModuleDependency{ - "QtQuick", - Storage::VersionNumber{2}, - moduleSourceId2, - {Storage::Module{"Qml", Storage::VersionNumber{2}}}}; - types[0].prototype = Storage::ExportedType{"Object"}; - auto document = Storage::Document{sourceId1, {Storage::Module{"QtQuick"}}}; + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"Qml", Storage::Version{}, sourceId1}}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[1].module = Storage::Module{"QtQuick"}; - ASSERT_THROW(storage.synchronize({moduleDependencyQtQuick2}, - {document}, - types, - {sourceId1, sourceId2, sourceId3, moduleSourceId2}, - {}), + ASSERT_THROW(storage.synchronize({}, importsSourceId2, {types[1]}, {sourceId2}, {}), QmlDesigner::TypeNameDoesNotExists); } -TEST_F(ProjectStorage, ChangePropertyTypeModuleIdWithExplicitTypeThrows) +TEST_F(ProjectStorage, ChangePropertyTypeModuleIdWithQualifiedType) { Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "Qml"}}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"Qml", Storage::Version{}, sourceId1}}; + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + types[0].propertyDeclarations[0].typeName = Storage::QualifiedImportedType{ + "Object", Storage::Import{"QtQuick", Storage::Version{}, sourceId1}}; types[1].module = Storage::Module{"QtQuick"}; + imports.emplace_back("QtQuick", Storage::Version{}, sourceId2); - ASSERT_THROW(storage.synchronize({}, {}, {types[1]}, {sourceId2}, {}), - QmlDesigner::TypeNameDoesNotExists); -} - -TEST_F(ProjectStorage, ChangePropertyTypeModuleIdWithExplicitType) -{ - Storage::Types types{createTypes()}; - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "Qml"}}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); - types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", - Storage::Module{ - "QtQuick"}}; - types[1].module = Storage::Module{"QtQuick"}; - - storage.synchronize({}, {}, types, {sourceId1, sourceId2}, {}); + storage.synchronize({}, imports, types, {sourceId1, sourceId2}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"QtQuick"}, @@ -3578,7 +3878,6 @@ TEST_F(ProjectStorage, ChangePropertyTypeModuleIdWithExplicitType) TEST_F(ProjectStorage, AddFileStatuses) { - setUpSourceIds(); FileStatus fileStatus1{sourceId1, 100, 100}; FileStatus fileStatus2{sourceId2, 101, 101}; @@ -3590,7 +3889,6 @@ TEST_F(ProjectStorage, AddFileStatuses) TEST_F(ProjectStorage, RemoveFileStatus) { - setUpSourceIds(); FileStatus fileStatus1{sourceId1, 100, 100}; FileStatus fileStatus2{sourceId2, 101, 101}; storage.synchronize({}, {}, {}, {sourceId1, sourceId2}, {fileStatus1, fileStatus2}); @@ -3602,7 +3900,6 @@ TEST_F(ProjectStorage, RemoveFileStatus) TEST_F(ProjectStorage, UpdateFileStatus) { - setUpSourceIds(); FileStatus fileStatus1{sourceId1, 100, 100}; FileStatus fileStatus2{sourceId2, 101, 101}; FileStatus fileStatus2b{sourceId2, 102, 102}; @@ -3616,7 +3913,6 @@ TEST_F(ProjectStorage, UpdateFileStatus) TEST_F(ProjectStorage, ThrowForInvalidSourceId) { - setUpSourceIds(); FileStatus fileStatus1{SourceId{}, 100, 100}; ASSERT_THROW(storage.synchronize({}, {}, {}, {sourceId1}, {fileStatus1}), @@ -3625,7 +3921,6 @@ TEST_F(ProjectStorage, ThrowForInvalidSourceId) TEST_F(ProjectStorage, FetchAllFileStatuses) { - setUpSourceIds(); FileStatus fileStatus1{sourceId1, 100, 100}; FileStatus fileStatus2{sourceId2, 101, 101}; storage.synchronize({}, {}, {}, {sourceId1, sourceId2}, {fileStatus1, fileStatus2}); @@ -3637,7 +3932,6 @@ TEST_F(ProjectStorage, FetchAllFileStatuses) TEST_F(ProjectStorage, FetchAllFileStatusesReverse) { - setUpSourceIds(); FileStatus fileStatus1{sourceId1, 100, 100}; FileStatus fileStatus2{sourceId2, 101, 101}; storage.synchronize({}, {}, {}, {sourceId1, sourceId2}, {fileStatus2, fileStatus1}); @@ -3649,7 +3943,6 @@ TEST_F(ProjectStorage, FetchAllFileStatusesReverse) TEST_F(ProjectStorage, FetchFileStatus) { - setUpSourceIds(); FileStatus fileStatus1{sourceId1, 100, 100}; FileStatus fileStatus2{sourceId2, 101, 101}; storage.synchronize({}, {}, {}, {sourceId1, sourceId2}, {fileStatus1, fileStatus2}); @@ -3662,12 +3955,17 @@ TEST_F(ProjectStorage, FetchFileStatus) TEST_F(ProjectStorage, SynchronizeTypesWithoutTypeName) { Storage::Types types{createTypesWithAliases()}; - storage.synchronize({}, {}, types, {sourceId1, sourceId2, sourceId3, sourceId4}, {}); + storage.synchronize( + modules, + imports, + types, + {sourceId1, sourceId2, sourceId3, sourceId4, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); types[3].typeName.clear(); types[3].module.name.clear(); - types[3].prototype = Storage::ExportedType{"Object"}; + types[3].prototype = Storage::ImportedType{"Object"}; - storage.synchronize({}, {}, {types[3]}, {sourceId4}, {}); + storage.synchronize({}, importsSourceId4, {types[3]}, {sourceId4}, {}); ASSERT_THAT(storage.fetchTypes(), Contains(AllOf(IsStorageType(Storage::Module{"/path/to"}, @@ -3680,4 +3978,523 @@ TEST_F(ProjectStorage, SynchronizeTypesWithoutTypeName) IsExportedType("Obj2")))))); } +TEST_F(ProjectStorage, FetchByMajorVersionForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Object"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{1}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchByMajorVersionForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{1}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Object", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchByMajorVersionAndMinorVersionForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{1, 2}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchByMajorVersionAndMinorVersionForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{1, 2}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, + FetchByMajorVersionAndMinorVersionForImportedTypeIfMinorVersionIsNotExportedThrows) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Object"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{1, 1}, sourceId2}; + + ASSERT_THROW(storage.synchronize({}, {import}, {type}, {sourceId2}, {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, + FetchByMajorVersionAndMinorVersionForQualifiedImportedTypeIfMinorVersionIsNotExportedThrows) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{1, 1}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Object", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + ASSERT_THROW(storage.synchronize({}, {import}, {type}, {sourceId2}, {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, FetchLowMinorVersionForImportedTypeThrows) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{1, 1}, sourceId2}; + + ASSERT_THROW(storage.synchronize({}, {import}, {type}, {sourceId2}, {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, FetchLowMinorVersionForQualifiedImportedTypeThrows) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{1, 1}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + ASSERT_THROW(storage.synchronize({}, {import}, {type}, {sourceId2}, {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, FetchHigherMinorVersionForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{1, 3}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchHigherMinorVersionForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{1, 3}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchDifferentMajorVersionForImportedTypeThrows) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{3, 1}, sourceId2}; + + ASSERT_THROW(storage.synchronize({}, {import}, {type}, {sourceId2}, {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, FetchDifferentMajorVersionForQualifiedImportedTypeThrows) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{3, 1}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + ASSERT_THROW(storage.synchronize({}, {import}, {type}, {sourceId2}, {}), + QmlDesigner::TypeNameDoesNotExists); +} + +TEST_F(ProjectStorage, FetchOtherTypeByDifferentVersionForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{2, 3}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject2"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchOtherTypeByDifferentVersionForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{2, 3}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject2"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchHighestVersionForImportWithoutVersionForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject4"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchHighestVersionForImportWithoutVersionForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject4"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchHighestVersionForImportWithMajorVersionForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"Obj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{2}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject3"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchHighestVersionForImportWithMajorVersionForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{2}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"Obj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject3"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchExportedTypeWithoutVersionFirstForImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::ImportedType{"BuiltInObj"}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + Storage::Import import{"Qml", Storage::Version{}, sourceId2}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, FetchExportedTypeWithoutVersionFirstForQualifiedImportedType) +{ + auto types = createVersionedTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + Storage::Import import{"Qml", Storage::Version{}, sourceId2}; + Storage::Type type{Storage::Module{"QtQuick"}, + "Item", + Storage::QualifiedImportedType{"BuiltInObj", import}, + TypeAccessSemantics::Reference, + sourceId2, + {Storage::ExportedType{"Item", Storage::Version{}}}}; + + storage.synchronize({}, {import}, {type}, {sourceId2}, {}); + + ASSERT_THAT(storage.fetchTypes(), + Contains(IsStorageType(Storage::Module{"QtQuick"}, + "Item", + Storage::NativeType{"QObject"}, + TypeAccessSemantics::Reference, + sourceId2))); +} + +TEST_F(ProjectStorage, EnsureThatPropertiesForRemovedTypesAreNotAnymoreRelinked) +{ + Storage::Type type{Storage::Module{"Qml"}, + "QObject", + Storage::NativeType{""}, + TypeAccessSemantics::Reference, + sourceId1, + {Storage::ExportedType{"Object", Storage::Version{}}}, + {Storage::PropertyDeclaration{"data", + Storage::NativeType{"QObject"}, + Storage::PropertyDeclarationTraits::IsList}}}; + Storage::Import import{"Qml", Storage::Version{}, sourceId1}; + storage.synchronize(modules, + {import}, + {type}, + {sourceId1, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + ASSERT_NO_THROW(storage.synchronize({}, {}, {}, {sourceId1}, {})); +} + +TEST_F(ProjectStorage, EnsureThatPrototypesForRemovedTypesAreNotAnymoreRelinked) +{ + auto types = createTypes(); + storage.synchronize(modules, + imports, + types, + {sourceId1, sourceId2, moduleSourceId1, moduleSourceId2, moduleSourceId3}, + {}); + + ASSERT_NO_THROW(storage.synchronize({}, {}, {}, {sourceId1, sourceId2}, {})); +} + } // namespace diff --git a/tests/unit/unittest/projectstoragemock.h b/tests/unit/unittest/projectstoragemock.h index 01fe3360f3c..6fecc58ad45 100644 --- a/tests/unit/unittest/projectstoragemock.h +++ b/tests/unit/unittest/projectstoragemock.h @@ -38,8 +38,8 @@ class ProjectStorageMock : public QmlDesigner::ProjectStorageInterface public: MOCK_METHOD(void, synchronize, - (QmlDesigner::Storage::ModuleDependencies moduleDependencies, - QmlDesigner::Storage::Documents documents, + (QmlDesigner::Storage::Modules modules, + QmlDesigner::Storage::Imports imports, QmlDesigner::Storage::Types types, QmlDesigner::SourceIds sourceIds, QmlDesigner::FileStatuses fileStatuses), diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp index 0e1089bc466..c008d1c20ab 100644 --- a/tests/unit/unittest/projectstorageupdater-test.cpp +++ b/tests/unit/unittest/projectstorageupdater-test.cpp @@ -45,6 +45,7 @@ using QmlDesigner::FileStatus; using QmlDesigner::SourceId; using QmlDesigner::Storage::TypeAccessSemantics; namespace Storage = QmlDesigner::Storage; +using QmlDesigner::Storage::Version; MATCHER_P5(IsStorageType, module, @@ -59,7 +60,7 @@ MATCHER_P5(IsStorageType, return type.module == module && type.typeName == typeName && type.accessSemantics == accessSemantics && type.sourceId == sourceId - && Storage::TypeName{prototype} == type.prototype; + && Storage::ImportedTypeName{prototype} == type.prototype; } MATCHER_P3(IsPropertyDeclaration, @@ -72,7 +73,7 @@ MATCHER_P3(IsPropertyDeclaration, const Storage::PropertyDeclaration &propertyDeclaration = arg; return propertyDeclaration.name == name - && Storage::TypeName{typeName} == propertyDeclaration.typeName + && Storage::ImportedTypeName{typeName} == propertyDeclaration.typeName && propertyDeclaration.traits == traits; } @@ -133,7 +134,7 @@ protected: qmlDocumentParserMock, qmlTypesParserMock}; SourceId objectTypeSourceId{sourcePathCache.sourceId("/path/Object")}; - Storage::Type objectType{Storage::Module{"Qml", 2}, + Storage::Type objectType{Storage::Module{"Qml"}, "QObject", Storage::NativeType{}, Storage::TypeAccessSemantics::Reference, @@ -330,11 +331,11 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) auto qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml"); auto qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml"); Storage::Type firstType; - firstType.prototype = Storage::ExportedType{"Object"}; + firstType.prototype = Storage::ImportedType{"Object"}; Storage::Type secondType; - secondType.prototype = Storage::ExportedType{"Object2"}; + secondType.prototype = Storage::ImportedType{"Object2"}; Storage::Type thirdType; - thirdType.prototype = Storage::ExportedType{"Object3"}; + thirdType.prototype = Storage::ImportedType{"Object3"}; auto firstQmlDocumentSourceId = sourcePathCache.sourceId("/path/First.qml"); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml")))) @@ -350,9 +351,9 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) EXPECT_CALL(projectStorageMock, synchronize(_, _, - Contains(AllOf(IsStorageType(Storage::Module{"Example", 1}, + Contains(AllOf(IsStorageType(Storage::Module{"Example"}, "First.qml", - Storage::ExportedType{"Object"}, + Storage::ImportedType{"Object"}, TypeAccessSemantics::Reference, firstQmlDocumentSourceId), Field(&Storage::Type::exportedTypes, diff --git a/tests/unit/unittest/qmltypesparsermock.h b/tests/unit/unittest/qmltypesparsermock.h index d321cb88377..bd817f16518 100644 --- a/tests/unit/unittest/qmltypesparsermock.h +++ b/tests/unit/unittest/qmltypesparsermock.h @@ -35,7 +35,7 @@ public: MOCK_METHOD(void, parse, (const QString &sourceContent, - QmlDesigner::Storage::ModuleDependencies &moduleDependencies, + QmlDesigner::Storage::Modules &modules, QmlDesigner::Storage::Types &types, QmlDesigner::SourceIds &sourceIds), (override));