ClangPchManager: Watch unchanged PCHs

Change-Id: I7f4c0f12e4fbf3714e5bfe7655cfa13cac85f71f
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-08-01 16:24:14 +02:00
parent 56d611e0a3
commit 4280a68d9f
10 changed files with 296 additions and 92 deletions

View File

@@ -410,7 +410,7 @@ public:
for (WatcherEntry entry : foundEntries) {
if (idPaths.empty() || idPaths.back().id != entry.id)
idPaths.push_back({entry.id, {}});
idPaths.emplace_back(entry.id, FilePathIds{});
idPaths.back().filePathIds.push_back(entry.filePathId);
}

View File

@@ -70,13 +70,23 @@ public:
class IdPaths
{
public:
ProjectChunkId id;
FilePathIds filePathIds;
IdPaths(ProjectPartId projectPartId, SourceType sourceType, FilePathIds &&filePathIds)
: id{projectPartId, sourceType}
, filePathIds(std::move(filePathIds))
{}
IdPaths(ProjectChunkId projectChunkId, FilePathIds &&filePathIds)
: id(projectChunkId)
, filePathIds(std::move(filePathIds))
{}
friend bool operator==(IdPaths first, IdPaths second)
{
return first.id == second.id && first.filePathIds == second.filePathIds;
}
public:
ProjectChunkId id;
FilePathIds filePathIds;
};
using ProjectChunkIds = std::vector<ProjectChunkId>;

View File

@@ -98,4 +98,22 @@ bool set_intersection_compare(
return false;
}
template<typename InputIt1, typename InputIt2, typename BinaryPredicate, typename Callable, typename Value>
Value mismatch_collect(InputIt1 first1,
InputIt1 last1,
InputIt2 first2,
InputIt2 last2,
Value value,
BinaryPredicate predicate,
Callable callable)
{
while (first1 != last1 && first2 != last2) {
if (predicate(*first1, *first2))
value = callable(*first1, *first2, value);
++first1, ++first2;
}
return value;
}
} // namespace ClangBackEnd

View File

@@ -190,6 +190,7 @@ struct Data // because we have a cycle dependency
preCompiledHeaderStorage,
buildDependencyProvider,
filePathCache,
includeWatcher,
generatedFiles};
PchCreatorManager pchCreatorManager{generatedFiles,
environment,

View File

@@ -196,13 +196,16 @@ void PchCreator::doInMainThreadAfterFinished()
if (m_projectPartPch.projectPartId.isValid()) {
m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
m_projectPartPch.projectPartId);
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::Source},
existingSources(m_watchedSources)}});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::UserInclude},
existingSources(m_watchedUserIncludes)}});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::ProjectInclude},
existingSources(m_watchedProjectIncludes)}});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::SystemInclude},
m_clangPathwatcher.updateIdPaths(
{{m_projectPartPch.projectPartId, SourceType::Source, existingSources(m_watchedSources)},
{m_projectPartPch.projectPartId,
SourceType::UserInclude,
existingSources(m_watchedUserIncludes)},
{m_projectPartPch.projectPartId,
SourceType::ProjectInclude,
existingSources(m_watchedProjectIncludes)},
{m_projectPartPch.projectPartId,
SourceType::SystemInclude,
existingSources(m_watchedSystemIncludes)}});
m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId);
}

View File

@@ -27,6 +27,7 @@
#include <builddependenciesstorage.h>
#include <filepathcachinginterface.h>
#include <filepathview.h>
#include <pchmanagerclientinterface.h>
#include <pchtaskgeneratorinterface.h>
#include <precompiledheadersupdatedmessage.h>
@@ -55,7 +56,6 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
, m_projectPartsManager(projectParts)
, m_generatedFiles(generatedFiles)
, m_buildDependenciesStorage(buildDependenciesStorage)
{
m_fileSystemWatcher.setNotifier(this);
}
@@ -72,6 +72,7 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectParts)
return projectPart.projectPartId;
});
}
} // namespace
void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)

View File

@@ -26,12 +26,16 @@
#include "projectpartsmanager.h"
#include <builddependenciesproviderinterface.h>
#include <clangpathwatcherinterface.h>
#include <filecontainerv2.h>
#include <filepathcachinginterface.h>
#include <generatedfilesinterface.h>
#include <projectpartcontainer.h>
#include <set_algorithm.h>
#include <usedmacrofilter.h>
#include <algorithm>
#include <utils/algorithm.h>
namespace ClangBackEnd {
@@ -73,6 +77,48 @@ Change changedSourceType(const SourceEntries &sources)
return change;
}
Change changedSourceType(SourceEntry sourceEntry, Change oldChange)
{
switch (sourceEntry.sourceType) {
case SourceType::SystemInclude:
case SourceType::TopSystemInclude:
return Change::System;
case SourceType::ProjectInclude:
case SourceType::TopProjectInclude:
if (oldChange != Change::System)
return Change::Project;
break;
case SourceType::Source:
case SourceType::UserInclude:
break;
}
return oldChange;
}
FilePathIds existingSources(const FilePathIds &sources, const FilePathIds &generatedFilePathIds)
{
FilePathIds existingSources;
existingSources.reserve(sources.size());
std::set_difference(sources.begin(),
sources.end(),
generatedFilePathIds.begin(),
generatedFilePathIds.end(),
std::back_inserter(existingSources));
return existingSources;
}
FilePathIds toFilePathIds(const V2::FileContainers &fileContainers,
FilePathCachingInterface &filePathCache)
{
auto filePaths = Utils::transform<std::vector<FilePathView>>(
fileContainers,
[](const V2::FileContainer &container) { return FilePathView(container.filePath); });
return filePathCache.filePathIds(filePaths);
}
} // namespace
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
@@ -129,6 +175,11 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
auto systemSplit = updateSystemProjectParts.end();
FilePathIds generatedFiles = toFilePathIds(m_generatedFiles.fileContainers(), m_filePathCache);
std::vector<IdPaths> watchedIdPaths;
watchedIdPaths.reserve(upToDateProjectParts.size() * 4);
for (ProjectPartContainer &projectPart : upToDateProjectParts) {
auto oldSources = m_buildDependenciesProvider.createSourceEntriesFromStorage(
projectPart.sourcePathIds, projectPart.projectPartId);
@@ -136,7 +187,7 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart,
Utils::clone(oldSources));
auto newSources = buildDependency.sources;
const auto &newSources = buildDependency.sources;
SourceEntries updatedSourceTyes;
updatedSourceTyes.reserve(newSources.size());
@@ -170,18 +221,19 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
SourceEntries updatedTimeStamps;
updatedTimeStamps.reserve(newSources.size());
std::set_difference(newSources.begin(),
Change change = mismatch_collect(
newSources.begin(),
newSources.end(),
oldSources.begin(),
oldSources.end(),
std::back_inserter(updatedTimeStamps),
Change::No,
[](SourceEntry first, SourceEntry second) {
return std::tie(first.sourceId, first.timeStamp)
< std::tie(second.sourceId, second.timeStamp);
return first.timeStamp > second.timeStamp;
},
[](SourceEntry first, SourceEntry, Change change) {
return changedSourceType(first, change);
});
auto change = changedSourceType(updatedTimeStamps);
switch (change) {
case Change::Project:
updateProjectProjectParts.emplace_back(std::move(projectPart));
@@ -192,11 +244,31 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
projectPart.projectPartId = -1;
break;
case Change::No:
UsedMacroFilter usedMacroFilter{newSources, {}, {}};
watchedIdPaths.emplace_back(projectPart.projectPartId,
SourceType::Source,
existingSources(usedMacroFilter.sources, generatedFiles));
watchedIdPaths.emplace_back(projectPart.projectPartId,
SourceType::UserInclude,
existingSources(usedMacroFilter.userIncludes,
generatedFiles));
watchedIdPaths.emplace_back(projectPart.projectPartId,
SourceType::ProjectInclude,
existingSources(usedMacroFilter.projectIncludes,
generatedFiles));
watchedIdPaths.emplace_back(projectPart.projectPartId,
SourceType::SystemInclude,
existingSources(usedMacroFilter.systemIncludes,
generatedFiles));
break;
}
}
}
if (watchedIdPaths.size())
m_clangPathwatcher.updateIdPaths(watchedIdPaths);
std::inplace_merge(updateSystemProjectParts.begin(), systemSplit, updateSystemProjectParts.end());
upToDateProjectParts.erase(std::remove_if(upToDateProjectParts.begin(),
upToDateProjectParts.end(),

View File

@@ -36,6 +36,9 @@
namespace ClangBackEnd {
class BuildDependenciesProviderInterface;
class FilePathCachingInterface;
class GeneratedFilesInterface;
class ClangPathWatcherInterface;
inline namespace Pch {
@@ -44,10 +47,16 @@ class ProjectPartsManager final : public ProjectPartsManagerInterface
public:
ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage,
PrecompiledHeaderStorageInterface &precompiledHeaderStorage,
BuildDependenciesProviderInterface &buildDependenciesProvider)
BuildDependenciesProviderInterface &buildDependenciesProvider,
FilePathCachingInterface &filePathCache,
ClangPathWatcherInterface &clangPathwatcher,
GeneratedFilesInterface &generatedFiles)
: m_projectPartsStorage(projectPartsStorage)
, m_precompiledHeaderStorage(precompiledHeaderStorage)
, m_buildDependenciesProvider(buildDependenciesProvider)
, m_filePathCache(filePathCache)
, m_clangPathwatcher(clangPathwatcher)
, m_generatedFiles(generatedFiles)
{}
UpToDataProjectParts update(ProjectPartContainers &&projectsParts) override;
@@ -71,6 +80,9 @@ private:
ProjectPartsStorageInterface &m_projectPartsStorage;
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
FilePathCachingInterface &m_filePathCache;
ClangPathWatcherInterface &m_clangPathwatcher;
GeneratedFilesInterface &m_generatedFiles;
};
} // namespace Pch

View File

@@ -228,30 +228,22 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess)
{
creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(UnorderedElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre(id(main2Path)))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(ElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
@@ -266,30 +258,22 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterFail)
pchTask1.projectIncludeSearchPaths = {};
creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(UnorderedElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre(id(main2Path)))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(ElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
@@ -421,29 +405,22 @@ TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls)
precompiledHeadersUpdated(
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(UnorderedElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre(id(main2Path)))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(ElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))),
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),

View File

@@ -25,6 +25,7 @@
#include "googletest.h"
#include "mockbuilddependenciesprovider.h"
#include "mockclangpathwatcher.h"
#include "mockfilepathcaching.h"
#include "mockgeneratedfiles.h"
#include "mockprecompiledheaderstorage.h"
@@ -37,25 +38,48 @@
namespace {
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers;
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
using ClangBackEnd::SourceType;
MATCHER_P3(IsIdPaths,
projectPartId,
sourceIds,
sourceType,
std::string(negation ? "isn't " : "is ")
+ PrintToString(ClangBackEnd::IdPaths{{projectPartId, sourceType},
Utils::clone(sourceIds)}))
{
const ClangBackEnd::IdPaths &idPaths = arg;
return idPaths.filePathIds == sourceIds && idPaths.id.sourceType == sourceType
&& idPaths.id.id == projectPartId;
}
class ProjectPartsManager : public testing::Test
{
protected:
ProjectPartsManager()
{
projectPartContainerWithoutPrecompiledHeader1.preCompiledHeaderWasGenerated = false;
ON_CALL(mockGeneratedFiles, fileContainers()).WillByDefault(ReturnRef(generatedFiles));
}
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
NiceMock<MockFilePathCaching> mockFilePathCaching;
NiceMock<MockGeneratedFiles> mockGeneratedFiles;
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage,
mockPrecompiledHeaderStorage,
mockBuildDependenciesProvider};
mockBuildDependenciesProvider,
mockFilePathCaching,
mockClangPathWatcher,
mockGeneratedFiles};
FilePathId firstHeader{1};
FilePathId secondHeader{2};
FilePathId firstSource{11};
@@ -649,7 +673,7 @@ TEST_F(ProjectPartsManager, SourcesTimeChanged)
TEST_F(ProjectPartsManager, SourcesTimeNotChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 99}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
@@ -832,4 +856,90 @@ TEST_F(ProjectPartsManager, ChangeFromUserIncludeToSource)
ASSERT_THAT(upToDate.updateProject, IsEmpty());
}
TEST_F(ProjectPartsManager, DontWatchNewSources)
{
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(_)).Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, DontWatchUpdatedSources)
{
manager.update({projectPartContainer1});
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(_)).Times(0);
manager.update({updatedProjectPartContainer1});
}
TEST_F(ProjectPartsManager, DontWatchChangedTimeStamps)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 101}};
ON_CALL(mockBuildDependenciesProvider, createSourceEntriesFromStorage(_, _))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(_, _))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(_)).Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, DontWatchChangedSources)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::ProjectInclude, 100}};
ON_CALL(mockBuildDependenciesProvider, createSourceEntriesFromStorage(_, _))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(_, _))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(_)).Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, WatchNoUpdatedSources)
{
manager.update({projectPartContainer1, projectPartContainer2});
SourceEntries sources1{{1, SourceType::TopSystemInclude, 100},
{2, SourceType::SystemInclude, 100},
{3, SourceType::TopProjectInclude, 100},
{4, SourceType::ProjectInclude, 100},
{5, SourceType::UserInclude, 100},
{6, SourceType::Source, 100}};
SourceEntries sources2{{11, SourceType::TopSystemInclude, 100},
{21, SourceType::SystemInclude, 100},
{31, SourceType::TopProjectInclude, 100},
{41, SourceType::ProjectInclude, 100},
{51, SourceType::UserInclude, 100},
{61, SourceType::Source, 100}};
ON_CALL(mockBuildDependenciesProvider, createSourceEntriesFromStorage(_, Eq(1)))
.WillByDefault(Return(sources1));
ON_CALL(mockBuildDependenciesProvider,
create(Field(&ProjectPartContainer::projectPartId, Eq(1)), _))
.WillByDefault(Return(ClangBackEnd::BuildDependency{sources1, {}, {}, {}, {}}));
ON_CALL(mockBuildDependenciesProvider, createSourceEntriesFromStorage(_, Eq(2)))
.WillByDefault(Return(sources2));
ON_CALL(mockBuildDependenciesProvider,
create(Field(&ProjectPartContainer::projectPartId, Eq(2)), _))
.WillByDefault(Return(ClangBackEnd::BuildDependency{sources2, {}, {}, {}, {}}));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(UnorderedElementsAre(
IsIdPaths(1, FilePathIds{6}, SourceType::Source),
IsIdPaths(2, FilePathIds{61}, SourceType::Source),
IsIdPaths(1, FilePathIds{5}, SourceType::UserInclude),
IsIdPaths(2, FilePathIds{51}, SourceType::UserInclude),
IsIdPaths(1, FilePathIds{3, 4}, SourceType::ProjectInclude),
IsIdPaths(2, FilePathIds{31, 41}, SourceType::ProjectInclude),
IsIdPaths(1, FilePathIds{1, 2}, SourceType::SystemInclude),
IsIdPaths(2, FilePathIds{11, 21}, SourceType::SystemInclude))));
manager.update({projectPartContainer1, projectPartContainer2});
}
} // namespace