Clang: Differentiate between user and non user includes for updating

We don't want to recreate a PCH if the include or source is not
contained by a PCH.

Change-Id: If52fc1aed92054b4165cdc634656147fbe8baa47
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-06-20 18:34:02 +02:00
parent c4b80a2ec0
commit cc87615fcd
37 changed files with 909 additions and 1105 deletions

View File

@@ -1,4 +1,4 @@
; /**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
@@ -57,7 +57,7 @@ void set_greedy_intersection_call(
class WatcherEntry class WatcherEntry
{ {
public: public:
ProjectPartId id; ProjectChunkId id;
DirectoryPathId directoryPathId; DirectoryPathId directoryPathId;
FilePathId filePathId; FilePathId filePathId;
long long lastModified = -1; long long lastModified = -1;
@@ -140,25 +140,6 @@ public:
m_notifier = notifier; m_notifier = notifier;
} }
static std::vector<uint> idsFromIdPaths(const std::vector<IdPaths> &idPaths)
{
std::vector<uint> ids;
ids.reserve(idPaths.size());
auto extractId = [] (const IdPaths &idPath) {
return idPath.id;
};
std::transform(idPaths.begin(),
idPaths.end(),
std::back_inserter(ids),
extractId);
std::sort(ids.begin(), ids.end());
return ids;
}
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths) std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
{ {
auto sumSize = [] (std::size_t size, const IdPaths &idPath) { auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
@@ -168,19 +149,19 @@ public:
return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize); return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize);
} }
std::pair<WatcherEntries, ProjectPartIds> convertIdPathsToWatcherEntriesAndIds( std::pair<WatcherEntries, ProjectChunkIds> convertIdPathsToWatcherEntriesAndIds(
const std::vector<IdPaths> &idPaths) const std::vector<IdPaths> &idPaths)
{ {
WatcherEntries entries; WatcherEntries entries;
entries.reserve(sizeOfIdPaths(idPaths)); entries.reserve(sizeOfIdPaths(idPaths));
ProjectPartIds ids; ProjectChunkIds ids;
ids.reserve(ids.size()); ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries); auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths) for (const IdPaths &idPath : idPaths)
{ {
ProjectPartId id = idPath.id; ProjectChunkId id = idPath.id;
ids.push_back(id); ids.push_back(id);
@@ -214,7 +195,7 @@ public:
m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths)); m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths));
} }
void removeUnusedEntries(const WatcherEntries &entries, const ProjectPartIds &ids) void removeUnusedEntries(const WatcherEntries &entries, const ProjectChunkIds &ids)
{ {
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
@@ -294,7 +275,7 @@ public:
} }
WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries, WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries,
const ProjectPartIds &ids) const const ProjectChunkIds &ids) const
{ {
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>()); auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
@@ -420,25 +401,22 @@ public:
return filePathIds; return filePathIds;
} }
ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries) std::vector<IdPaths> idPathsForWatcherEntries(WatcherEntries &&foundEntries)
{ {
ProjectPartIds ids; std::sort(foundEntries.begin(), foundEntries.end(), [](WatcherEntry first, WatcherEntry second) {
ids.reserve(foundEntries.size()); return std::tie(first.id, first.filePathId) < std::tie(second.id, second.filePathId);
});
std::transform(foundEntries.begin(), std::vector<IdPaths> idPaths;
foundEntries.end(), idPaths.reserve(foundEntries.size());
std::back_inserter(ids),
[&](WatcherEntry entry) { return entry.id; });
return ids; for (WatcherEntry entry : foundEntries) {
} if (idPaths.empty() || idPaths.back().id != entry.id)
idPaths.push_back({entry.id, {}});
idPaths.back().filePathIds.push_back(entry.filePathId);
}
ProjectPartIds uniqueIds(ProjectPartIds &&ids) return idPaths;
{
std::sort(ids.begin(), ids.end());
ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
return std::move(ids);
} }
void addChangedPathForFilePath(DirectoryPathIds &&directoryPathIds) void addChangedPathForFilePath(DirectoryPathIds &&directoryPathIds)
@@ -446,10 +424,12 @@ public:
if (m_notifier) { if (m_notifier) {
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(directoryPathIds)); WatcherEntries foundEntries = watchedEntriesForPaths(std::move(directoryPathIds));
ProjectPartIds changedIds = idsForWatcherEntries(foundEntries); FilePathIds watchedFilePathIds = watchedPaths(foundEntries);
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds))); std::vector<IdPaths> changedIdPaths = idPathsForWatcherEntries(std::move(foundEntries));
m_notifier->pathsChanged(watchedPaths(foundEntries));
m_notifier->pathsChanged(watchedFilePathIds);
m_notifier->pathsWithIdsChanged(changedIdPaths);
} }
} }

View File

@@ -26,9 +26,8 @@
#pragma once #pragma once
#include "clangsupport_global.h" #include "clangsupport_global.h"
#include "filepathid.h"
#include <filepathid.h> #include "idpaths.h"
#include <projectpartid.h>
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
@@ -41,7 +40,7 @@ public:
ClangPathWatcherNotifier(const ClangPathWatcherNotifier &) = delete; ClangPathWatcherNotifier(const ClangPathWatcherNotifier &) = delete;
ClangPathWatcherNotifier &operator=(const ClangPathWatcherNotifier &) = delete; ClangPathWatcherNotifier &operator=(const ClangPathWatcherNotifier &) = delete;
virtual void pathsWithIdsChanged(const ProjectPartIds &ids) = 0; virtual void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) = 0;
virtual void pathsChanged(const FilePathIds &filePathIds) = 0; virtual void pathsChanged(const FilePathIds &filePathIds) = 0;
protected: protected:

View File

@@ -120,6 +120,7 @@ HEADERS += \
$$PWD/projectpartid.h \ $$PWD/projectpartid.h \
$$PWD/projectpartsstorage.h \ $$PWD/projectpartsstorage.h \
$$PWD/projectpartsstorageinterface.h \ $$PWD/projectpartsstorageinterface.h \
$$PWD/projectsourcechunk.h \
$$PWD/requestcompletionsmessage.h \ $$PWD/requestcompletionsmessage.h \
$$PWD/echomessage.h \ $$PWD/echomessage.h \
$$PWD/endmessage.h \ $$PWD/endmessage.h \

View File

@@ -25,21 +25,60 @@
#pragma once #pragma once
#include "projectpartid.h"
#include "filepathid.h" #include "filepathid.h"
#include "projectpartid.h"
#include "sourceentry.h"
namespace ClangBackEnd { namespace ClangBackEnd {
class ProjectChunkId
{
public:
ProjectPartId id;
SourceType sourceType;
friend bool operator==(ProjectChunkId first, ProjectChunkId second)
{
return first.id == second.id && first.sourceType == second.sourceType;
}
friend bool operator==(ProjectChunkId first, ProjectPartId second)
{
return first.id == second;
}
friend bool operator==(ProjectPartId first, ProjectChunkId second)
{
return first == second.id;
}
friend bool operator!=(ProjectChunkId first, ProjectChunkId second)
{
return !(first == second);
}
friend bool operator<(ProjectChunkId first, ProjectChunkId second)
{
return std::tie(first.id, first.sourceType) < std::tie(second.id, second.sourceType);
}
friend bool operator<(ProjectChunkId first, ProjectPartId second) { return first.id < second; }
friend bool operator<(ProjectPartId first, ProjectChunkId second) { return first < second.id; }
};
class IdPaths class IdPaths
{ {
public: public:
ProjectPartId id; ProjectChunkId id;
FilePathIds filePathIds; FilePathIds filePathIds;
friend bool operator==(const IdPaths &first, const 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;
} }
}; };
using ProjectChunkIds = std::vector<ProjectChunkId>;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include "clangsupport_global.h" #include "clangsupport_global.h"
#include "filepathid.h"
#include "projectpartid.h" #include "projectpartid.h"
#include <utils/smallstringio.h> #include <utils/smallstringio.h>
@@ -37,6 +38,7 @@ class PrecompiledHeadersUpdatedMessage
public: public:
PrecompiledHeadersUpdatedMessage() = default; PrecompiledHeadersUpdatedMessage() = default;
PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId) PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId)
{ {
projectPartIds.push_back(projectPartId); projectPartIds.push_back(projectPartId);
} }

View File

@@ -225,7 +225,8 @@ struct Data // because we have a cycle dependency
PchManagerServer clangPchManagerServer{includeWatcher, PchManagerServer clangPchManagerServer{includeWatcher,
pchTaskGenerator, pchTaskGenerator,
projectParts, projectParts,
generatedFiles}; generatedFiles,
buildDependencyStorage};
TaskScheduler systemTaskScheduler{pchCreatorManager, TaskScheduler systemTaskScheduler{pchCreatorManager,
pchTaskQueue, pchTaskQueue,
pchCreationProgressCounter, pchCreationProgressCounter,

View File

@@ -71,6 +71,11 @@ public:
return fetchPchSourcesStatement.template values<FilePathId>(1024, projectPartId.projectPathId); return fetchPchSourcesStatement.template values<FilePathId>(1024, projectPartId.projectPathId);
} }
FilePathIds fetchSources(ProjectPartId projectPartId) const override
{
return fetchSourcesStatement.template values<FilePathId>(1024, projectPartId.projectPathId);
}
void insertOrUpdateFileStatuses(const FileStatuses &fileStatuses) override void insertOrUpdateFileStatuses(const FileStatuses &fileStatuses) override
{ {
WriteStatement &statement = insertOrUpdateFileStatusesStatement; WriteStatement &statement = insertOrUpdateFileStatusesStatement;
@@ -144,6 +149,94 @@ public:
transaction.commit(); transaction.commit();
} }
void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds,
TimeStamp indexingTimeStamp) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (FilePathId filePathId : filePathIds) {
inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId,
indexingTimeStamp.value);
}
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp);
}
}
void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override
{
for (FileStatus fileStatus : fileStatuses) {
inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId,
fileStatus.lastModified);
}
}
SourceTimeStamps fetchIndexingTimeStamps() const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIndexingTimeStampsStatement.template values<SourceTimeStamp, 2>(
1024);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIndexingTimeStamps();
}
}
SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIncludedIndexingTimeStampsStatement
.template values<SourceTimeStamp, 2>(1024, sourcePathId.filePathId);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIncludedIndexingTimeStamps(sourcePathId);
}
}
FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override
{
try {
FilePathIds dependentSourceIds;
Sqlite::DeferredTransaction transaction{database};
for (FilePathId sourcePathId : sourcePathIds) {
FilePathIds newDependentSourceIds;
newDependentSourceIds.reserve(dependentSourceIds.size() + 1024);
auto newIds = fetchDependentSourceIdsStatement
.template values<FilePathId>(1024, sourcePathId.filePathId);
std::set_union(dependentSourceIds.begin(),
dependentSourceIds.end(),
newIds.begin(),
newIds.end(),
std::back_inserter(newDependentSourceIds));
dependentSourceIds = std::move(newDependentSourceIds);
}
transaction.commit();
return dependentSourceIds;
} catch (const Sqlite::StatementIsBusy &) {
return fetchDependentSourceIds(sourcePathIds);
}
}
static Utils::SmallString toJson(const Utils::SmallStringVector &strings) static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
{ {
QJsonDocument document; QJsonDocument document;
@@ -255,6 +348,8 @@ public:
"SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? AND sourceType IN (0, 1, " "SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? AND sourceType IN (0, 1, "
"3, 4) ORDER BY sourceId", "3, 4) ORDER BY sourceId",
database}; database};
mutable ReadStatement fetchSourcesStatement{
"SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? ORDER BY sourceId", database};
mutable ReadStatement fetchSourceDependenciesStatement{ mutable ReadStatement fetchSourceDependenciesStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION " "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION "
"SELECT dependencySourceId FROM sourceDependencies, " "SELECT dependencySourceId FROM sourceDependencies, "
@@ -279,5 +374,24 @@ public:
database}; database};
WriteStatement deleteAllProjectPartsFilesWithProjectPartNameStatement{ WriteStatement deleteAllProjectPartsFilesWithProjectPartNameStatement{
"DELETE FROM projectPartsFiles WHERE projectPartId = ?", database}; "DELETE FROM projectPartsFiles WHERE projectPartId = ?", database};
WriteStatement inserOrUpdateIndexingTimesStampStatement{
"INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON "
"CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002",
database};
mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, "
"indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId",
database};
mutable ReadStatement fetchIndexingTimeStampsStatement{
"SELECT sourceId, indexingTimeStamp FROM fileStatuses", database};
mutable ReadStatement fetchDependentSourceIdsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId "
"FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM "
"sourceDependencies) ORDER BY sourceId",
database};
}; };
} }

View File

@@ -57,6 +57,12 @@ public:
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0; virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0;
virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 0; virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 0;
virtual FilePathIds fetchPchSources(ProjectPartId projectPartId) const = 0; virtual FilePathIds fetchPchSources(ProjectPartId projectPartId) const = 0;
virtual FilePathIds fetchSources(ProjectPartId projectPartId) const = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected: protected:
~BuildDependenciesStorageInterface() = default; ~BuildDependenciesStorageInterface() = default;

View File

@@ -45,6 +45,8 @@
#include <QProcess> #include <QProcess>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <iostream>
namespace ClangBackEnd { namespace ClangBackEnd {
namespace { namespace {
@@ -110,11 +112,28 @@ Utils::SmallStringVector PchCreator::generateClangCompilerArguments(const PchTas
return builder.commandLine; return builder.commandLine;
} }
FilePathIds PchCreator::existingSources(FilePathIds sources) const
{
FilePathIds existingSources;
existingSources.reserve(sources.size());
std::set_difference(sources.begin(),
sources.end(),
m_generatedFilePathIds.begin(),
m_generatedFilePathIds.end(),
std::back_inserter(existingSources));
return existingSources;
}
void PchCreator::generatePch(PchTask &&pchTask) void PchCreator::generatePch(PchTask &&pchTask)
{ {
m_projectPartPch.projectPartId = pchTask.projectPartId(); m_projectPartPch.projectPartId = pchTask.projectPartId();
m_projectPartPch.lastModified = QDateTime::currentSecsSinceEpoch(); m_projectPartPch.lastModified = QDateTime::currentSecsSinceEpoch();
m_sources = std::move(pchTask.sources); m_watchedSystemIncludes = std::move(pchTask.watchedSystemIncludes);
m_watchedProjectIncludes = std::move(pchTask.watchedProjectIncludes);
m_watchedUserIncludes = std::move(pchTask.watchedUserIncludes);
m_watchedSources = std::move(pchTask.watchedUserSources);
if (pchTask.includes.empty()) if (pchTask.includes.empty())
return; return;
@@ -166,23 +185,26 @@ void PchCreator::clear()
{ {
m_clangTool = ClangTool{}; m_clangTool = ClangTool{};
m_projectPartPch = {}; m_projectPartPch = {};
m_sources.clear(); m_watchedSystemIncludes.clear();
m_watchedProjectIncludes.clear();
m_watchedUserIncludes.clear();
m_watchedSources.clear();
} }
void PchCreator::doInMainThreadAfterFinished() void PchCreator::doInMainThreadAfterFinished()
{ {
if (m_projectPartPch.projectPartId.isValid()) { if (m_projectPartPch.projectPartId.isValid()) {
FilePathIds existingSources;
existingSources.reserve(m_sources.size());
std::set_difference(m_sources.begin(),
m_sources.end(),
m_generatedFilePathIds.begin(),
m_generatedFilePathIds.end(),
std::back_inserter(existingSources));
m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified, m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
m_projectPartPch.projectPartId); m_projectPartPch.projectPartId);
m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingSources}}); m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::Source},
m_pchManagerClient.precompiledHeadersUpdated({m_projectPartPch.projectPartId}); 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},
existingSources(m_watchedSystemIncludes)}});
m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId);
} }
} }

View File

@@ -80,19 +80,24 @@ public:
static Utils::SmallStringVector generateClangCompilerArguments(const PchTask &pchTask, static Utils::SmallStringVector generateClangCompilerArguments(const PchTask &pchTask,
FilePathView pchPath); FilePathView pchPath);
const ClangTool &clangTool() const const ClangTool &clangTool() const { return m_clangTool; }
{
return m_clangTool;
}
const FilePathIds &sources() const { return m_sources; } FilePathIds existingSources(FilePathIds sources) const;
const FilePathIds &watchedSystemIncludes() const { return m_watchedSystemIncludes; }
const FilePathIds &watchedProjectIncludes() const { return m_watchedProjectIncludes; }
const FilePathIds &watchedUserIncludes() const { return m_watchedUserIncludes; }
const FilePathIds &watchedSources() const { return m_watchedSources; }
private: private:
mutable std::mt19937_64 randomNumberGenator{std::random_device{}()}; mutable std::mt19937_64 randomNumberGenator{std::random_device{}()};
ClangTool m_clangTool; ClangTool m_clangTool;
ProjectPartPch m_projectPartPch; ProjectPartPch m_projectPartPch;
FilePathCaching m_filePathCache; FilePathCaching m_filePathCache;
FilePathIds m_sources; FilePathIds m_watchedSystemIncludes;
FilePathIds m_watchedProjectIncludes;
FilePathIds m_watchedUserIncludes;
FilePathIds m_watchedSources;
FilePathIds m_generatedFilePathIds; FilePathIds m_generatedFilePathIds;
Environment &m_environment; Environment &m_environment;
PchManagerClientInterface &m_pchManagerClient; PchManagerClientInterface &m_pchManagerClient;

View File

@@ -25,10 +25,11 @@
#include "pchmanagerserver.h" #include "pchmanagerserver.h"
#include <builddependenciesstorage.h>
#include <pchmanagerclientinterface.h> #include <pchmanagerclientinterface.h>
#include <pchtaskgeneratorinterface.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <progressmessage.h> #include <progressmessage.h>
#include <pchtaskgeneratorinterface.h>
#include <removegeneratedfilesmessage.h> #include <removegeneratedfilesmessage.h>
#include <removeprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updategeneratedfilesmessage.h> #include <updategeneratedfilesmessage.h>
@@ -39,16 +40,20 @@
#include <QApplication> #include <QApplication>
#include <algorithm>
namespace ClangBackEnd { namespace ClangBackEnd {
PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
PchTaskGeneratorInterface &pchTaskGenerator, PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts, ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles) GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage)
: m_fileSystemWatcher(fileSystemWatcher) : m_fileSystemWatcher(fileSystemWatcher)
, m_pchTaskGenerator(pchTaskGenerator) , m_pchTaskGenerator(pchTaskGenerator)
, m_projectPartsManager(projectParts) , m_projectPartsManager(projectParts)
, m_generatedFiles(generatedFiles) , m_generatedFiles(generatedFiles)
, m_buildDependenciesStorage(buildDependenciesStorage)
{ {
m_fileSystemWatcher.setNotifier(this); m_fileSystemWatcher.setNotifier(this);
} }
@@ -130,18 +135,74 @@ void PchManagerServer::removeGeneratedFiles(RemoveGeneratedFilesMessage &&messag
m_generatedFiles.remove(message.takeGeneratedFiles()); m_generatedFiles.remove(message.takeGeneratedFiles());
} }
void PchManagerServer::pathsWithIdsChanged(const ProjectPartIds &ids) namespace {
struct FilterResults
{ {
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(ids); ProjectPartIds systemIds;
ProjectPartIds projectIds;
ProjectPartIds userIds;
};
std::pair<ProjectPartIds, ProjectPartIds> pchProjectPartIds(const std::vector<IdPaths> &idPaths)
{
ProjectPartIds changedProjectPartIds;
changedProjectPartIds.reserve(idPaths.size());
ProjectPartIds changedPchProjectPartIds;
changedPchProjectPartIds.reserve(idPaths.size());
for (const IdPaths &idPath : idPaths) {
switch (idPath.id.sourceType) {
case SourceType::TopSystemInclude:
case SourceType::SystemInclude:
case SourceType::TopProjectInclude:
case SourceType::ProjectInclude:
changedPchProjectPartIds.push_back(idPath.id.id);
break;
case SourceType::UserInclude:
case SourceType::Source:
changedProjectPartIds.push_back(idPath.id.id);
break;
}
}
changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end()),
changedPchProjectPartIds.end());
changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end()),
changedPchProjectPartIds.end());
ProjectPartIds changedUserProjectPartIds;
changedProjectPartIds.reserve(changedProjectPartIds.size());
std::set_difference(changedProjectPartIds.begin(),
changedProjectPartIds.end(),
changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end(),
std::back_inserter(changedUserProjectPartIds));
return {changedPchProjectPartIds, changedUserProjectPartIds};
}
} // namespace
void PchManagerServer::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths)
{
auto changedProjectPartIds = pchProjectPartIds(idPaths);
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(changedProjectPartIds.first);
for (ArgumentsEntry &entry : entries) { for (ArgumentsEntry &entry : entries) {
m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids), m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids),
std::move(entry.arguments)); std::move(entry.arguments));
} }
client()->precompiledHeadersUpdated(std::move(changedProjectPartIds.second));
} }
void PchManagerServer::pathsChanged(const FilePathIds &/*filePathIds*/) void PchManagerServer::pathsChanged(const FilePathIds &filePathIds)
{ {
m_buildDependenciesStorage.insertOrUpdateIndexingTimeStamps(filePathIds, 0);
} }
void PchManagerServer::setPchCreationProgress(int progress, int total) void PchManagerServer::setPchCreationProgress(int progress, int total)

View File

@@ -39,6 +39,7 @@ namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage; class SourceRangesAndDiagnosticsForQueryMessage;
class PchTaskGeneratorInterface; class PchTaskGeneratorInterface;
class BuildDependenciesStorageInterface;
class PchManagerServer : public PchManagerServerInterface, class PchManagerServer : public PchManagerServerInterface,
public ClangPathWatcherNotifier, public ClangPathWatcherNotifier,
@@ -49,7 +50,8 @@ public:
PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
PchTaskGeneratorInterface &pchTaskGenerator, PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts, ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles); GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage);
void end() override; void end() override;
void updateProjectParts(UpdateProjectPartsMessage &&message) override; void updateProjectParts(UpdateProjectPartsMessage &&message) override;
@@ -57,7 +59,7 @@ public:
void updateGeneratedFiles(UpdateGeneratedFilesMessage &&message) override; void updateGeneratedFiles(UpdateGeneratedFilesMessage &&message) override;
void removeGeneratedFiles(RemoveGeneratedFilesMessage &&message) override; void removeGeneratedFiles(RemoveGeneratedFilesMessage &&message) override;
void pathsWithIdsChanged(const ProjectPartIds &ids) override; void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const FilePathIds &filePathIds) override; void pathsChanged(const FilePathIds &filePathIds) override;
void setPchCreationProgress(int progress, int total); void setPchCreationProgress(int progress, int total);
@@ -68,6 +70,7 @@ private:
PchTaskGeneratorInterface &m_pchTaskGenerator; PchTaskGeneratorInterface &m_pchTaskGenerator;
ProjectPartsManagerInterface &m_projectPartsManager; ProjectPartsManagerInterface &m_projectPartsManager;
GeneratedFilesInterface &m_generatedFiles; GeneratedFilesInterface &m_generatedFiles;
BuildDependenciesStorageInterface &m_buildDependenciesStorage;
ToolChainsArgumentsCache m_toolChainsArgumentsCache; ToolChainsArgumentsCache m_toolChainsArgumentsCache;
}; };

View File

@@ -42,7 +42,10 @@ class PchTask
public: public:
PchTask(ProjectPartId projectPartId, PchTask(ProjectPartId projectPartId,
FilePathIds &&includes, FilePathIds &&includes,
FilePathIds &&sources, FilePathIds &&watchedSystemIncludes,
FilePathIds &&watchedProjectIncludes,
FilePathIds &&watchedUserIncludes,
FilePathIds &&watchedUserSources,
CompilerMacros &&compilerMacros, CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&usedMacros, // TODO remove Utils::SmallStringVector &&usedMacros, // TODO remove
Utils::SmallStringVector toolChainArguments, Utils::SmallStringVector toolChainArguments,
@@ -53,7 +56,10 @@ public:
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None) Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None)
: projectPartIds({projectPartId}) : projectPartIds({projectPartId})
, includes(includes) , includes(includes)
, sources(sources) , watchedSystemIncludes(watchedSystemIncludes)
, watchedProjectIncludes(watchedProjectIncludes)
, watchedUserIncludes(watchedUserIncludes)
, watchedUserSources(watchedUserSources)
, compilerMacros(compilerMacros) , compilerMacros(compilerMacros)
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths)) , systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths)) , projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
@@ -65,7 +71,10 @@ public:
PchTask(ProjectPartIds &&projectPartIds, PchTask(ProjectPartIds &&projectPartIds,
FilePathIds &&includes, FilePathIds &&includes,
FilePathIds &&sources, FilePathIds &&watchedSystemIncludes,
FilePathIds &&watchedProjectIncludes,
FilePathIds &&watchedUserIncludes,
FilePathIds &&watchedUserSources,
CompilerMacros &&compilerMacros, CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&usedMacros, // TODO remove Utils::SmallStringVector &&usedMacros, // TODO remove
Utils::SmallStringVector toolChainArguments, Utils::SmallStringVector toolChainArguments,
@@ -76,7 +85,10 @@ public:
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None) Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None)
: projectPartIds(std::move(projectPartIds)) : projectPartIds(std::move(projectPartIds))
, includes(includes) , includes(includes)
, sources(sources) , watchedSystemIncludes(watchedSystemIncludes)
, watchedProjectIncludes(watchedProjectIncludes)
, watchedUserIncludes(watchedUserIncludes)
, watchedUserSources(watchedUserSources)
, compilerMacros(compilerMacros) , compilerMacros(compilerMacros)
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths)) , systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths)) , projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
@@ -90,6 +102,10 @@ public:
{ {
return first.systemPchPath == second.systemPchPath return first.systemPchPath == second.systemPchPath
&& first.projectPartIds == second.projectPartIds && first.includes == second.includes && first.projectPartIds == second.projectPartIds && first.includes == second.includes
&& first.watchedSystemIncludes == second.watchedSystemIncludes
&& first.watchedProjectIncludes == second.watchedProjectIncludes
&& first.watchedUserIncludes == second.watchedUserIncludes
&& first.watchedUserSources == second.watchedUserSources
&& first.compilerMacros == second.compilerMacros && first.compilerMacros == second.compilerMacros
&& first.systemIncludeSearchPaths == second.systemIncludeSearchPaths && first.systemIncludeSearchPaths == second.systemIncludeSearchPaths
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths && first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
@@ -105,7 +121,10 @@ public:
FilePath systemPchPath; FilePath systemPchPath;
ProjectPartIds projectPartIds; ProjectPartIds projectPartIds;
FilePathIds includes; FilePathIds includes;
FilePathIds sources; FilePathIds watchedSystemIncludes;
FilePathIds watchedProjectIncludes;
FilePathIds watchedUserIncludes;
FilePathIds watchedUserSources;
CompilerMacros compilerMacros; CompilerMacros compilerMacros;
IncludeSearchPaths systemIncludeSearchPaths; IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths; IncludeSearchPaths projectIncludeSearchPaths;

View File

@@ -52,6 +52,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId, pchTaskSets.emplace_back(PchTask{projectPart.projectPartId,
std::move(filter.topSystemIncludes), std::move(filter.topSystemIncludes),
{}, {},
{},
{},
{},
std::move(filter.systemCompilerMacros), std::move(filter.systemCompilerMacros),
std::move(filter.systemUsedMacros), std::move(filter.systemUsedMacros),
projectPart.toolChainArguments, projectPart.toolChainArguments,
@@ -62,6 +65,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
projectPart.languageExtension}, projectPart.languageExtension},
PchTask{projectPart.projectPartId, PchTask{projectPart.projectPartId,
std::move(filter.topProjectIncludes), std::move(filter.topProjectIncludes),
std::move(filter.systemIncludes),
std::move(filter.projectIncludes),
std::move(filter.userIncludes),
std::move(filter.sources), std::move(filter.sources),
std::move(filter.projectCompilerMacros), std::move(filter.projectCompilerMacros),
std::move(filter.projectUsedMacros), std::move(filter.projectUsedMacros),

View File

@@ -98,8 +98,8 @@ bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds), firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
std::move(secondTask.projectPartIds)); std::move(secondTask.projectPartIds));
firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes)); firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes));
firstTask.sources = merge(std::move(firstTask.sources), firstTask.watchedSystemIncludes = merge(std::move(firstTask.watchedSystemIncludes),
std::move(secondTask.sources)); std::move(secondTask.watchedSystemIncludes));
firstTask.compilerMacros = std::move(macros); firstTask.compilerMacros = std::move(macros);
firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths( firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths(
std::move(firstTask.systemIncludeSearchPaths), std::move(firstTask.systemIncludeSearchPaths),

View File

@@ -99,6 +99,7 @@ public:
projectIncludes.reserve(sources.size()); projectIncludes.reserve(sources.size());
topSystemIncludes.reserve(sources.size() / 10); topSystemIncludes.reserve(sources.size() / 10);
topProjectIncludes.reserve(sources.size() / 10); topProjectIncludes.reserve(sources.size() / 10);
userIncludes.reserve(sources.size());
this->sources.reserve(sources.size()); this->sources.reserve(sources.size());
for (SourceEntry source : sources) for (SourceEntry source : sources)
@@ -128,23 +129,22 @@ private:
case SourceType::TopSystemInclude: case SourceType::TopSystemInclude:
topSystemIncludes.emplace_back(source.sourceId); topSystemIncludes.emplace_back(source.sourceId);
systemIncludes.emplace_back(source.sourceId); systemIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break; break;
case SourceType::SystemInclude: case SourceType::SystemInclude:
systemIncludes.emplace_back(source.sourceId); systemIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break; break;
case SourceType::TopProjectInclude: case SourceType::TopProjectInclude:
topProjectIncludes.emplace_back(source.sourceId); topProjectIncludes.emplace_back(source.sourceId);
projectIncludes.emplace_back(source.sourceId); projectIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break; break;
case SourceType::ProjectInclude: case SourceType::ProjectInclude:
projectIncludes.emplace_back(source.sourceId); projectIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break; break;
case SourceType::UserInclude: case SourceType::UserInclude:
userIncludes.emplace_back(source.sourceId);
break;
case SourceType::Source: case SourceType::Source:
sources.emplace_back(source.sourceId);
break; break;
} }
@@ -215,6 +215,7 @@ private:
public: public:
FilePathIds sources; FilePathIds sources;
FilePathIds userIncludes;
FilePathIds projectIncludes; FilePathIds projectIncludes;
FilePathIds systemIncludes; FilePathIds systemIncludes;
FilePathIds topProjectIncludes; FilePathIds topProjectIncludes;

View File

@@ -98,7 +98,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
std::vector<SymbolIndexerTask> symbolIndexerTask; std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(projectPart.sourcePathIds.size()); symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
for (FilePathId sourcePathId : projectPart.sourcePathIds) { for (FilePathId sourcePathId : projectPart.sourcePathIds) {
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps( SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
sourcePathId); sourcePathId);
if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) { if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
@@ -122,7 +122,8 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
auto store = [&] { auto store = [&] {
Sqlite::ImmediateTransaction transaction{m_transactionInterface}; Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(
symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations()); symbolsCollector.sourceLocations());
transaction.commit(); transaction.commit();
@@ -144,28 +145,17 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
} }
} }
m_pathWatcher.updateIdPaths( m_pathWatcher.updateIdPaths({{{projectPartId, SourceType::Source},
{{projectPartId, m_buildDependencyStorage.fetchPchSources(projectPartId)}}); m_buildDependencyStorage.fetchPchSources(projectPartId)}});
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries(); m_symbolIndexerTaskQueue.processEntries();
} }
void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {} void SymbolIndexer::pathsWithIdsChanged(const std::vector<IdPaths> &) {}
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds) void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
{ {
m_modifiedTimeChecker.pathsChanged(filePathIds); m_modifiedTimeChecker.pathsChanged(filePathIds);
FilePathIds dependentSourcePathIds = m_symbolStorage.fetchDependentSourceIds(filePathIds);
std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(dependentSourcePathIds.size());
for (FilePathId dependentSourcePathId : dependentSourcePathIds)
updateChangedPath(dependentSourcePathId, symbolIndexerTask);
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries();
} }
void SymbolIndexer::updateChangedPath(FilePathId filePathId, void SymbolIndexer::updateChangedPath(FilePathId filePathId,
@@ -182,7 +172,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
ProjectPartId projectPartId = optionalArtefact->projectPartId; ProjectPartId projectPartId = optionalArtefact->projectPartId;
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId); SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
filePathId);
auto indexing = [optionalArtefact = std::move(optionalArtefact), auto indexing = [optionalArtefact = std::move(optionalArtefact),
filePathId, filePathId,
@@ -207,7 +198,7 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
auto store = [&] { auto store = [&] {
Sqlite::ImmediateTransaction transaction{m_transactionInterface}; Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations()); symbolsCollector.sourceLocations());
transaction.commit(); transaction.commit();

View File

@@ -60,7 +60,7 @@ public:
void updateProjectParts(ProjectPartContainers &&projectParts); void updateProjectParts(ProjectPartContainers &&projectParts);
void updateProjectPart(ProjectPartContainer &&projectPart); void updateProjectPart(ProjectPartContainer &&projectPart);
void pathsWithIdsChanged(const ProjectPartIds &ids) override; void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const FilePathIds &filePathIds) override; void pathsChanged(const FilePathIds &filePathIds) override;
void updateChangedPath(FilePathId filePath, void updateChangedPath(FilePathId filePath,
std::vector<SymbolIndexerTask> &symbolIndexerTask); std::vector<SymbolIndexerTask> &symbolIndexerTask);
@@ -75,6 +75,9 @@ public:
FilePathIds updatableFilePathIds(const ProjectPartContainer &projectPart, FilePathIds updatableFilePathIds(const ProjectPartContainer &projectPart,
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const; const Utils::optional<ProjectPartArtefact> &optionalArtefact) const;
private:
FilePathIds filterProjectPartSources(const FilePathIds &filePathIds) const;
private: private:
SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue; SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue;
SymbolStorageInterface &m_symbolStorage; SymbolStorageInterface &m_symbolStorage;

View File

@@ -70,93 +70,6 @@ public:
deleteNewLocationsTable(); deleteNewLocationsTable();
} }
void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (FilePathId filePathId : filePathIds) {
inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId,
indexingTimeStamp.value);
}
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp);
}
}
void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override
{
for (FileStatus fileStatus : fileStatuses) {
inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId,
fileStatus.lastModified);
}
}
SourceTimeStamps fetchIndexingTimeStamps() const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIndexingTimeStampsStatement.template values<SourceTimeStamp, 2>(
1024);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIndexingTimeStamps();
}
}
SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIncludedIndexingTimeStampsStatement
.template values<SourceTimeStamp, 2>(1024, sourcePathId.filePathId);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIncludedIndexingTimeStamps(sourcePathId);
}
}
FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override
{
try {
FilePathIds dependentSourceIds;
Sqlite::DeferredTransaction transaction{database};
for (FilePathId sourcePathId : sourcePathIds) {
FilePathIds newDependentSourceIds;
newDependentSourceIds.reserve(dependentSourceIds.size() + 1024);
auto newIds = fetchDependentSourceIdsStatement
.template values<FilePathId>(1024, sourcePathId.filePathId);
std::set_union(dependentSourceIds.begin(),
dependentSourceIds.end(),
newIds.begin(),
newIds.end(),
std::back_inserter(newDependentSourceIds));
dependentSourceIds = std::move(newDependentSourceIds);
}
transaction.commit();
return dependentSourceIds;
} catch (const Sqlite::StatementIsBusy &) {
return fetchDependentSourceIds(sourcePathIds);
}
}
void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries) void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries)
{ {
WriteStatement &statement = insertSymbolsToNewSymbolsStatement; WriteStatement &statement = insertSymbolsToNewSymbolsStatement;
@@ -278,25 +191,6 @@ public:
database}; database};
WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database}; WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database};
WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database}; WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database};
WriteStatement inserOrUpdateIndexingTimesStampStatement{
"INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON "
"CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002",
database};
mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, "
"indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId",
database};
mutable ReadStatement fetchIndexingTimeStampsStatement{
"SELECT sourceId, indexingTimeStamp FROM fileStatuses", database};
mutable ReadStatement fetchDependentSourceIdsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId "
"FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM "
"sourceDependencies) ORDER BY sourceId",
database};
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -48,11 +48,6 @@ public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries, virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations) const SourceLocationEntries &sourceLocations)
= 0; = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected: protected:
~SymbolStorageInterface() = default; ~SymbolStorageInterface() = default;

View File

@@ -28,8 +28,11 @@
#include "mockfilepathcaching.h" #include "mockfilepathcaching.h"
#include "mocksqlitedatabase.h" #include "mocksqlitedatabase.h"
#include <sqlitedatabase.h>
#include <builddependenciesstorage.h> #include <builddependenciesstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
#include <utils/optional.h> #include <utils/optional.h>
@@ -70,7 +73,12 @@ protected:
MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement; MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement;
MockSqliteWriteStatement &deleteAllProjectPartsFilesWithProjectPartNameStatement MockSqliteWriteStatement &deleteAllProjectPartsFilesWithProjectPartNameStatement
= storage.deleteAllProjectPartsFilesWithProjectPartNameStatement; = storage.deleteAllProjectPartsFilesWithProjectPartNameStatement;
MockSqliteReadStatement &fetchProjectPartsFilesStatement = storage.fetchPchSourcesStatement; MockSqliteReadStatement &fetchPchSourcesStatement = storage.fetchPchSourcesStatement;
MockSqliteReadStatement &fetchSourcesStatement = storage.fetchSourcesStatement;
MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement;
MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement;
}; };
TEST_F(BuildDependenciesStorage, ConvertStringsToJson) TEST_F(BuildDependenciesStorage, ConvertStringsToJson)
@@ -233,13 +241,163 @@ TEST_F(BuildDependenciesStorage, FetchUsedMacros)
ASSERT_THAT(usedMacros, result); ASSERT_THAT(usedMacros, result);
} }
TEST_F(BuildDependenciesStorage, FetchSources) TEST_F(BuildDependenciesStorage, FetchPchSources)
{ {
ClangBackEnd::FilePathIds result{3, 5, 7}; ClangBackEnd::FilePathIds result{3, 5, 7};
EXPECT_CALL(fetchProjectPartsFilesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result)); EXPECT_CALL(fetchPchSourcesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result));
auto sources = storage.fetchPchSources(22); auto sources = storage.fetchPchSources(22);
ASSERT_THAT(sources, result); ASSERT_THAT(sources, result);
} }
TEST_F(BuildDependenciesStorage, FetchSources)
{
ClangBackEnd::FilePathIds result{3, 5, 7};
EXPECT_CALL(fetchSourcesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result));
auto sources = storage.fetchSources(22);
ASSERT_THAT(sources, result);
}
TEST_F(BuildDependenciesStorage, FetchIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIndexingTimeStamps();
}
TEST_F(BuildDependenciesStorage, InsertIndexingTimeStamp)
{
ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}};
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(37)));
storage.insertOrUpdateIndexingTimeStamps(fileStatuses);
}
TEST_F(BuildDependenciesStorage, InsertIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(34)));
EXPECT_CALL(mockDatabase, commit());
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
}
TEST_F(BuildDependenciesStorage, FetchIncludedIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIncludedIndexingTimeStamps(1);
}
TEST_F(BuildDependenciesStorage, FetchDependentSourceIdsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(7)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchDependentSourceIds({3, 2, 7});
}
class BuildDependenciesStorageSlow : public testing::Test
{
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::BuildDependenciesStorage<> storage{database};
};
TEST_F(BuildDependenciesStorageSlow, InsertIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34}));
}
TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
storage.insertOrUpdateIndexingTimeStamps({1}, 37);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34}));
}
TEST_F(BuildDependenciesStorageSlow, InsertIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}});
storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(BuildDependenciesStorageSlow, FetchIncludedIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34);
storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}});
auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1);
ASSERT_THAT(timeStamps,
ElementsAre(SourceTimeStamp{1, 34},
SourceTimeStamp{2, 34},
SourceTimeStamp{3, 34},
SourceTimeStamp{4, 34}));
}
TEST_F(BuildDependenciesStorageSlow, FetchDependentSourceIds)
{
storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}});
auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7});
ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7}));
}
} // namespace } // namespace

View File

@@ -48,8 +48,11 @@ using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathId; using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds; using ClangBackEnd::FilePathIds;
using ClangBackEnd::FilePathView; using ClangBackEnd::FilePathView;
using ClangBackEnd::IdPaths;
using ClangBackEnd::ProjectChunkId;
using ClangBackEnd::ProjectPartId; using ClangBackEnd::ProjectPartId;
using ClangBackEnd::ProjectPartIds; using ClangBackEnd::ProjectPartIds;
using ClangBackEnd::SourceType;
using ClangBackEnd::WatcherEntries; using ClangBackEnd::WatcherEntries;
using ClangBackEnd::WatcherEntry; using ClangBackEnd::WatcherEntry;
@@ -111,9 +114,9 @@ protected:
NiceMock<MockFileSystem> mockFileSystem; NiceMock<MockFileSystem> mockFileSystem;
Watcher watcher{mockFilePathCache, mockFileSystem, &notifier}; Watcher watcher{mockFilePathCache, mockFileSystem, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
ProjectPartId id1{2}; ProjectChunkId id1{2, SourceType::ProjectInclude};
ProjectPartId id2{3}; ProjectChunkId id2{2, SourceType::Source};
ProjectPartId id3{4}; ProjectChunkId id3{4, SourceType::SystemInclude};
FilePathView path1{"/path/path1"}; FilePathView path1{"/path/path1"};
FilePathView path2{"/path/path2"}; FilePathView path2{"/path/path2"};
FilePathView path3{"/path2/path1"}; FilePathView path3{"/path2/path1"};
@@ -128,14 +131,15 @@ protected:
Utils::PathString directoryPathString2 = directoryPath2; Utils::PathString directoryPathString2 = directoryPath2;
FilePathIds pathIds = {1, 2, 3, 4, 5}; FilePathIds pathIds = {1, 2, 3, 4, 5};
ClangBackEnd::DirectoryPathIds directoryPaths = {1, 2, 3}; ClangBackEnd::DirectoryPathIds directoryPaths = {1, 2, 3};
ClangBackEnd::ProjectPartIds ids{id1, id2, id3}; ClangBackEnd::ProjectChunkIds ids{id1, id2, id3};
WatcherEntry watcherEntry1{ids[0], directoryPaths[0], pathIds[0]}; WatcherEntry watcherEntry1{id1, directoryPaths[0], pathIds[0]};
WatcherEntry watcherEntry2{ids[1], directoryPaths[0], pathIds[0]}; WatcherEntry watcherEntry2{id2, directoryPaths[0], pathIds[0]};
WatcherEntry watcherEntry3{ids[0], directoryPaths[0], pathIds[1]}; WatcherEntry watcherEntry3{id1, directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry4{ids[1], directoryPaths[0], pathIds[1]}; WatcherEntry watcherEntry4{id2, directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry5{ids[2], directoryPaths[0], pathIds[1]}; WatcherEntry watcherEntry5{id3, directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry6{ids[0], directoryPaths[1], pathIds[2]}; WatcherEntry watcherEntry6{id1, directoryPaths[1], pathIds[2]};
WatcherEntry watcherEntry7{ids[1], directoryPaths[1], pathIds[3]}; WatcherEntry watcherEntry7{id2, directoryPaths[1], pathIds[3]};
WatcherEntry watcherEntry8{id3, directoryPaths[1], pathIds[3]};
}; };
TEST_F(ClangPathWatcher, AddIdPaths) TEST_F(ClangPathWatcher, AddIdPaths)
@@ -260,12 +264,13 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
TEST_F(ClangPathWatcher, RemoveEntriesWithId) TEST_F(ClangPathWatcher, RemoveEntriesWithId)
{ {
watcher.updateIdPaths( watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}},
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}}); {id2, {pathIds[0], pathIds[1]}},
{id3, {pathIds[1], pathIds[3]}}});
watcher.removeIds({id1}); watcher.removeIds({2});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry2, watcherEntry4, watcherEntry5)); ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry5, watcherEntry8));
} }
TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds) TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds)
@@ -284,28 +289,28 @@ TEST_F(ClangPathWatcher, RemoveNoPathsForOneId)
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)) EXPECT_CALL(mockQFileSytemWatcher, removePaths(_))
.Times(0); .Times(0);
watcher.removeIds({id3}); watcher.removeIds({id3.id});
} }
TEST_F(ClangPathWatcher, RemovePathForOneId) TEST_F(ClangPathWatcher, RemovePathForOneId)
{ {
watcher.updateIdPaths( watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); {{id1, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0], pathIds[1], pathIds[3]}}});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath2))); EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath2)));
watcher.removeIds({id2}); watcher.removeIds({id3.id});
} }
TEST_F(ClangPathWatcher, RemoveNoPathSecondTime) TEST_F(ClangPathWatcher, RemoveNoPathSecondTime)
{ {
watcher.updateIdPaths( watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
watcher.removeIds({id2}); watcher.removeIds({id2.id});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)).Times(0); EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)).Times(0);
watcher.removeIds({id2}); watcher.removeIds({id2.id});
} }
TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId) TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
@@ -315,7 +320,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath, directoryPath2))); EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath, directoryPath2)));
watcher.removeIds({id1, id2, id3}); watcher.removeIds({id1.id, id2.id, id3.id});
} }
TEST_F(ClangPathWatcher, RemoveOnePathForTwoId) TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
@@ -325,7 +330,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath))); EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath)));
watcher.removeIds({id1, id2}); watcher.removeIds({id1.id, id2.id});
} }
TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId) TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId)
@@ -349,13 +354,14 @@ TEST_F(ClangPathWatcher, RemoveUnusedEntries)
TEST_F(ClangPathWatcher, TwoNotifyFileChanges) TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
{ {
watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}}, watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}},
{id2, {pathIds[0], pathIds[1], pathIds[3]}}, {id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}},
{id3, {pathIds[4]}}}); {id3, {pathIds[4]}}});
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2)); ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[1]))).WillByDefault(Return(2)); ON_CALL(mockFileSystem, lastModified(Eq(pathIds[1]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2)); ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2));
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2))); EXPECT_CALL(notifier,
pathsWithIdsChanged(ElementsAre(IdPaths{id1, {1, 2}}, IdPaths{id2, {1, 2, 4}})));
mockQFileSytemWatcher.directoryChanged(directoryPath); mockQFileSytemWatcher.directoryChanged(directoryPath);
mockQFileSytemWatcher.directoryChanged(directoryPath2); mockQFileSytemWatcher.directoryChanged(directoryPath2);

View File

@@ -52,8 +52,8 @@ public:
CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; } CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; }
public: public:
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}}; ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}}; ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
}; };
template <> template <>

View File

@@ -359,9 +359,8 @@ std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry)
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry) std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry)
{ {
out << "(" out << "(" << entry.directoryPathId << ", " << entry.filePathId << ", " << entry.id << ", "
<< entry.id << ", " << entry.lastModified << ", "
<< entry.filePathId
<< ")"; << ")";
return out; return out;
@@ -1290,6 +1289,17 @@ std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths)
{ {
return out << "(" << pchPaths.projectPchPath << ", " << pchPaths.systemPchPath << ")"; return out << "(" << pchPaths.projectPchPath << ", " << pchPaths.systemPchPath << ")";
} }
std::ostream &operator<<(std::ostream &out, const ProjectChunkId &chunk)
{
return out << "(" << chunk.id << ", " << typeToString(chunk.sourceType) << ")";
}
std::ostream &operator<<(std::ostream &out, const DirectoryPathId &id)
{
return out << id.directoryPathId;
}
void PrintTo(const FilePath &filePath, ::std::ostream *os) void PrintTo(const FilePath &filePath, ::std::ostream *os)
{ {
*os << filePath; *os << filePath;

View File

@@ -200,6 +200,8 @@ struct ArgumentsEntry;
class ProjectPartContainer; class ProjectPartContainer;
class ProjectPartId; class ProjectPartId;
class PchPaths; class PchPaths;
class ProjectChunkId;
class DirectoryPathId;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -293,6 +295,8 @@ std::ostream &operator<<(std::ostream &out, const ArgumentsEntry &entry);
std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container); std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container);
std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId); std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId);
std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths); std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths);
std::ostream &operator<<(std::ostream &out, const ProjectChunkId &chunk);
std::ostream &operator<<(std::ostream &out, const DirectoryPathId &id);
void PrintTo(const FilePath &filePath, ::std::ostream *os); void PrintTo(const FilePath &filePath, ::std::ostream *os);
void PrintTo(const FilePathView &filePathView, ::std::ostream *os); void PrintTo(const FilePathView &filePathView, ::std::ostream *os);

View File

@@ -53,5 +53,16 @@ public:
void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId)); void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchPchSources, MOCK_CONST_METHOD1(fetchPchSources,
ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId)); ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchSources,
ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD2(insertOrUpdateIndexingTimeStamps,
void(const ClangBackEnd::FilePathIds &filePathIds,
ClangBackEnd::TimeStamp indexingTimeStamp));
MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &));
MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps());
MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps,
ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId));
MOCK_CONST_METHOD1(fetchDependentSourceIds,
ClangBackEnd::FilePathIds(const ClangBackEnd::FilePathIds &sourcePathIds));
}; };

View File

@@ -32,7 +32,7 @@
class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier
{ {
public: public:
MOCK_METHOD1(pathsWithIdsChanged, void(const ClangBackEnd::ProjectPartIds &ids)); MOCK_METHOD1(pathsWithIdsChanged, void(const std::vector<ClangBackEnd::IdPaths> &idPaths));
MOCK_METHOD1(pathsChanged, MOCK_METHOD1(pathsChanged,
void (const ClangBackEnd::FilePathIds &filePathIds)); void (const ClangBackEnd::FilePathIds &filePathIds));

View File

@@ -37,11 +37,4 @@ public:
MOCK_METHOD2(addSymbolsAndSourceLocations, MOCK_METHOD2(addSymbolsAndSourceLocations,
void(const ClangBackEnd::SymbolEntries &symbolEentries, void(const ClangBackEnd::SymbolEntries &symbolEentries,
const ClangBackEnd::SourceLocationEntries &sourceLocations)); const ClangBackEnd::SourceLocationEntries &sourceLocations));
MOCK_METHOD2(insertOrUpdateIndexingTimeStamps,
void(const FilePathIds &filePathIds, ClangBackEnd::TimeStamp indexingTimeStamp));
MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &));
MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps());
MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps,
ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId));
MOCK_CONST_METHOD1(fetchDependentSourceIds, FilePathIds(const FilePathIds &sourcePathIds));
}; };

View File

@@ -34,12 +34,13 @@
#include "mockpchmanagerclient.h" #include "mockpchmanagerclient.h"
#include "testenvironment.h" #include "testenvironment.h"
#include <refactoringdatabaseinitializer.h>
#include <filepathcaching.h> #include <filepathcaching.h>
#include <generatedfiles.h> #include <generatedfiles.h>
#include <pchcreator.h> #include <pchcreator.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <progressmessage.h> #include <progressmessage.h>
#include <refactoringdatabaseinitializer.h>
#include <updateprojectpartsmessage.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
@@ -55,12 +56,14 @@ using ClangBackEnd::GeneratedFiles;
using ClangBackEnd::IdPaths; using ClangBackEnd::IdPaths;
using ClangBackEnd::IncludeSearchPathType; using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::PchTask; using ClangBackEnd::PchTask;
using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
using ClangBackEnd::ProjectChunkId;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartPch; using ClangBackEnd::ProjectPartPch;
using ClangBackEnd::SourceEntries; using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry; using ClangBackEnd::SourceEntry;
using ClangBackEnd::SourceType; using ClangBackEnd::SourceType;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::ProjectPartContainer;
using Utils::PathString; using Utils::PathString;
using Utils::SmallString; using Utils::SmallString;
@@ -91,6 +94,13 @@ protected:
return creator.filePathCache().filePathId(path); return creator.filePathCache().filePathId(path);
} }
FilePathIds sorted(FilePathIds &&filePathIds)
{
std::sort(filePathIds.begin(), filePathIds.end());
return std::move(filePathIds);
}
protected: protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
@@ -111,14 +121,19 @@ protected:
mockBuildDependenciesStorage}; mockBuildDependenciesStorage};
PchTask pchTask1{ PchTask pchTask1{
1, 1,
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), sorted({id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
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")}),
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), sorted({id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), id(TESTDATA_DIR "/builddependencycollector/system/system2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), id(generatedFilePath)}),
id(generatedFilePath), sorted({id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(main2Path)}, id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(generatedFilePath)}),
sorted({id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(generatedFilePath)}),
sorted({id(main2Path), id(generatedFilePath)}),
{}, {},
{}, {},
{}, {},
@@ -213,15 +228,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess)
{ {
creator.generatePch(std::move(pchTask1)); creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher, EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf( updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, 1), Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds, Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre( UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), EXPECT_CALL(
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"))))))); mockClangPathWatcher,
updateIdPaths(ElementsAre(
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}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h")))))));
creator.doInMainThreadAfterFinished(); creator.doInMainThreadAfterFinished();
} }
@@ -232,15 +266,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterFail)
pchTask1.projectIncludeSearchPaths = {}; pchTask1.projectIncludeSearchPaths = {};
creator.generatePch(std::move(pchTask1)); creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher, EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf( updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, 1), Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds, Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre( UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), EXPECT_CALL(
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"))))))); mockClangPathWatcher,
updateIdPaths(ElementsAre(
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}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h")))))));
creator.doInMainThreadAfterFinished(); creator.doInMainThreadAfterFinished();
} }
@@ -282,15 +335,40 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
ASSERT_FALSE(creator.projectPartPch().isValid()); ASSERT_FALSE(creator.projectPartPch().isValid());
} }
TEST_F(PchCreatorVerySlowTest, SourcesCleared) TEST_F(PchCreatorVerySlowTest, WatchedSystemIncludesCleared)
{ {
creator.generatePch(std::move(pchTask1)); creator.generatePch(std::move(pchTask1));
creator.clear(); creator.clear();
ASSERT_THAT(creator.sources(), IsEmpty()); ASSERT_THAT(creator.watchedSystemIncludes(), IsEmpty());
} }
TEST_F(PchCreatorVerySlowTest, WatchedProjectIncludesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.watchedProjectIncludes(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, WatchedUserIncludesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.watchedUserIncludes(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, WatchedSourcesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.watchedSources(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, ClangToolCleared) TEST_F(PchCreatorVerySlowTest, ClangToolCleared)
{ {
creator.generatePch(std::move(pchTask1)); creator.generatePch(std::move(pchTask1));
@@ -306,6 +384,9 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask
0, 0,
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")}, {id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")},
{}, {},
{},
{},
{},
{{"DEFINE", "1", 1}}, {{"DEFINE", "1", 1}},
{}, {},
{}, {},
@@ -336,20 +417,37 @@ TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls)
{ {
pchTask1.includes = {}; pchTask1.includes = {};
creator.generatePch(std::move(pchTask1)); creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockPchManagerClient, EXPECT_CALL(mockPchManagerClient,
precompiledHeadersUpdated( precompiledHeadersUpdated(
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds, Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
ElementsAre(Eq(creator.projectPartPch().projectPartId))))); ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher, EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf( updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, 1), Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds, Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre( UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), EXPECT_CALL(
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"))))))); mockClangPathWatcher,
updateIdPaths(ElementsAre(
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}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h")))))));
EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(Gt(0), Eq(1))); EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(Gt(0), Eq(1)));
creator.doInMainThreadAfterFinished(); creator.doInMainThreadAfterFinished();

View File

@@ -25,11 +25,12 @@
#include "googletest.h" #include "googletest.h"
#include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h" #include "mockclangpathwatcher.h"
#include "mockgeneratedfiles.h"
#include "mockpchmanagerclient.h" #include "mockpchmanagerclient.h"
#include "mockpchtaskgenerator.h" #include "mockpchtaskgenerator.h"
#include "mockprojectpartsmanager.h" #include "mockprojectpartsmanager.h"
#include "mockgeneratedfiles.h"
#include <filepathcaching.h> #include <filepathcaching.h>
#include <pchmanagerserver.h> #include <pchmanagerserver.h>
@@ -42,12 +43,13 @@
#include <updateprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
namespace { namespace {
using Utils::PathString; using ClangBackEnd::FilePathId;
using Utils::SmallString;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers; using ClangBackEnd::ProjectPartContainers;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::FileContainers;
using Utils::PathString;
using Utils::SmallString;
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts; using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
class PchManagerServer : public ::testing::Test class PchManagerServer : public ::testing::Test
@@ -71,21 +73,27 @@ protected:
NiceMock<MockClangPathWatcher> mockClangPathWatcher; NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockProjectPartsManager> mockProjectPartsManager; NiceMock<MockProjectPartsManager> mockProjectPartsManager;
NiceMock<MockGeneratedFiles> mockGeneratedFiles; NiceMock<MockGeneratedFiles> mockGeneratedFiles;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
ClangBackEnd::PchManagerServer server{mockClangPathWatcher, ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
mockPchTaskGenerator, mockPchTaskGenerator,
mockProjectPartsManager, mockProjectPartsManager,
mockGeneratedFiles}; mockGeneratedFiles,
mockBuildDependenciesStorage};
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
ClangBackEnd::ProjectPartId projectPartId1{1}; ClangBackEnd::ProjectPartId projectPartId1{1};
ClangBackEnd::ProjectPartId projectPartId2{2}; ClangBackEnd::ProjectPartId projectPartId2{2};
ClangBackEnd::ProjectPartId projectPartId3{3};
ClangBackEnd::ProjectPartId projectPartId4{4};
ClangBackEnd::ProjectPartId projectPartId5{5};
ClangBackEnd::ProjectPartId projectPartId6{6};
PathString main1Path = TESTDATA_DIR "/BuildDependencyCollector_main3.cpp"; PathString main1Path = TESTDATA_DIR "/BuildDependencyCollector_main3.cpp";
PathString main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp"; PathString main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.h"; PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.h";
PathString header2Path = TESTDATA_DIR "/BuildDependencyCollector_header2.h"; PathString header2Path = TESTDATA_DIR "/BuildDependencyCollector_header2.h";
ClangBackEnd::IdPaths idPath{projectPartId1, {1, 2}}; ClangBackEnd::IdPaths idPath{{projectPartId1, ClangBackEnd::SourceType::Source}, {1, 2}};
ProjectPartContainer projectPart1{ ProjectPartContainer projectPart1{
projectPartId1, projectPartId1,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
@@ -108,6 +116,50 @@ protected:
Utils::Language::C, Utils::Language::C,
Utils::LanguageVersion::C11, Utils::LanguageVersion::C11,
Utils::LanguageExtension::All}; Utils::LanguageExtension::All};
ProjectPartContainer projectPart3{
projectPartId3,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header1Path)},
{id(main1Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart4{
projectPartId4,
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header2Path)},
{id(main2Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart5{
projectPartId5,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header1Path)},
{id(main1Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart6{
projectPartId6,
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header2Path)},
{id(main2Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2}; std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2};
std::vector<ProjectPartContainer> projectParts1{projectPart1}; std::vector<ProjectPartContainer> projectParts1{projectPart1};
std::vector<ProjectPartContainer> projectParts2{projectPart2}; std::vector<ProjectPartContainer> projectParts2{projectPart2};
@@ -169,19 +221,68 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
ClangBackEnd::PchManagerServer server{mockClangPathWatcher, ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
mockPchTaskGenerator, mockPchTaskGenerator,
mockProjectPartsManager, mockProjectPartsManager,
mockGeneratedFiles}; mockGeneratedFiles,
mockBuildDependenciesStorage};
} }
TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds) TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds)
{ {
server.updateProjectParts( server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}}); {projectPart1, projectPart2, projectPart3, projectPart4, projectPart5, projectPart6},
{"toolChainArgument"}});
EXPECT_CALL(mockProjectPartsManager, projects(ElementsAre(projectPart1.projectPartId))) EXPECT_CALL(mockProjectPartsManager,
.WillOnce(Return(std::vector<ClangBackEnd::ProjectPartContainer>{{projectPart1}})); projects(ElementsAre(projectPart1.projectPartId,
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(ElementsAre(projectPart1), ElementsAre("toolChainArgument"))); projectPart2.projectPartId,
projectPart4.projectPartId,
projectPart5.projectPartId)))
.WillOnce(Return(std::vector<ClangBackEnd::ProjectPartContainer>{
{projectPart1, projectPart2, projectPart4, projectPart5}}));
EXPECT_CALL(mockPchTaskGenerator,
addProjectParts(ElementsAre(projectPart1, projectPart2, projectPart4, projectPart5),
ElementsAre("toolChainArgument")));
server.pathsWithIdsChanged({projectPartId1}); server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}},
{{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}},
{{projectPartId6, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, DontUpdateProjectPartQueueByPathIdsIfItUserFile)
{
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{{projectPart1, projectPart2},
{"toolChainArgument"}});
EXPECT_CALL(mockProjectPartsManager, projects(_)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, ShortcutPrecompiledHeaderGenerationForUserIncludesAndSources)
{
EXPECT_CALL(mockPchManagerClient,
precompiledHeadersUpdated(
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
UnorderedElementsAre(projectPartId3, projectPartId6))));
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}},
{{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}},
{{projectPartId6, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, ResetTimeStampForChangedFilesInDatabase)
{
EXPECT_CALL(mockBuildDependenciesStorage,
insertOrUpdateIndexingTimeStamps(ElementsAre(FilePathId{1}, FilePathId{3}, FilePathId{5}),
TypedEq<ClangBackEnd::TimeStamp>(0)));
server.pathsChanged({1, 3, 5});
} }
TEST_F(PchManagerServer, SetPchCreationProgress) TEST_F(PchManagerServer, SetPchCreationProgress)
@@ -214,7 +315,7 @@ TEST_F(PchManagerServer, RemoveToolChainsArguments)
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0); EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
server.removeProjectParts(removeProjectPartsMessage.clone()); server.removeProjectParts(removeProjectPartsMessage.clone());
server.pathsWithIdsChanged({projectPart1.projectPartId}); server.pathsWithIdsChanged({{{projectPart1.projectPartId, ClangBackEnd::SourceType::Source}, {}}});
} }
TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid) TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid)

View File

@@ -84,7 +84,8 @@ protected:
{2, SourceType::UserInclude, 1}, {2, SourceType::UserInclude, 1},
{3, SourceType::TopProjectInclude, 1}, {3, SourceType::TopProjectInclude, 1},
{4, SourceType::SystemInclude, 1}, {4, SourceType::SystemInclude, 1},
{5, SourceType::TopSystemInclude, 1}}; {5, SourceType::TopSystemInclude, 1},
{6, SourceType::Source, 1}};
UsedMacros usedMacros{{"LIANG", 0},{"YI", 1}, {"ER", 2}, {"SAN", 3}, {"SE", 4}, {"WU", 5}}; UsedMacros usedMacros{{"LIANG", 0},{"YI", 1}, {"ER", 2}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
BuildDependency buildDependency{firstSources, usedMacros, {}, {}, {}}; BuildDependency buildDependency{firstSources, usedMacros, {}, {}, {}};
}; };
@@ -100,7 +101,10 @@ TEST_F(PchTaskGenerator, AddProjectParts)
Field(&PchTaskSet::system, Field(&PchTaskSet::system,
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})), AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(5)), Field(&PchTask::includes, ElementsAre(5)),
Field(&PchTask::sources, IsEmpty()), Field(&PchTask::watchedSystemIncludes, IsEmpty()),
Field(&PchTask::watchedProjectIncludes, IsEmpty()),
Field(&PchTask::watchedUserIncludes, IsEmpty()),
Field(&PchTask::watchedUserSources, IsEmpty()),
Field(&PchTask::compilerMacros, Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})), ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})),
Field(&PchTask::systemIncludeSearchPaths, Field(&PchTask::systemIncludeSearchPaths,
@@ -117,7 +121,10 @@ TEST_F(PchTaskGenerator, AddProjectParts)
&PchTaskSet::project, &PchTaskSet::project,
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})), AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(3)), Field(&PchTask::includes, ElementsAre(3)),
Field(&PchTask::sources, ElementsAre(1, 3, 4, 5)), Field(&PchTask::watchedSystemIncludes, ElementsAre(4, 5)),
Field(&PchTask::watchedProjectIncludes, ElementsAre(1, 3)),
Field(&PchTask::watchedUserIncludes, ElementsAre(2)),
Field(&PchTask::watchedUserSources, ElementsAre(6)),
Field(&PchTask::compilerMacros, Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})), ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
Field(&PchTask::systemIncludeSearchPaths, Field(&PchTask::systemIncludeSearchPaths,

View File

@@ -67,6 +67,9 @@ protected:
PchTask systemTask1{1, PchTask systemTask1{1,
{1, 2}, {1, 2},
{1, 2}, {1, 2},
{2, 3},
{3, 4},
{6, 7},
{{"YI", "1", 1}, {"SAN", "3", 3}}, {{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}, {{"LIANG", 0}, {"YI", 1}},
{"--yi"}, {"--yi"},
@@ -75,6 +78,9 @@ protected:
PchTask systemTask2{2, PchTask systemTask2{2,
{1, 2}, {1, 2},
{1, 2}, {1, 2},
{2, 3},
{3, 4},
{6, 7},
{{"YI", "1", 1}, {"SAN", "3", 3}}, {{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}, {{"LIANG", 0}, {"YI", 1}},
{"--yi"}, {"--yi"},
@@ -83,6 +89,9 @@ protected:
PchTask systemTask2b{2, PchTask systemTask2b{2,
{3, 4}, {3, 4},
{3, 4}, {3, 4},
{5, 6},
{4, 7},
{8, 9},
{{"YI", "1", 1}, {"SAN", "3", 3}}, {{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}, {{"LIANG", 0}, {"YI", 1}},
{"--yi"}, {"--yi"},
@@ -91,6 +100,9 @@ protected:
PchTask systemTask3{3, PchTask systemTask3{3,
{1, 2}, {1, 2},
{1, 2}, {1, 2},
{2, 3},
{3, 4},
{6, 7},
{{"YI", "1", 1}, {"SAN", "3", 3}}, {{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}, {{"LIANG", 0}, {"YI", 1}},
{"--yi"}, {"--yi"},
@@ -99,6 +111,9 @@ protected:
PchTask projectTask1{1, PchTask projectTask1{1,
{11, 12}, {11, 12},
{11, 12}, {11, 12},
{12, 13},
{13, 14},
{16, 17},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}, {{"ER", 2}, {"SAN", 3}},
{"--yi"}, {"--yi"},
@@ -107,6 +122,9 @@ protected:
PchTask projectTask2{2, PchTask projectTask2{2,
{11, 12}, {11, 12},
{11, 12}, {11, 12},
{12, 13},
{13, 14},
{16, 17},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}, {{"ER", 2}, {"SAN", 3}},
{"--yi"}, {"--yi"},
@@ -115,6 +133,9 @@ protected:
PchTask projectTask2b{2, PchTask projectTask2b{2,
{21, 22}, {21, 22},
{11, 12}, {11, 12},
{22, 23},
{23, 24},
{26, 27},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}, {{"ER", 2}, {"SAN", 3}},
{"--yi"}, {"--yi"},
@@ -123,6 +144,9 @@ protected:
PchTask projectTask3{3, PchTask projectTask3{3,
{21, 22}, {21, 22},
{21, 22}, {21, 22},
{22, 23},
{23, 24},
{26, 27},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}, {{"ER", 2}, {"SAN", 3}},
{"--yi"}, {"--yi"},
@@ -131,6 +155,9 @@ protected:
PchTask systemTask4{{1, 3}, PchTask systemTask4{{1, 3},
{1, 2}, {1, 2},
{1, 2}, {1, 2},
{2, 3},
{3, 4},
{5, 8},
{{"YI", "1", 1}, {"SAN", "3", 3}}, {{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}, {{"LIANG", 0}, {"YI", 1}},
{"--yi"}, {"--yi"},

View File

@@ -54,7 +54,10 @@ protected:
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue}; ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
PchTask systemTask1{1, PchTask systemTask1{1,
{1, 2}, {1, 2},
{1, 2, 3}, {},
{},
{},
{},
{{"YI", "1", 1}, {"SAN", "3", 3}}, {{"YI", "1", 1}, {"SAN", "3", 3}},
{"YI", "LIANG"}, {"YI", "LIANG"},
{"--yi"}, {"--yi"},
@@ -66,6 +69,9 @@ protected:
PchTask projectTask1{1, PchTask projectTask1{1,
{11, 12}, {11, 12},
{11, 12}, {11, 12},
{21, 22},
{31, 32},
{41, 42},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"}, {"ER", "SAN"},
{"--yi"}, {"--yi"},
@@ -75,7 +81,10 @@ protected:
{"/to/path2", 2, IncludeSearchPathType::User}}}; {"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask2{2, PchTask systemTask2{2,
{11, 12}, {11, 12},
{11, 12, 13}, {},
{},
{},
{},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"}, {"ER", "SAN"},
{"--yi"}, {"--yi"},
@@ -87,6 +96,9 @@ protected:
PchTask projectTask2{2, PchTask projectTask2{2,
{11, 12}, {11, 12},
{11, 12}, {11, 12},
{21, 22},
{31, 32},
{41, 42},
{{"SE", "4", 4}, {"WU", "5", 5}}, {{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"}, {"ER", "SAN"},
{"--yi"}, {"--yi"},
@@ -97,7 +109,10 @@ protected:
{"/to/path2", 2, IncludeSearchPathType::User}}}; {"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask3{3, PchTask systemTask3{3,
{1, 2}, {1, 2},
{1, 2}, {},
{},
{},
{},
{{"YI", "2", 1}, {"SAN", "3", 3}}, {{"YI", "2", 1}, {"SAN", "3", 3}},
{"YI", "LIANG"}, {"YI", "LIANG"},
{"--yi"}, {"--yi"},
@@ -268,18 +283,25 @@ TEST_F(PchTasksMerger, DontMergeIncludes)
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2)); ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
} }
TEST_F(PchTasksMerger, MergeAllIncludes) TEST_F(PchTasksMerger, DontMergeWatchedSystemSources)
{ {
Merger::mergePchTasks(systemTask1, systemTask2); Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.sources, ElementsAre(1, 2, 3, 11, 12, 13)); ASSERT_THAT(systemTask1.watchedSystemIncludes, IsEmpty());
} }
TEST_F(PchTasksMerger, DontAllMergeIncludes) TEST_F(PchTasksMerger, DontMergeWatchedProjectSources)
{ {
Merger::mergePchTasks(systemTask1, systemTask3); Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.sources, ElementsAre(1, 2, 3)); ASSERT_THAT(systemTask1.watchedProjectIncludes, IsEmpty());
}
TEST_F(PchTasksMerger, DontMergeWatchedUserSources)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.watchedUserSources, IsEmpty());
} }
TEST_F(PchTasksMerger, MergeProjectIds) TEST_F(PchTasksMerger, MergeProjectIds)

View File

@@ -463,7 +463,6 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
Storage storage{database}; Storage storage{database};
ClangBackEnd::SymbolStorage<> symbolStorage{database};
ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database}; ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
}; };
@@ -505,13 +504,13 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps) TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps)
{ {
symbolStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34); buildDependenciesStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34);
buildDependenciesStorage.insertOrUpdateSourceDependencies( buildDependenciesStorage.insertOrUpdateSourceDependencies(
{{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}}); {{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}});
storage.resetIndexingTimeStamps({projectPart1, projectPart2}); storage.resetIndexingTimeStamps({projectPart1, projectPart2});
ASSERT_THAT(symbolStorage.fetchIndexingTimeStamps(), ASSERT_THAT(buildDependenciesStorage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 0}, ElementsAre(SourceTimeStamp{1, 0},
SourceTimeStamp{2, 0}, SourceTimeStamp{2, 0},
SourceTimeStamp{3, 0}, SourceTimeStamp{3, 0},

View File

@@ -116,11 +116,11 @@ protected:
.WillByDefault(Return(artefact)); .WillByDefault(Return(artefact));
ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1)); ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1));
ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true)); ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds)) ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(sourceFileIds))
.WillByDefault(Return(sourceFileIds)); .WillByDefault(Return(sourceFileIds));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0]))) ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
.WillByDefault(Return(FilePathIds{sourceFileIds[0]})); .WillByDefault(Return(FilePathIds{sourceFileIds[0]}));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(main1PathId))) ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
.WillByDefault(Return(FilePathIds{main1PathId})); .WillByDefault(Return(FilePathIds{main1PathId}));
mockCollector.setIsUsed(false); mockCollector.setIsUsed(false);
@@ -879,16 +879,16 @@ TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps)
Utils::LanguageVersion::CXX14, Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None}; Utils::LanguageExtension::None};
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId))) EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
.WillOnce(Return(dependentSourceTimeStamps1)); .WillOnce(Return(dependentSourceTimeStamps1));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1)); EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1));
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId))) EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
.WillOnce(Return(dependentSourceTimeStamps2)); .WillOnce(Return(dependentSourceTimeStamps2));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2)); EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2));
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1)); EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1)); EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2)); EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2)); EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
indexer.updateProjectParts({projectPart}); indexer.updateProjectParts({projectPart});
} }
@@ -917,642 +917,6 @@ TEST_F(SymbolIndexer, DependentSourceAreUpToDate)
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1});
} }
TEST_F(SymbolIndexer, SourcesAreWatched)
{
using ClangBackEnd::IdPaths;
InSequence s;
FilePathIds sourcePathIds{4, 6, 8};
EXPECT_CALL(mockBuildDependenciesStorage, fetchPchSources(projectPart1.projectPartId))
.WillOnce(Return(sourcePathIds));
EXPECT_CALL(mockPathWatcher,
updateIdPaths(ElementsAre(AllOf(Field(&IdPaths::id, projectPart1.projectPartId),
Field(&IdPaths::filePathIds, sourcePathIds)))));
indexer.updateProjectParts({projectPart1});
}
TEST_F(SymbolIndexer, CallSetNotifier)
{
EXPECT_CALL(mockPathWatcher, setNotifier(_));
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
mockSymbolStorage,
mockBuildDependenciesStorage,
mockPrecompiledHeaderStorage,
mockPathWatcher,
filePathCache,
fileStatusCache,
mockSqliteTransactionBackend,
mockProjectPartsStorage,
mockModifiedTimeChecker,
testEnvironment};
}
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
{
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1]));
indexer.pathsChanged(sourceFileIds);
}
TEST_F(SymbolIndexer, PathChangedCallsFetchSourcePathIds)
{
InSequence s;
EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
.WillOnce(Return(FilePathIds{2, 6, 5}));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{2}));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{6}));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{5}));
indexer.pathsChanged(sourceFileIds);
}
TEST_F(SymbolIndexer, PathChangedFetchIncludedIndexingTimeStamps)
{
InSequence s;
ProjectPartContainer projectPart{1,
{"-Wno-pragma-once-outside-header"},
{{"BAR", "1", 1}, {"FOO", "1", 2}},
Utils::clone(systemIncludeSearchPaths),
Utils::clone(projectIncludeSearchPaths),
{header1PathId},
{main1PathId, main2PathId},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None};
EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillOnce(Return(FilePathIds{1, 2}));
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(1)))
.WillOnce(Return(dependentSourceTimeStamps1));
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(2)))
.WillOnce(Return(dependentSourceTimeStamps2));
EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses1));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses2));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
indexer.pathsChanged({1, 3});
}
TEST_F(SymbolIndexer, PathChangedFetchesDependentSourceIdsFromStorage)
{
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1]));
indexer.pathsChanged(sourceFileIds);
}
TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
{
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)));
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
{
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]))
.WillOnce(Return(nullArtefact));
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(_)).Times(0);
EXPECT_CALL(mockCollector, setFile(_, _)).Times(0);
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(_, _)).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasNoError)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectPch)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectAndSystemPch)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasOnlyError)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsSystemPchPathsAndHasErrorWithProjectPch)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{{}, "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsNoPchPathsAndHasErrors)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
{
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(artefact));
ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillByDefault(Return(pchPaths));
std::vector<SymbolIndexerTask> symbolIndexerTask;
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
{
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(artefact));
std::vector<SymbolIndexerTask> symbolIndexerTask;
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent) TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent)
{ {
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(A<ProjectPartId>())) ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(A<ProjectPartId>()))
@@ -1660,7 +1024,8 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache)
{ {
auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp"); auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp");
ON_CALL(mockFileSystem, lastModified(Eq(sourceId))).WillByDefault(Return(65)); ON_CALL(mockFileSystem, lastModified(Eq(sourceId))).WillByDefault(Return(65));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId})); ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(_))
.WillByDefault(Return(FilePathIds{sourceId}));
indexer.pathsChanged({sourceId}); indexer.pathsChanged({sourceId});

View File

@@ -69,10 +69,6 @@ protected:
MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement; MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement;
MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement; MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement;
MockSqliteWriteStatement &deleteNewLocationsTableStatement = storage.deleteNewLocationsTableStatement; MockSqliteWriteStatement &deleteNewLocationsTableStatement = storage.deleteNewLocationsTableStatement;
MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement;
MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement;
SymbolEntries symbolEntries{{1, {"functionUSR", "function", SymbolKind::Function}}, SymbolEntries symbolEntries{{1, {"functionUSR", "function", SymbolKind::Function}},
{2, {"function2USR", "function2", SymbolKind::Function}}}; {2, {"function2USR", "function2", SymbolKind::Function}}};
SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration}, SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration},
@@ -192,145 +188,4 @@ TEST_F(SymbolStorage, AddTablesInConstructor)
Storage storage{mockDatabase}; Storage storage{mockDatabase};
} }
TEST_F(SymbolStorage, FetchIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIndexingTimeStamps();
}
TEST_F(SymbolStorage, InsertIndexingTimeStamp)
{
ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}};
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(37)));
storage.insertOrUpdateIndexingTimeStamps(fileStatuses);
}
TEST_F(SymbolStorage, InsertIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(34)));
EXPECT_CALL(mockDatabase, commit());
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
}
TEST_F(SymbolStorage, FetchIncludedIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIncludedIndexingTimeStamps(1);
}
TEST_F(SymbolStorage, FetchDependentSourceIdsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(7)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchDependentSourceIds({3, 2, 7});
}
class SymbolStorageSlow : public testing::Test
{
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::SymbolStorage<> storage{database};
ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
};
TEST_F(SymbolStorageSlow, InsertIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34}));
}
TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
storage.insertOrUpdateIndexingTimeStamps({1}, 37);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34}));
}
TEST_F(SymbolStorageSlow, InsertIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}});
storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(SymbolStorageSlow, FetchIncludedIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34);
buildDependenciesStorage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}});
auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1);
ASSERT_THAT(timeStamps,
ElementsAre(SourceTimeStamp{1, 34},
SourceTimeStamp{2, 34},
SourceTimeStamp{3, 34},
SourceTimeStamp{4, 34}));
}
TEST_F(SymbolStorageSlow, FetchDependentSourceIds)
{
buildDependenciesStorage.insertOrUpdateSourceDependencies(
{{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}});
auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7});
ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7}));
}
} // namespace } // namespace

View File

@@ -97,8 +97,14 @@ TEST_F(UsedMacroFilter, Sources)
{ {
ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros); ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros);
ASSERT_THAT(filter.sources, ASSERT_THAT(filter.sources, ElementsAre(FilePathId{6}));
ElementsAre(FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5})); }
TEST_F(UsedMacroFilter, UserIncludes)
{
ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros);
ASSERT_THAT(filter.userIncludes, ElementsAre(FilePathId{1}));
} }
TEST_F(UsedMacroFilter, SystemUsedMacros) TEST_F(UsedMacroFilter, SystemUsedMacros)