forked from qt-creator/qt-creator
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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
|
||||||
class ModifiedTimeCheckerInterface
|
class ModifiedTimeCheckerInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 += \
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -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,23 +111,27 @@ 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) {
|
|
||||||
symbolsCollector.setFile(sourcePathId, arguments);
|
|
||||||
|
|
||||||
bool success = symbolsCollector.collectSymbols();
|
if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
|
||||||
|
auto indexing = [arguments = commandLineBuilder.commandLine, sourcePathId, this](
|
||||||
|
SymbolsCollectorInterface &symbolsCollector) {
|
||||||
|
symbolsCollector.setFile(sourcePathId, arguments);
|
||||||
|
|
||||||
if (success) {
|
bool success = symbolsCollector.collectSymbols();
|
||||||
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
|
||||||
|
|
||||||
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
|
if (success) {
|
||||||
symbolsCollector.sourceLocations());
|
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
||||||
transaction.commit();
|
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
|
||||||
}
|
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
|
||||||
};
|
symbolsCollector.sourceLocations());
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
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));
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ class UpdateProjectPartsMessage;
|
|||||||
class DocumentsChangedMessage;
|
class DocumentsChangedMessage;
|
||||||
class DocumentVisibilityChangedMessage;
|
class DocumentVisibilityChangedMessage;
|
||||||
class FilePath;
|
class FilePath;
|
||||||
template <char WindowsSlash>
|
template<char WindowsSlash>
|
||||||
class AbstractFilePathView;
|
class AbstractFilePathView;
|
||||||
using FilePathView = AbstractFilePathView<'/'>;
|
using FilePathView = AbstractFilePathView<'/'>;
|
||||||
using NativeFilePathView = AbstractFilePathView<'\\'>;
|
using NativeFilePathView = AbstractFilePathView<'\\'>;
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
|
};
|
||||||
|
|||||||
@@ -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 &());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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&);
|
||||||
|
|||||||
@@ -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));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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});
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user