forked from qt-creator/qt-creator
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:
@@ -1,4 +1,4 @@
|
||||
; /****************************************************************************
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
@@ -57,7 +57,7 @@ void set_greedy_intersection_call(
|
||||
class WatcherEntry
|
||||
{
|
||||
public:
|
||||
ProjectPartId id;
|
||||
ProjectChunkId id;
|
||||
DirectoryPathId directoryPathId;
|
||||
FilePathId filePathId;
|
||||
long long lastModified = -1;
|
||||
@@ -140,25 +140,6 @@ public:
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
std::pair<WatcherEntries, ProjectPartIds> convertIdPathsToWatcherEntriesAndIds(
|
||||
std::pair<WatcherEntries, ProjectChunkIds> convertIdPathsToWatcherEntriesAndIds(
|
||||
const std::vector<IdPaths> &idPaths)
|
||||
{
|
||||
WatcherEntries entries;
|
||||
entries.reserve(sizeOfIdPaths(idPaths));
|
||||
ProjectPartIds ids;
|
||||
ProjectChunkIds ids;
|
||||
ids.reserve(ids.size());
|
||||
|
||||
auto outputIterator = std::back_inserter(entries);
|
||||
|
||||
for (const IdPaths &idPath : idPaths)
|
||||
{
|
||||
ProjectPartId id = idPath.id;
|
||||
ProjectChunkId id = idPath.id;
|
||||
|
||||
ids.push_back(id);
|
||||
|
||||
@@ -214,7 +195,7 @@ public:
|
||||
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);
|
||||
|
||||
@@ -294,7 +275,7 @@ public:
|
||||
}
|
||||
|
||||
WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries,
|
||||
const ProjectPartIds &ids) const
|
||||
const ProjectChunkIds &ids) const
|
||||
{
|
||||
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
|
||||
|
||||
@@ -420,25 +401,22 @@ public:
|
||||
return filePathIds;
|
||||
}
|
||||
|
||||
ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries)
|
||||
std::vector<IdPaths> idPathsForWatcherEntries(WatcherEntries &&foundEntries)
|
||||
{
|
||||
ProjectPartIds ids;
|
||||
ids.reserve(foundEntries.size());
|
||||
std::sort(foundEntries.begin(), foundEntries.end(), [](WatcherEntry first, WatcherEntry second) {
|
||||
return std::tie(first.id, first.filePathId) < std::tie(second.id, second.filePathId);
|
||||
});
|
||||
|
||||
std::transform(foundEntries.begin(),
|
||||
foundEntries.end(),
|
||||
std::back_inserter(ids),
|
||||
[&](WatcherEntry entry) { return entry.id; });
|
||||
std::vector<IdPaths> idPaths;
|
||||
idPaths.reserve(foundEntries.size());
|
||||
|
||||
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)
|
||||
{
|
||||
std::sort(ids.begin(), ids.end());
|
||||
ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
|
||||
|
||||
return std::move(ids);
|
||||
return idPaths;
|
||||
}
|
||||
|
||||
void addChangedPathForFilePath(DirectoryPathIds &&directoryPathIds)
|
||||
@@ -446,10 +424,12 @@ public:
|
||||
if (m_notifier) {
|
||||
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(directoryPathIds));
|
||||
|
||||
ProjectPartIds changedIds = idsForWatcherEntries(foundEntries);
|
||||
FilePathIds watchedFilePathIds = watchedPaths(foundEntries);
|
||||
|
||||
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds)));
|
||||
m_notifier->pathsChanged(watchedPaths(foundEntries));
|
||||
std::vector<IdPaths> changedIdPaths = idPathsForWatcherEntries(std::move(foundEntries));
|
||||
|
||||
m_notifier->pathsChanged(watchedFilePathIds);
|
||||
m_notifier->pathsWithIdsChanged(changedIdPaths);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,9 +26,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "clangsupport_global.h"
|
||||
|
||||
#include <filepathid.h>
|
||||
#include <projectpartid.h>
|
||||
#include "filepathid.h"
|
||||
#include "idpaths.h"
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
@@ -41,7 +40,7 @@ public:
|
||||
ClangPathWatcherNotifier(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;
|
||||
|
||||
protected:
|
||||
|
@@ -120,6 +120,7 @@ HEADERS += \
|
||||
$$PWD/projectpartid.h \
|
||||
$$PWD/projectpartsstorage.h \
|
||||
$$PWD/projectpartsstorageinterface.h \
|
||||
$$PWD/projectsourcechunk.h \
|
||||
$$PWD/requestcompletionsmessage.h \
|
||||
$$PWD/echomessage.h \
|
||||
$$PWD/endmessage.h \
|
||||
|
@@ -25,21 +25,60 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "projectpartid.h"
|
||||
#include "filepathid.h"
|
||||
#include "projectpartid.h"
|
||||
#include "sourceentry.h"
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
ProjectPartId id;
|
||||
ProjectChunkId id;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
using ProjectChunkIds = std::vector<ProjectChunkId>;
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "clangsupport_global.h"
|
||||
#include "filepathid.h"
|
||||
#include "projectpartid.h"
|
||||
|
||||
#include <utils/smallstringio.h>
|
||||
@@ -37,6 +38,7 @@ class PrecompiledHeadersUpdatedMessage
|
||||
public:
|
||||
PrecompiledHeadersUpdatedMessage() = default;
|
||||
PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId)
|
||||
|
||||
{
|
||||
projectPartIds.push_back(projectPartId);
|
||||
}
|
||||
|
@@ -225,7 +225,8 @@ struct Data // because we have a cycle dependency
|
||||
PchManagerServer clangPchManagerServer{includeWatcher,
|
||||
pchTaskGenerator,
|
||||
projectParts,
|
||||
generatedFiles};
|
||||
generatedFiles,
|
||||
buildDependencyStorage};
|
||||
TaskScheduler systemTaskScheduler{pchCreatorManager,
|
||||
pchTaskQueue,
|
||||
pchCreationProgressCounter,
|
||||
|
@@ -71,6 +71,11 @@ public:
|
||||
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
|
||||
{
|
||||
WriteStatement &statement = insertOrUpdateFileStatusesStatement;
|
||||
@@ -144,6 +149,94 @@ public:
|
||||
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)
|
||||
{
|
||||
QJsonDocument document;
|
||||
@@ -255,6 +348,8 @@ public:
|
||||
"SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? AND sourceType IN (0, 1, "
|
||||
"3, 4) ORDER BY sourceId",
|
||||
database};
|
||||
mutable ReadStatement fetchSourcesStatement{
|
||||
"SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? ORDER BY sourceId", database};
|
||||
mutable ReadStatement fetchSourceDependenciesStatement{
|
||||
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION "
|
||||
"SELECT dependencySourceId FROM sourceDependencies, "
|
||||
@@ -279,5 +374,24 @@ public:
|
||||
database};
|
||||
WriteStatement deleteAllProjectPartsFilesWithProjectPartNameStatement{
|
||||
"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};
|
||||
};
|
||||
}
|
||||
|
@@ -57,6 +57,12 @@ public:
|
||||
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0;
|
||||
virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 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:
|
||||
~BuildDependenciesStorageInterface() = default;
|
||||
|
@@ -45,6 +45,8 @@
|
||||
#include <QProcess>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
namespace {
|
||||
@@ -110,11 +112,28 @@ Utils::SmallStringVector PchCreator::generateClangCompilerArguments(const PchTas
|
||||
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)
|
||||
{
|
||||
m_projectPartPch.projectPartId = pchTask.projectPartId();
|
||||
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())
|
||||
return;
|
||||
|
||||
@@ -166,23 +185,26 @@ void PchCreator::clear()
|
||||
{
|
||||
m_clangTool = ClangTool{};
|
||||
m_projectPartPch = {};
|
||||
m_sources.clear();
|
||||
m_watchedSystemIncludes.clear();
|
||||
m_watchedProjectIncludes.clear();
|
||||
m_watchedUserIncludes.clear();
|
||||
m_watchedSources.clear();
|
||||
}
|
||||
|
||||
void PchCreator::doInMainThreadAfterFinished()
|
||||
{
|
||||
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_projectPartPch.projectPartId);
|
||||
m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingSources}});
|
||||
m_pchManagerClient.precompiledHeadersUpdated({m_projectPartPch.projectPartId});
|
||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::Source},
|
||||
existingSources(m_watchedSources)}});
|
||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::UserInclude},
|
||||
existingSources(m_watchedUserIncludes)}});
|
||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::ProjectInclude},
|
||||
existingSources(m_watchedProjectIncludes)}});
|
||||
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::SystemInclude},
|
||||
existingSources(m_watchedSystemIncludes)}});
|
||||
m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -80,19 +80,24 @@ public:
|
||||
static Utils::SmallStringVector generateClangCompilerArguments(const PchTask &pchTask,
|
||||
FilePathView pchPath);
|
||||
|
||||
const ClangTool &clangTool() const
|
||||
{
|
||||
return m_clangTool;
|
||||
}
|
||||
const ClangTool &clangTool() const { 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:
|
||||
mutable std::mt19937_64 randomNumberGenator{std::random_device{}()};
|
||||
ClangTool m_clangTool;
|
||||
ProjectPartPch m_projectPartPch;
|
||||
FilePathCaching m_filePathCache;
|
||||
FilePathIds m_sources;
|
||||
FilePathIds m_watchedSystemIncludes;
|
||||
FilePathIds m_watchedProjectIncludes;
|
||||
FilePathIds m_watchedUserIncludes;
|
||||
FilePathIds m_watchedSources;
|
||||
FilePathIds m_generatedFilePathIds;
|
||||
Environment &m_environment;
|
||||
PchManagerClientInterface &m_pchManagerClient;
|
||||
|
@@ -25,10 +25,11 @@
|
||||
|
||||
#include "pchmanagerserver.h"
|
||||
|
||||
#include <builddependenciesstorage.h>
|
||||
#include <pchmanagerclientinterface.h>
|
||||
#include <pchtaskgeneratorinterface.h>
|
||||
#include <precompiledheadersupdatedmessage.h>
|
||||
#include <progressmessage.h>
|
||||
#include <pchtaskgeneratorinterface.h>
|
||||
#include <removegeneratedfilesmessage.h>
|
||||
#include <removeprojectpartsmessage.h>
|
||||
#include <updategeneratedfilesmessage.h>
|
||||
@@ -39,16 +40,20 @@
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
|
||||
PchTaskGeneratorInterface &pchTaskGenerator,
|
||||
ProjectPartsManagerInterface &projectParts,
|
||||
GeneratedFilesInterface &generatedFiles)
|
||||
GeneratedFilesInterface &generatedFiles,
|
||||
BuildDependenciesStorageInterface &buildDependenciesStorage)
|
||||
: m_fileSystemWatcher(fileSystemWatcher)
|
||||
, m_pchTaskGenerator(pchTaskGenerator)
|
||||
, m_projectPartsManager(projectParts)
|
||||
, m_generatedFiles(generatedFiles)
|
||||
, m_buildDependenciesStorage(buildDependenciesStorage)
|
||||
{
|
||||
m_fileSystemWatcher.setNotifier(this);
|
||||
}
|
||||
@@ -130,18 +135,74 @@ void PchManagerServer::removeGeneratedFiles(RemoveGeneratedFilesMessage &&messag
|
||||
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) {
|
||||
m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids),
|
||||
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)
|
||||
|
@@ -39,6 +39,7 @@ namespace ClangBackEnd {
|
||||
|
||||
class SourceRangesAndDiagnosticsForQueryMessage;
|
||||
class PchTaskGeneratorInterface;
|
||||
class BuildDependenciesStorageInterface;
|
||||
|
||||
class PchManagerServer : public PchManagerServerInterface,
|
||||
public ClangPathWatcherNotifier,
|
||||
@@ -49,7 +50,8 @@ public:
|
||||
PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
|
||||
PchTaskGeneratorInterface &pchTaskGenerator,
|
||||
ProjectPartsManagerInterface &projectParts,
|
||||
GeneratedFilesInterface &generatedFiles);
|
||||
GeneratedFilesInterface &generatedFiles,
|
||||
BuildDependenciesStorageInterface &buildDependenciesStorage);
|
||||
|
||||
void end() override;
|
||||
void updateProjectParts(UpdateProjectPartsMessage &&message) override;
|
||||
@@ -57,7 +59,7 @@ public:
|
||||
void updateGeneratedFiles(UpdateGeneratedFilesMessage &&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 setPchCreationProgress(int progress, int total);
|
||||
@@ -68,6 +70,7 @@ private:
|
||||
PchTaskGeneratorInterface &m_pchTaskGenerator;
|
||||
ProjectPartsManagerInterface &m_projectPartsManager;
|
||||
GeneratedFilesInterface &m_generatedFiles;
|
||||
BuildDependenciesStorageInterface &m_buildDependenciesStorage;
|
||||
ToolChainsArgumentsCache m_toolChainsArgumentsCache;
|
||||
};
|
||||
|
||||
|
@@ -42,7 +42,10 @@ class PchTask
|
||||
public:
|
||||
PchTask(ProjectPartId projectPartId,
|
||||
FilePathIds &&includes,
|
||||
FilePathIds &&sources,
|
||||
FilePathIds &&watchedSystemIncludes,
|
||||
FilePathIds &&watchedProjectIncludes,
|
||||
FilePathIds &&watchedUserIncludes,
|
||||
FilePathIds &&watchedUserSources,
|
||||
CompilerMacros &&compilerMacros,
|
||||
Utils::SmallStringVector &&usedMacros, // TODO remove
|
||||
Utils::SmallStringVector toolChainArguments,
|
||||
@@ -53,7 +56,10 @@ public:
|
||||
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None)
|
||||
: projectPartIds({projectPartId})
|
||||
, includes(includes)
|
||||
, sources(sources)
|
||||
, watchedSystemIncludes(watchedSystemIncludes)
|
||||
, watchedProjectIncludes(watchedProjectIncludes)
|
||||
, watchedUserIncludes(watchedUserIncludes)
|
||||
, watchedUserSources(watchedUserSources)
|
||||
, compilerMacros(compilerMacros)
|
||||
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
|
||||
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
|
||||
@@ -65,7 +71,10 @@ public:
|
||||
|
||||
PchTask(ProjectPartIds &&projectPartIds,
|
||||
FilePathIds &&includes,
|
||||
FilePathIds &&sources,
|
||||
FilePathIds &&watchedSystemIncludes,
|
||||
FilePathIds &&watchedProjectIncludes,
|
||||
FilePathIds &&watchedUserIncludes,
|
||||
FilePathIds &&watchedUserSources,
|
||||
CompilerMacros &&compilerMacros,
|
||||
Utils::SmallStringVector &&usedMacros, // TODO remove
|
||||
Utils::SmallStringVector toolChainArguments,
|
||||
@@ -76,7 +85,10 @@ public:
|
||||
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None)
|
||||
: projectPartIds(std::move(projectPartIds))
|
||||
, includes(includes)
|
||||
, sources(sources)
|
||||
, watchedSystemIncludes(watchedSystemIncludes)
|
||||
, watchedProjectIncludes(watchedProjectIncludes)
|
||||
, watchedUserIncludes(watchedUserIncludes)
|
||||
, watchedUserSources(watchedUserSources)
|
||||
, compilerMacros(compilerMacros)
|
||||
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
|
||||
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
|
||||
@@ -90,6 +102,10 @@ public:
|
||||
{
|
||||
return first.systemPchPath == second.systemPchPath
|
||||
&& 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.systemIncludeSearchPaths == second.systemIncludeSearchPaths
|
||||
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
|
||||
@@ -105,7 +121,10 @@ public:
|
||||
FilePath systemPchPath;
|
||||
ProjectPartIds projectPartIds;
|
||||
FilePathIds includes;
|
||||
FilePathIds sources;
|
||||
FilePathIds watchedSystemIncludes;
|
||||
FilePathIds watchedProjectIncludes;
|
||||
FilePathIds watchedUserIncludes;
|
||||
FilePathIds watchedUserSources;
|
||||
CompilerMacros compilerMacros;
|
||||
IncludeSearchPaths systemIncludeSearchPaths;
|
||||
IncludeSearchPaths projectIncludeSearchPaths;
|
||||
|
@@ -52,6 +52,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
|
||||
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId,
|
||||
std::move(filter.topSystemIncludes),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
std::move(filter.systemCompilerMacros),
|
||||
std::move(filter.systemUsedMacros),
|
||||
projectPart.toolChainArguments,
|
||||
@@ -62,6 +65,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
|
||||
projectPart.languageExtension},
|
||||
PchTask{projectPart.projectPartId,
|
||||
std::move(filter.topProjectIncludes),
|
||||
std::move(filter.systemIncludes),
|
||||
std::move(filter.projectIncludes),
|
||||
std::move(filter.userIncludes),
|
||||
std::move(filter.sources),
|
||||
std::move(filter.projectCompilerMacros),
|
||||
std::move(filter.projectUsedMacros),
|
||||
|
@@ -98,8 +98,8 @@ bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
|
||||
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
|
||||
std::move(secondTask.projectPartIds));
|
||||
firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes));
|
||||
firstTask.sources = merge(std::move(firstTask.sources),
|
||||
std::move(secondTask.sources));
|
||||
firstTask.watchedSystemIncludes = merge(std::move(firstTask.watchedSystemIncludes),
|
||||
std::move(secondTask.watchedSystemIncludes));
|
||||
firstTask.compilerMacros = std::move(macros);
|
||||
firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths(
|
||||
std::move(firstTask.systemIncludeSearchPaths),
|
||||
|
@@ -99,6 +99,7 @@ public:
|
||||
projectIncludes.reserve(sources.size());
|
||||
topSystemIncludes.reserve(sources.size() / 10);
|
||||
topProjectIncludes.reserve(sources.size() / 10);
|
||||
userIncludes.reserve(sources.size());
|
||||
this->sources.reserve(sources.size());
|
||||
|
||||
for (SourceEntry source : sources)
|
||||
@@ -128,23 +129,22 @@ private:
|
||||
case SourceType::TopSystemInclude:
|
||||
topSystemIncludes.emplace_back(source.sourceId);
|
||||
systemIncludes.emplace_back(source.sourceId);
|
||||
sources.emplace_back(source.sourceId);
|
||||
break;
|
||||
case SourceType::SystemInclude:
|
||||
systemIncludes.emplace_back(source.sourceId);
|
||||
sources.emplace_back(source.sourceId);
|
||||
break;
|
||||
case SourceType::TopProjectInclude:
|
||||
topProjectIncludes.emplace_back(source.sourceId);
|
||||
projectIncludes.emplace_back(source.sourceId);
|
||||
sources.emplace_back(source.sourceId);
|
||||
break;
|
||||
case SourceType::ProjectInclude:
|
||||
projectIncludes.emplace_back(source.sourceId);
|
||||
sources.emplace_back(source.sourceId);
|
||||
break;
|
||||
case SourceType::UserInclude:
|
||||
userIncludes.emplace_back(source.sourceId);
|
||||
break;
|
||||
case SourceType::Source:
|
||||
sources.emplace_back(source.sourceId);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -215,6 +215,7 @@ private:
|
||||
|
||||
public:
|
||||
FilePathIds sources;
|
||||
FilePathIds userIncludes;
|
||||
FilePathIds projectIncludes;
|
||||
FilePathIds systemIncludes;
|
||||
FilePathIds topProjectIncludes;
|
||||
|
@@ -98,7 +98,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
|
||||
std::vector<SymbolIndexerTask> symbolIndexerTask;
|
||||
symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
|
||||
for (FilePathId sourcePathId : projectPart.sourcePathIds) {
|
||||
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(
|
||||
SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
|
||||
sourcePathId);
|
||||
|
||||
if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
|
||||
@@ -122,7 +122,8 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
|
||||
|
||||
auto store = [&] {
|
||||
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
||||
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
|
||||
m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(
|
||||
symbolsCollector.fileStatuses());
|
||||
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
|
||||
symbolsCollector.sourceLocations());
|
||||
transaction.commit();
|
||||
@@ -144,28 +145,17 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
|
||||
}
|
||||
}
|
||||
|
||||
m_pathWatcher.updateIdPaths(
|
||||
{{projectPartId, m_buildDependencyStorage.fetchPchSources(projectPartId)}});
|
||||
m_pathWatcher.updateIdPaths({{{projectPartId, SourceType::Source},
|
||||
m_buildDependencyStorage.fetchPchSources(projectPartId)}});
|
||||
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
|
||||
m_symbolIndexerTaskQueue.processEntries();
|
||||
}
|
||||
|
||||
void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {}
|
||||
void SymbolIndexer::pathsWithIdsChanged(const std::vector<IdPaths> &) {}
|
||||
|
||||
void SymbolIndexer::pathsChanged(const FilePathIds &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,
|
||||
@@ -182,7 +172,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
|
||||
|
||||
ProjectPartId projectPartId = optionalArtefact->projectPartId;
|
||||
|
||||
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId);
|
||||
SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
|
||||
filePathId);
|
||||
|
||||
auto indexing = [optionalArtefact = std::move(optionalArtefact),
|
||||
filePathId,
|
||||
@@ -207,7 +198,7 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
|
||||
|
||||
auto store = [&] {
|
||||
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
||||
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
|
||||
m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
|
||||
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
|
||||
symbolsCollector.sourceLocations());
|
||||
transaction.commit();
|
||||
|
@@ -60,7 +60,7 @@ public:
|
||||
void updateProjectParts(ProjectPartContainers &&projectParts);
|
||||
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 updateChangedPath(FilePathId filePath,
|
||||
std::vector<SymbolIndexerTask> &symbolIndexerTask);
|
||||
@@ -75,6 +75,9 @@ public:
|
||||
FilePathIds updatableFilePathIds(const ProjectPartContainer &projectPart,
|
||||
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const;
|
||||
|
||||
private:
|
||||
FilePathIds filterProjectPartSources(const FilePathIds &filePathIds) const;
|
||||
|
||||
private:
|
||||
SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue;
|
||||
SymbolStorageInterface &m_symbolStorage;
|
||||
|
@@ -70,93 +70,6 @@ public:
|
||||
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)
|
||||
{
|
||||
WriteStatement &statement = insertSymbolsToNewSymbolsStatement;
|
||||
@@ -278,25 +191,6 @@ public:
|
||||
database};
|
||||
WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", 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
|
||||
|
@@ -48,11 +48,6 @@ public:
|
||||
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
|
||||
const SourceLocationEntries &sourceLocations)
|
||||
= 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:
|
||||
~SymbolStorageInterface() = default;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
#include "mockfilepathcaching.h"
|
||||
#include "mocksqlitedatabase.h"
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
#include <builddependenciesstorage.h>
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <sqlitedatabase.h>
|
||||
#include <sqlitereadstatement.h>
|
||||
#include <sqlitewritestatement.h>
|
||||
|
||||
#include <utils/optional.h>
|
||||
|
||||
@@ -70,7 +73,12 @@ protected:
|
||||
MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement;
|
||||
MockSqliteWriteStatement &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)
|
||||
@@ -233,13 +241,163 @@ TEST_F(BuildDependenciesStorage, FetchUsedMacros)
|
||||
ASSERT_THAT(usedMacros, result);
|
||||
}
|
||||
|
||||
TEST_F(BuildDependenciesStorage, FetchSources)
|
||||
TEST_F(BuildDependenciesStorage, FetchPchSources)
|
||||
{
|
||||
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);
|
||||
|
||||
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
|
||||
|
@@ -48,8 +48,11 @@ using ClangBackEnd::FilePath;
|
||||
using ClangBackEnd::FilePathId;
|
||||
using ClangBackEnd::FilePathIds;
|
||||
using ClangBackEnd::FilePathView;
|
||||
using ClangBackEnd::IdPaths;
|
||||
using ClangBackEnd::ProjectChunkId;
|
||||
using ClangBackEnd::ProjectPartId;
|
||||
using ClangBackEnd::ProjectPartIds;
|
||||
using ClangBackEnd::SourceType;
|
||||
using ClangBackEnd::WatcherEntries;
|
||||
using ClangBackEnd::WatcherEntry;
|
||||
|
||||
@@ -111,9 +114,9 @@ protected:
|
||||
NiceMock<MockFileSystem> mockFileSystem;
|
||||
Watcher watcher{mockFilePathCache, mockFileSystem, ¬ifier};
|
||||
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
|
||||
ProjectPartId id1{2};
|
||||
ProjectPartId id2{3};
|
||||
ProjectPartId id3{4};
|
||||
ProjectChunkId id1{2, SourceType::ProjectInclude};
|
||||
ProjectChunkId id2{2, SourceType::Source};
|
||||
ProjectChunkId id3{4, SourceType::SystemInclude};
|
||||
FilePathView path1{"/path/path1"};
|
||||
FilePathView path2{"/path/path2"};
|
||||
FilePathView path3{"/path2/path1"};
|
||||
@@ -128,14 +131,15 @@ protected:
|
||||
Utils::PathString directoryPathString2 = directoryPath2;
|
||||
FilePathIds pathIds = {1, 2, 3, 4, 5};
|
||||
ClangBackEnd::DirectoryPathIds directoryPaths = {1, 2, 3};
|
||||
ClangBackEnd::ProjectPartIds ids{id1, id2, id3};
|
||||
WatcherEntry watcherEntry1{ids[0], directoryPaths[0], pathIds[0]};
|
||||
WatcherEntry watcherEntry2{ids[1], directoryPaths[0], pathIds[0]};
|
||||
WatcherEntry watcherEntry3{ids[0], directoryPaths[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry4{ids[1], directoryPaths[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry5{ids[2], directoryPaths[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry6{ids[0], directoryPaths[1], pathIds[2]};
|
||||
WatcherEntry watcherEntry7{ids[1], directoryPaths[1], pathIds[3]};
|
||||
ClangBackEnd::ProjectChunkIds ids{id1, id2, id3};
|
||||
WatcherEntry watcherEntry1{id1, directoryPaths[0], pathIds[0]};
|
||||
WatcherEntry watcherEntry2{id2, directoryPaths[0], pathIds[0]};
|
||||
WatcherEntry watcherEntry3{id1, directoryPaths[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry4{id2, directoryPaths[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry5{id3, directoryPaths[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry6{id1, directoryPaths[1], pathIds[2]};
|
||||
WatcherEntry watcherEntry7{id2, directoryPaths[1], pathIds[3]};
|
||||
WatcherEntry watcherEntry8{id3, directoryPaths[1], pathIds[3]};
|
||||
};
|
||||
|
||||
TEST_F(ClangPathWatcher, AddIdPaths)
|
||||
@@ -260,12 +264,13 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
|
||||
|
||||
TEST_F(ClangPathWatcher, RemoveEntriesWithId)
|
||||
{
|
||||
watcher.updateIdPaths(
|
||||
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}});
|
||||
watcher.updateIdPaths({{id1, {pathIds[0], 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)
|
||||
@@ -284,28 +289,28 @@ TEST_F(ClangPathWatcher, RemoveNoPathsForOneId)
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_))
|
||||
.Times(0);
|
||||
|
||||
watcher.removeIds({id3});
|
||||
watcher.removeIds({id3.id});
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, RemovePathForOneId)
|
||||
{
|
||||
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)));
|
||||
|
||||
watcher.removeIds({id2});
|
||||
watcher.removeIds({id3.id});
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, RemoveNoPathSecondTime)
|
||||
{
|
||||
watcher.updateIdPaths(
|
||||
{{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);
|
||||
|
||||
watcher.removeIds({id2});
|
||||
watcher.removeIds({id2.id});
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
|
||||
@@ -315,7 +320,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
|
||||
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath, directoryPath2)));
|
||||
|
||||
watcher.removeIds({id1, id2, id3});
|
||||
watcher.removeIds({id1.id, id2.id, id3.id});
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
|
||||
@@ -325,7 +330,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
|
||||
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath)));
|
||||
|
||||
watcher.removeIds({id1, id2});
|
||||
watcher.removeIds({id1.id, id2.id});
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId)
|
||||
@@ -349,13 +354,14 @@ TEST_F(ClangPathWatcher, RemoveUnusedEntries)
|
||||
TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
|
||||
{
|
||||
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]}}});
|
||||
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[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(directoryPath2);
|
||||
|
@@ -52,8 +52,8 @@ public:
|
||||
CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; }
|
||||
|
||||
public:
|
||||
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}};
|
||||
ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}};
|
||||
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
|
||||
ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@@ -359,9 +359,8 @@ std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry)
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry)
|
||||
{
|
||||
out << "("
|
||||
<< entry.id << ", "
|
||||
<< entry.filePathId
|
||||
out << "(" << entry.directoryPathId << ", " << entry.filePathId << ", " << entry.id << ", "
|
||||
<< entry.lastModified << ", "
|
||||
<< ")";
|
||||
|
||||
return out;
|
||||
@@ -1290,6 +1289,17 @@ std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths)
|
||||
{
|
||||
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)
|
||||
{
|
||||
*os << filePath;
|
||||
|
@@ -200,6 +200,8 @@ struct ArgumentsEntry;
|
||||
class ProjectPartContainer;
|
||||
class ProjectPartId;
|
||||
class PchPaths;
|
||||
class ProjectChunkId;
|
||||
class DirectoryPathId;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
|
||||
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 ProjectPartId &projectPathId);
|
||||
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 FilePathView &filePathView, ::std::ostream *os);
|
||||
|
@@ -53,5 +53,16 @@ public:
|
||||
void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId));
|
||||
MOCK_CONST_METHOD1(fetchPchSources,
|
||||
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));
|
||||
};
|
||||
|
||||
|
@@ -32,7 +32,7 @@
|
||||
class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD1(pathsWithIdsChanged, void(const ClangBackEnd::ProjectPartIds &ids));
|
||||
MOCK_METHOD1(pathsWithIdsChanged, void(const std::vector<ClangBackEnd::IdPaths> &idPaths));
|
||||
|
||||
MOCK_METHOD1(pathsChanged,
|
||||
void (const ClangBackEnd::FilePathIds &filePathIds));
|
||||
|
@@ -37,11 +37,4 @@ public:
|
||||
MOCK_METHOD2(addSymbolsAndSourceLocations,
|
||||
void(const ClangBackEnd::SymbolEntries &symbolEentries,
|
||||
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));
|
||||
};
|
||||
|
@@ -34,12 +34,13 @@
|
||||
#include "mockpchmanagerclient.h"
|
||||
#include "testenvironment.h"
|
||||
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <generatedfiles.h>
|
||||
#include <pchcreator.h>
|
||||
#include <precompiledheadersupdatedmessage.h>
|
||||
#include <progressmessage.h>
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <updateprojectpartsmessage.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
@@ -55,12 +56,14 @@ using ClangBackEnd::GeneratedFiles;
|
||||
using ClangBackEnd::IdPaths;
|
||||
using ClangBackEnd::IncludeSearchPathType;
|
||||
using ClangBackEnd::PchTask;
|
||||
using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
|
||||
using ClangBackEnd::ProjectChunkId;
|
||||
using ClangBackEnd::ProjectPartContainer;
|
||||
using ClangBackEnd::ProjectPartPch;
|
||||
using ClangBackEnd::SourceEntries;
|
||||
using ClangBackEnd::SourceEntry;
|
||||
using ClangBackEnd::SourceType;
|
||||
using ClangBackEnd::V2::FileContainer;
|
||||
using ClangBackEnd::ProjectPartContainer;
|
||||
|
||||
using Utils::PathString;
|
||||
using Utils::SmallString;
|
||||
@@ -91,6 +94,13 @@ protected:
|
||||
return creator.filePathCache().filePathId(path);
|
||||
}
|
||||
|
||||
FilePathIds sorted(FilePathIds &&filePathIds)
|
||||
{
|
||||
std::sort(filePathIds.begin(), filePathIds.end());
|
||||
|
||||
return std::move(filePathIds);
|
||||
}
|
||||
|
||||
protected:
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
@@ -111,14 +121,19 @@ protected:
|
||||
mockBuildDependenciesStorage};
|
||||
PchTask pchTask1{
|
||||
1,
|
||||
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
|
||||
{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/external2.h")}),
|
||||
sorted({id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/system/system2.h"),
|
||||
id(generatedFilePath)}),
|
||||
sorted({id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(generatedFilePath),
|
||||
id(main2Path)},
|
||||
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));
|
||||
|
||||
EXPECT_CALL(mockClangPathWatcher,
|
||||
updateIdPaths(ElementsAre(
|
||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(id(main2Path)))))));
|
||||
|
||||
EXPECT_CALL(mockClangPathWatcher,
|
||||
updateIdPaths(ElementsAre(AllOf(
|
||||
Field(&ClangBackEnd::IdPaths::id, 1),
|
||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
|
||||
EXPECT_CALL(
|
||||
mockClangPathWatcher,
|
||||
updateIdPaths(ElementsAre(
|
||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
|
||||
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();
|
||||
}
|
||||
@@ -232,15 +266,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterFail)
|
||||
pchTask1.projectIncludeSearchPaths = {};
|
||||
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,
|
||||
updateIdPaths(ElementsAre(AllOf(
|
||||
Field(&ClangBackEnd::IdPaths::id, 1),
|
||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
|
||||
EXPECT_CALL(
|
||||
mockClangPathWatcher,
|
||||
updateIdPaths(ElementsAre(
|
||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
|
||||
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();
|
||||
}
|
||||
@@ -282,15 +335,40 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
|
||||
ASSERT_FALSE(creator.projectPartPch().isValid());
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorVerySlowTest, SourcesCleared)
|
||||
TEST_F(PchCreatorVerySlowTest, WatchedSystemIncludesCleared)
|
||||
{
|
||||
creator.generatePch(std::move(pchTask1));
|
||||
|
||||
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)
|
||||
{
|
||||
creator.generatePch(std::move(pchTask1));
|
||||
@@ -306,6 +384,9 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask
|
||||
0,
|
||||
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{"DEFINE", "1", 1}},
|
||||
{},
|
||||
{},
|
||||
@@ -336,20 +417,37 @@ TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls)
|
||||
{
|
||||
pchTask1.includes = {};
|
||||
creator.generatePch(std::move(pchTask1));
|
||||
|
||||
EXPECT_CALL(mockPchManagerClient,
|
||||
precompiledHeadersUpdated(
|
||||
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
|
||||
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,
|
||||
updateIdPaths(ElementsAre(AllOf(
|
||||
Field(&ClangBackEnd::IdPaths::id, 1),
|
||||
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
|
||||
EXPECT_CALL(
|
||||
mockClangPathWatcher,
|
||||
updateIdPaths(ElementsAre(
|
||||
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
|
||||
Field(&ClangBackEnd::IdPaths::filePathIds,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
|
||||
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)));
|
||||
|
||||
creator.doInMainThreadAfterFinished();
|
||||
|
@@ -25,11 +25,12 @@
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include "mockbuilddependenciesstorage.h"
|
||||
#include "mockclangpathwatcher.h"
|
||||
#include "mockgeneratedfiles.h"
|
||||
#include "mockpchmanagerclient.h"
|
||||
#include "mockpchtaskgenerator.h"
|
||||
#include "mockprojectpartsmanager.h"
|
||||
#include "mockgeneratedfiles.h"
|
||||
|
||||
#include <filepathcaching.h>
|
||||
#include <pchmanagerserver.h>
|
||||
@@ -42,12 +43,13 @@
|
||||
#include <updateprojectpartsmessage.h>
|
||||
|
||||
namespace {
|
||||
using Utils::PathString;
|
||||
using Utils::SmallString;
|
||||
using ClangBackEnd::V2::FileContainer;
|
||||
using ClangBackEnd::V2::FileContainers;
|
||||
using ClangBackEnd::FilePathId;
|
||||
using ClangBackEnd::ProjectPartContainer;
|
||||
using ClangBackEnd::ProjectPartContainers;
|
||||
using ClangBackEnd::V2::FileContainer;
|
||||
using ClangBackEnd::V2::FileContainers;
|
||||
using Utils::PathString;
|
||||
using Utils::SmallString;
|
||||
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
|
||||
|
||||
class PchManagerServer : public ::testing::Test
|
||||
@@ -71,21 +73,27 @@ protected:
|
||||
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
|
||||
NiceMock<MockProjectPartsManager> mockProjectPartsManager;
|
||||
NiceMock<MockGeneratedFiles> mockGeneratedFiles;
|
||||
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
||||
ClangBackEnd::FilePathCaching filePathCache{database};
|
||||
ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
|
||||
mockPchTaskGenerator,
|
||||
mockProjectPartsManager,
|
||||
mockGeneratedFiles};
|
||||
mockGeneratedFiles,
|
||||
mockBuildDependenciesStorage};
|
||||
NiceMock<MockPchManagerClient> mockPchManagerClient;
|
||||
ClangBackEnd::ProjectPartId projectPartId1{1};
|
||||
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 main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp";
|
||||
PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.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{
|
||||
projectPartId1,
|
||||
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
|
||||
@@ -108,6 +116,50 @@ protected:
|
||||
Utils::Language::C,
|
||||
Utils::LanguageVersion::C11,
|
||||
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> projectParts1{projectPart1};
|
||||
std::vector<ProjectPartContainer> projectParts2{projectPart2};
|
||||
@@ -169,19 +221,68 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
|
||||
ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
|
||||
mockPchTaskGenerator,
|
||||
mockProjectPartsManager,
|
||||
mockGeneratedFiles};
|
||||
mockGeneratedFiles,
|
||||
mockBuildDependenciesStorage};
|
||||
}
|
||||
|
||||
TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds)
|
||||
{
|
||||
server.updateProjectParts(
|
||||
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
|
||||
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{
|
||||
{projectPart1, projectPart2, projectPart3, projectPart4, projectPart5, projectPart6},
|
||||
{"toolChainArgument"}});
|
||||
|
||||
EXPECT_CALL(mockProjectPartsManager, projects(ElementsAre(projectPart1.projectPartId)))
|
||||
.WillOnce(Return(std::vector<ClangBackEnd::ProjectPartContainer>{{projectPart1}}));
|
||||
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(ElementsAre(projectPart1), ElementsAre("toolChainArgument")));
|
||||
EXPECT_CALL(mockProjectPartsManager,
|
||||
projects(ElementsAre(projectPart1.projectPartId,
|
||||
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)
|
||||
@@ -214,7 +315,7 @@ TEST_F(PchManagerServer, RemoveToolChainsArguments)
|
||||
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
|
||||
server.removeProjectParts(removeProjectPartsMessage.clone());
|
||||
|
||||
server.pathsWithIdsChanged({projectPart1.projectPartId});
|
||||
server.pathsWithIdsChanged({{{projectPart1.projectPartId, ClangBackEnd::SourceType::Source}, {}}});
|
||||
}
|
||||
|
||||
TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid)
|
||||
|
@@ -84,7 +84,8 @@ protected:
|
||||
{2, SourceType::UserInclude, 1},
|
||||
{3, SourceType::TopProjectInclude, 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}};
|
||||
BuildDependency buildDependency{firstSources, usedMacros, {}, {}, {}};
|
||||
};
|
||||
@@ -100,7 +101,10 @@ TEST_F(PchTaskGenerator, AddProjectParts)
|
||||
Field(&PchTaskSet::system,
|
||||
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
|
||||
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,
|
||||
ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})),
|
||||
Field(&PchTask::systemIncludeSearchPaths,
|
||||
@@ -117,7 +121,10 @@ TEST_F(PchTaskGenerator, AddProjectParts)
|
||||
&PchTaskSet::project,
|
||||
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
|
||||
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,
|
||||
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
|
||||
Field(&PchTask::systemIncludeSearchPaths,
|
||||
|
@@ -67,6 +67,9 @@ protected:
|
||||
PchTask systemTask1{1,
|
||||
{1, 2},
|
||||
{1, 2},
|
||||
{2, 3},
|
||||
{3, 4},
|
||||
{6, 7},
|
||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||
{{"LIANG", 0}, {"YI", 1}},
|
||||
{"--yi"},
|
||||
@@ -75,6 +78,9 @@ protected:
|
||||
PchTask systemTask2{2,
|
||||
{1, 2},
|
||||
{1, 2},
|
||||
{2, 3},
|
||||
{3, 4},
|
||||
{6, 7},
|
||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||
{{"LIANG", 0}, {"YI", 1}},
|
||||
{"--yi"},
|
||||
@@ -83,6 +89,9 @@ protected:
|
||||
PchTask systemTask2b{2,
|
||||
{3, 4},
|
||||
{3, 4},
|
||||
{5, 6},
|
||||
{4, 7},
|
||||
{8, 9},
|
||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||
{{"LIANG", 0}, {"YI", 1}},
|
||||
{"--yi"},
|
||||
@@ -91,6 +100,9 @@ protected:
|
||||
PchTask systemTask3{3,
|
||||
{1, 2},
|
||||
{1, 2},
|
||||
{2, 3},
|
||||
{3, 4},
|
||||
{6, 7},
|
||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||
{{"LIANG", 0}, {"YI", 1}},
|
||||
{"--yi"},
|
||||
@@ -99,6 +111,9 @@ protected:
|
||||
PchTask projectTask1{1,
|
||||
{11, 12},
|
||||
{11, 12},
|
||||
{12, 13},
|
||||
{13, 14},
|
||||
{16, 17},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{{"ER", 2}, {"SAN", 3}},
|
||||
{"--yi"},
|
||||
@@ -107,6 +122,9 @@ protected:
|
||||
PchTask projectTask2{2,
|
||||
{11, 12},
|
||||
{11, 12},
|
||||
{12, 13},
|
||||
{13, 14},
|
||||
{16, 17},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{{"ER", 2}, {"SAN", 3}},
|
||||
{"--yi"},
|
||||
@@ -115,6 +133,9 @@ protected:
|
||||
PchTask projectTask2b{2,
|
||||
{21, 22},
|
||||
{11, 12},
|
||||
{22, 23},
|
||||
{23, 24},
|
||||
{26, 27},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{{"ER", 2}, {"SAN", 3}},
|
||||
{"--yi"},
|
||||
@@ -123,6 +144,9 @@ protected:
|
||||
PchTask projectTask3{3,
|
||||
{21, 22},
|
||||
{21, 22},
|
||||
{22, 23},
|
||||
{23, 24},
|
||||
{26, 27},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{{"ER", 2}, {"SAN", 3}},
|
||||
{"--yi"},
|
||||
@@ -131,6 +155,9 @@ protected:
|
||||
PchTask systemTask4{{1, 3},
|
||||
{1, 2},
|
||||
{1, 2},
|
||||
{2, 3},
|
||||
{3, 4},
|
||||
{5, 8},
|
||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||
{{"LIANG", 0}, {"YI", 1}},
|
||||
{"--yi"},
|
||||
|
@@ -54,7 +54,10 @@ protected:
|
||||
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
|
||||
PchTask systemTask1{1,
|
||||
{1, 2},
|
||||
{1, 2, 3},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||
{"YI", "LIANG"},
|
||||
{"--yi"},
|
||||
@@ -66,6 +69,9 @@ protected:
|
||||
PchTask projectTask1{1,
|
||||
{11, 12},
|
||||
{11, 12},
|
||||
{21, 22},
|
||||
{31, 32},
|
||||
{41, 42},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{"ER", "SAN"},
|
||||
{"--yi"},
|
||||
@@ -75,7 +81,10 @@ protected:
|
||||
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||
PchTask systemTask2{2,
|
||||
{11, 12},
|
||||
{11, 12, 13},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{"ER", "SAN"},
|
||||
{"--yi"},
|
||||
@@ -87,6 +96,9 @@ protected:
|
||||
PchTask projectTask2{2,
|
||||
{11, 12},
|
||||
{11, 12},
|
||||
{21, 22},
|
||||
{31, 32},
|
||||
{41, 42},
|
||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||
{"ER", "SAN"},
|
||||
{"--yi"},
|
||||
@@ -97,7 +109,10 @@ protected:
|
||||
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||
PchTask systemTask3{3,
|
||||
{1, 2},
|
||||
{1, 2},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{{"YI", "2", 1}, {"SAN", "3", 3}},
|
||||
{"YI", "LIANG"},
|
||||
{"--yi"},
|
||||
@@ -268,18 +283,25 @@ TEST_F(PchTasksMerger, DontMergeIncludes)
|
||||
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
|
||||
}
|
||||
|
||||
TEST_F(PchTasksMerger, MergeAllIncludes)
|
||||
TEST_F(PchTasksMerger, DontMergeWatchedSystemSources)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
|
@@ -463,7 +463,6 @@ protected:
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
Storage storage{database};
|
||||
ClangBackEnd::SymbolStorage<> symbolStorage{database};
|
||||
ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
|
||||
};
|
||||
|
||||
@@ -505,13 +504,13 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
|
||||
|
||||
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(
|
||||
{{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}});
|
||||
|
||||
storage.resetIndexingTimeStamps({projectPart1, projectPart2});
|
||||
|
||||
ASSERT_THAT(symbolStorage.fetchIndexingTimeStamps(),
|
||||
ASSERT_THAT(buildDependenciesStorage.fetchIndexingTimeStamps(),
|
||||
ElementsAre(SourceTimeStamp{1, 0},
|
||||
SourceTimeStamp{2, 0},
|
||||
SourceTimeStamp{3, 0},
|
||||
|
@@ -116,11 +116,11 @@ protected:
|
||||
.WillByDefault(Return(artefact));
|
||||
ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1));
|
||||
ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true));
|
||||
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
|
||||
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(sourceFileIds))
|
||||
.WillByDefault(Return(sourceFileIds));
|
||||
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
|
||||
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
|
||||
.WillByDefault(Return(FilePathIds{sourceFileIds[0]}));
|
||||
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
|
||||
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
|
||||
.WillByDefault(Return(FilePathIds{main1PathId}));
|
||||
mockCollector.setIsUsed(false);
|
||||
|
||||
@@ -879,16 +879,16 @@ TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps)
|
||||
Utils::LanguageVersion::CXX14,
|
||||
Utils::LanguageExtension::None};
|
||||
|
||||
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
|
||||
EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
|
||||
.WillOnce(Return(dependentSourceTimeStamps1));
|
||||
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1));
|
||||
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
|
||||
EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
|
||||
.WillOnce(Return(dependentSourceTimeStamps2));
|
||||
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2));
|
||||
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(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
|
||||
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
|
||||
|
||||
indexer.updateProjectParts({projectPart});
|
||||
}
|
||||
@@ -917,642 +917,6 @@ TEST_F(SymbolIndexer, DependentSourceAreUpToDate)
|
||||
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)
|
||||
{
|
||||
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(A<ProjectPartId>()))
|
||||
@@ -1660,7 +1024,8 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache)
|
||||
{
|
||||
auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp");
|
||||
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});
|
||||
|
||||
|
@@ -69,10 +69,6 @@ protected:
|
||||
MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement;
|
||||
MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement;
|
||||
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}},
|
||||
{2, {"function2USR", "function2", SymbolKind::Function}}};
|
||||
SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration},
|
||||
@@ -192,145 +188,4 @@ TEST_F(SymbolStorage, AddTablesInConstructor)
|
||||
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
|
||||
|
@@ -97,8 +97,14 @@ TEST_F(UsedMacroFilter, Sources)
|
||||
{
|
||||
ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros);
|
||||
|
||||
ASSERT_THAT(filter.sources,
|
||||
ElementsAre(FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5}));
|
||||
ASSERT_THAT(filter.sources, ElementsAre(FilePathId{6}));
|
||||
}
|
||||
|
||||
TEST_F(UsedMacroFilter, UserIncludes)
|
||||
{
|
||||
ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros);
|
||||
|
||||
ASSERT_THAT(filter.userIncludes, ElementsAre(FilePathId{1}));
|
||||
}
|
||||
|
||||
TEST_F(UsedMacroFilter, SystemUsedMacros)
|
||||
|
Reference in New Issue
Block a user