Clang: Optimize file path cache

We now fetch all directories and sources from the database at file
path cache creation.

Change-Id: I92510b49a234128f4c82b840611db82ead3f1a54
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-08-06 13:12:03 +02:00
parent 912b4763e0
commit f9fb4508d4
23 changed files with 295 additions and 210 deletions

View File

@@ -29,6 +29,7 @@
#include "filepath.h" #include "filepath.h"
#include "filepathexceptions.h" #include "filepathexceptions.h"
#include "filepathid.h" #include "filepathid.h"
#include "filepathstoragesources.h"
#include "filepathview.h" #include "filepathview.h"
#include "stringcache.h" #include "stringcache.h"
@@ -39,84 +40,36 @@ namespace ClangBackEnd {
template <typename FilePathStorage> template <typename FilePathStorage>
class CLANGSUPPORT_GCCEXPORT FilePathCache class CLANGSUPPORT_GCCEXPORT FilePathCache
{ {
class FileNameView
{
public:
friend bool operator==(const FileNameView &first, const FileNameView &second)
{
return first.directoryId == second.directoryId
&& first.fileName == second.fileName;
}
static
int compare(FileNameView first, FileNameView second) noexcept
{
int directoryDifference = first.directoryId - second.directoryId;
if (directoryDifference)
return directoryDifference;
return Utils::compare(first.fileName, second.fileName);
}
public:
Utils::SmallStringView fileName;
int directoryId;
};
class FileNameEntry
{
public:
FileNameEntry(Utils::SmallStringView fileName, int directoryId)
: fileName(fileName),
directoryId(directoryId)
{}
FileNameEntry(FileNameView view)
: fileName(view.fileName),
directoryId(view.directoryId)
{}
friend bool operator==(const FileNameEntry &first, const FileNameEntry &second)
{
return first.directoryId == second.directoryId
&& first.fileName == second.fileName;
}
operator FileNameView() const
{
return {fileName, directoryId};
}
operator Utils::SmallString() &&
{
return std::move(fileName);
}
public:
Utils::SmallString fileName;
int directoryId;
};
using DirectoryPathCache = StringCache<Utils::PathString, using DirectoryPathCache = StringCache<Utils::PathString,
Utils::SmallStringView, Utils::SmallStringView,
int, int,
SharedMutex, SharedMutex,
decltype(&Utils::reverseCompare), decltype(&Utils::reverseCompare),
Utils::reverseCompare>; Utils::reverseCompare,
Sources::Directory>;
using FileNameCache = StringCache<FileNameEntry, using FileNameCache = StringCache<FileNameEntry,
FileNameView, FileNameView,
int, int,
SharedMutex, SharedMutex,
decltype(&FileNameView::compare), decltype(&FileNameView::compare),
FileNameView::compare>; FileNameView::compare,
Sources::Source>;
FilePathCache(const FilePathCache &) = default;
FilePathCache &operator=(const FilePathCache &) = default;
public: public:
FilePathCache(FilePathStorage &filePathStorage) FilePathCache(FilePathStorage &filePathStorage)
: m_filePathStorage(filePathStorage) : m_filePathStorage(filePathStorage)
{} {
m_directoryPathCache.populate(filePathStorage.fetchAllDirectories());
m_fileNameCache.populate(filePathStorage.fetchAllSources());
}
FilePathCache(const FilePathCache &) = delete; FilePathCache(FilePathCache &&) = default;
FilePathCache &operator=(const FilePathCache &) = delete; FilePathCache &operator=(FilePathCache &&) = default;
FilePathCache clone() { return *this; }
FilePathId filePathId(FilePathView filePath) const FilePathId filePathId(FilePathView filePath) const
{ {

View File

@@ -52,4 +52,29 @@ DirectoryPathId FilePathCaching::directoryPathId(FilePathId filePathId) const
return m_cache.directoryPathId(filePathId); return m_cache.directoryPathId(filePathId);
} }
FilePathId CopyableFilePathCaching::filePathId(FilePathView filePath) const
{
return m_cache.filePathId(filePath);
}
FilePath CopyableFilePathCaching::filePath(FilePathId filePathId) const
{
return m_cache.filePath(filePathId);
}
DirectoryPathId CopyableFilePathCaching::directoryPathId(Utils::SmallStringView directoryPath) const
{
return m_cache.directoryPathId(directoryPath);
}
Utils::PathString CopyableFilePathCaching::directoryPath(DirectoryPathId directoryPathId) const
{
return m_cache.directoryPath(directoryPathId);
}
DirectoryPathId CopyableFilePathCaching::directoryPathId(FilePathId filePathId) const
{
return m_cache.directoryPathId(filePathId);
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -40,9 +40,11 @@ namespace ClangBackEnd {
class CLANGSUPPORT_EXPORT FilePathCaching final : public FilePathCachingInterface class CLANGSUPPORT_EXPORT FilePathCaching final : public FilePathCachingInterface
{ {
friend class CopyableFilePathCaching;
using Factory = FilePathStorageSqliteStatementFactory<Sqlite::Database>; using Factory = FilePathStorageSqliteStatementFactory<Sqlite::Database>;
using Storage = FilePathStorage<Factory>; using Storage = FilePathStorage<Factory>;
using Cache = FilePathCache<Storage>; using Cache = FilePathCache<Storage>;
public: public:
FilePathCaching(Sqlite::Database &database) FilePathCaching(Sqlite::Database &database)
: m_factory(database) : m_factory(database)
@@ -60,4 +62,25 @@ private:
Cache m_cache{m_storage}; Cache m_cache{m_storage};
}; };
class CLANGSUPPORT_EXPORT CopyableFilePathCaching final : public FilePathCachingInterface
{
using Factory = FilePathStorageSqliteStatementFactory<Sqlite::Database>;
using Storage = FilePathStorage<Factory>;
using Cache = FilePathCache<Storage>;
public:
CopyableFilePathCaching(FilePathCaching &cache)
: m_cache(cache.m_cache.clone())
{}
FilePathId filePathId(FilePathView filePath) const override;
FilePath filePath(FilePathId filePathId) const override;
DirectoryPathId directoryPathId(Utils::SmallStringView directoryPath) const override;
Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override;
DirectoryPathId directoryPathId(FilePathId filePathId) const override;
private:
Cache m_cache;
};
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -212,7 +212,7 @@ public:
ReadStatement &statement = m_statementFactory.selectAllSources; ReadStatement &statement = m_statementFactory.selectAllSources;
auto sources = statement.template values<Sources::Source, 2>(8192); auto sources = statement.template values<Sources::Source, 3>(8192);
transaction.commit(); transaction.commit();

View File

@@ -33,41 +33,106 @@
#include <unordered_map> #include <unordered_map>
namespace ClangBackEnd { namespace ClangBackEnd {
namespace Sources {
class Directory template<typename StringType, typename StringViewType, typename IndexType>
class StringCacheEntry
{ {
public: public:
Directory(int directoryId, Utils::PathString &&directoryPath) StringCacheEntry(StringViewType string, IndexType id)
: directoryId(directoryId), directoryPath(std::move(directoryPath)) : string(string)
, id(id)
{} {}
friend operator StringViewType() const { return string; }
bool operator==(const Directory &first, const Directory &second)
{
return first.directoryId == second.directoryId && first.directoryPath == second.directoryPath;
}
public: public:
int directoryId; StringType string;
Utils::PathString directoryPath; IndexType id;
}; };
class Source class FileNameView
{ {
public: public:
Source(int sourceId, Utils::PathString &&sourceName) friend bool operator==(const FileNameView &first, const FileNameView &second)
: sourceId(sourceId), sourceName(std::move(sourceName))
{}
friend
bool operator==(const Source &first, const Source &second)
{ {
return first.sourceId == second.sourceId && first.sourceName == second.sourceName; return first.directoryId == second.directoryId && first.fileName == second.fileName;
}
static int compare(FileNameView first, FileNameView second) noexcept
{
int directoryDifference = first.directoryId - second.directoryId;
if (directoryDifference)
return directoryDifference;
return Utils::compare(first.fileName, second.fileName);
} }
public: public:
int sourceId; Utils::SmallStringView fileName;
Utils::PathString sourceName; int directoryId;
};
class FileNameEntry
{
public:
FileNameEntry(Utils::SmallStringView fileName, int directoryId)
: fileName(fileName)
, directoryId(directoryId)
{}
FileNameEntry(FileNameView view)
: fileName(view.fileName)
, directoryId(view.directoryId)
{}
friend bool operator==(const FileNameEntry &first, const FileNameEntry &second)
{
return first.directoryId == second.directoryId && first.fileName == second.fileName;
}
friend bool operator!=(const FileNameEntry &first, const FileNameEntry &second)
{
return !(first == second);
}
operator FileNameView() const { return {fileName, directoryId}; }
operator Utils::SmallString() && { return std::move(fileName); }
public:
Utils::SmallString fileName;
int directoryId;
};
namespace Sources {
class Directory : public StringCacheEntry<Utils::PathString, Utils::SmallStringView, int>
{
using Base = StringCacheEntry<Utils::PathString, Utils::SmallStringView, int>;
public:
using Base::Base;
friend bool operator==(const Directory &first, const Directory &second)
{
return first.id == second.id && first.string == second.string;
}
};
class Source : public StringCacheEntry<FileNameEntry, FileNameView, int>
{
using Base = StringCacheEntry<FileNameEntry, FileNameView, int>;
public:
using Base::Base;
Source(Utils::SmallStringView sourceName, int directoryId, int sourceId)
: Base{{sourceName, directoryId}, sourceId}
{}
friend bool operator==(const Source &first, const Source &second)
{
return first.id == second.id && first.string == second.string;
}
}; };
class SourceNameAndDirectoryId class SourceNameAndDirectoryId

View File

@@ -50,13 +50,8 @@ public:
database database
}; };
ReadStatement selectDirectoryPathFromDirectoriesByDirectoryId{ ReadStatement selectDirectoryPathFromDirectoriesByDirectoryId{
"SELECT directoryPath FROM directories WHERE directoryId = ?", "SELECT directoryPath FROM directories WHERE directoryId = ?", database};
database ReadStatement selectAllDirectories{"SELECT directoryPath, directoryId FROM directories", database};
};
ReadStatement selectAllDirectories{
"SELECT directoryId, directoryPath FROM directories",
database
};
WriteStatement insertIntoDirectories{ WriteStatement insertIntoDirectories{
"INSERT INTO directories(directoryPath) VALUES (?)", "INSERT INTO directories(directoryPath) VALUES (?)",
database database
@@ -75,10 +70,7 @@ public:
"INSERT INTO sources(directoryId, sourceName) VALUES (?,?)", "INSERT INTO sources(directoryId, sourceName) VALUES (?,?)",
database database
}; };
ReadStatement selectAllSources{ ReadStatement selectAllSources{"SELECT sourceName, directoryId, sourceId FROM sources", database};
"SELECT sourceId, sourceName FROM sources",
database
};
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,9 +25,11 @@
#pragma once #pragma once
#include "filepathstoragesources.h"
#include "stringcachealgorithms.h" #include "stringcachealgorithms.h"
#include "stringcachefwd.h" #include "stringcachefwd.h"
#include <utils/algorithm.h>
#include <utils/optional.h> #include <utils/optional.h>
#include <utils/smallstringfwd.h> #include <utils/smallstringfwd.h>
@@ -90,42 +92,17 @@ private:
QReadWriteLock m_mutex; QReadWriteLock m_mutex;
}; };
template <typename StringType, template<typename StringType,
typename StringViewType,
typename IndexType>
class StringCacheEntry
{
public:
StringCacheEntry(StringType &&string, IndexType id)
: string(std::move(string)),
id(id)
{}
operator StringViewType() const
{
return string;
}
StringType string;
IndexType id;
};
template <typename StringType,
typename StringViewType,
typename IndexType>
using StringCacheEntries = std::vector<StringCacheEntry<StringType, StringViewType, IndexType>>;
template <typename StringType,
typename StringViewType, typename StringViewType,
typename IndexType, typename IndexType,
typename Mutex, typename Mutex,
typename Compare, typename Compare,
Compare compare = Utils::compare> Compare compare = Utils::compare,
typename CacheEntry = StringCacheEntry<StringType, StringViewType, IndexType>>
class StringCache class StringCache
{ {
public: public:
using CacheEntry = StringCacheEntry<StringType, StringViewType, IndexType>; using CacheEntries = std::vector<CacheEntry>;
using CacheEntries = StringCacheEntries<StringType, StringViewType, IndexType>;
using const_iterator = typename CacheEntries::const_iterator; using const_iterator = typename CacheEntries::const_iterator;
using Found = ClangBackEnd::Found<const_iterator>; using Found = ClangBackEnd::Found<const_iterator>;
@@ -135,8 +112,19 @@ public:
m_indices.reserve(reserveSize); m_indices.reserve(reserveSize);
} }
StringCache(const StringCache &) = delete; StringCache(const StringCache &other)
StringCache &operator=(const StringCache &) = delete; : m_strings(other.m_strings)
, m_indices(other.m_indices)
{}
StringCache &operator=(const StringCache &other)
{
if (*this != other) {
m_strings = other.m_strings;
m_indices = other.m_indices;
}
return *this;
}
void populate(CacheEntries &&entries) void populate(CacheEntries &&entries)
{ {
@@ -154,14 +142,25 @@ public:
}); });
m_strings = std::move(entries); m_strings = std::move(entries);
m_indices.resize(m_strings.size());
int max_id = 0;
auto found = std::max_element(m_strings.begin(),
m_strings.end(),
[](const auto &first, const auto &second) {
return first.id < second.id;
});
if (found != m_strings.end())
max_id = found->id + 1;
m_indices.resize(max_id, -1);
auto begin = m_strings.cbegin(); auto begin = m_strings.cbegin();
for (auto current = begin; current != m_strings.end(); ++current) for (auto current = begin; current != m_strings.end(); ++current)
m_indices.at(current->id) = std::distance(begin, current); m_indices[current->id] = std::distance(begin, current);
} }
IndexType stringId(StringViewType stringView) IndexType stringId(StringViewType stringView)
{ {
std::shared_lock<Mutex> sharedLock(m_mutex); std::shared_lock<Mutex> sharedLock(m_mutex);
@@ -176,7 +175,7 @@ public:
found = find(stringView); found = find(stringView);
if (!found.wasFound) { if (!found.wasFound) {
IndexType index = insertString(found.iterator, stringView, IndexType(m_indices.size())); IndexType index = insertString(found.iterator, stringView, IndexType(m_indices.size()));
found.iterator = m_strings.begin() + index;; found.iterator = m_strings.begin() + index;
} }
return found.iterator->id; return found.iterator->id;
@@ -300,7 +299,7 @@ private:
StringViewType stringView, StringViewType stringView,
IndexType id) IndexType id)
{ {
auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id); auto inserted = m_strings.emplace(beforeIterator, stringView, id);
auto newIndex = IndexType(std::distance(m_strings.begin(), inserted)); auto newIndex = IndexType(std::distance(m_strings.begin(), inserted));

View File

@@ -31,12 +31,7 @@ namespace ClangBackEnd {
class NonLockingMutex; class NonLockingMutex;
template <typename StringType, template<typename StringType, typename StringViewType, typename IndexType, typename Mutex, typename Compare, Compare compare, typename CacheEntry>
typename StringViewType,
typename IndexType,
typename Mutex,
typename Compare,
Compare compare>
class StringCache; class StringCache;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -139,13 +139,13 @@ public:
using Processor = ClangBackEnd::PchCreator; using Processor = ClangBackEnd::PchCreator;
PchCreatorManager(const ClangBackEnd::GeneratedFiles &generatedFiles, PchCreatorManager(const ClangBackEnd::GeneratedFiles &generatedFiles,
ClangBackEnd::Environment &environment, ClangBackEnd::Environment &environment,
Sqlite::Database &database, ClangBackEnd::FilePathCaching &filePathCache,
PchManagerServer &pchManagerServer, PchManagerServer &pchManagerServer,
ClangBackEnd::ClangPathWatcherInterface &pathWatcher, ClangBackEnd::ClangPathWatcherInterface &pathWatcher,
ClangBackEnd::BuildDependenciesStorageInterface &buildDependenciesStorage) ClangBackEnd::BuildDependenciesStorageInterface &buildDependenciesStorage)
: ProcessorManager(generatedFiles) : ProcessorManager(generatedFiles)
, m_environment(environment) , m_environment(environment)
, m_database(database) , m_filePathCache(filePathCache)
, m_pchManagerServer(pchManagerServer) , m_pchManagerServer(pchManagerServer)
, m_pathWatcher(pathWatcher) , m_pathWatcher(pathWatcher)
, m_buildDependenciesStorage(buildDependenciesStorage) , m_buildDependenciesStorage(buildDependenciesStorage)
@@ -155,7 +155,7 @@ protected:
std::unique_ptr<ClangBackEnd::PchCreator> createProcessor() const override std::unique_ptr<ClangBackEnd::PchCreator> createProcessor() const override
{ {
return std::make_unique<PchCreator>(m_environment, return std::make_unique<PchCreator>(m_environment,
m_database, m_filePathCache,
*m_pchManagerServer.client(), *m_pchManagerServer.client(),
m_pathWatcher, m_pathWatcher,
m_buildDependenciesStorage); m_buildDependenciesStorage);
@@ -163,7 +163,7 @@ protected:
private: private:
ClangBackEnd::Environment &m_environment; ClangBackEnd::Environment &m_environment;
Sqlite::Database &m_database; ClangBackEnd::FilePathCaching &m_filePathCache;
ClangBackEnd::PchManagerServer &m_pchManagerServer; ClangBackEnd::PchManagerServer &m_pchManagerServer;
ClangBackEnd::ClangPathWatcherInterface &m_pathWatcher; ClangBackEnd::ClangPathWatcherInterface &m_pathWatcher;
ClangBackEnd::BuildDependenciesStorageInterface &m_buildDependenciesStorage; ClangBackEnd::BuildDependenciesStorageInterface &m_buildDependenciesStorage;
@@ -194,7 +194,7 @@ struct Data // because we have a cycle dependency
generatedFiles}; generatedFiles};
PchCreatorManager pchCreatorManager{generatedFiles, PchCreatorManager pchCreatorManager{generatedFiles,
environment, environment,
database, filePathCache,
clangPchManagerServer, clangPchManagerServer,
includeWatcher, includeWatcher,
buildDependencyStorage}; buildDependencyStorage};

View File

@@ -211,7 +211,7 @@ void PchCreator::doInMainThreadAfterFinished()
} }
} }
const FilePathCaching &PchCreator::filePathCache() const FilePathCachingInterface &PchCreator::filePathCache()
{ {
return m_filePathCache; return m_filePathCache;
} }

View File

@@ -54,14 +54,16 @@ class PchCreator final : public PchCreatorInterface
{ {
public: public:
PchCreator(Environment &environment, PchCreator(Environment &environment,
Sqlite::Database &database, FilePathCaching &filePathCache,
PchManagerClientInterface &pchManagerClient, PchManagerClientInterface &pchManagerClient,
ClangPathWatcherInterface &clangPathwatcher, ClangPathWatcherInterface &clangPathwatcher,
BuildDependenciesStorageInterface &buildDependenciesStorage) BuildDependenciesStorageInterface &buildDependenciesStorage)
: m_filePathCache(database), m_environment(environment), : m_filePathCache(filePathCache)
m_pchManagerClient(pchManagerClient), , m_environment(environment)
m_clangPathwatcher(clangPathwatcher), , m_pchManagerClient(pchManagerClient)
m_buildDependenciesStorage(buildDependenciesStorage) {} , m_clangPathwatcher(clangPathwatcher)
, m_buildDependenciesStorage(buildDependenciesStorage)
{}
void generatePch(PchTask &&pchTask) override; void generatePch(PchTask &&pchTask) override;
const ProjectPartPch &projectPartPch() override; const ProjectPartPch &projectPartPch() override;
@@ -71,7 +73,7 @@ public:
void clear() override; void clear() override;
void doInMainThreadAfterFinished() override; void doInMainThreadAfterFinished() override;
const FilePathCaching &filePathCache(); const FilePathCachingInterface &filePathCache();
Utils::SmallString generatePchIncludeFileContent(const FilePathIds &includeIds) const; Utils::SmallString generatePchIncludeFileContent(const FilePathIds &includeIds) const;
bool generatePch(NativeFilePathView path, Utils::SmallStringView content); bool generatePch(NativeFilePathView path, Utils::SmallStringView content);
@@ -93,7 +95,7 @@ private:
mutable std::mt19937_64 randomNumberGenator{std::random_device{}()}; mutable std::mt19937_64 randomNumberGenator{std::random_device{}()};
ClangTool m_clangTool; ClangTool m_clangTool;
ProjectPartPch m_projectPartPch; ProjectPartPch m_projectPartPch;
FilePathCaching m_filePathCache; CopyableFilePathCaching m_filePathCache;
FilePathIds m_watchedSystemIncludes; FilePathIds m_watchedSystemIncludes;
FilePathIds m_watchedProjectIncludes; FilePathIds m_watchedProjectIncludes;
FilePathIds m_watchedUserIncludes; FilePathIds m_watchedUserIncludes;

View File

@@ -63,19 +63,19 @@ class SymbolsCollectorManager final : public ClangBackEnd::ProcessorManager<Symb
public: public:
using Processor = SymbolsCollector; using Processor = SymbolsCollector;
SymbolsCollectorManager(const ClangBackEnd::GeneratedFiles &generatedFiles, SymbolsCollectorManager(const ClangBackEnd::GeneratedFiles &generatedFiles,
Sqlite::Database &database) FilePathCaching &filePathCache)
: ProcessorManager(generatedFiles), : ProcessorManager(generatedFiles)
m_database(database) , m_filePathCache(filePathCache)
{} {}
protected: protected:
std::unique_ptr<SymbolsCollector> createProcessor() const std::unique_ptr<SymbolsCollector> createProcessor() const
{ {
return std::make_unique<SymbolsCollector>(m_database); return std::make_unique<SymbolsCollector>(m_filePathCache);
} }
private: private:
Sqlite::Database &m_database; FilePathCaching &m_filePathCache;
}; };
class SymbolIndexing final : public SymbolIndexingInterface class SymbolIndexing final : public SymbolIndexingInterface
@@ -84,7 +84,7 @@ public:
using BuildDependenciesStorage = ClangBackEnd::BuildDependenciesStorage<Sqlite::Database>; using BuildDependenciesStorage = ClangBackEnd::BuildDependenciesStorage<Sqlite::Database>;
using SymbolStorage = ClangBackEnd::SymbolStorage<Sqlite::Database>; using SymbolStorage = ClangBackEnd::SymbolStorage<Sqlite::Database>;
SymbolIndexing(Sqlite::Database &database, SymbolIndexing(Sqlite::Database &database,
FilePathCachingInterface &filePathCache, FilePathCaching &filePathCache,
const GeneratedFiles &generatedFiles, const GeneratedFiles &generatedFiles,
ProgressCounter::SetProgressCallback &&setProgressCallback, ProgressCounter::SetProgressCallback &&setProgressCallback,
const Environment &environment) const Environment &environment)
@@ -93,7 +93,7 @@ public:
, m_precompiledHeaderStorage(database) , m_precompiledHeaderStorage(database)
, m_projectPartsStorage(database) , m_projectPartsStorage(database)
, m_symbolStorage(database) , m_symbolStorage(database)
, m_collectorManger(generatedFiles, database) , m_collectorManger(generatedFiles, filePathCache)
, m_progressCounter(std::move(setProgressCallback)) , m_progressCounter(std::move(setProgressCallback))
, m_indexer(m_indexerQueue, , m_indexer(m_indexerQueue,
m_symbolStorage, m_symbolStorage,

View File

@@ -31,8 +31,8 @@
namespace ClangBackEnd { namespace ClangBackEnd {
SymbolsCollector::SymbolsCollector(Sqlite::Database &database) SymbolsCollector::SymbolsCollector(FilePathCaching &filePathCache)
: m_filePathCache(database) : m_filePathCache(filePathCache)
, m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries, , m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries,
m_sourceLocationEntries, m_sourceLocationEntries,
m_filePathCache, m_filePathCache,

View File

@@ -42,7 +42,7 @@ namespace ClangBackEnd {
class SymbolsCollector final : public SymbolsCollectorInterface class SymbolsCollector final : public SymbolsCollectorInterface
{ {
public: public:
SymbolsCollector(Sqlite::Database &database); SymbolsCollector(FilePathCaching &filePathCache);
void addFiles(const FilePathIds &filePathIds, void addFiles(const FilePathIds &filePathIds,
const Utils::SmallStringVector &arguments); const Utils::SmallStringVector &arguments);
@@ -65,7 +65,7 @@ public:
bool isClean() const { return m_clangTool.isClean(); } bool isClean() const { return m_clangTool.isClean(); }
private: private:
FilePathCaching m_filePathCache; CopyableFilePathCaching m_filePathCache;
ClangTool m_clangTool; ClangTool m_clangTool;
SymbolEntries m_symbolEntries; SymbolEntries m_symbolEntries;
SourceLocationEntries m_sourceLocationEntries; SourceLocationEntries m_sourceLocationEntries;

View File

@@ -58,11 +58,21 @@ protected:
.WillByDefault(Return(Utils::PathString("/path/to"))); .WillByDefault(Return(Utils::PathString("/path/to")));
ON_CALL(mockStorage, fetchSourceNameAndDirectoryId(42)) ON_CALL(mockStorage, fetchSourceNameAndDirectoryId(42))
.WillByDefault(Return(SourceNameAndDirectoryId("file.cpp", 5))); .WillByDefault(Return(SourceNameAndDirectoryId("file.cpp", 5)));
ON_CALL(mockStorageFilled, fetchAllSources())
.WillByDefault(Return(std::vector<ClangBackEnd::Sources::Source>({
{"file.cpp", 6, 72},
{"file2.cpp", 5, 63},
{"file.cpp", 5, 42},
})));
ON_CALL(mockStorageFilled, fetchAllDirectories())
.WillByDefault(Return(
std::vector<ClangBackEnd::Sources::Directory>({{"/path2/to", 6}, {"/path/to", 5}})));
} }
protected: protected:
NiceMock<MockFilePathStorage> mockStorage; NiceMock<MockFilePathStorage> mockStorage;
Cache cache{mockStorage}; Cache cache{mockStorage};
NiceMock<MockFilePathStorage> mockStorageFilled;
}; };
TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId) TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId)
@@ -316,4 +326,48 @@ TEST_F(FilePathCache, FetchDirectoryPathIdAfterFetchingFilePathByFilePathId)
ASSERT_THAT(directoryId, Eq(5)); ASSERT_THAT(directoryId, Eq(5));
} }
TEST_F(FilePathCache, FetchAllDirectoriesAndSourcesAtCreation)
{
EXPECT_CALL(mockStorage, fetchAllDirectories());
EXPECT_CALL(mockStorage, fetchAllSources());
Cache cache{mockStorage};
}
TEST_F(FilePathCache, GetFileIdInFilledCache)
{
Cache cacheFilled{mockStorageFilled};
auto id = cacheFilled.filePathId("/path2/to/file.cpp");
ASSERT_THAT(id, Eq(72));
}
TEST_F(FilePathCache, GetDirectoryIdInFilledCache)
{
Cache cacheFilled{mockStorageFilled};
auto id = cacheFilled.directoryPathId(42);
ASSERT_THAT(id, Eq(5));
}
TEST_F(FilePathCache, GetDirectoryPathInFilledCache)
{
Cache cacheFilled{mockStorageFilled};
auto path = cacheFilled.directoryPath(5);
ASSERT_THAT(path, Eq("/path/to"));
}
TEST_F(FilePathCache, GetFilePathInFilledCache)
{
Cache cacheFilled{mockStorageFilled};
auto path = cacheFilled.filePath(42);
ASSERT_THAT(path, Eq("/path/to/file.cpp"));
}
} // namespace } // namespace

View File

@@ -56,9 +56,8 @@ protected:
.WillByDefault(Return(Utils::optional<int>(5))); .WillByDefault(Return(Utils::optional<int>(5)));
ON_CALL(mockDatabase, lastInsertedRowId()) ON_CALL(mockDatabase, lastInsertedRowId())
.WillByDefault(Return(12)); .WillByDefault(Return(12));
ON_CALL(selectAllDirectories, ON_CALL(selectAllDirectories, valuesReturnStdVectorDirectory(_))
valuesReturnStdVectorDirectory(_)) .WillByDefault(Return(std::vector<Directory>{{"/path/to", 1}, {"/other/path", 2}}));
.WillByDefault(Return(std::vector<Directory>{{1, "/path/to"}, {2, "/other/path"}}));
ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(_, _)) valueReturnInt32(_, _))
.WillByDefault(Return(Utils::optional<int>())); .WillByDefault(Return(Utils::optional<int>()));
@@ -68,9 +67,8 @@ protected:
ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(5, Utils::SmallStringView("file.h"))) valueReturnInt32(5, Utils::SmallStringView("file.h")))
.WillByDefault(Return(Utils::optional<int>(42))); .WillByDefault(Return(Utils::optional<int>(42)));
ON_CALL(selectAllSources, ON_CALL(selectAllSources, valuesReturnStdVectorSource(_))
valuesReturnStdVectorSource(_)) .WillByDefault(Return(std::vector<Source>{{"file.h", 1, 1}, {"file.cpp", 2, 4}}));
.WillByDefault(Return(std::vector<Source>{{1, "file.h"}, {4, "file.cpp"}}));
ON_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, ON_CALL(selectDirectoryPathFromDirectoriesByDirectoryId,
valueReturnPathString(5)) valueReturnPathString(5))
.WillByDefault(Return(Utils::optional<Utils::PathString>("/path/to"))); .WillByDefault(Return(Utils::optional<Utils::PathString>("/path/to")));
@@ -407,16 +405,14 @@ TEST_F(FilePathStorage, SelectAllDirectories)
{ {
auto directories = storage.fetchAllDirectories(); auto directories = storage.fetchAllDirectories();
ASSERT_THAT(directories, ASSERT_THAT(directories, ElementsAre(Directory{"/path/to", 1}, Directory{"/other/path", 2}));
ElementsAre(Directory{1, "/path/to"}, Directory{2, "/other/path"}));
} }
TEST_F(FilePathStorage, SelectAllSources) TEST_F(FilePathStorage, SelectAllSources)
{ {
auto sources = storage.fetchAllSources(); auto sources = storage.fetchAllSources();
ASSERT_THAT(sources, ASSERT_THAT(sources, ElementsAre(Source{"file.h", 1, 1}, Source{"file.cpp", 2, 4}));
ElementsAre(Source{1, "file.h"}, Source{4, "file.cpp"}));
} }
TEST_F(FilePathStorage, CallSelectAllDirectories) TEST_F(FilePathStorage, CallSelectAllDirectories)

View File

@@ -73,12 +73,6 @@ TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceNameAndDirectoryIdBySo
Eq("SELECT sourceName, directoryId FROM sources WHERE sourceId = ?")); Eq("SELECT sourceName, directoryId FROM sources WHERE sourceId = ?"));
} }
TEST_F(FilePathStorageSqliteStatementFactory, SelectAllDirectories)
{
ASSERT_THAT(factory.selectAllDirectories.sqlStatement,
Eq("SELECT directoryId, directoryPath FROM directories"));
}
TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoDirectories) TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoDirectories)
{ {
ASSERT_THAT(factory.insertIntoDirectories.sqlStatement, ASSERT_THAT(factory.insertIntoDirectories.sqlStatement,
@@ -91,10 +85,4 @@ TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoSources)
Eq("INSERT INTO sources(directoryId, sourceName) VALUES (?,?)")); Eq("INSERT INTO sources(directoryId, sourceName) VALUES (?,?)"));
} }
TEST_F(FilePathStorageSqliteStatementFactory, SelectAllSources)
{
ASSERT_THAT(factory.selectAllSources.sqlStatement,
Eq("SELECT sourceId, sourceName FROM sources"));
}
} }

View File

@@ -40,5 +40,7 @@ public:
Utils::PathString (int directoryId)); Utils::PathString (int directoryId));
MOCK_METHOD1(fetchSourceNameAndDirectoryId, MOCK_METHOD1(fetchSourceNameAndDirectoryId,
ClangBackEnd::Sources::SourceNameAndDirectoryId (int sourceId)); ClangBackEnd::Sources::SourceNameAndDirectoryId (int sourceId));
MOCK_METHOD0(fetchAllDirectories, std::vector<ClangBackEnd::Sources::Directory>());
MOCK_METHOD0(fetchAllSources, std::vector<ClangBackEnd::Sources::Source>());
}; };

View File

@@ -103,8 +103,8 @@ std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directo
return valuesReturnStdVectorDirectory(reserveSize); return valuesReturnStdVectorDirectory(reserveSize);
} }
template <> template<>
std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 2>(std::size_t reserveSize) std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 3>(std::size_t reserveSize)
{ {
return valuesReturnStdVectorSource(reserveSize); return valuesReturnStdVectorSource(reserveSize);
} }

View File

@@ -223,8 +223,8 @@ FilePathIds MockSqliteReadStatement::values<ClangBackEnd::FilePathId>(std::size_
template <> template <>
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize); std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize);
template <> template<>
std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 2>(std::size_t reserveSize); std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 3>(std::size_t reserveSize);
template <> template <>
Utils::optional<int> Utils::optional<int>

View File

@@ -114,8 +114,9 @@ protected:
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
NiceMock<MockClangPathWatcher> mockClangPathWatcher; NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage; NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
ClangBackEnd::FilePathCaching filePathCache{database};
ClangBackEnd::PchCreator creator{environment, ClangBackEnd::PchCreator creator{environment,
database, filePathCache,
mockPchManagerClient, mockPchManagerClient,
mockClangPathWatcher, mockClangPathWatcher,
mockBuildDependenciesStorage}; mockBuildDependenciesStorage};

View File

@@ -194,9 +194,9 @@ TEST_F(StringCache, PopulateWithEmptyVector)
TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries) TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries)
{ {
CacheEntries entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1}, {filePath2.clone(), 3},
{filePath3.clone(), 2}, {filePath3.clone(), 2},
{filePath4.clone(), 3}}; {filePath4.clone(), 5}};
cache.uncheckedPopulate(std::move(entries)); cache.uncheckedPopulate(std::move(entries));
@@ -207,11 +207,11 @@ TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries)
{ {
CacheEntries entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1}, {filePath2.clone(), 1},
{filePath3.clone(), 2}, {filePath3.clone(), 7},
{filePath4.clone(), 3}}; {filePath4.clone(), 3}};
cache.uncheckedPopulate(std::move(entries)); cache.uncheckedPopulate(std::move(entries));
auto string = cache.string(2); auto string = cache.string(7);
ASSERT_THAT(string, filePath3); ASSERT_THAT(string, filePath3);
} }
@@ -226,16 +226,6 @@ TEST_F(StringCache, EntriesHaveUniqueIds)
ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException); ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException);
} }
TEST_F(StringCache, IdsAreHigherLowerEntriesSize)
{
CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1},
{filePath3.clone(), 4},
{filePath4.clone(), 3}};
ASSERT_THROW(cache.populate(std::move(entries)), std::out_of_range);
}
TEST_F(StringCache, MultipleEntries) TEST_F(StringCache, MultipleEntries)
{ {
CacheEntries entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},

View File

@@ -177,7 +177,7 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
FilePathCaching filePathCache{database}; FilePathCaching filePathCache{database};
ClangBackEnd::SymbolsCollector collector{database}; ClangBackEnd::SymbolsCollector collector{filePathCache};
}; };
TEST_F(SymbolsCollector, CollectSymbolName) TEST_F(SymbolsCollector, CollectSymbolName)