QmlDesigner: Project Storage Watcher updates only some directories

Updates only the entries for the given source context (directory) ids
and skips everything else. It is enabling partial updates
for directories in a project.

[&, &ids = ids] the strange capture clause steams from a C++ issue.

Tak-number: QDS-9456
Change-Id: Id3abcd39ac429ba4483124f334d50c2999f5e6a8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2023-03-16 15:42:40 +01:00
parent 4c3530f5ee
commit cb0fc5fd1f
2 changed files with 98 additions and 24 deletions

View File

@@ -60,10 +60,31 @@ public:
void updateIdPaths(const std::vector<IdPaths> &idPaths) override void updateIdPaths(const std::vector<IdPaths> &idPaths) override
{ {
auto entriesAndIds = convertIdPathsToWatcherEntriesAndIds(idPaths); const auto &[entires, ids] = convertIdPathsToWatcherEntriesAndIds(idPaths);
addEntries(entriesAndIds.first); addEntries(entires);
removeUnusedEntries(entriesAndIds.first, entriesAndIds.second);
auto notContainsdId = [&, &ids = ids](WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
};
removeUnusedEntries(entires, notContainsdId);
}
void updateContextIdPaths(const std::vector<IdPaths> &idPaths,
const SourceContextIds &sourceContextIds)
{
const auto &[entires, ids] = convertIdPathsToWatcherEntriesAndIds(idPaths);
addEntries(entires);
auto notContainsdId = [&, &ids = ids](WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id)
|| !std::binary_search(sourceContextIds.begin(),
sourceContextIds.end(),
entry.sourceContextId);
};
removeUnusedEntries(entires, notContainsdId);
} }
void removeIds(const ProjectPartIds &ids) override void removeIds(const ProjectPartIds &ids) override
@@ -133,9 +154,10 @@ public:
m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths)); m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths));
} }
void removeUnusedEntries(const WatcherEntries &entries, const ProjectChunkIds &ids) template<typename Filter>
void removeUnusedEntries(const WatcherEntries &entries, Filter filter)
{ {
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, filter);
removeFromWatchedEntries(oldEntries); removeFromWatchedEntries(oldEntries);
@@ -195,9 +217,7 @@ public:
} }
template<typename Compare> template<typename Compare>
WatcherEntries notAnymoreWatchedEntries( WatcherEntries notAnymoreWatchedEntries(const WatcherEntries &newEntries, Compare compare) const
const WatcherEntries &newEntries,
Compare compare) const
{ {
WatcherEntries notAnymoreWatchedEntries; WatcherEntries notAnymoreWatchedEntries;
notAnymoreWatchedEntries.reserve(m_watchedEntries.size()); notAnymoreWatchedEntries.reserve(m_watchedEntries.size());
@@ -212,16 +232,12 @@ public:
return notAnymoreWatchedEntries; return notAnymoreWatchedEntries;
} }
WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries, template<typename Filter>
const ProjectChunkIds &ids) const WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries, Filter filter) const
{ {
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>()); auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
auto newEnd = std::remove_if(oldEntries.begin(), auto newEnd = std::remove_if(oldEntries.begin(), oldEntries.end(), filter);
oldEntries.end(),
[&] (WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
});
oldEntries.erase(newEnd, oldEntries.end()); oldEntries.erase(newEnd, oldEntries.end());

View File

@@ -69,7 +69,8 @@ protected:
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
ProjectChunkId projectChunkId1{ProjectPartId::create(2), SourceType::Qml}; ProjectChunkId projectChunkId1{ProjectPartId::create(2), SourceType::Qml};
ProjectChunkId projectChunkId2{ProjectPartId::create(2), SourceType::QmlUi}; ProjectChunkId projectChunkId2{ProjectPartId::create(2), SourceType::QmlUi};
ProjectChunkId projectChunkId3{ProjectPartId::create(4), SourceType::QmlTypes}; ProjectChunkId projectChunkId3{ProjectPartId::create(3), SourceType::QmlTypes};
ProjectChunkId projectChunkId4{ProjectPartId::create(4), SourceType::Qml};
SourcePathView path1{"/path/path1"}; SourcePathView path1{"/path/path1"};
SourcePathView path2{"/path/path2"}; SourcePathView path2{"/path/path2"};
SourcePathView path3{"/path2/path1"}; SourcePathView path3{"/path2/path1"};
@@ -99,6 +100,11 @@ protected:
WatcherEntry watcherEntry6{projectChunkId1, sourceContextIds[1], sourceIds[2]}; WatcherEntry watcherEntry6{projectChunkId1, sourceContextIds[1], sourceIds[2]};
WatcherEntry watcherEntry7{projectChunkId2, sourceContextIds[1], sourceIds[3]}; WatcherEntry watcherEntry7{projectChunkId2, sourceContextIds[1], sourceIds[3]};
WatcherEntry watcherEntry8{projectChunkId3, sourceContextIds[1], sourceIds[3]}; WatcherEntry watcherEntry8{projectChunkId3, sourceContextIds[1], sourceIds[3]};
WatcherEntry watcherEntry9{projectChunkId4, sourceContextIds[0], sourceIds[0]};
WatcherEntry watcherEntry10{projectChunkId4, sourceContextIds[0], sourceIds[1]};
WatcherEntry watcherEntry11{projectChunkId4, sourceContextIds[1], sourceIds[2]};
WatcherEntry watcherEntry12{projectChunkId4, sourceContextIds[1], sourceIds[3]};
WatcherEntry watcherEntry13{projectChunkId4, sourceContextIds[2], sourceIds[4]};
}; };
TEST_F(ProjectStoragePathWatcher, AddIdPaths) TEST_F(ProjectStoragePathWatcher, AddIdPaths)
@@ -310,9 +316,13 @@ TEST_F(ProjectStoragePathWatcher, RemoveOnePathForTwoId)
TEST_F(ProjectStoragePathWatcher, NotAnymoreWatchedEntriesWithId) TEST_F(ProjectStoragePathWatcher, NotAnymoreWatchedEntriesWithId)
{ {
auto notContainsdId = [&](WatcherEntry entry) {
return entry.id != ids[0] && entry.id != ids[1];
};
watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5})); watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}));
auto oldEntries = watcher.notAnymoreWatchedEntriesWithIds({watcherEntry1, watcherEntry4}, {ids[0], ids[1]}); auto oldEntries = watcher.notAnymoreWatchedEntriesWithIds({watcherEntry1, watcherEntry4},
notContainsdId);
ASSERT_THAT(oldEntries, ElementsAre(watcherEntry2, watcherEntry3)); ASSERT_THAT(oldEntries, ElementsAre(watcherEntry2, watcherEntry3));
} }
@@ -386,15 +396,63 @@ TEST_F(ProjectStoragePathWatcher, NoDuplicatePathChanges)
mockQFileSytemWatcher.directoryChanged(sourceContextPath); mockQFileSytemWatcher.directoryChanged(sourceContextPath);
} }
TEST_F(ProjectStoragePathWatcher, UpdateContextIdPathsAndRemoveUnusedPaths) TEST_F(ProjectStoragePathWatcher, UpdateContextIdPathsAddsEntryInNewDirectory)
{ {
watcher.updateIdPaths({{projectChunkId1, {sourceIds[0], sourceIds[1]}}, watcher.updateIdPaths({
{projectChunkId2, {sourceIds[0], sourceIds[1]}}, {projectChunkId1, {sourceIds[0], sourceIds[1], sourceIds[2]}},
{projectChunkId3, {sourceIds[1]}}}); {projectChunkId4, {sourceIds[0], sourceIds[1], sourceIds[2], sourceIds[3]}},
});
watcher.updateIdPaths({{projectChunkId1, {sourceIds[0]}}, {projectChunkId2, {sourceIds[1]}}}); watcher.updateContextIdPaths({{projectChunkId4, {sourceIds[4]}}}, {sourceContextIds[2]});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5)); ASSERT_THAT(watcher.watchedEntries(),
UnorderedElementsAre(watcherEntry1,
watcherEntry3,
watcherEntry6,
watcherEntry9,
watcherEntry10,
watcherEntry11,
watcherEntry12,
watcherEntry13));
}
TEST_F(ProjectStoragePathWatcher, UpdateContextIdPathsAddsEntryToDirectory)
{
watcher.updateIdPaths({
{projectChunkId1, {sourceIds[0], sourceIds[1], sourceIds[2]}},
{projectChunkId4, {sourceIds[1], sourceIds[3]}},
});
watcher.updateContextIdPaths({{projectChunkId4,
{sourceIds[0], sourceIds[1], sourceIds[2], sourceIds[3]}}},
{sourceContextIds[1]});
ASSERT_THAT(watcher.watchedEntries(),
UnorderedElementsAre(watcherEntry1,
watcherEntry3,
watcherEntry6,
watcherEntry9,
watcherEntry10,
watcherEntry11,
watcherEntry12));
}
TEST_F(ProjectStoragePathWatcher, UpdateContextIdPathsRemovesEntry)
{
watcher.updateIdPaths({
{projectChunkId1, {sourceIds[0], sourceIds[1], sourceIds[2]}},
{projectChunkId4, {sourceIds[0], sourceIds[1], sourceIds[2], sourceIds[3]}},
});
watcher.updateContextIdPaths({{projectChunkId4, {sourceIds[3]}}}, {sourceContextIds[1]});
ASSERT_THAT(watcher.watchedEntries(),
UnorderedElementsAre(watcherEntry1,
watcherEntry3,
watcherEntry6,
watcherEntry9,
watcherEntry10,
watcherEntry12));
} }
} // namespace } // namespace