Clang: Minimize reindexing

We optimal indexer is only reindexing if the index would be changed. This
patch is a step in that direction. We only reindex now if the file or
project has changed. It fixes some typos too.

Task-number: QTCREATORBUG-21150
Change-Id: I6ea1c13282fbcd70253b9b2939aed37580dbd160
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2019-03-21 17:55:24 +01:00
parent 7595c9f305
commit 56b01f7463
37 changed files with 736 additions and 120 deletions

View File

@@ -213,6 +213,9 @@ HEADERS += \
$$PWD/includesearchpath.h \ $$PWD/includesearchpath.h \
$$PWD/commandlinebuilder.h \ $$PWD/commandlinebuilder.h \
$$PWD/projectpartartefact.h \ $$PWD/projectpartartefact.h \
$$PWD/projectpartcontainer.h $$PWD/projectpartcontainer.h \
$$PWD/sourceentry.h \
$$PWD/modifiedtimecheckerinterface.h \
$$PWD/modifiedtimechecker.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -25,17 +25,18 @@
#pragma once #pragma once
#include "filepathcachinginterface.h"
#include "modifiedtimecheckerinterface.h" #include "modifiedtimecheckerinterface.h"
#include <filepathcachinginterface.h>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
namespace ClangBackEnd { namespace ClangBackEnd {
template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries>
{ {
using SourceEntry = typename SourceEntries::value_type;
public: public:
using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>; using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>;
ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache) ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache)
@@ -67,7 +68,7 @@ public:
std::back_inserter(timeStampsToUpdate)); std::back_inserter(timeStampsToUpdate));
for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) { for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) {
sourceTimeStamp.lastModified = m_getModifiedTime( sourceTimeStamp.timeStamp = m_getModifiedTime(
m_filePathCache.filePath(sourceTimeStamp.sourceId)); m_filePathCache.filePath(sourceTimeStamp.sourceId));
} }
} }
@@ -78,21 +79,22 @@ private:
class CompareSourceId class CompareSourceId
{ {
public: public:
bool operator()(SourceTimeStamp first, SourceTimeStamp second) { bool operator()(SourceTimeStamp first, SourceTimeStamp second)
return first.sourceId < second.sourceId;
}
bool operator()(SourceEntry first, SourceEntry second)
{ {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }
bool operator()(SourceTimeStamp first, SourceEntry second) bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
{ {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }
bool operator()(SourceEntry first, SourceTimeStamp second) bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
{
return first.sourceId < second.sourceId;
}
bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
{ {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }
@@ -112,23 +114,22 @@ private:
public: public:
bool operator()(SourceTimeStamp first, SourceTimeStamp second) bool operator()(SourceTimeStamp first, SourceTimeStamp second)
{ {
return first.lastModified <= second.lastModified; return first.timeStamp <= second.timeStamp;
} }
bool operator()(SourceEntry first, SourceEntry second) bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
{ {
return first.pchCreationTimeStamp <= return first.timeStamp <= second.timeStamp;
second.pchCreationTimeStamp;
} }
bool operator()(SourceTimeStamp first, SourceEntry second) bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
{ {
return first.lastModified <= second.pchCreationTimeStamp; return first.timeStamp <= second.timeStamp;
} }
bool operator()(SourceEntry first, SourceTimeStamp second) bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
{ {
return first.pchCreationTimeStamp <= second.lastModified; return first.timeStamp <= second.timeStamp;
} }
}; };
@@ -144,7 +145,7 @@ private:
SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries); SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries);
for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) { for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) {
newSourceTimeStamp.lastModified = m_getModifiedTime( newSourceTimeStamp.timeStamp = m_getModifiedTime(
m_filePathCache.filePath(newSourceTimeStamp.sourceId)); m_filePathCache.filePath(newSourceTimeStamp.sourceId));
} }
@@ -169,17 +170,17 @@ private:
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }
bool operator()(SourceEntry first, SourceEntry second) bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
{ {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }
bool operator()(SourceTimeStamp first, SourceEntry second) bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
{ {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }
bool operator()(SourceEntry first, SourceTimeStamp second) bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
{ {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
} }

View File

@@ -29,6 +29,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
class ModifiedTimeCheckerInterface class ModifiedTimeCheckerInterface
{ {
public: public:

View File

@@ -245,6 +245,22 @@ public:
return statement.template value<ProjectPartArtefact, 8>(projectPartId.projectPathId); return statement.template value<ProjectPartArtefact, 8>(projectPartId.projectPathId);
} }
void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (const ProjectPartContainer &projectPart : projectsParts) {
for (FilePathId sourcePathId : projectPart.sourcePathIds)
resetDependentIndexingTimeStampsStatement.write(sourcePathId.filePathId);
}
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
resetIndexingTimeStamps(projectsParts);
}
}
Sqlite::TransactionInterface &transactionBackend() override { return database; } Sqlite::TransactionInterface &transactionBackend() override { return database; }
static Utils::SmallString toJson(const Utils::SmallStringVector &strings) static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
@@ -343,5 +359,11 @@ public:
"SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database}; "SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database};
mutable ReadStatement fetchProjectPrecompiledHeaderPathStatement{ mutable ReadStatement fetchProjectPrecompiledHeaderPathStatement{
"SELECT projectPchPath FROM precompiledHeaders WHERE projectPartId = ?", database}; "SELECT projectPchPath FROM precompiledHeaders WHERE projectPartId = ?", database};
WriteStatement resetDependentIndexingTimeStampsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.sourceId == collectedDependencies.sourceId) UPDATE fileStatuses SET "
"indexingTimeStamp = NULL WHERE sourceId IN (SELECT sourceId FROM collectedDependencies)",
database};
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -63,6 +63,7 @@ public:
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0; virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact( virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(
ProjectPartId projectPartId) const = 0; ProjectPartId projectPartId) const = 0;
virtual void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) = 0;
virtual Sqlite::TransactionInterface &transactionBackend() = 0; virtual Sqlite::TransactionInterface &transactionBackend() = 0;

View File

@@ -177,6 +177,7 @@ public:
Sqlite::Contraint::PrimaryKey); Sqlite::Contraint::PrimaryKey);
table.addColumn("size", Sqlite::ColumnType::Integer); table.addColumn("size", Sqlite::ColumnType::Integer);
table.addColumn("lastModified", Sqlite::ColumnType::Integer); table.addColumn("lastModified", Sqlite::ColumnType::Integer);
table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer);
table.initialize(database); table.initialize(database);
} }
@@ -188,6 +189,7 @@ public:
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
const Sqlite::Column &dependencySourceIdColumn = table.addColumn("dependencySourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &dependencySourceIdColumn = table.addColumn("dependencySourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn, dependencySourceIdColumn}); table.addIndex({sourceIdColumn, dependencySourceIdColumn});
table.addIndex({dependencySourceIdColumn, sourceIdColumn});
table.initialize(database); table.initialize(database);
} }

View File

@@ -64,12 +64,12 @@ class SourceTimeStamp
using int64 = long long; using int64 = long long;
public: public:
SourceTimeStamp(int sourceId, int64 lastModified) SourceTimeStamp(int sourceId, int64 lastModified)
: lastModified(lastModified) : timeStamp(lastModified)
, sourceId(sourceId) , sourceId(sourceId)
{} {}
SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified) SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified)
: lastModified(lastModified) : timeStamp(lastModified)
, sourceId(sourceId) , sourceId(sourceId)
{} {}
@@ -90,7 +90,7 @@ public:
friend bool operator==(SourceTimeStamp first, SourceTimeStamp second) friend bool operator==(SourceTimeStamp first, SourceTimeStamp second)
{ {
return first.sourceId == second.sourceId && first.lastModified == second.lastModified; return first.sourceId == second.sourceId && first.timeStamp == second.timeStamp;
} }
friend bool operator!=(SourceTimeStamp first, SourceTimeStamp second) friend bool operator!=(SourceTimeStamp first, SourceTimeStamp second)
@@ -99,7 +99,7 @@ public:
} }
public: public:
TimeStamp lastModified; TimeStamp timeStamp;
FilePathId sourceId; FilePathId sourceId;
}; };
@@ -110,21 +110,22 @@ class SourceEntry
using int64 = long long; using int64 = long long;
public: public:
SourceEntry(int sourceId, SourceEntry(int sourceId, int64 timeStamp, int sourceType, int hasMissingIncludes)
int64 pchCreationTimeStamp, : timeStamp(timeStamp)
int sourceType, , sourceId(sourceId)
int hasMissingIncludes) , sourceType(static_cast<SourceType>(sourceType))
: pchCreationTimeStamp(pchCreationTimeStamp), sourceId(sourceId), , hasMissingIncludes(static_cast<HasMissingIncludes>(hasMissingIncludes))
sourceType(static_cast<SourceType>(sourceType)), {}
hasMissingIncludes(
static_cast<HasMissingIncludes>(hasMissingIncludes)) {}
SourceEntry(FilePathId sourceId, SourceEntry(FilePathId sourceId,
SourceType sourceType, SourceType sourceType,
TimeStamp pchCreationTimeStamp, TimeStamp timeStamp,
HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No) HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No)
: pchCreationTimeStamp(pchCreationTimeStamp), sourceId(sourceId), : timeStamp(timeStamp)
sourceType(sourceType), hasMissingIncludes(hasMissingIncludes) {} , sourceId(sourceId)
, sourceType(sourceType)
, hasMissingIncludes(hasMissingIncludes)
{}
friend bool operator<(SourceEntry first, SourceEntry second) { friend bool operator<(SourceEntry first, SourceEntry second) {
return first.sourceId < second.sourceId; return first.sourceId < second.sourceId;
@@ -133,13 +134,13 @@ public:
friend bool operator==(SourceEntry first, SourceEntry second) friend bool operator==(SourceEntry first, SourceEntry second)
{ {
return first.sourceId == second.sourceId && first.sourceType == second.sourceType return first.sourceId == second.sourceId && first.sourceType == second.sourceType
&& first.pchCreationTimeStamp == second.pchCreationTimeStamp; && first.timeStamp == second.timeStamp;
} }
friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); } friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); }
public: public:
TimeStamp pchCreationTimeStamp; TimeStamp timeStamp;
FilePathId sourceId; FilePathId sourceId;
SourceType sourceType = SourceType::UserInclude; SourceType sourceType = SourceType::UserInclude;
HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No; HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No;

View File

@@ -47,7 +47,7 @@ void CompletionChunksToTextConverter::parseChunks(
m_codeCompletionChunks.cend(), m_codeCompletionChunks.cend(),
[this] (const ClangBackEnd::CodeCompletionChunk &chunk) [this] (const ClangBackEnd::CodeCompletionChunk &chunk)
{ {
parseDependendOnTheOptionalState(chunk); parseDependentOnTheOptionalState(chunk);
m_previousCodeCompletionChunk = chunk; m_previousCodeCompletionChunk = chunk;
}); });
} }
@@ -200,7 +200,7 @@ void CompletionChunksToTextConverter::parse(
} }
} }
void CompletionChunksToTextConverter::parseDependendOnTheOptionalState( void CompletionChunksToTextConverter::parseDependentOnTheOptionalState(
const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk) const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
{ {
wrapInCursiveTagIfOptional(codeCompletionChunk); wrapInCursiveTagIfOptional(codeCompletionChunk);

View File

@@ -75,7 +75,7 @@ public:
private: private:
void parse(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk); void parse(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
void parseDependendOnTheOptionalState(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk); void parseDependentOnTheOptionalState(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
void parseResultType(const Utf8String &text); void parseResultType(const Utf8String &text);
void parseText(const Utf8String &text); void parseText(const Utf8String &text);
void wrapInCursiveTagIfOptional(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk); void wrapInCursiveTagIfOptional(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);

View File

@@ -455,6 +455,8 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX2a: case LanguageVersion::CXX2a:
option = (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a")); option = (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a"));
break; break;
case LanguageVersion::None:
break;
} }
add(option, /*gccOnlyOption=*/true); add(option, /*gccOnlyOption=*/true);

View File

@@ -215,7 +215,8 @@ struct Data // because we have a cycle dependency
[&](ClangBackEnd::FilePathView path) -> TimeStamp { [&](ClangBackEnd::FilePathView path) -> TimeStamp {
return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch(); return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch();
}}; }};
ClangBackEnd::ModifiedTimeChecker modifiedTimeChecker{getModifiedTime, filePathCache}; ClangBackEnd::ModifiedTimeChecker<ClangBackEnd::SourceEntries> modifiedTimeChecker{getModifiedTime,
filePathCache};
ClangBackEnd::BuildDependenciesProvider buildDependencyProvider{buildDependencyStorage, ClangBackEnd::BuildDependenciesProvider buildDependencyProvider{buildDependencyStorage,
modifiedTimeChecker, modifiedTimeChecker,
buildDependencyCollector, buildDependencyCollector,

View File

@@ -27,6 +27,8 @@
#include "builddependenciesproviderinterface.h" #include "builddependenciesproviderinterface.h"
#include <modifiedtimecheckerinterface.h>
namespace Sqlite { namespace Sqlite {
class TransactionInterface; class TransactionInterface;
} }
@@ -34,14 +36,13 @@ class TransactionInterface;
namespace ClangBackEnd { namespace ClangBackEnd {
class BuildDependenciesStorageInterface; class BuildDependenciesStorageInterface;
class ModifiedTimeCheckerInterface;
class BuildDependencyGeneratorInterface; class BuildDependencyGeneratorInterface;
class BuildDependenciesProvider : public BuildDependenciesProviderInterface class BuildDependenciesProvider : public BuildDependenciesProviderInterface
{ {
public: public:
BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage, BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage,
ModifiedTimeCheckerInterface &modifiedTimeChecker, ModifiedTimeCheckerInterface<> &modifiedTimeChecker,
BuildDependencyGeneratorInterface &buildDependenciesGenerator, BuildDependencyGeneratorInterface &buildDependenciesGenerator,
Sqlite::TransactionInterface &transactionBackend) Sqlite::TransactionInterface &transactionBackend)
: m_storage(buildDependenciesStorage) : m_storage(buildDependenciesStorage)
@@ -61,7 +62,7 @@ private:
private: private:
BuildDependenciesStorageInterface &m_storage; BuildDependenciesStorageInterface &m_storage;
ModifiedTimeCheckerInterface &m_modifiedTimeChecker; ModifiedTimeCheckerInterface<> &m_modifiedTimeChecker;
BuildDependencyGeneratorInterface &m_generator; BuildDependencyGeneratorInterface &m_generator;
Sqlite::TransactionInterface &m_transactionBackend; Sqlite::TransactionInterface &m_transactionBackend;
}; };

View File

@@ -29,8 +29,6 @@ HEADERS += \
$$PWD/builddependenciesprovider.h \ $$PWD/builddependenciesprovider.h \
$$PWD/builddependenciesstorageinterface.h \ $$PWD/builddependenciesstorageinterface.h \
$$PWD/builddependency.h \ $$PWD/builddependency.h \
$$PWD/modifiedtimecheckerinterface.h \
$$PWD/sourceentry.h \
$$PWD/builddependenciesstorage.h \ $$PWD/builddependenciesstorage.h \
$$PWD/builddependencygeneratorinterface.h \ $$PWD/builddependencygeneratorinterface.h \
$$PWD/usedmacrofilter.h \ $$PWD/usedmacrofilter.h \
@@ -40,8 +38,7 @@ HEADERS += \
$$PWD/pchtaskqueue.h \ $$PWD/pchtaskqueue.h \
$$PWD/generatepchactionfactory.h \ $$PWD/generatepchactionfactory.h \
$$PWD/pchtaskgeneratorinterface.h \ $$PWD/pchtaskgeneratorinterface.h \
$$PWD/toolchainargumentscache.h \ $$PWD/toolchainargumentscache.h
$$PWD/modifiedtimechecker.h
!isEmpty(LIBTOOLING_LIBS) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \

View File

@@ -293,7 +293,7 @@ public:
entry.get().hasMissingIncludes = HasMissingIncludes::Yes; entry.get().hasMissingIncludes = HasMissingIncludes::Yes;
} }
SourceDependencies sourceDependenciesSortedByDependendFilePathId() const SourceDependencies sourceDependenciesSortedByDependentFilePathId() const
{ {
auto sourceDependencies = m_buildDependency.sourceDependencies; auto sourceDependencies = m_buildDependency.sourceDependencies;
std::sort(sourceDependencies.begin(), sourceDependencies.end(), [](auto first, auto second) { std::sort(sourceDependencies.begin(), sourceDependencies.end(), [](auto first, auto second) {
@@ -309,7 +309,7 @@ public:
sortAndMakeUnique(m_containsMissingIncludes); sortAndMakeUnique(m_containsMissingIncludes);
collectSourceWithMissingIncludes(m_containsMissingIncludes, collectSourceWithMissingIncludes(m_containsMissingIncludes,
sourceDependenciesSortedByDependendFilePathId()); sourceDependenciesSortedByDependentFilePathId());
removeSourceWithMissingIncludesFromSources(); removeSourceWithMissingIncludesFromSources();
} }

View File

@@ -65,7 +65,7 @@ ProjectPartContainers ProjectPartsManager::update(ProjectPartContainers &&projec
} }
m_projectPartsStorage.updateProjectParts(updatedProjectParts); m_projectPartsStorage.updateProjectParts(updatedProjectParts);
m_projectPartsStorage.resetIndexingTimeStamps(updatedProjectParts);
m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders( m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders(
toProjectPartIds(updatedProjectParts)); toProjectPartIds(updatedProjectParts));

View File

@@ -66,7 +66,8 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
FilePathCachingInterface &filePathCache, FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache, FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface, Sqlite::TransactionInterface &transactionInterface,
ProjectPartsStorageInterface &projectPartsStorage) ProjectPartsStorageInterface &projectPartsStorage,
ModifiedTimeCheckerInterface<SourceTimeStamps> &modifiedTimeChecker)
: m_symbolIndexerTaskQueue(symbolIndexerTaskQueue) : m_symbolIndexerTaskQueue(symbolIndexerTaskQueue)
, m_symbolStorage(symbolStorage) , m_symbolStorage(symbolStorage)
, m_buildDependencyStorage(buildDependenciesStorage) , m_buildDependencyStorage(buildDependenciesStorage)
@@ -76,6 +77,7 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
, m_fileStatusCache(fileStatusCache) , m_fileStatusCache(fileStatusCache)
, m_transactionInterface(transactionInterface) , m_transactionInterface(transactionInterface)
, m_projectPartsStorage(projectPartsStorage) , m_projectPartsStorage(projectPartsStorage)
, m_modifiedTimeChecker(modifiedTimeChecker)
{ {
pathWatcher.setNotifier(this); pathWatcher.setNotifier(this);
} }
@@ -109,16 +111,19 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
std::vector<SymbolIndexerTask> symbolIndexerTask; std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(projectPart.sourcePathIds.size()); symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
for (FilePathId sourcePathId : projectPart.sourcePathIds) { for (FilePathId sourcePathId : projectPart.sourcePathIds) {
auto indexing = [arguments = commandLineBuilder.commandLine, SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(
sourcePathId, sourcePathId);
this](SymbolsCollectorInterface &symbolsCollector) {
if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
auto indexing = [arguments = commandLineBuilder.commandLine, sourcePathId, this](
SymbolsCollectorInterface &symbolsCollector) {
symbolsCollector.setFile(sourcePathId, arguments); symbolsCollector.setFile(sourcePathId, arguments);
bool success = symbolsCollector.collectSymbols(); bool success = symbolsCollector.collectSymbols();
if (success) { if (success) {
Sqlite::ImmediateTransaction transaction{m_transactionInterface}; Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations()); symbolsCollector.sourceLocations());
transaction.commit(); transaction.commit();
@@ -127,6 +132,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing)); symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing));
} }
}
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries(); m_symbolIndexerTaskQueue.processEntries();
@@ -136,11 +142,13 @@ void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {}
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds) void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
{ {
std::vector<SymbolIndexerTask> symbolIndexerTask; FilePathIds dependentSourcePathIds = m_symbolStorage.fetchDependentSourceIds(filePathIds);
symbolIndexerTask.reserve(filePathIds.size());
for (FilePathId filePathId : filePathIds) std::vector<SymbolIndexerTask> symbolIndexerTask;
updateChangedPath(filePathId, symbolIndexerTask); symbolIndexerTask.reserve(dependentSourcePathIds.size());
for (FilePathId dependentSourcePathId : dependentSourcePathIds)
updateChangedPath(dependentSourcePathId, symbolIndexerTask);
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries(); m_symbolIndexerTaskQueue.processEntries();
@@ -161,6 +169,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
= m_precompiledHeaderStorage.fetchPrecompiledHeader(optionalArtefact->projectPartId); = m_precompiledHeaderStorage.fetchPrecompiledHeader(optionalArtefact->projectPartId);
transaction.commit(); transaction.commit();
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId);
const ProjectPartArtefact &artefact = *optionalArtefact; const ProjectPartArtefact &artefact = *optionalArtefact;
auto pchPath = optionalProjectPartPch ? optionalProjectPartPch->pchPath : FilePath{}; auto pchPath = optionalProjectPartPch ? optionalProjectPartPch->pchPath : FilePath{};
@@ -176,10 +186,9 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
if (success) { if (success) {
Sqlite::ImmediateTransaction transaction{m_transactionInterface}; Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations()); symbolsCollector.sourceLocations());
transaction.commit(); transaction.commit();
} }
}; };

View File

@@ -32,6 +32,7 @@
#include "clangpathwatcher.h" #include "clangpathwatcher.h"
#include <filecontainerv2.h> #include <filecontainerv2.h>
#include <modifiedtimecheckerinterface.h>
#include <precompiledheaderstorageinterface.h> #include <precompiledheaderstorageinterface.h>
#include <projectpartcontainer.h> #include <projectpartcontainer.h>
#include <projectpartsstorageinterface.h> #include <projectpartsstorageinterface.h>
@@ -51,7 +52,8 @@ public:
FilePathCachingInterface &filePathCache, FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache, FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface, Sqlite::TransactionInterface &transactionInterface,
ProjectPartsStorageInterface &projectPartsStorage); ProjectPartsStorageInterface &projectPartsStorage,
ModifiedTimeCheckerInterface<SourceTimeStamps> &modifiedTimeChecker);
void updateProjectParts(ProjectPartContainers &&projectParts); void updateProjectParts(ProjectPartContainers &&projectParts);
void updateProjectPart(ProjectPartContainer &&projectPart); void updateProjectPart(ProjectPartContainer &&projectPart);
@@ -81,6 +83,7 @@ private:
FileStatusCache &m_fileStatusCache; FileStatusCache &m_fileStatusCache;
Sqlite::TransactionInterface &m_transactionInterface; Sqlite::TransactionInterface &m_transactionInterface;
ProjectPartsStorageInterface &m_projectPartsStorage; ProjectPartsStorageInterface &m_projectPartsStorage;
ModifiedTimeCheckerInterface<SourceTimeStamps> &m_modifiedTimeChecker;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -38,13 +38,16 @@
#include <precompiledheaderstorage.h> #include <precompiledheaderstorage.h>
#include <projectpartsstorage.h> #include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <filepathcachingfwd.h> #include <filepathcachingfwd.h>
#include <modifiedtimechecker.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <sqlitereadstatement.h> #include <sqlitereadstatement.h>
#include <sqlitewritestatement.h> #include <sqlitewritestatement.h>
#include <QDateTime>
#include <QFileInfo>
#include <QFileSystemWatcher> #include <QFileSystemWatcher>
#include <thread> #include <thread>
@@ -130,6 +133,12 @@ private:
FileStatusCache m_fileStatusCache{m_filePathCache}; FileStatusCache m_fileStatusCache{m_filePathCache};
SymbolsCollectorManager m_collectorManger; SymbolsCollectorManager m_collectorManger;
ProgressCounter m_progressCounter; ProgressCounter m_progressCounter;
std::function<TimeStamp(FilePathView filePath)> getModifiedTime{
[&](ClangBackEnd::FilePathView path) -> TimeStamp {
return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch();
}};
ModifiedTimeChecker<ClangBackEnd::SourceTimeStamps> m_modifiedTimeChecker{getModifiedTime,
m_filePathCache};
SymbolIndexer m_indexer{m_indexerQueue, SymbolIndexer m_indexer{m_indexerQueue,
m_symbolStorage, m_symbolStorage,
m_buildDependencyStorage, m_buildDependencyStorage,
@@ -138,7 +147,8 @@ private:
m_filePathCache, m_filePathCache,
m_fileStatusCache, m_fileStatusCache,
m_symbolStorage.database, m_symbolStorage.database,
m_projectPartsStorage}; m_projectPartsStorage,
m_modifiedTimeChecker};
SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter}; SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter};
SymbolIndexerTaskScheduler m_indexerScheduler; SymbolIndexerTaskScheduler m_indexerScheduler;
}; };

View File

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

View File

@@ -28,6 +28,9 @@
#include "sourcelocationentry.h" #include "sourcelocationentry.h"
#include "symbolentry.h" #include "symbolentry.h"
#include <filestatus.h>
#include <sourceentry.h>
#include <compilermacro.h> #include <compilermacro.h>
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
@@ -45,6 +48,11 @@ public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries, virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations) const SourceLocationEntries &sourceLocations)
= 0; = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected: protected:
~SymbolStorageInterface() = default; ~SymbolStorageInterface() = default;

View File

@@ -58,7 +58,7 @@ class BuildDependenciesProvider : public testing::Test
protected: protected:
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend; NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage; NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
NiceMock<MockModifiedTimeChecker> mockModifiedTimeChecker; NiceMock<MockSourceEntriesModifiedTimeChecker> mockModifiedTimeChecker;
NiceMock<MockBuildDependencyGenerator> mockBuildDependenciesGenerator; NiceMock<MockBuildDependencyGenerator> mockBuildDependenciesGenerator;
ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage, ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage,
mockModifiedTimeChecker, mockModifiedTimeChecker,

View File

@@ -201,7 +201,7 @@ TEST_F(DocumentSlowTest, NeedsReparseAfterChangeOfMainFile)
ASSERT_TRUE(document.isDirty()); ASSERT_TRUE(document.isDirty());
} }
TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile) TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependentFile)
{ {
document.parse(); document.parse();
@@ -210,7 +210,7 @@ TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile)
ASSERT_FALSE(document.isDirty()); ASSERT_FALSE(document.isDirty());
} }
TEST_F(DocumentSlowTest, NeedsReparsingForDependendFile) TEST_F(DocumentSlowTest, NeedsReparsingForDependentFile)
{ {
document.parse(); document.parse();

View File

@@ -97,16 +97,16 @@ TEST_F(UpdateAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentRevisionChange
ASSERT_TRUE(waitUntilJobFinished(job)); ASSERT_TRUE(waitUntilJobFinished(job));
} }
TEST_F(UpdateAnnotationsJobSlowTest, UpdatesDependendFilePaths) TEST_F(UpdateAnnotationsJobSlowTest, UpdatesDependentFilePaths)
{ {
const QSet<Utf8String> dependendOnFilesBefore = document.dependedFilePaths(); const QSet<Utf8String> dependentOnFilesBefore = document.dependedFilePaths();
job.setContext(jobContext); job.setContext(jobContext);
job.prepareAsyncRun(); job.prepareAsyncRun();
job.runAsync(); job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job)); ASSERT_TRUE(waitUntilJobFinished(job));
ASSERT_THAT(dependendOnFilesBefore, Not(document.dependedFilePaths())); ASSERT_THAT(dependentOnFilesBefore, Not(document.dependedFilePaths()));
} }
TEST_F(UpdateAnnotationsJobSlowTest, UpdatesUnresolvedFilePaths) TEST_F(UpdateAnnotationsJobSlowTest, UpdatesUnresolvedFilePaths)

View File

@@ -1230,6 +1230,16 @@ std::ostream &operator<<(std::ostream &out, const SourceEntry &entry)
<< typeToString(entry.hasMissingIncludes) << ")"; << typeToString(entry.hasMissingIncludes) << ")";
} }
std::ostream &operator<<(std::ostream &out, const SourceTimeStamp &sourceTimeStamp)
{
return out << "(" << sourceTimeStamp.sourceId << ", " << sourceTimeStamp.timeStamp << ")";
}
std::ostream &operator<<(std::ostream &out, const TimeStamp &timeStamp)
{
return out << timeStamp.value;
}
const char *typeToString(IncludeSearchPathType type) const char *typeToString(IncludeSearchPathType type)
{ {
switch (type) { switch (type) {

View File

@@ -190,6 +190,8 @@ class PchTask;
class PchTaskSet; class PchTaskSet;
class BuildDependency; class BuildDependency;
class SourceEntry; class SourceEntry;
class SourceTimeStamp;
class TimeStamp;
class FilePathCaching; class FilePathCaching;
struct SlotUsage; struct SlotUsage;
class IncludeSearchPath; class IncludeSearchPath;
@@ -281,6 +283,8 @@ std::ostream &operator<<(std::ostream &out, const PchTask &task);
std::ostream &operator<<(std::ostream &out, const PchTaskSet &taskSet); std::ostream &operator<<(std::ostream &out, const PchTaskSet &taskSet);
std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency); std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency);
std::ostream &operator<<(std::ostream &out, const SourceEntry &entry); std::ostream &operator<<(std::ostream &out, const SourceEntry &entry);
std::ostream &operator<<(std::ostream &out, const SourceTimeStamp &sourceTimeStamp);
std::ostream &operator<<(std::ostream &out, const TimeStamp &timeStamp);
std::ostream &operator<<(std::ostream &out, const SlotUsage &slotUsage); std::ostream &operator<<(std::ostream &out, const SlotUsage &slotUsage);
std::ostream &operator<<(std::ostream &out, const IncludeSearchPathType &pathType); std::ostream &operator<<(std::ostream &out, const IncludeSearchPathType &pathType);
std::ostream &operator<<(std::ostream &out, const IncludeSearchPath &path); std::ostream &operator<<(std::ostream &out, const IncludeSearchPath &path);

View File

@@ -29,9 +29,17 @@
#include <modifiedtimecheckerinterface.h> #include <modifiedtimecheckerinterface.h>
class MockModifiedTimeChecker : public ClangBackEnd::ModifiedTimeCheckerInterface class MockSourceEntriesModifiedTimeChecker
: public ClangBackEnd::ModifiedTimeCheckerInterface<ClangBackEnd::SourceEntries>
{ {
public: public:
MOCK_CONST_METHOD1(isUpToDate, MOCK_CONST_METHOD1(isUpToDate,
bool (const ClangBackEnd::SourceEntries &sourceEntries)); bool (const ClangBackEnd::SourceEntries &sourceEntries));
}; };
class MockSourceTimeStampsModifiedTimeChecker
: public ClangBackEnd::ModifiedTimeCheckerInterface<ClangBackEnd::SourceTimeStamps>
{
public:
MOCK_CONST_METHOD1(isUpToDate, bool(const ClangBackEnd::SourceTimeStamps &sourceTimeStamps));
};

View File

@@ -56,5 +56,7 @@ public:
MOCK_CONST_METHOD1(fetchProjectPartArtefact, MOCK_CONST_METHOD1(fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>( Utils::optional<ClangBackEnd::ProjectPartArtefact>(
ClangBackEnd::ProjectPartId projectPartId)); ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD1(resetIndexingTimeStamps,
void(const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD0(transactionBackend, Sqlite::TransactionInterface &()); MOCK_METHOD0(transactionBackend, Sqlite::TransactionInterface &());
}; };

View File

@@ -222,6 +222,19 @@ SourceEntries MockSqliteReadStatement::values<SourceEntry, 4>(std::size_t reserv
return valuesReturnSourceEntries(reserveSize, filePathId, projectPartId); return valuesReturnSourceEntries(reserveSize, filePathId, projectPartId);
} }
template<>
SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize)
{
return valuesReturnSourceTimeStamps(reserveSize);
}
template<>
SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize,
const int &sourcePathId)
{
return valuesReturnSourceTimeStamps(reserveSize, sourcePathId);
}
template <> template <>
Utils::optional<Sources::SourceNameAndDirectoryId> Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int &id) MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int &id)

View File

@@ -50,6 +50,8 @@
using ClangBackEnd::FilePathIds; using ClangBackEnd::FilePathIds;
using ClangBackEnd::SourceEntries; using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry; using ClangBackEnd::SourceEntry;
using ClangBackEnd::SourceTimeStamp;
using ClangBackEnd::SourceTimeStamps;
using ClangRefactoring::SourceLocation; using ClangRefactoring::SourceLocation;
using ClangRefactoring::SourceLocations; using ClangRefactoring::SourceLocations;
using std::int64_t; using std::int64_t;
@@ -136,6 +138,9 @@ public:
MOCK_METHOD1(valueReturnProjectPartId, MOCK_METHOD1(valueReturnProjectPartId,
Utils::optional<ClangBackEnd::ProjectPartId>(Utils::SmallStringView)); Utils::optional<ClangBackEnd::ProjectPartId>(Utils::SmallStringView));
MOCK_METHOD1(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t));
MOCK_METHOD2(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t, int sourcePathId));
template <typename ResultType, template <typename ResultType,
int ResultTypeCount = 1, int ResultTypeCount = 1,
typename... QueryType> typename... QueryType>
@@ -283,6 +288,13 @@ SourceEntries MockSqliteReadStatement::values<SourceEntry, 4>(std::size_t reserv
const int &, const int &,
const int &); const int &);
template<>
SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize);
template<>
SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize,
const int &sourcePathId);
template <> template <>
Utils::optional<Sources::SourceNameAndDirectoryId> Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&); MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&);

View File

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

View File

@@ -57,7 +57,7 @@ protected:
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
decltype(getModifiedTimeCallback.AsStdFunction()) callback = getModifiedTimeCallback decltype(getModifiedTimeCallback.AsStdFunction()) callback = getModifiedTimeCallback
.AsStdFunction(); .AsStdFunction();
ClangBackEnd::ModifiedTimeChecker checker{callback, filePathCache}; ClangBackEnd::ModifiedTimeChecker<> checker{callback, filePathCache};
SourceEntries upToDateEntries = {{id("/path1"), SourceType::UserInclude, 100}, SourceEntries upToDateEntries = {{id("/path1"), SourceType::UserInclude, 100},
{id("/path2"), SourceType::SystemInclude, 30}}; {id("/path2"), SourceType::SystemInclude, 30}};
SourceEntries notUpToDateEntries = {{id("/path1"), SourceType::UserInclude, 50}, SourceEntries notUpToDateEntries = {{id("/path1"), SourceType::UserInclude, 50},

View File

@@ -302,6 +302,7 @@ TEST_F(ProjectPartsManager, UpdateCallsIfNewProjectPartIsAdded)
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1))); EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage, EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId))); deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)));
manager.update({projectPartContainer1}); manager.update({projectPartContainer1});
} }
@@ -337,6 +338,16 @@ TEST_F(ProjectPartsManager, UpdateCallsNotDeleteProjectPrecompiledHeadersIfNoNew
manager.update({projectPartContainer1}); manager.update({projectPartContainer1});
} }
TEST_F(ProjectPartsManager, UpdateCallsNotResetIndexingTimeStampsIfNoNewerProjectPartsExists)
{
manager.update({projectPartContainer1});
EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)))
.Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, UpdateCallsIfOldProjectPartIsAdded) TEST_F(ProjectPartsManager, UpdateCallsIfOldProjectPartIsAdded)
{ {
EXPECT_CALL(mockProjectPartsStorage, EXPECT_CALL(mockProjectPartsStorage,
@@ -346,6 +357,8 @@ TEST_F(ProjectPartsManager, UpdateCallsIfOldProjectPartIsAdded)
EXPECT_CALL(mockPrecompiledHeaderStorage, EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId))) deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)))
.Times(0); .Times(0);
EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)))
.Times(0);
manager.update({projectPartContainer1}); manager.update({projectPartContainer1});
} }
@@ -361,6 +374,8 @@ TEST_F(ProjectPartsManager, UpdateCallsIfUpdatedProjectPartIsAdded)
updateProjectParts(ElementsAre(updatedProjectPartContainer1))); updateProjectParts(ElementsAre(updatedProjectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage, EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId))); deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
EXPECT_CALL(mockProjectPartsStorage,
resetIndexingTimeStamps(ElementsAre(updatedProjectPartContainer1)));
manager.update({updatedProjectPartContainer1}); manager.update({updatedProjectPartContainer1});
} }

View File

@@ -27,12 +27,13 @@
#include "mocksqlitedatabase.h" #include "mocksqlitedatabase.h"
#include <builddependenciesstorage.h>
#include <projectpartsstorage.h> #include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <sqlitereadstatement.h> #include <sqlitereadstatement.h>
#include <sqlitewritestatement.h> #include <sqlitewritestatement.h>
#include <symbolstorage.h>
namespace { namespace {
using ClangBackEnd::FilePathId; using ClangBackEnd::FilePathId;
@@ -104,6 +105,7 @@ protected:
MockSqliteReadStatement &fetchProjectPartsHeadersByIdStatement = storage.fetchProjectPartsHeadersByIdStatement; MockSqliteReadStatement &fetchProjectPartsHeadersByIdStatement = storage.fetchProjectPartsHeadersByIdStatement;
MockSqliteReadStatement &fetchProjectPartsSourcesByIdStatement = storage.fetchProjectPartsSourcesByIdStatement; MockSqliteReadStatement &fetchProjectPartsSourcesByIdStatement = storage.fetchProjectPartsSourcesByIdStatement;
MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderPathStatement; MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderPathStatement;
MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement;
IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn}, IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}}; {"/other/includes", 2, IncludeSearchPathType::System}};
IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User}, IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User},
@@ -424,6 +426,35 @@ TEST_F(ProjectPartsStorage, FetchProjectPartArtefactByProjectPartIdReturnArtefac
ASSERT_THAT(result, Eq(artefact)); ASSERT_THAT(result, Eq(artefact));
} }
TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStamps)
{
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(3)));
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(4)));
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(7)));
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(8)));
EXPECT_CALL(mockDatabase, commit());
storage.resetIndexingTimeStamps({projectPart1, projectPart2});
}
TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(3)));
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(4)));
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(7)));
EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(8)));
EXPECT_CALL(mockDatabase, commit());
storage.resetIndexingTimeStamps({projectPart1, projectPart2});
}
class ProjectPartsStorageSlow : public testing::Test, public Data class ProjectPartsStorageSlow : public testing::Test, public Data
{ {
using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>; using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>;
@@ -432,6 +463,8 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
Storage storage{database}; Storage storage{database};
ClangBackEnd::SymbolStorage<> symbolStorage{database};
ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
}; };
TEST_F(ProjectPartsStorageSlow, FetchProjectPartName) TEST_F(ProjectPartsStorageSlow, FetchProjectPartName)
@@ -469,4 +502,26 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
ASSERT_THAT(projectParts, ElementsAre(projectPart1, projectPart2)); ASSERT_THAT(projectParts, ElementsAre(projectPart1, projectPart2));
} }
TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps)
{
symbolStorage.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(),
ElementsAre(SourceTimeStamp{1, 0},
SourceTimeStamp{2, 0},
SourceTimeStamp{3, 0},
SourceTimeStamp{4, 0},
SourceTimeStamp{5, 0},
SourceTimeStamp{6, 0},
SourceTimeStamp{7, 0},
SourceTimeStamp{8, 0},
SourceTimeStamp{9, 34},
SourceTimeStamp{10, 34}));
}
} // namespace } // namespace

View File

@@ -131,7 +131,7 @@ TEST_F(RefactoringDatabaseInitializer, AddFileStatusesTable)
mockDatabase, mockDatabase,
execute(Eq( execute(Eq(
"CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, " "CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, "
"lastModified INTEGER)"))); "lastModified INTEGER, indexingTimeStamp INTEGER)")));
initializer.createFileStatusesTable(); initializer.createFileStatusesTable();
} }
@@ -140,8 +140,19 @@ TEST_F(RefactoringDatabaseInitializer, AddSourceDependenciesTable)
{ {
InSequence s; InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)"))); EXPECT_CALL(mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)"))); execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, "
"dependencySourceId INTEGER)")));
EXPECT_CALL(
mockDatabase,
execute(
Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON "
"sourceDependencies(sourceId, dependencySourceId)")));
EXPECT_CALL(
mockDatabase,
execute(
Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_dependencySourceId_sourceId ON "
"sourceDependencies(dependencySourceId, sourceId)")));
initializer.createSourceDependenciesTable(); initializer.createSourceDependenciesTable();
} }
@@ -189,40 +200,88 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
EXPECT_CALL(mockDatabase, isInitialized()).WillOnce(Return(false)); EXPECT_CALL(mockDatabase, isInitialized()).WillOnce(Return(false));
EXPECT_CALL(mockDatabase, exclusiveBegin()); EXPECT_CALL(mockDatabase, exclusiveBegin());
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT, symbolKind INTEGER, signature TEXT)"))); EXPECT_CALL(mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr "
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_symbolKind_symbolName ON symbols(symbolKind, symbolName)"))); "TEXT, symbolName TEXT, symbolKind INTEGER, signature TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER, locationKind INTEGER)"))); EXPECT_CALL(mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_locations_sourceId_line_column ON locations(sourceId, line, column)"))); execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_locationKind ON locations(sourceId, locationKind)"))); EXPECT_CALL(mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, directoryId INTEGER, sourceName TEXT)"))); execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_symbolKind_symbolName ON "
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_sources_directoryId_sourceName ON sources(directoryId, sourceName)"))); "symbols(symbolKind, symbolName)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY KEY, directoryPath TEXT)"))); EXPECT_CALL(mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_directories_directoryPath ON directories(directoryPath)"))); execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, "
"column INTEGER, sourceId INTEGER, locationKind INTEGER)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_locations_sourceId_line_column "
"ON locations(sourceId, line, column)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_locationKind ON "
"locations(sourceId, locationKind)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, "
"directoryId INTEGER, sourceName TEXT)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_sources_directoryId_sourceName "
"ON sources(directoryId, sourceName)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY "
"KEY, directoryPath TEXT)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_directories_directoryPath ON "
"directories(directoryPath)")));
EXPECT_CALL(mockDatabase, EXPECT_CALL(mockDatabase,
execute( execute(
Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY " Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY "
"KEY, projectPartName TEXT, toolChainArguments TEXT, compilerMacros " "KEY, projectPartName TEXT, toolChainArguments TEXT, compilerMacros "
"TEXT, systemIncludeSearchPaths TEXT, projectIncludeSearchPaths TEXT, " "TEXT, systemIncludeSearchPaths TEXT, projectIncludeSearchPaths TEXT, "
"language INTEGER, languageVersion INTEGER, languageExtension INTEGER)"))); "language INTEGER, languageVersion INTEGER, languageExtension INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectParts_projectPartName ON projectParts(projectPartName)"))); EXPECT_CALL(mockDatabase,
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectParts_projectPartName "
"ON projectParts(projectPartName)")));
EXPECT_CALL(mockDatabase, EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsFiles(projectPartId INTEGER, " execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsFiles(projectPartId INTEGER, "
"sourceId INTEGER, sourceType INTEGER, pchCreationTimeStamp INTEGER, " "sourceId INTEGER, sourceType INTEGER, pchCreationTimeStamp INTEGER, "
"hasMissingIncludes INTEGER)"))); "hasMissingIncludes INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsFiles_sourceId_projectPartId ON projectPartsFiles(sourceId, projectPartId)"))); EXPECT_CALL(
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_projectPartsFiles_projectPartId ON projectPartsFiles(projectPartId)"))); mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS usedMacros(usedMacroId INTEGER PRIMARY KEY, sourceId INTEGER, macroName TEXT)"))); execute(
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_sourceId_macroName ON usedMacros(sourceId, macroName)"))); Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsFiles_sourceId_projectPartId "
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)"))); "ON projectPartsFiles(sourceId, projectPartId)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE INDEX IF NOT EXISTS index_projectPartsFiles_projectPartId ON "
"projectPartsFiles(projectPartId)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS usedMacros(usedMacroId INTEGER PRIMARY KEY, "
"sourceId INTEGER, macroName TEXT)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_sourceId_macroName ON "
"usedMacros(sourceId, macroName)")));
EXPECT_CALL(
mockDatabase,
execute(
Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)")));
EXPECT_CALL( EXPECT_CALL(
mockDatabase, mockDatabase,
execute(Eq( execute(Eq(
"CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, " "CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, "
"lastModified INTEGER)"))); "lastModified INTEGER, indexingTimeStamp INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)"))); EXPECT_CALL(mockDatabase,
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)"))); execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, "
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, systemPchPath TEXT, systemPchBuildTime INTEGER)"))); "dependencySourceId INTEGER)")));
EXPECT_CALL(
mockDatabase,
execute(
Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON "
"sourceDependencies(sourceId, dependencySourceId)")));
EXPECT_CALL(
mockDatabase,
execute(
Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_dependencySourceId_sourceId ON "
"sourceDependencies(dependencySourceId, sourceId)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER "
"PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, "
"systemPchPath TEXT, systemPchBuildTime INTEGER)")));
EXPECT_CALL(mockDatabase, EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsHeaders(projectPartId INTEGER, " execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsHeaders(projectPartId INTEGER, "
"sourceId INTEGER)"))); "sourceId INTEGER)")));
@@ -271,7 +330,7 @@ TEST_F(RefactoringDatabaseInitializer, DontCreateIfAlreadyInitialized)
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)"))).Times(0); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)"))).Times(0);
EXPECT_CALL(mockDatabase, EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, " execute(Eq("CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, "
"size INTEGER, lastModified INTEGER, isInPrecompiledHeader INTEGER)"))) "size INTEGER, lastModified INTEGER, indexingTimeStamp INTEGER)")))
.Times(0); .Times(0);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)"))).Times(0); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)"))).Times(0);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)"))).Times(0); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)"))).Times(0);

View File

@@ -28,6 +28,7 @@
#include "mockbuilddependenciesstorage.h" #include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h" #include "mockclangpathwatcher.h"
#include "mockfilepathcaching.h" #include "mockfilepathcaching.h"
#include "mockmodifiedtimechecker.h"
#include "mockprecompiledheaderstorage.h" #include "mockprecompiledheaderstorage.h"
#include "mockprojectpartsstorage.h" #include "mockprojectpartsstorage.h"
#include "mocksqlitetransactionbackend.h" #include "mocksqlitetransactionbackend.h"
@@ -113,7 +114,12 @@ protected:
.WillByDefault(Return(artefact)); .WillByDefault(Return(artefact));
ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1)); ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1));
ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true)); ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
.WillByDefault(Return(sourceFileIds));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
.WillByDefault(Return(FilePathIds{sourceFileIds[0]}));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
.WillByDefault(Return(FilePathIds{main1PathId}));
mockCollector.setIsUsed(false); mockCollector.setIsUsed(false);
generatedFiles.update(unsaved); generatedFiles.update(unsaved);
@@ -230,6 +236,10 @@ protected:
Utils::Language::Cxx, Utils::Language::Cxx,
Utils::LanguageVersion::CXX14, Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None}; Utils::LanguageExtension::None};
ClangBackEnd::SourceTimeStamps dependentSourceTimeStamps1{{1, 32}};
ClangBackEnd::SourceTimeStamps dependentSourceTimeStamps2{{2, 35}};
ClangBackEnd::FileStatuses fileStatuses1{{1, 0, 32}};
ClangBackEnd::FileStatuses fileStatuses2{{2, 0, 35}};
Utils::optional<ClangBackEnd::ProjectPartArtefact > nullArtefact; Utils::optional<ClangBackEnd::ProjectPartArtefact > nullArtefact;
ClangBackEnd::ProjectPartPch projectPartPch{74, "/path/to/pch", 4}; ClangBackEnd::ProjectPartPch projectPartPch{74, "/path/to/pch", 4};
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend; NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
@@ -243,6 +253,7 @@ protected:
Manager collectorManger{generatedFiles}; Manager collectorManger{generatedFiles};
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback; NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()}; ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
NiceMock<MockSourceTimeStampsModifiedTimeChecker> mockModifiedTimeChecker;
ClangBackEnd::SymbolIndexer indexer{indexerQueue, ClangBackEnd::SymbolIndexer indexer{indexerQueue,
mockSymbolStorage, mockSymbolStorage,
mockBuildDependenciesStorage, mockBuildDependenciesStorage,
@@ -251,7 +262,8 @@ protected:
filePathCache, filePathCache,
fileStatusCache, fileStatusCache,
mockSqliteTransactionBackend, mockSqliteTransactionBackend,
mockProjectPartsStorage}; mockProjectPartsStorage,
mockModifiedTimeChecker};
SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter}; SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter};
Scheduler indexerScheduler{collectorManger, Scheduler indexerScheduler{collectorManger,
indexerQueue, indexerQueue,
@@ -493,6 +505,58 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1});
} }
TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps)
{
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, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
.WillOnce(Return(dependentSourceTimeStamps1));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1));
EXPECT_CALL(mockSymbolStorage, 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(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
indexer.updateProjectParts({projectPart});
}
TEST_F(SymbolIndexer, DependentSourceAreNotUpToDate)
{
InSequence s;
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillOnce(Return(false));
EXPECT_CALL(mockCollector, setFile(main1PathId, _));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
indexer.updateProjectParts({projectPart1});
}
TEST_F(SymbolIndexer, DependentSourceAreUpToDate)
{
InSequence s;
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillOnce(Return(true));
EXPECT_CALL(mockCollector, setFile(main1PathId, _)).Times(0);
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
indexer.updateProjectParts({projectPart1});
}
TEST_F(SymbolIndexer, CallSetNotifier) TEST_F(SymbolIndexer, CallSetNotifier)
{ {
EXPECT_CALL(mockPathWatcher, setNotifier(_)); EXPECT_CALL(mockPathWatcher, setNotifier(_));
@@ -505,7 +569,8 @@ TEST_F(SymbolIndexer, CallSetNotifier)
filePathCache, filePathCache,
fileStatusCache, fileStatusCache,
mockSqliteTransactionBackend, mockSqliteTransactionBackend,
mockProjectPartsStorage}; mockProjectPartsStorage,
mockModifiedTimeChecker};
} }
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage) TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
@@ -516,6 +581,54 @@ TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
indexer.pathsChanged(sourceFileIds); 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) TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
{ {
InSequence s; InSequence s;
@@ -797,6 +910,7 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache)
auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp"); auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp");
auto oldLastModified = fileStatusCache.lastModifiedTime(sourceId); auto oldLastModified = fileStatusCache.lastModifiedTime(sourceId);
touchFile(sourceId); touchFile(sourceId);
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId}));
indexer.pathsChanged({sourceId}); indexer.pathsChanged({sourceId});

View File

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

View File

@@ -113,7 +113,7 @@ TEST_F(TranslationUnitUpdaterSlowTest, NotUpdatingParseTimePointForReparseOnly)
ASSERT_FALSE(result.hasParsed()); ASSERT_FALSE(result.hasParsed());
} }
TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependendOnFilesOnParse) TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependentOnFilesOnParse)
{ {
::TranslationUnitUpdater updater = createUpdater(createInput()); ::TranslationUnitUpdater updater = createUpdater(createInput());