diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp index df8fc02bc01..d628b3191cc 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp @@ -79,6 +79,18 @@ void addSourceIds(SourceIds &sourceIds, const Storage::ProjectDatas &projectData sourceIds.push_back(projectData.sourceId); } +Storage::Version convertVersion(LanguageUtils::ComponentVersion version) +{ + return Storage::Version{version.majorVersion(), version.minorVersion()}; +} + +Storage::IsAutoVersion convertToIsAutoVersion(QmlDirParser::Import::Flags flags) +{ + if (flags & QmlDirParser::Import::Flag::Auto) + return Storage::IsAutoVersion::Yes; + return Storage::IsAutoVersion::No; +} + void addDependencies(Storage::Imports &dependencies, SourceId sourceId, const QList &qmldirDependencies, @@ -91,6 +103,30 @@ void addDependencies(Storage::Imports &dependencies, } } +void addModuleExportedImports(Storage::ModuleExportedImports &imports, + ModuleId moduleId, + const QList &qmldirImports, + ProjectStorageInterface &projectStorage) +{ + for (const QmlDirParser::Import &qmldirImport : qmldirImports) { + if (qmldirImport.flags & QmlDirParser::Import::Flag::Optional) + continue; + + ModuleId exportedModuleId = projectStorage.moduleId(Utils::PathString{qmldirImport.module}); + imports.emplace_back(moduleId, + exportedModuleId, + convertVersion(qmldirImport.version), + convertToIsAutoVersion(qmldirImport.flags)); + + ModuleId exportedCppModuleId = projectStorage.moduleId( + Utils::PathString{qmldirImport.module} + "-cppnative"); + imports.emplace_back(moduleId, + exportedCppModuleId, + Storage::Version{}, + Storage::IsAutoVersion::No); + } +} + } // namespace void ProjectStorageUpdater::update(QStringList qmlDirs, QStringList qmlTypesPaths) @@ -162,6 +198,12 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs, Utils::PathString moduleName{parser.typeNamespace()}; ModuleId moduleId = m_projectStorage.moduleId(moduleName); + addModuleExportedImports(package.moduleExportedImports, + moduleId, + parser.imports(), + m_projectStorage); + package.updatedModuleIds.push_back(moduleId); + const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId); addSourceIds(package.updatedSourceIds, qmlProjectDatas); addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas); diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp index b5e407dc2c7..69ed54ef9b5 100644 --- a/tests/unit/unittest/projectstorageupdater-test.cpp +++ b/tests/unit/unittest/projectstorageupdater-test.cpp @@ -48,6 +48,8 @@ namespace Storage = QmlDesigner::Storage; using QmlDesigner::IdPaths; using QmlDesigner::Storage::FileType; using QmlDesigner::Storage::Import; +using QmlDesigner::Storage::IsAutoVersion; +using QmlDesigner::Storage::ModuleExportedImport; using QmlDesigner::Storage::ProjectData; using QmlDesigner::Storage::SynchronizationPackage; using QmlDesigner::Storage::Version; @@ -245,6 +247,8 @@ protected: ModuleId exampleCppNativeModuleId{storage.moduleId("Example-cppnative")}; ModuleId builtinModuleId{storage.moduleId("QML")}; ModuleId builtinCppNativeModuleId{storage.moduleId("QML-cppnative")}; + ModuleId quickModuleId{storage.moduleId("Quick")}; + ModuleId quickCppNativeModuleId{storage.moduleId("Quick-cppnative")}; Storage::Type objectType{"QObject", Storage::ImportedType{}, Storage::TypeAccessSemantics::Reference, @@ -1089,4 +1093,60 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies) updater.update(qmlDirs, {}); } +TEST_F(ProjectStorageUpdater, SynchronizeQmldirImports) +{ + QString qmldir{R"(module Example + import Qml auto + import QML 2.1 + import Quick + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + + EXPECT_CALL(projectStorageMock, + synchronize( + AllOf(Field(&SynchronizationPackage::moduleExportedImports, + UnorderedElementsAre(ModuleExportedImport{exampleModuleId, + qmlModuleId, + Storage::Version{}, + IsAutoVersion::Yes}, + ModuleExportedImport{exampleModuleId, + qmlCppNativeModuleId, + Storage::Version{}, + IsAutoVersion::No}, + ModuleExportedImport{exampleModuleId, + builtinModuleId, + Storage::Version{2, 1}, + IsAutoVersion::No}, + ModuleExportedImport{exampleModuleId, + builtinCppNativeModuleId, + Storage::Version{}, + IsAutoVersion::No}, + ModuleExportedImport{exampleModuleId, + quickModuleId, + Storage::Version{}, + IsAutoVersion::No}, + ModuleExportedImport{exampleModuleId, + quickCppNativeModuleId, + Storage::Version{}, + IsAutoVersion::No})), + Field(&SynchronizationPackage::updatedModuleIds, + ElementsAre(exampleModuleId))))); + + updater.update(qmlDirs, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports) +{ + QString qmldir{R"(module Example + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + + EXPECT_CALL(projectStorageMock, + synchronize(AllOf(Field(&SynchronizationPackage::moduleExportedImports, IsEmpty()), + Field(&SynchronizationPackage::updatedModuleIds, + ElementsAre(exampleModuleId))))); + + updater.update(qmlDirs, {}); +} + } // namespace