From 2d5062918aace38e9360ac8ae05464ba22baeb4d Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 15 Mar 2023 13:56:26 +0100 Subject: [PATCH] QmlDesigner: Project storage watcher watches unchanged files The Qml documents and Qmltypes files cannot added or removed if the project data is parsed. So the can simply been added to the watched files. Task-number: QDS-9178 Change-Id: Iaa30425241ac7ad3c2434b9c6c5955e894ec6049 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann Reviewed-by: --- .../projectstorage/projectstorageupdater.cpp | 14 +- .../projectstorage/projectstorageupdater.h | 4 +- .../unittest/projectstorageupdater-test.cpp | 179 +++++++++++++++++- 3 files changed, 182 insertions(+), 15 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp index 9d484507bb3..a9d11754613 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp @@ -342,7 +342,9 @@ void ProjectStorageUpdater::updateDirectories(const QStringList &directories, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds, - directoryPath); + directoryPath, + watchedQmlSourceIds, + watchedQmltypesSourceIds); break; } case FileState::NotExists: { @@ -406,13 +408,16 @@ void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::Pr Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds, SourceIds ¬UpdatedSourceIds, - Utils::SmallStringView directoryPath) + Utils::SmallStringView directoryPath, + SourceIds &watchedQmlSourceIds, + SourceIds &watchedQmltypesSourceIds) { for (const Storage::Synchronization::ProjectData &projectData : projectDatas) { switch (projectData.fileType) { case Storage::Synchronization::FileType::QmlTypes: { - auto qmltypesPath = m_pathCache.sourcePath(projectData.sourceId); + watchedQmltypesSourceIds.push_back(projectData.sourceId); + auto qmltypesPath = m_pathCache.sourcePath(projectData.sourceId); parseTypeInfo(projectData, qmltypesPath, package, @@ -421,8 +426,9 @@ void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::Pr break; } case Storage::Synchronization::FileType::QmlDocument: { - SourcePath qmlDocumentPath = m_pathCache.sourcePath(projectData.sourceId); + watchedQmlSourceIds.push_back(projectData.sourceId); + SourcePath qmlDocumentPath = m_pathCache.sourcePath(projectData.sourceId); parseQmlComponent(qmlDocumentPath.name(), qmlDocumentPath, directoryPath, diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h index 8d5ce48ff36..e948342f9ae 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h @@ -124,7 +124,9 @@ private: Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds, SourceIds ¬UpdatedSourceIds, - Utils::SmallStringView directoryPath); + Utils::SmallStringView directoryPath, + SourceIds &watchedQmlSourceIds, + SourceIds &watchedQmltypesSourceIds); FileState parseTypeInfo(const Storage::Synchronization::ProjectData &projectData, Utils::SmallStringView qmltypesPath, Storage::Synchronization::SynchronizationPackage &package, diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp index 6b83375e260..d5a3d72cd0e 100644 --- a/tests/unit/unittest/projectstorageupdater-test.cpp +++ b/tests/unit/unittest/projectstorageupdater-test.cpp @@ -161,6 +161,11 @@ public: setContent(u"/path/Second.qml", qmlDocument3); setContent(u"/path/example.qmltypes", qmltypes1); setContent(u"/path/types/example2.qmltypes", qmltypes2); + setContent(u"/path/one/First.qml", qmlDocument1); + setContent(u"/path/one/Second.qml", qmlDocument2); + setContent(u"/path/two/Third.qml", qmlDocument3); + setContent(u"/path/one/example.qmltypes", qmltypes1); + setContent(u"/path/two/example2.qmltypes", qmltypes2); ON_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _)) .WillByDefault([&](auto, auto &imports, auto, auto) { @@ -1510,6 +1515,29 @@ TEST_F(ProjectStorageUpdater, UpdatePathWatcherDirectoryDoesNotExists) updater.update(directories3, {}, projectPartId); } +TEST_F(ProjectStorageUpdater, UpdatePathWatcherDirectoryDoesNotChanged) +{ + setFilesDontChanged({qmldir1SourceId, qmldir2SourceId, path1SourceId, path2SourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::Directory, + {path1SourceId, path2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherDirectoryRemoved) +{ + setFilesRemoved({qmldir1SourceId, path1SourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains( + IdPaths{projectPartId, QmlDesigner::SourceType::Directory, {path2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmldirs) { EXPECT_CALL(patchWatcherMock, @@ -1532,6 +1560,29 @@ TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmldirDoesNotExists) updater.update(directories3, {}, projectPartId); } +TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmldirDoesNotChanged) +{ + setFilesDontChanged({qmldir1SourceId, qmldir2SourceId, path1SourceId, path2SourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::QmlDir, + {qmldir1SourceId, qmldir2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmldirRemoved) +{ + setFilesRemoved({qmldir1SourceId, path1SourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains( + IdPaths{projectPartId, QmlDesigner::SourceType::QmlDir, {qmldir2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmlFiles) { QString qmldir1{R"(module Example @@ -1540,9 +1591,6 @@ TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmlFiles) setQmlFileNames(u"/path/one", {"First.qml", "Second.qml"}); setQmlFileNames(u"/path/two", {"Third.qml"}); setContent(u"/path/one/qmldir", qmldir1); - setContent(u"/path/one/First.qml", qmlDocument1); - setContent(u"/path/one/Second.qml", qmlDocument2); - setContent(u"/path/two/Third.qml", qmlDocument3); EXPECT_CALL(patchWatcherMock, updateIdPaths(Contains(IdPaths{projectPartId, @@ -1552,7 +1600,66 @@ TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmlFiles) updater.update(directories2, {}, projectPartId); } -TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmltypesFilesInQmldirFiles) +TEST_F(ProjectStorageUpdater, UpdatePathWatcherOnlyQmlFilesDontChanged) +{ + QString qmldir1{R"(module Example + FirstType 1.0 First.qml + Second 1.0 Second.qml)"}; + setQmlFileNames(u"/path/one", {"First.qml", "Second.qml"}); + setQmlFileNames(u"/path/two", {"Third.qml"}); + setContent(u"/path/one/qmldir", qmldir1); + setFilesDontChanged({firstSourceId, secondSourceId, thirdSourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::Qml, + {firstSourceId, secondSourceId, thirdSourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherOnlyQmlFilesChanged) +{ + setFilesDontChanged({qmldir1SourceId, qmldir2SourceId, path1SourceId, path2SourceId}); + setFilesChanged({firstSourceId, secondSourceId, thirdSourceId}); + setProjectDatas(path1SourceId, + {{path1SourceId, firstSourceId, exampleModuleId, FileType::QmlDocument}, + {path1SourceId, secondSourceId, exampleModuleId, FileType::QmlDocument}}); + setProjectDatas(path2SourceId, + {{path2SourceId, thirdSourceId, ModuleId{}, FileType::QmlDocument}}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::Qml, + {firstSourceId, secondSourceId, thirdSourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmlFilesAndDirectoriesDontChanged) +{ + setFilesDontChanged({qmldir1SourceId, + qmldir2SourceId, + path1SourceId, + path2SourceId, + firstSourceId, + secondSourceId, + thirdSourceId}); + setProjectDatas(path1SourceId, + {{path1SourceId, firstSourceId, exampleModuleId, FileType::QmlDocument}, + {path1SourceId, secondSourceId, exampleModuleId, FileType::QmlDocument}}); + setProjectDatas(path2SourceId, + {{path2SourceId, thirdSourceId, ModuleId{}, FileType::QmlDocument}}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::Qml, + {firstSourceId, secondSourceId, thirdSourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmltypesFilesInQmldir) { QString qmldir1{R"(module Example typeinfo example.qmltypes)"}; @@ -1560,10 +1667,64 @@ TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmltypesFilesInQmldirFiles) typeinfo example2.qmltypes)"}; setContent(u"/path/one/qmldir", qmldir1); setContent(u"/path/two/qmldir", qmldir2); - setContent(u"/path/one/example.qmltypes", qmltypes1); - setContent(u"/path/two/example2.qmltypes", qmltypes2); - SourceId qmltypes1SourceId = sourcePathCache.sourceId("/path/one/example.qmltypes"); - SourceId qmltypes2SourceId = sourcePathCache.sourceId("/path/two/example2.qmltypes"); + + setFilesDontChanged({firstSourceId, secondSourceId, thirdSourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::QmlTypes, + {qmltypes1SourceId, qmltypes2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherOnlyQmltypesFilesInQmldirDontChanged) +{ + QString qmldir1{R"(module Example + typeinfo example.qmltypes)"}; + QString qmldir2{R"(module Example2 + typeinfo example2.qmltypes)"}; + setContent(u"/path/one/qmldir", qmldir1); + setContent(u"/path/two/qmldir", qmldir2); + setFilesDontChanged({qmltypes1SourceId, qmltypes2SourceId}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::QmlTypes, + {qmltypes1SourceId, qmltypes2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherOnlyQmltypesFilesChanged) +{ + setFilesDontChanged({qmldir1SourceId, qmldir2SourceId, path1SourceId, path2SourceId}); + setFilesChanged({qmltypes1SourceId, qmltypes2SourceId}); + setProjectDatas(path1SourceId, + {{path1SourceId, qmltypes1SourceId, exampleModuleId, FileType::QmlTypes}}); + setProjectDatas(path2SourceId, + {{path2SourceId, qmltypes2SourceId, exampleModuleId, FileType::QmlTypes}}); + + EXPECT_CALL(patchWatcherMock, + updateIdPaths(Contains(IdPaths{projectPartId, + QmlDesigner::SourceType::QmlTypes, + {qmltypes1SourceId, qmltypes2SourceId}}))); + + updater.update(directories2, {}, projectPartId); +} + +TEST_F(ProjectStorageUpdater, UpdatePathWatcherQmltypesFilesAndDirectoriesDontChanged) +{ + setFilesDontChanged({qmldir1SourceId, + qmldir2SourceId, + path1SourceId, + path2SourceId, + qmltypes1SourceId, + qmltypes2SourceId}); + setProjectDatas(path1SourceId, + {{path1SourceId, qmltypes1SourceId, exampleModuleId, FileType::QmlTypes}}); + setProjectDatas(path2SourceId, + {{path2SourceId, qmltypes2SourceId, exampleModuleId, FileType::QmlTypes}}); EXPECT_CALL(patchWatcherMock, updateIdPaths(Contains(IdPaths{projectPartId, @@ -1579,8 +1740,6 @@ TEST_F(ProjectStorageUpdater, UpdatePathWatcherBuiltinQmltypesFiles) QString builtinQmltyplesPath2{"/path/two/example2.qmltypes"}; setContent(builtinQmltyplesPath1, qmltypes1); setContent(builtinQmltyplesPath2, qmltypes2); - SourceId qmltypes1SourceId = sourcePathCache.sourceId("/path/one/example.qmltypes"); - SourceId qmltypes2SourceId = sourcePathCache.sourceId("/path/two/example2.qmltypes"); EXPECT_CALL(patchWatcherMock, updateIdPaths(Contains(IdPaths{projectPartId,