forked from qt-creator/qt-creator
ClangPchManager: Watch unchanged PCHs
Change-Id: I7f4c0f12e4fbf3714e5bfe7655cfa13cac85f71f Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -410,7 +410,7 @@ public:
|
|||||||
|
|
||||||
for (WatcherEntry entry : foundEntries) {
|
for (WatcherEntry entry : foundEntries) {
|
||||||
if (idPaths.empty() || idPaths.back().id != entry.id)
|
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);
|
idPaths.back().filePathIds.push_back(entry.filePathId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -70,13 +70,23 @@ public:
|
|||||||
class IdPaths
|
class IdPaths
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectChunkId id;
|
IdPaths(ProjectPartId projectPartId, SourceType sourceType, FilePathIds &&filePathIds)
|
||||||
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)
|
friend bool operator==(IdPaths first, IdPaths second)
|
||||||
{
|
{
|
||||||
return first.id == second.id && first.filePathIds == second.filePathIds;
|
return first.id == second.id && first.filePathIds == second.filePathIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProjectChunkId id;
|
||||||
|
FilePathIds filePathIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ProjectChunkIds = std::vector<ProjectChunkId>;
|
using ProjectChunkIds = std::vector<ProjectChunkId>;
|
||||||
|
@@ -98,4 +98,22 @@ bool set_intersection_compare(
|
|||||||
|
|
||||||
return false;
|
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
|
} // namespace ClangBackEnd
|
||||||
|
@@ -190,6 +190,7 @@ struct Data // because we have a cycle dependency
|
|||||||
preCompiledHeaderStorage,
|
preCompiledHeaderStorage,
|
||||||
buildDependencyProvider,
|
buildDependencyProvider,
|
||||||
filePathCache,
|
filePathCache,
|
||||||
|
includeWatcher,
|
||||||
generatedFiles};
|
generatedFiles};
|
||||||
PchCreatorManager pchCreatorManager{generatedFiles,
|
PchCreatorManager pchCreatorManager{generatedFiles,
|
||||||
environment,
|
environment,
|
||||||
|
@@ -196,13 +196,16 @@ void PchCreator::doInMainThreadAfterFinished()
|
|||||||
if (m_projectPartPch.projectPartId.isValid()) {
|
if (m_projectPartPch.projectPartId.isValid()) {
|
||||||
m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
|
m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
|
||||||
m_projectPartPch.projectPartId);
|
m_projectPartPch.projectPartId);
|
||||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::Source},
|
m_clangPathwatcher.updateIdPaths(
|
||||||
existingSources(m_watchedSources)}});
|
{{m_projectPartPch.projectPartId, SourceType::Source, existingSources(m_watchedSources)},
|
||||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::UserInclude},
|
{m_projectPartPch.projectPartId,
|
||||||
existingSources(m_watchedUserIncludes)}});
|
SourceType::UserInclude,
|
||||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::ProjectInclude},
|
existingSources(m_watchedUserIncludes)},
|
||||||
existingSources(m_watchedProjectIncludes)}});
|
{m_projectPartPch.projectPartId,
|
||||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::SystemInclude},
|
SourceType::ProjectInclude,
|
||||||
|
existingSources(m_watchedProjectIncludes)},
|
||||||
|
{m_projectPartPch.projectPartId,
|
||||||
|
SourceType::SystemInclude,
|
||||||
existingSources(m_watchedSystemIncludes)}});
|
existingSources(m_watchedSystemIncludes)}});
|
||||||
m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId);
|
m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId);
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <builddependenciesstorage.h>
|
#include <builddependenciesstorage.h>
|
||||||
#include <filepathcachinginterface.h>
|
#include <filepathcachinginterface.h>
|
||||||
|
#include <filepathview.h>
|
||||||
#include <pchmanagerclientinterface.h>
|
#include <pchmanagerclientinterface.h>
|
||||||
#include <pchtaskgeneratorinterface.h>
|
#include <pchtaskgeneratorinterface.h>
|
||||||
#include <precompiledheadersupdatedmessage.h>
|
#include <precompiledheadersupdatedmessage.h>
|
||||||
@@ -55,7 +56,6 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
|
|||||||
, m_projectPartsManager(projectParts)
|
, m_projectPartsManager(projectParts)
|
||||||
, m_generatedFiles(generatedFiles)
|
, m_generatedFiles(generatedFiles)
|
||||||
, m_buildDependenciesStorage(buildDependenciesStorage)
|
, m_buildDependenciesStorage(buildDependenciesStorage)
|
||||||
|
|
||||||
{
|
{
|
||||||
m_fileSystemWatcher.setNotifier(this);
|
m_fileSystemWatcher.setNotifier(this);
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,7 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectParts)
|
|||||||
return projectPart.projectPartId;
|
return projectPart.projectPartId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
|
void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
|
||||||
|
@@ -26,12 +26,16 @@
|
|||||||
#include "projectpartsmanager.h"
|
#include "projectpartsmanager.h"
|
||||||
|
|
||||||
#include <builddependenciesproviderinterface.h>
|
#include <builddependenciesproviderinterface.h>
|
||||||
|
#include <clangpathwatcherinterface.h>
|
||||||
#include <filecontainerv2.h>
|
#include <filecontainerv2.h>
|
||||||
#include <filepathcachinginterface.h>
|
#include <filepathcachinginterface.h>
|
||||||
|
#include <generatedfilesinterface.h>
|
||||||
#include <projectpartcontainer.h>
|
#include <projectpartcontainer.h>
|
||||||
#include <set_algorithm.h>
|
#include <set_algorithm.h>
|
||||||
|
#include <usedmacrofilter.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
@@ -73,6 +77,48 @@ Change changedSourceType(const SourceEntries &sources)
|
|||||||
return change;
|
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
|
} // namespace
|
||||||
|
|
||||||
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
|
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
|
||||||
@@ -129,6 +175,11 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
|
|||||||
|
|
||||||
auto systemSplit = updateSystemProjectParts.end();
|
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) {
|
for (ProjectPartContainer &projectPart : upToDateProjectParts) {
|
||||||
auto oldSources = m_buildDependenciesProvider.createSourceEntriesFromStorage(
|
auto oldSources = m_buildDependenciesProvider.createSourceEntriesFromStorage(
|
||||||
projectPart.sourcePathIds, projectPart.projectPartId);
|
projectPart.sourcePathIds, projectPart.projectPartId);
|
||||||
@@ -136,7 +187,7 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
|
|||||||
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart,
|
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart,
|
||||||
Utils::clone(oldSources));
|
Utils::clone(oldSources));
|
||||||
|
|
||||||
auto newSources = buildDependency.sources;
|
const auto &newSources = buildDependency.sources;
|
||||||
|
|
||||||
SourceEntries updatedSourceTyes;
|
SourceEntries updatedSourceTyes;
|
||||||
updatedSourceTyes.reserve(newSources.size());
|
updatedSourceTyes.reserve(newSources.size());
|
||||||
@@ -170,18 +221,19 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
|
|||||||
SourceEntries updatedTimeStamps;
|
SourceEntries updatedTimeStamps;
|
||||||
updatedTimeStamps.reserve(newSources.size());
|
updatedTimeStamps.reserve(newSources.size());
|
||||||
|
|
||||||
std::set_difference(newSources.begin(),
|
Change change = mismatch_collect(
|
||||||
|
newSources.begin(),
|
||||||
newSources.end(),
|
newSources.end(),
|
||||||
oldSources.begin(),
|
oldSources.begin(),
|
||||||
oldSources.end(),
|
oldSources.end(),
|
||||||
std::back_inserter(updatedTimeStamps),
|
Change::No,
|
||||||
[](SourceEntry first, SourceEntry second) {
|
[](SourceEntry first, SourceEntry second) {
|
||||||
return std::tie(first.sourceId, first.timeStamp)
|
return first.timeStamp > second.timeStamp;
|
||||||
< std::tie(second.sourceId, second.timeStamp);
|
},
|
||||||
|
[](SourceEntry first, SourceEntry, Change change) {
|
||||||
|
return changedSourceType(first, change);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto change = changedSourceType(updatedTimeStamps);
|
|
||||||
|
|
||||||
switch (change) {
|
switch (change) {
|
||||||
case Change::Project:
|
case Change::Project:
|
||||||
updateProjectProjectParts.emplace_back(std::move(projectPart));
|
updateProjectProjectParts.emplace_back(std::move(projectPart));
|
||||||
@@ -192,11 +244,31 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
|
|||||||
projectPart.projectPartId = -1;
|
projectPart.projectPartId = -1;
|
||||||
break;
|
break;
|
||||||
case Change::No:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (watchedIdPaths.size())
|
||||||
|
m_clangPathwatcher.updateIdPaths(watchedIdPaths);
|
||||||
|
|
||||||
std::inplace_merge(updateSystemProjectParts.begin(), systemSplit, updateSystemProjectParts.end());
|
std::inplace_merge(updateSystemProjectParts.begin(), systemSplit, updateSystemProjectParts.end());
|
||||||
upToDateProjectParts.erase(std::remove_if(upToDateProjectParts.begin(),
|
upToDateProjectParts.erase(std::remove_if(upToDateProjectParts.begin(),
|
||||||
upToDateProjectParts.end(),
|
upToDateProjectParts.end(),
|
||||||
|
@@ -36,6 +36,9 @@
|
|||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class BuildDependenciesProviderInterface;
|
class BuildDependenciesProviderInterface;
|
||||||
|
class FilePathCachingInterface;
|
||||||
|
class GeneratedFilesInterface;
|
||||||
|
class ClangPathWatcherInterface;
|
||||||
|
|
||||||
inline namespace Pch {
|
inline namespace Pch {
|
||||||
|
|
||||||
@@ -44,10 +47,16 @@ class ProjectPartsManager final : public ProjectPartsManagerInterface
|
|||||||
public:
|
public:
|
||||||
ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage,
|
ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage,
|
||||||
PrecompiledHeaderStorageInterface &precompiledHeaderStorage,
|
PrecompiledHeaderStorageInterface &precompiledHeaderStorage,
|
||||||
BuildDependenciesProviderInterface &buildDependenciesProvider)
|
BuildDependenciesProviderInterface &buildDependenciesProvider,
|
||||||
|
FilePathCachingInterface &filePathCache,
|
||||||
|
ClangPathWatcherInterface &clangPathwatcher,
|
||||||
|
GeneratedFilesInterface &generatedFiles)
|
||||||
: m_projectPartsStorage(projectPartsStorage)
|
: m_projectPartsStorage(projectPartsStorage)
|
||||||
, m_precompiledHeaderStorage(precompiledHeaderStorage)
|
, m_precompiledHeaderStorage(precompiledHeaderStorage)
|
||||||
, m_buildDependenciesProvider(buildDependenciesProvider)
|
, m_buildDependenciesProvider(buildDependenciesProvider)
|
||||||
|
, m_filePathCache(filePathCache)
|
||||||
|
, m_clangPathwatcher(clangPathwatcher)
|
||||||
|
, m_generatedFiles(generatedFiles)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
UpToDataProjectParts update(ProjectPartContainers &&projectsParts) override;
|
UpToDataProjectParts update(ProjectPartContainers &&projectsParts) override;
|
||||||
@@ -71,6 +80,9 @@ private:
|
|||||||
ProjectPartsStorageInterface &m_projectPartsStorage;
|
ProjectPartsStorageInterface &m_projectPartsStorage;
|
||||||
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
|
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
|
||||||
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
|
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
|
||||||
|
FilePathCachingInterface &m_filePathCache;
|
||||||
|
ClangPathWatcherInterface &m_clangPathwatcher;
|
||||||
|
GeneratedFilesInterface &m_generatedFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Pch
|
} // namespace Pch
|
||||||
|
@@ -228,30 +228,22 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess)
|
|||||||
{
|
{
|
||||||
creator.generatePch(std::move(pchTask1));
|
creator.generatePch(std::move(pchTask1));
|
||||||
|
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
EXPECT_CALL(
|
||||||
updateIdPaths(ElementsAre(
|
mockClangPathWatcher,
|
||||||
|
updateIdPaths(UnorderedElementsAre(
|
||||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre(id(main2Path)))),
|
||||||
UnorderedElementsAre(id(main2Path)))))));
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
||||||
|
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
|
||||||
updateIdPaths(ElementsAre(AllOf(
|
|
||||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
|
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))),
|
||||||
EXPECT_CALL(
|
|
||||||
mockClangPathWatcher,
|
|
||||||
updateIdPaths(ElementsAre(
|
|
||||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))),
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
|
||||||
updateIdPaths(ElementsAre(AllOf(
|
|
||||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
|
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||||
@@ -266,30 +258,22 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterFail)
|
|||||||
pchTask1.projectIncludeSearchPaths = {};
|
pchTask1.projectIncludeSearchPaths = {};
|
||||||
creator.generatePch(std::move(pchTask1));
|
creator.generatePch(std::move(pchTask1));
|
||||||
|
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
EXPECT_CALL(
|
||||||
updateIdPaths(ElementsAre(
|
mockClangPathWatcher,
|
||||||
|
updateIdPaths(UnorderedElementsAre(
|
||||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre(id(main2Path)))),
|
||||||
UnorderedElementsAre(id(main2Path)))))));
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
||||||
|
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
|
||||||
updateIdPaths(ElementsAre(AllOf(
|
|
||||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
|
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))),
|
||||||
EXPECT_CALL(
|
|
||||||
mockClangPathWatcher,
|
|
||||||
updateIdPaths(ElementsAre(
|
|
||||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))),
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
|
||||||
updateIdPaths(ElementsAre(AllOf(
|
|
||||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
|
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||||
@@ -421,29 +405,22 @@ TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls)
|
|||||||
precompiledHeadersUpdated(
|
precompiledHeadersUpdated(
|
||||||
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
|
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
|
||||||
ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
|
ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
EXPECT_CALL(
|
||||||
updateIdPaths(ElementsAre(
|
mockClangPathWatcher,
|
||||||
|
updateIdPaths(UnorderedElementsAre(
|
||||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre(id(main2Path)))),
|
||||||
UnorderedElementsAre(id(main2Path)))))));
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
|
||||||
updateIdPaths(ElementsAre(AllOf(
|
|
||||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
|
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))),
|
||||||
EXPECT_CALL(
|
|
||||||
mockClangPathWatcher,
|
|
||||||
updateIdPaths(ElementsAre(
|
|
||||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))),
|
||||||
EXPECT_CALL(mockClangPathWatcher,
|
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
|
||||||
updateIdPaths(ElementsAre(AllOf(
|
|
||||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
|
|
||||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "googletest.h"
|
#include "googletest.h"
|
||||||
#include "mockbuilddependenciesprovider.h"
|
#include "mockbuilddependenciesprovider.h"
|
||||||
|
#include "mockclangpathwatcher.h"
|
||||||
#include "mockfilepathcaching.h"
|
#include "mockfilepathcaching.h"
|
||||||
#include "mockgeneratedfiles.h"
|
#include "mockgeneratedfiles.h"
|
||||||
#include "mockprecompiledheaderstorage.h"
|
#include "mockprecompiledheaderstorage.h"
|
||||||
@@ -37,25 +38,48 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using ClangBackEnd::FilePathId;
|
using ClangBackEnd::FilePathId;
|
||||||
|
using ClangBackEnd::FilePathIds;
|
||||||
using ClangBackEnd::ProjectPartContainer;
|
using ClangBackEnd::ProjectPartContainer;
|
||||||
using ClangBackEnd::ProjectPartContainers;
|
using ClangBackEnd::ProjectPartContainers;
|
||||||
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
|
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
|
||||||
using ClangBackEnd::SourceEntries;
|
using ClangBackEnd::SourceEntries;
|
||||||
|
using ClangBackEnd::SourceEntry;
|
||||||
using ClangBackEnd::SourceType;
|
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
|
class ProjectPartsManager : public testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
ProjectPartsManager()
|
ProjectPartsManager()
|
||||||
{
|
{
|
||||||
projectPartContainerWithoutPrecompiledHeader1.preCompiledHeaderWasGenerated = false;
|
projectPartContainerWithoutPrecompiledHeader1.preCompiledHeaderWasGenerated = false;
|
||||||
|
ON_CALL(mockGeneratedFiles, fileContainers()).WillByDefault(ReturnRef(generatedFiles));
|
||||||
}
|
}
|
||||||
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
|
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
|
||||||
NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
|
NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
|
||||||
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
|
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
|
||||||
|
NiceMock<MockFilePathCaching> mockFilePathCaching;
|
||||||
|
NiceMock<MockGeneratedFiles> mockGeneratedFiles;
|
||||||
|
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
|
||||||
ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage,
|
ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage,
|
||||||
mockPrecompiledHeaderStorage,
|
mockPrecompiledHeaderStorage,
|
||||||
mockBuildDependenciesProvider};
|
mockBuildDependenciesProvider,
|
||||||
|
mockFilePathCaching,
|
||||||
|
mockClangPathWatcher,
|
||||||
|
mockGeneratedFiles};
|
||||||
FilePathId firstHeader{1};
|
FilePathId firstHeader{1};
|
||||||
FilePathId secondHeader{2};
|
FilePathId secondHeader{2};
|
||||||
FilePathId firstSource{11};
|
FilePathId firstSource{11};
|
||||||
@@ -649,7 +673,7 @@ TEST_F(ProjectPartsManager, SourcesTimeChanged)
|
|||||||
TEST_F(ProjectPartsManager, SourcesTimeNotChanged)
|
TEST_F(ProjectPartsManager, SourcesTimeNotChanged)
|
||||||
{
|
{
|
||||||
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
|
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
|
||||||
SourceEntries newSources{{1, SourceType::SystemInclude, 100}};
|
SourceEntries newSources{{1, SourceType::SystemInclude, 99}};
|
||||||
manager.update({projectPartContainer1});
|
manager.update({projectPartContainer1});
|
||||||
ON_CALL(mockBuildDependenciesProvider,
|
ON_CALL(mockBuildDependenciesProvider,
|
||||||
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
|
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
|
||||||
@@ -832,4 +856,90 @@ TEST_F(ProjectPartsManager, ChangeFromUserIncludeToSource)
|
|||||||
ASSERT_THAT(upToDate.updateProject, IsEmpty());
|
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
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user