summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2019-03-21 17:55:24 +0100
committerMarco Bubke <marco.bubke@qt.io>2019-04-02 13:08:44 +0000
commit56b01f74633c310807cf3fc00766cfa01002297f (patch)
treea8e0a09154f4c95dd8b16db2a8512c2f5b5b0946
parent7595c9f3052cf7c2ca05f3157c945371952ca0b5 (diff)
downloadqt-creator-56b01f74633c310807cf3fc00766cfa01002297f.tar.gz
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>
-rw-r--r--src/libs/clangsupport/clangsupport-lib.pri5
-rw-r--r--src/libs/clangsupport/modifiedtimechecker.h (renamed from src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h)43
-rw-r--r--src/libs/clangsupport/modifiedtimecheckerinterface.h (renamed from src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h)1
-rw-r--r--src/libs/clangsupport/projectpartsstorage.h22
-rw-r--r--src/libs/clangsupport/projectpartsstorageinterface.h1
-rw-r--r--src/libs/clangsupport/refactoringdatabaseinitializer.h2
-rw-r--r--src/libs/clangsupport/sourceentry.h (renamed from src/tools/clangpchmanagerbackend/source/sourceentry.h)35
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp4
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h2
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp2
-rw-r--r--src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp3
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h7
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri5
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h4
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp2
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexer.cpp55
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexer.h5
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexing.h14
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorage.h108
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorageinterface.h8
-rw-r--r--tests/unit/unittest/builddependenciesprovider-test.cpp2
-rw-r--r--tests/unit/unittest/clangdocument-test.cpp4
-rw-r--r--tests/unit/unittest/clangupdateannotationsjob-test.cpp6
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp10
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h6
-rw-r--r--tests/unit/unittest/mockmodifiedtimechecker.h10
-rw-r--r--tests/unit/unittest/mockprojectpartsstorage.h2
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.cpp13
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.h12
-rw-r--r--tests/unit/unittest/mocksymbolstorage.h7
-rw-r--r--tests/unit/unittest/modifiedtimechecker-test.cpp2
-rw-r--r--tests/unit/unittest/projectpartsmanager-test.cpp15
-rw-r--r--tests/unit/unittest/projectpartsstorage-test.cpp57
-rw-r--r--tests/unit/unittest/refactoringdatabaseinitializer-test.cpp107
-rw-r--r--tests/unit/unittest/symbolindexer-test.cpp120
-rw-r--r--tests/unit/unittest/symbolstorage-test.cpp153
-rw-r--r--tests/unit/unittest/translationunitupdater-test.cpp2
37 files changed, 736 insertions, 120 deletions
diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri
index 0668382803..086755d5dc 100644
--- a/src/libs/clangsupport/clangsupport-lib.pri
+++ b/src/libs/clangsupport/clangsupport-lib.pri
@@ -213,6 +213,9 @@ HEADERS += \
$$PWD/includesearchpath.h \
$$PWD/commandlinebuilder.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
diff --git a/src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h b/src/libs/clangsupport/modifiedtimechecker.h
index d641de054c..c9b62c4673 100644
--- a/src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h
+++ b/src/libs/clangsupport/modifiedtimechecker.h
@@ -25,17 +25,18 @@
#pragma once
+#include "filepathcachinginterface.h"
#include "modifiedtimecheckerinterface.h"
-#include <filepathcachinginterface.h>
-
#include <algorithm>
#include <iterator>
namespace ClangBackEnd {
-
-class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface
+template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
+class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries>
{
+ using SourceEntry = typename SourceEntries::value_type;
+
public:
using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>;
ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache)
@@ -67,7 +68,7 @@ public:
std::back_inserter(timeStampsToUpdate));
for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) {
- sourceTimeStamp.lastModified = m_getModifiedTime(
+ sourceTimeStamp.timeStamp = m_getModifiedTime(
m_filePathCache.filePath(sourceTimeStamp.sourceId));
}
}
@@ -78,21 +79,22 @@ private:
class CompareSourceId
{
public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second) {
+ bool operator()(SourceTimeStamp first, SourceTimeStamp second)
+ {
return first.sourceId < second.sourceId;
}
- bool operator()(SourceEntry first, SourceEntry second)
+ bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
{
return first.sourceId < second.sourceId;
}
- bool operator()(SourceTimeStamp first, SourceEntry second)
+ bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
{
return first.sourceId < second.sourceId;
}
- bool operator()(SourceEntry first, SourceTimeStamp second)
+ bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
{
return first.sourceId < second.sourceId;
}
@@ -112,23 +114,22 @@ private:
public:
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 <=
- second.pchCreationTimeStamp;
+ return first.timeStamp <= second.timeStamp;
}
- 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);
for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) {
- newSourceTimeStamp.lastModified = m_getModifiedTime(
+ newSourceTimeStamp.timeStamp = m_getModifiedTime(
m_filePathCache.filePath(newSourceTimeStamp.sourceId));
}
@@ -169,17 +170,17 @@ private:
return first.sourceId < second.sourceId;
}
- bool operator()(SourceEntry first, SourceEntry second)
+ bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
{
return first.sourceId < second.sourceId;
}
- bool operator()(SourceTimeStamp first, SourceEntry second)
+ bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
{
return first.sourceId < second.sourceId;
}
- bool operator()(SourceEntry first, SourceTimeStamp second)
+ bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
{
return first.sourceId < second.sourceId;
}
diff --git a/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h b/src/libs/clangsupport/modifiedtimecheckerinterface.h
index c0cae1cf4b..a0e79b0701 100644
--- a/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h
+++ b/src/libs/clangsupport/modifiedtimecheckerinterface.h
@@ -29,6 +29,7 @@
namespace ClangBackEnd {
+template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
class ModifiedTimeCheckerInterface
{
public:
diff --git a/src/libs/clangsupport/projectpartsstorage.h b/src/libs/clangsupport/projectpartsstorage.h
index 4e29cee03e..e54a7a61d1 100644
--- a/src/libs/clangsupport/projectpartsstorage.h
+++ b/src/libs/clangsupport/projectpartsstorage.h
@@ -245,6 +245,22 @@ public:
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; }
static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
@@ -343,5 +359,11 @@ public:
"SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database};
mutable ReadStatement fetchProjectPrecompiledHeaderPathStatement{
"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
diff --git a/src/libs/clangsupport/projectpartsstorageinterface.h b/src/libs/clangsupport/projectpartsstorageinterface.h
index 1127f70b1f..2d0675e657 100644
--- a/src/libs/clangsupport/projectpartsstorageinterface.h
+++ b/src/libs/clangsupport/projectpartsstorageinterface.h
@@ -63,6 +63,7 @@ public:
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(
ProjectPartId projectPartId) const = 0;
+ virtual void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) = 0;
virtual Sqlite::TransactionInterface &transactionBackend() = 0;
diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h
index efca925413..a7058d3204 100644
--- a/src/libs/clangsupport/refactoringdatabaseinitializer.h
+++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h
@@ -177,6 +177,7 @@ public:
Sqlite::Contraint::PrimaryKey);
table.addColumn("size", Sqlite::ColumnType::Integer);
table.addColumn("lastModified", Sqlite::ColumnType::Integer);
+ table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer);
table.initialize(database);
}
@@ -188,6 +189,7 @@ public:
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
const Sqlite::Column &dependencySourceIdColumn = table.addColumn("dependencySourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn, dependencySourceIdColumn});
+ table.addIndex({dependencySourceIdColumn, sourceIdColumn});
table.initialize(database);
}
diff --git a/src/tools/clangpchmanagerbackend/source/sourceentry.h b/src/libs/clangsupport/sourceentry.h
index 5c45db6bde..c593f1fcd3 100644
--- a/src/tools/clangpchmanagerbackend/source/sourceentry.h
+++ b/src/libs/clangsupport/sourceentry.h
@@ -64,12 +64,12 @@ class SourceTimeStamp
using int64 = long long;
public:
SourceTimeStamp(int sourceId, int64 lastModified)
- : lastModified(lastModified)
+ : timeStamp(lastModified)
, sourceId(sourceId)
{}
SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified)
- : lastModified(lastModified)
+ : timeStamp(lastModified)
, sourceId(sourceId)
{}
@@ -90,7 +90,7 @@ public:
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)
@@ -99,7 +99,7 @@ public:
}
public:
- TimeStamp lastModified;
+ TimeStamp timeStamp;
FilePathId sourceId;
};
@@ -110,21 +110,22 @@ class SourceEntry
using int64 = long long;
public:
- SourceEntry(int sourceId,
- int64 pchCreationTimeStamp,
- int sourceType,
- int hasMissingIncludes)
- : pchCreationTimeStamp(pchCreationTimeStamp), sourceId(sourceId),
- sourceType(static_cast<SourceType>(sourceType)),
- hasMissingIncludes(
- static_cast<HasMissingIncludes>(hasMissingIncludes)) {}
+ SourceEntry(int sourceId, int64 timeStamp, int sourceType, int hasMissingIncludes)
+ : timeStamp(timeStamp)
+ , sourceId(sourceId)
+ , sourceType(static_cast<SourceType>(sourceType))
+ , hasMissingIncludes(static_cast<HasMissingIncludes>(hasMissingIncludes))
+ {}
SourceEntry(FilePathId sourceId,
SourceType sourceType,
- TimeStamp pchCreationTimeStamp,
+ TimeStamp timeStamp,
HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No)
- : pchCreationTimeStamp(pchCreationTimeStamp), sourceId(sourceId),
- sourceType(sourceType), hasMissingIncludes(hasMissingIncludes) {}
+ : timeStamp(timeStamp)
+ , sourceId(sourceId)
+ , sourceType(sourceType)
+ , hasMissingIncludes(hasMissingIncludes)
+ {}
friend bool operator<(SourceEntry first, SourceEntry second) {
return first.sourceId < second.sourceId;
@@ -133,13 +134,13 @@ public:
friend bool operator==(SourceEntry first, SourceEntry second)
{
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); }
public:
- TimeStamp pchCreationTimeStamp;
+ TimeStamp timeStamp;
FilePathId sourceId;
SourceType sourceType = SourceType::UserInclude;
HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No;
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
index 5af48386bd..ad5ee50476 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
@@ -47,7 +47,7 @@ void CompletionChunksToTextConverter::parseChunks(
m_codeCompletionChunks.cend(),
[this] (const ClangBackEnd::CodeCompletionChunk &chunk)
{
- parseDependendOnTheOptionalState(chunk);
+ parseDependentOnTheOptionalState(chunk);
m_previousCodeCompletionChunk = chunk;
});
}
@@ -200,7 +200,7 @@ void CompletionChunksToTextConverter::parse(
}
}
-void CompletionChunksToTextConverter::parseDependendOnTheOptionalState(
+void CompletionChunksToTextConverter::parseDependentOnTheOptionalState(
const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
{
wrapInCursiveTagIfOptional(codeCompletionChunk);
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
index 88654ed3fd..09ad15e30f 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
@@ -75,7 +75,7 @@ public:
private:
void parse(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parseDependendOnTheOptionalState(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
+ void parseDependentOnTheOptionalState(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
void parseResultType(const Utf8String &text);
void parseText(const Utf8String &text);
void wrapInCursiveTagIfOptional(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp
index 8dfe0c7977..a1e01911d6 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/compileroptionsbuilder.cpp
@@ -455,6 +455,8 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX2a:
option = (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a"));
break;
+ case LanguageVersion::None:
+ break;
}
add(option, /*gccOnlyOption=*/true);
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
index dc1c7085e7..a7ca916f15 100644
--- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
@@ -215,7 +215,8 @@ struct Data // because we have a cycle dependency
[&](ClangBackEnd::FilePathView path) -> TimeStamp {
return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch();
}};
- ClangBackEnd::ModifiedTimeChecker modifiedTimeChecker{getModifiedTime, filePathCache};
+ ClangBackEnd::ModifiedTimeChecker<ClangBackEnd::SourceEntries> modifiedTimeChecker{getModifiedTime,
+ filePathCache};
ClangBackEnd::BuildDependenciesProvider buildDependencyProvider{buildDependencyStorage,
modifiedTimeChecker,
buildDependencyCollector,
diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h
index 9700b83aa3..a006b10a06 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h
+++ b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h
@@ -27,6 +27,8 @@
#include "builddependenciesproviderinterface.h"
+#include <modifiedtimecheckerinterface.h>
+
namespace Sqlite {
class TransactionInterface;
}
@@ -34,14 +36,13 @@ class TransactionInterface;
namespace ClangBackEnd {
class BuildDependenciesStorageInterface;
-class ModifiedTimeCheckerInterface;
class BuildDependencyGeneratorInterface;
class BuildDependenciesProvider : public BuildDependenciesProviderInterface
{
public:
BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage,
- ModifiedTimeCheckerInterface &modifiedTimeChecker,
+ ModifiedTimeCheckerInterface<> &modifiedTimeChecker,
BuildDependencyGeneratorInterface &buildDependenciesGenerator,
Sqlite::TransactionInterface &transactionBackend)
: m_storage(buildDependenciesStorage)
@@ -61,7 +62,7 @@ private:
private:
BuildDependenciesStorageInterface &m_storage;
- ModifiedTimeCheckerInterface &m_modifiedTimeChecker;
+ ModifiedTimeCheckerInterface<> &m_modifiedTimeChecker;
BuildDependencyGeneratorInterface &m_generator;
Sqlite::TransactionInterface &m_transactionBackend;
};
diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
index 61bcedc262..bbf3bf16f4 100644
--- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
+++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
@@ -29,8 +29,6 @@ HEADERS += \
$$PWD/builddependenciesprovider.h \
$$PWD/builddependenciesstorageinterface.h \
$$PWD/builddependency.h \
- $$PWD/modifiedtimecheckerinterface.h \
- $$PWD/sourceentry.h \
$$PWD/builddependenciesstorage.h \
$$PWD/builddependencygeneratorinterface.h \
$$PWD/usedmacrofilter.h \
@@ -40,8 +38,7 @@ HEADERS += \
$$PWD/pchtaskqueue.h \
$$PWD/generatepchactionfactory.h \
$$PWD/pchtaskgeneratorinterface.h \
- $$PWD/toolchainargumentscache.h \
- $$PWD/modifiedtimechecker.h
+ $$PWD/toolchainargumentscache.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \
diff --git a/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h
index f3b365d8d5..9db095bd75 100644
--- a/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h
+++ b/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h
@@ -293,7 +293,7 @@ public:
entry.get().hasMissingIncludes = HasMissingIncludes::Yes;
}
- SourceDependencies sourceDependenciesSortedByDependendFilePathId() const
+ SourceDependencies sourceDependenciesSortedByDependentFilePathId() const
{
auto sourceDependencies = m_buildDependency.sourceDependencies;
std::sort(sourceDependencies.begin(), sourceDependencies.end(), [](auto first, auto second) {
@@ -309,7 +309,7 @@ public:
sortAndMakeUnique(m_containsMissingIncludes);
collectSourceWithMissingIncludes(m_containsMissingIncludes,
- sourceDependenciesSortedByDependendFilePathId());
+ sourceDependenciesSortedByDependentFilePathId());
removeSourceWithMissingIncludesFromSources();
}
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp
index 584d06ded2..cc4ca53d7d 100644
--- a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp
+++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp
@@ -65,7 +65,7 @@ ProjectPartContainers ProjectPartsManager::update(ProjectPartContainers &&projec
}
m_projectPartsStorage.updateProjectParts(updatedProjectParts);
-
+ m_projectPartsStorage.resetIndexingTimeStamps(updatedProjectParts);
m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders(
toProjectPartIds(updatedProjectParts));
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
index e21268322a..6d0978e54a 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
+++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
@@ -66,7 +66,8 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface,
- ProjectPartsStorageInterface &projectPartsStorage)
+ ProjectPartsStorageInterface &projectPartsStorage,
+ ModifiedTimeCheckerInterface<SourceTimeStamps> &modifiedTimeChecker)
: m_symbolIndexerTaskQueue(symbolIndexerTaskQueue)
, m_symbolStorage(symbolStorage)
, m_buildDependencyStorage(buildDependenciesStorage)
@@ -76,6 +77,7 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
, m_fileStatusCache(fileStatusCache)
, m_transactionInterface(transactionInterface)
, m_projectPartsStorage(projectPartsStorage)
+ , m_modifiedTimeChecker(modifiedTimeChecker)
{
pathWatcher.setNotifier(this);
}
@@ -109,23 +111,27 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
for (FilePathId sourcePathId : projectPart.sourcePathIds) {
- auto indexing = [arguments = commandLineBuilder.commandLine,
- sourcePathId,
- this](SymbolsCollectorInterface &symbolsCollector) {
- symbolsCollector.setFile(sourcePathId, arguments);
-
- bool success = symbolsCollector.collectSymbols();
-
- if (success) {
- Sqlite::ImmediateTransaction transaction{m_transactionInterface};
-
- m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
- symbolsCollector.sourceLocations());
- transaction.commit();
- }
- };
-
- symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing));
+ SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(
+ sourcePathId);
+
+ if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
+ auto indexing = [arguments = commandLineBuilder.commandLine, sourcePathId, this](
+ SymbolsCollectorInterface &symbolsCollector) {
+ symbolsCollector.setFile(sourcePathId, arguments);
+
+ bool success = symbolsCollector.collectSymbols();
+
+ if (success) {
+ Sqlite::ImmediateTransaction transaction{m_transactionInterface};
+ m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
+ m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
+ symbolsCollector.sourceLocations());
+ transaction.commit();
+ }
+ };
+
+ symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing));
+ }
}
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
@@ -136,11 +142,13 @@ void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {}
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
{
+ FilePathIds dependentSourcePathIds = m_symbolStorage.fetchDependentSourceIds(filePathIds);
+
std::vector<SymbolIndexerTask> symbolIndexerTask;
- symbolIndexerTask.reserve(filePathIds.size());
+ symbolIndexerTask.reserve(dependentSourcePathIds.size());
- for (FilePathId filePathId : filePathIds)
- updateChangedPath(filePathId, symbolIndexerTask);
+ for (FilePathId dependentSourcePathId : dependentSourcePathIds)
+ updateChangedPath(dependentSourcePathId, symbolIndexerTask);
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries();
@@ -161,6 +169,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
= m_precompiledHeaderStorage.fetchPrecompiledHeader(optionalArtefact->projectPartId);
transaction.commit();
+ SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId);
+
const ProjectPartArtefact &artefact = *optionalArtefact;
auto pchPath = optionalProjectPartPch ? optionalProjectPartPch->pchPath : FilePath{};
@@ -176,10 +186,9 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
if (success) {
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
-
+ m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
-
transaction.commit();
}
};
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.h b/src/tools/clangrefactoringbackend/source/symbolindexer.h
index c398c0f2bf..d574d0e01d 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexer.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexer.h
@@ -32,6 +32,7 @@
#include "clangpathwatcher.h"
#include <filecontainerv2.h>
+#include <modifiedtimecheckerinterface.h>
#include <precompiledheaderstorageinterface.h>
#include <projectpartcontainer.h>
#include <projectpartsstorageinterface.h>
@@ -51,7 +52,8 @@ public:
FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface,
- ProjectPartsStorageInterface &projectPartsStorage);
+ ProjectPartsStorageInterface &projectPartsStorage,
+ ModifiedTimeCheckerInterface<SourceTimeStamps> &modifiedTimeChecker);
void updateProjectParts(ProjectPartContainers &&projectParts);
void updateProjectPart(ProjectPartContainer &&projectPart);
@@ -81,6 +83,7 @@ private:
FileStatusCache &m_fileStatusCache;
Sqlite::TransactionInterface &m_transactionInterface;
ProjectPartsStorageInterface &m_projectPartsStorage;
+ ModifiedTimeCheckerInterface<SourceTimeStamps> &m_modifiedTimeChecker;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h
index c942059bad..10df4e397b 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexing.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h
@@ -38,13 +38,16 @@
#include <precompiledheaderstorage.h>
#include <projectpartsstorage.h>
-#include <refactoringdatabaseinitializer.h>
#include <filepathcachingfwd.h>
+#include <modifiedtimechecker.h>
+#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
+#include <QDateTime>
+#include <QFileInfo>
#include <QFileSystemWatcher>
#include <thread>
@@ -130,6 +133,12 @@ private:
FileStatusCache m_fileStatusCache{m_filePathCache};
SymbolsCollectorManager m_collectorManger;
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,
m_symbolStorage,
m_buildDependencyStorage,
@@ -138,7 +147,8 @@ private:
m_filePathCache,
m_fileStatusCache,
m_symbolStorage.database,
- m_projectPartsStorage};
+ m_projectPartsStorage,
+ m_modifiedTimeChecker};
SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter};
SymbolIndexerTaskScheduler m_indexerScheduler;
};
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h
index 9dffe48c96..f21b0412b8 100644
--- a/src/tools/clangrefactoringbackend/source/symbolstorage.h
+++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h
@@ -41,7 +41,7 @@
namespace ClangBackEnd {
-template <typename DatabaseType>
+template<typename DatabaseType = Sqlite::Database>
class SymbolStorage final : public SymbolStorageInterface
{
using Database = DatabaseType;
@@ -70,6 +70,93 @@ public:
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)
{
WriteStatement &statement = insertSymbolsToNewSymbolsStatement;
@@ -191,6 +278,25 @@ public:
database};
WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database};
WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database};
+ WriteStatement inserOrUpdateIndexingTimesStampStatement{
+ "INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON "
+ "CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002",
+ database};
+ mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{
+ "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
+ "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
+ "sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, "
+ "indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId",
+ database};
+ mutable ReadStatement fetchIndexingTimeStampsStatement{
+ "SELECT sourceId, indexingTimeStamp FROM fileStatuses", database};
+ mutable ReadStatement fetchDependentSourceIdsStatement{
+ "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
+ "sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE "
+ "sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId "
+ "FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM "
+ "sourceDependencies) ORDER BY sourceId",
+ database};
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
index 1d04c4d168..d3c8035e8c 100644
--- a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
+++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
@@ -28,6 +28,9 @@
#include "sourcelocationentry.h"
#include "symbolentry.h"
+#include <filestatus.h>
+#include <sourceentry.h>
+
#include <compilermacro.h>
#include <sqlitetransaction.h>
@@ -45,6 +48,11 @@ public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations)
= 0;
+ virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
+ virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
+ virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
+ virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
+ virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected:
~SymbolStorageInterface() = default;
diff --git a/tests/unit/unittest/builddependenciesprovider-test.cpp b/tests/unit/unittest/builddependenciesprovider-test.cpp
index 772a435a58..c9794c8cc0 100644
--- a/tests/unit/unittest/builddependenciesprovider-test.cpp
+++ b/tests/unit/unittest/builddependenciesprovider-test.cpp
@@ -58,7 +58,7 @@ class BuildDependenciesProvider : public testing::Test
protected:
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
- NiceMock<MockModifiedTimeChecker> mockModifiedTimeChecker;
+ NiceMock<MockSourceEntriesModifiedTimeChecker> mockModifiedTimeChecker;
NiceMock<MockBuildDependencyGenerator> mockBuildDependenciesGenerator;
ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage,
mockModifiedTimeChecker,
diff --git a/tests/unit/unittest/clangdocument-test.cpp b/tests/unit/unittest/clangdocument-test.cpp
index 26a4ab1bfd..4978f41fd7 100644
--- a/tests/unit/unittest/clangdocument-test.cpp
+++ b/tests/unit/unittest/clangdocument-test.cpp
@@ -201,7 +201,7 @@ TEST_F(DocumentSlowTest, NeedsReparseAfterChangeOfMainFile)
ASSERT_TRUE(document.isDirty());
}
-TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile)
+TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependentFile)
{
document.parse();
@@ -210,7 +210,7 @@ TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile)
ASSERT_FALSE(document.isDirty());
}
-TEST_F(DocumentSlowTest, NeedsReparsingForDependendFile)
+TEST_F(DocumentSlowTest, NeedsReparsingForDependentFile)
{
document.parse();
diff --git a/tests/unit/unittest/clangupdateannotationsjob-test.cpp b/tests/unit/unittest/clangupdateannotationsjob-test.cpp
index 0bcd5a67c0..79623619c1 100644
--- a/tests/unit/unittest/clangupdateannotationsjob-test.cpp
+++ b/tests/unit/unittest/clangupdateannotationsjob-test.cpp
@@ -97,16 +97,16 @@ TEST_F(UpdateAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentRevisionChange
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.prepareAsyncRun();
job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job));
- ASSERT_THAT(dependendOnFilesBefore, Not(document.dependedFilePaths()));
+ ASSERT_THAT(dependentOnFilesBefore, Not(document.dependedFilePaths()));
}
TEST_F(UpdateAnnotationsJobSlowTest, UpdatesUnresolvedFilePaths)
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 8644edea4d..84add6b4a1 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -1230,6 +1230,16 @@ std::ostream &operator<<(std::ostream &out, const SourceEntry &entry)
<< 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)
{
switch (type) {
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 9e2c5632f5..2d83535d14 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -165,7 +165,7 @@ class UpdateProjectPartsMessage;
class DocumentsChangedMessage;
class DocumentVisibilityChangedMessage;
class FilePath;
-template <char WindowsSlash>
+template<char WindowsSlash>
class AbstractFilePathView;
using FilePathView = AbstractFilePathView<'/'>;
using NativeFilePathView = AbstractFilePathView<'\\'>;
@@ -190,6 +190,8 @@ class PchTask;
class PchTaskSet;
class BuildDependency;
class SourceEntry;
+class SourceTimeStamp;
+class TimeStamp;
class FilePathCaching;
struct SlotUsage;
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 BuildDependency &dependency);
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 IncludeSearchPathType &pathType);
std::ostream &operator<<(std::ostream &out, const IncludeSearchPath &path);
diff --git a/tests/unit/unittest/mockmodifiedtimechecker.h b/tests/unit/unittest/mockmodifiedtimechecker.h
index 5f0559f682..bf101988b1 100644
--- a/tests/unit/unittest/mockmodifiedtimechecker.h
+++ b/tests/unit/unittest/mockmodifiedtimechecker.h
@@ -29,9 +29,17 @@
#include <modifiedtimecheckerinterface.h>
-class MockModifiedTimeChecker : public ClangBackEnd::ModifiedTimeCheckerInterface
+class MockSourceEntriesModifiedTimeChecker
+ : public ClangBackEnd::ModifiedTimeCheckerInterface<ClangBackEnd::SourceEntries>
{
public:
MOCK_CONST_METHOD1(isUpToDate,
bool (const ClangBackEnd::SourceEntries &sourceEntries));
};
+
+class MockSourceTimeStampsModifiedTimeChecker
+ : public ClangBackEnd::ModifiedTimeCheckerInterface<ClangBackEnd::SourceTimeStamps>
+{
+public:
+ MOCK_CONST_METHOD1(isUpToDate, bool(const ClangBackEnd::SourceTimeStamps &sourceTimeStamps));
+};
diff --git a/tests/unit/unittest/mockprojectpartsstorage.h b/tests/unit/unittest/mockprojectpartsstorage.h
index 114a7fab0e..e8dcbc94b2 100644
--- a/tests/unit/unittest/mockprojectpartsstorage.h
+++ b/tests/unit/unittest/mockprojectpartsstorage.h
@@ -56,5 +56,7 @@ public:
MOCK_CONST_METHOD1(fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>(
ClangBackEnd::ProjectPartId projectPartId));
+ MOCK_METHOD1(resetIndexingTimeStamps,
+ void(const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD0(transactionBackend, Sqlite::TransactionInterface &());
};
diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp
index c12d40b9ea..2e9d74acf6 100644
--- a/tests/unit/unittest/mocksqlitereadstatement.cpp
+++ b/tests/unit/unittest/mocksqlitereadstatement.cpp
@@ -222,6 +222,19 @@ SourceEntries MockSqliteReadStatement::values<SourceEntry, 4>(std::size_t reserv
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 <>
Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int &id)
diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h
index e3ab740b6e..135a6d1851 100644
--- a/tests/unit/unittest/mocksqlitereadstatement.h
+++ b/tests/unit/unittest/mocksqlitereadstatement.h
@@ -50,6 +50,8 @@
using ClangBackEnd::FilePathIds;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
+using ClangBackEnd::SourceTimeStamp;
+using ClangBackEnd::SourceTimeStamps;
using ClangRefactoring::SourceLocation;
using ClangRefactoring::SourceLocations;
using std::int64_t;
@@ -136,6 +138,9 @@ public:
MOCK_METHOD1(valueReturnProjectPartId,
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,
int ResultTypeCount = 1,
typename... QueryType>
@@ -283,6 +288,13 @@ SourceEntries MockSqliteReadStatement::values<SourceEntry, 4>(std::size_t reserv
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 <>
Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&);
diff --git a/tests/unit/unittest/mocksymbolstorage.h b/tests/unit/unittest/mocksymbolstorage.h
index a174389735..7b77868e8a 100644
--- a/tests/unit/unittest/mocksymbolstorage.h
+++ b/tests/unit/unittest/mocksymbolstorage.h
@@ -37,4 +37,11 @@ public:
MOCK_METHOD2(addSymbolsAndSourceLocations,
void(const ClangBackEnd::SymbolEntries &symbolEentries,
const ClangBackEnd::SourceLocationEntries &sourceLocations));
+ MOCK_METHOD2(insertOrUpdateIndexingTimeStamps,
+ void(const FilePathIds &filePathIds, ClangBackEnd::TimeStamp indexingTimeStamp));
+ MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &));
+ MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps());
+ MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps,
+ ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId));
+ MOCK_CONST_METHOD1(fetchDependentSourceIds, FilePathIds(const FilePathIds &sourcePathIds));
};
diff --git a/tests/unit/unittest/modifiedtimechecker-test.cpp b/tests/unit/unittest/modifiedtimechecker-test.cpp
index 8e0c881b38..ff0c3c66d8 100644
--- a/tests/unit/unittest/modifiedtimechecker-test.cpp
+++ b/tests/unit/unittest/modifiedtimechecker-test.cpp
@@ -57,7 +57,7 @@ protected:
ClangBackEnd::FilePathCaching filePathCache{database};
decltype(getModifiedTimeCallback.AsStdFunction()) callback = getModifiedTimeCallback
.AsStdFunction();
- ClangBackEnd::ModifiedTimeChecker checker{callback, filePathCache};
+ ClangBackEnd::ModifiedTimeChecker<> checker{callback, filePathCache};
SourceEntries upToDateEntries = {{id("/path1"), SourceType::UserInclude, 100},
{id("/path2"), SourceType::SystemInclude, 30}};
SourceEntries notUpToDateEntries = {{id("/path1"), SourceType::UserInclude, 50},
diff --git a/tests/unit/unittest/projectpartsmanager-test.cpp b/tests/unit/unittest/projectpartsmanager-test.cpp
index 235a7553ba..b12cbb6b2e 100644
--- a/tests/unit/unittest/projectpartsmanager-test.cpp
+++ b/tests/unit/unittest/projectpartsmanager-test.cpp
@@ -302,6 +302,7 @@ TEST_F(ProjectPartsManager, UpdateCallsIfNewProjectPartIsAdded)
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
+ EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)));
manager.update({projectPartContainer1});
}
@@ -337,6 +338,16 @@ TEST_F(ProjectPartsManager, UpdateCallsNotDeleteProjectPrecompiledHeadersIfNoNew
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)
{
EXPECT_CALL(mockProjectPartsStorage,
@@ -346,6 +357,8 @@ TEST_F(ProjectPartsManager, UpdateCallsIfOldProjectPartIsAdded)
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)))
.Times(0);
+ EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)))
+ .Times(0);
manager.update({projectPartContainer1});
}
@@ -361,6 +374,8 @@ TEST_F(ProjectPartsManager, UpdateCallsIfUpdatedProjectPartIsAdded)
updateProjectParts(ElementsAre(updatedProjectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
+ EXPECT_CALL(mockProjectPartsStorage,
+ resetIndexingTimeStamps(ElementsAre(updatedProjectPartContainer1)));
manager.update({updatedProjectPartContainer1});
}
diff --git a/tests/unit/unittest/projectpartsstorage-test.cpp b/tests/unit/unittest/projectpartsstorage-test.cpp
index 963248cd29..3c13f33ad6 100644
--- a/tests/unit/unittest/projectpartsstorage-test.cpp
+++ b/tests/unit/unittest/projectpartsstorage-test.cpp
@@ -27,12 +27,13 @@
#include "mocksqlitedatabase.h"
+#include <builddependenciesstorage.h>
#include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
-
+#include <symbolstorage.h>
namespace {
using ClangBackEnd::FilePathId;
@@ -104,6 +105,7 @@ protected:
MockSqliteReadStatement &fetchProjectPartsHeadersByIdStatement = storage.fetchProjectPartsHeadersByIdStatement;
MockSqliteReadStatement &fetchProjectPartsSourcesByIdStatement = storage.fetchProjectPartsSourcesByIdStatement;
MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderPathStatement;
+ MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement;
IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}};
IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User},
@@ -424,6 +426,35 @@ TEST_F(ProjectPartsStorage, FetchProjectPartArtefactByProjectPartIdReturnArtefac
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
{
using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>;
@@ -432,6 +463,8 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
Storage storage{database};
+ ClangBackEnd::SymbolStorage<> symbolStorage{database};
+ ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
};
TEST_F(ProjectPartsStorageSlow, FetchProjectPartName)
@@ -469,4 +502,26 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
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
diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
index 4865e2ebff..7177060311 100644
--- a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
+++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
@@ -131,7 +131,7 @@ TEST_F(RefactoringDatabaseInitializer, AddFileStatusesTable)
mockDatabase,
execute(Eq(
"CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, "
- "lastModified INTEGER)")));
+ "lastModified INTEGER, indexingTimeStamp INTEGER)")));
initializer.createFileStatusesTable();
}
@@ -140,8 +140,19 @@ TEST_F(RefactoringDatabaseInitializer, AddSourceDependenciesTable)
{
InSequence s;
- EXPECT_CALL(mockDatabase, 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 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();
}
@@ -189,40 +200,88 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
EXPECT_CALL(mockDatabase, isInitialized()).WillOnce(Return(false));
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, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_symbolKind_symbolName ON symbols(symbolKind, symbolName)")));
- EXPECT_CALL(mockDatabase, 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,
+ execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr "
+ "TEXT, symbolName TEXT, symbolKind INTEGER, signature TEXT)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_symbolKind_symbolName ON "
+ "symbols(symbolKind, symbolName)")));
+ EXPECT_CALL(mockDatabase,
+ 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,
execute(
Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY "
"KEY, projectPartName TEXT, toolChainArguments TEXT, compilerMacros "
"TEXT, systemIncludeSearchPaths TEXT, projectIncludeSearchPaths TEXT, "
"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,
execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsFiles(projectPartId INTEGER, "
"sourceId INTEGER, sourceType INTEGER, pchCreationTimeStamp INTEGER, "
"hasMissingIncludes INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsFiles_sourceId_projectPartId 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(
+ mockDatabase,
+ execute(
+ Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsFiles_sourceId_projectPartId "
+ "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(
mockDatabase,
execute(Eq(
"CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, "
- "lastModified INTEGER)")));
- EXPECT_CALL(mockDatabase, 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 TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, systemPchPath TEXT, systemPchBuildTime INTEGER)")));
+ "lastModified INTEGER, indexingTimeStamp INTEGER)")));
+ EXPECT_CALL(mockDatabase,
+ 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)")));
+ 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,
execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsHeaders(projectPartId 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 TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, "
- "size INTEGER, lastModified INTEGER, isInPrecompiledHeader INTEGER)")))
+ "size INTEGER, lastModified INTEGER, indexingTimeStamp 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);
diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp
index edfcb286ad..0be2d3b0e5 100644
--- a/tests/unit/unittest/symbolindexer-test.cpp
+++ b/tests/unit/unittest/symbolindexer-test.cpp
@@ -28,6 +28,7 @@
#include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h"
#include "mockfilepathcaching.h"
+#include "mockmodifiedtimechecker.h"
#include "mockprecompiledheaderstorage.h"
#include "mockprojectpartsstorage.h"
#include "mocksqlitetransactionbackend.h"
@@ -113,7 +114,12 @@ protected:
.WillByDefault(Return(artefact));
ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1));
ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true));
-
+ ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
+ .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);
generatedFiles.update(unsaved);
@@ -230,6 +236,10 @@ protected:
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
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;
ClangBackEnd::ProjectPartPch projectPartPch{74, "/path/to/pch", 4};
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
@@ -243,6 +253,7 @@ protected:
Manager collectorManger{generatedFiles};
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
+ NiceMock<MockSourceTimeStampsModifiedTimeChecker> mockModifiedTimeChecker;
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
mockSymbolStorage,
mockBuildDependenciesStorage,
@@ -251,7 +262,8 @@ protected:
filePathCache,
fileStatusCache,
mockSqliteTransactionBackend,
- mockProjectPartsStorage};
+ mockProjectPartsStorage,
+ mockModifiedTimeChecker};
SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter};
Scheduler indexerScheduler{collectorManger,
indexerQueue,
@@ -493,6 +505,58 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS
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)
{
EXPECT_CALL(mockPathWatcher, setNotifier(_));
@@ -505,7 +569,8 @@ TEST_F(SymbolIndexer, CallSetNotifier)
filePathCache,
fileStatusCache,
mockSqliteTransactionBackend,
- mockProjectPartsStorage};
+ mockProjectPartsStorage,
+ mockModifiedTimeChecker};
}
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
@@ -516,6 +581,54 @@ TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
indexer.pathsChanged(sourceFileIds);
}
+TEST_F(SymbolIndexer, PathChangedCallsFetchSourcePathIds)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
+ .WillOnce(Return(FilePathIds{2, 6, 5}));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{2}));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{6}));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{5}));
+
+ indexer.pathsChanged(sourceFileIds);
+}
+
+TEST_F(SymbolIndexer, PathChangedFetchIncludedIndexingTimeStamps)
+{
+ InSequence s;
+ ProjectPartContainer projectPart{1,
+ {"-Wno-pragma-once-outside-header"},
+ {{"BAR", "1", 1}, {"FOO", "1", 2}},
+ Utils::clone(systemIncludeSearchPaths),
+ Utils::clone(projectIncludeSearchPaths),
+ {header1PathId},
+ {main1PathId, main2PathId},
+ Utils::Language::Cxx,
+ Utils::LanguageVersion::CXX14,
+ Utils::LanguageExtension::None};
+
+ EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillOnce(Return(FilePathIds{1, 2}));
+ EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(1)))
+ .WillOnce(Return(dependentSourceTimeStamps1));
+ EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(2)))
+ .WillOnce(Return(dependentSourceTimeStamps2));
+ EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses1));
+ EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
+ EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses2));
+ EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
+
+ indexer.pathsChanged({1, 3});
+}
+
+TEST_F(SymbolIndexer, PathChangedFetchesDependentSourceIdsFromStorage)
+{
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1]));
+
+ indexer.pathsChanged(sourceFileIds);
+}
+
TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
{
InSequence s;
@@ -797,6 +910,7 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache)
auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp");
auto oldLastModified = fileStatusCache.lastModifiedTime(sourceId);
touchFile(sourceId);
+ ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId}));
indexer.pathsChanged({sourceId});
diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp
index 059b1a3c0f..a29b7f92aa 100644
--- a/tests/unit/unittest/symbolstorage-test.cpp
+++ b/tests/unit/unittest/symbolstorage-test.cpp
@@ -28,17 +28,22 @@
#include "mockfilepathcaching.h"
#include "mocksqlitedatabase.h"
-#include <symbolstorage.h>
+#include <builddependenciesstorage.h>
+#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
+#include <sqlitereadstatement.h>
+#include <sqlitewritestatement.h>
+#include <symbolstorage.h>
#include <utils/optional.h>
namespace {
-
using ClangBackEnd::FilePathCachingInterface;
+using ClangBackEnd::FilePathId;
using ClangBackEnd::SourceLocationEntries;
using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::SourceLocationKind;
+using ClangBackEnd::SourceTimeStamp;
using ClangBackEnd::SymbolEntries;
using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SymbolIndex;
@@ -64,6 +69,10 @@ protected:
MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement;
MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement;
MockSqliteWriteStatement &deleteNewLocationsTableStatement = storage.deleteNewLocationsTableStatement;
+ MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement;
+ MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement;
+ MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement;
+ MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement;
SymbolEntries symbolEntries{{1, {"functionUSR", "function", SymbolKind::Function}},
{2, {"function2USR", "function2", SymbolKind::Function}}};
SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration},
@@ -183,5 +192,145 @@ TEST_F(SymbolStorage, AddTablesInConstructor)
Storage storage{mockDatabase};
}
+TEST_F(SymbolStorage, FetchIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, rollback());
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.fetchIndexingTimeStamps();
+}
+
+TEST_F(SymbolStorage, InsertIndexingTimeStamp)
+{
+ ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}};
+
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(37)));
+
+ storage.insertOrUpdateIndexingTimeStamps(fileStatuses);
+}
+
+TEST_F(SymbolStorage, InsertIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, immediateBegin());
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(34)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
+}
+
+TEST_F(SymbolStorage, FetchIncludedIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
+ valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, rollback());
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
+ valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.fetchIncludedIndexingTimeStamps(1);
+}
+
+TEST_F(SymbolStorage, FetchDependentSourceIdsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, rollback());
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)));
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(7)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.fetchDependentSourceIds({3, 2, 7});
+}
+
+class SymbolStorageSlow : public testing::Test
+{
+protected:
+ Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
+ ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
+ ClangBackEnd::SymbolStorage<> storage{database};
+ ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
+};
+
+TEST_F(SymbolStorageSlow, InsertIndexingTimeStamps)
+{
+ storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34}));
+}
+
+TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamps)
+{
+ storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
+
+ storage.insertOrUpdateIndexingTimeStamps({1}, 37);
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34}));
}
+TEST_F(SymbolStorageSlow, InsertIndexingTimeStamp)
+{
+ storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}});
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
+}
+
+TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamp)
+{
+ storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}});
+
+ storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}});
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
+}
+
+TEST_F(SymbolStorageSlow, FetchIncludedIndexingTimeStamps)
+{
+ storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34);
+ buildDependenciesStorage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}});
+
+ auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1);
+
+ ASSERT_THAT(timeStamps,
+ ElementsAre(SourceTimeStamp{1, 34},
+ SourceTimeStamp{2, 34},
+ SourceTimeStamp{3, 34},
+ SourceTimeStamp{4, 34}));
+}
+
+TEST_F(SymbolStorageSlow, FetchDependentSourceIds)
+{
+ buildDependenciesStorage.insertOrUpdateSourceDependencies(
+ {{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}});
+
+ auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7});
+
+ ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7}));
+}
+} // namespace
diff --git a/tests/unit/unittest/translationunitupdater-test.cpp b/tests/unit/unittest/translationunitupdater-test.cpp
index b491018956..eecc06b8a7 100644
--- a/tests/unit/unittest/translationunitupdater-test.cpp
+++ b/tests/unit/unittest/translationunitupdater-test.cpp
@@ -113,7 +113,7 @@ TEST_F(TranslationUnitUpdaterSlowTest, NotUpdatingParseTimePointForReparseOnly)
ASSERT_FALSE(result.hasParsed());
}
-TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependendOnFilesOnParse)
+TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependentOnFilesOnParse)
{
::TranslationUnitUpdater updater = createUpdater(createInput());