Clang: Add symbol storage

Extend file path cache to 64 bit integer.

Change-Id: I5627f13d59a3214f389087038482cbcc8d0eb484
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-08-21 12:00:27 +02:00
parent 81d43b8a11
commit f49a1d721c
48 changed files with 1297 additions and 231 deletions

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "stringcachefwd.h"
#include <utils/smallstringview.h> #include <utils/smallstringview.h>
#include <utils/smallstringfwd.h> #include <utils/smallstringfwd.h>
@@ -52,11 +54,11 @@ public:
void unlock() {} void unlock() {}
}; };
template <typename StringType> template <typename StringType, typename IndexType>
class StringCacheEntry class StringCacheEntry
{ {
public: public:
StringCacheEntry(StringType &&string, uint id) StringCacheEntry(StringType &&string, IndexType id)
: string(std::move(string)), : string(std::move(string)),
id(id) id(id)
{} {}
@@ -77,22 +79,27 @@ public:
} }
StringType string; StringType string;
uint id; IndexType id;
}; };
template <typename StringType> template <typename StringType, typename IndexType>
using StringCacheEntries = std::vector<StringCacheEntry<StringType>>; using StringCacheEntries = std::vector<StringCacheEntry<StringType, IndexType>>;
using FileCacheCacheEntry = StringCacheEntry<Utils::PathString, FilePathIndex>;
using FileCacheCacheEntries = std::vector<FileCacheCacheEntry>;
template <typename StringType, template <typename StringType,
typename Mutex = NonLockingMutex> typename IndexType,
typename Mutex>
class StringCache class StringCache
{ {
using const_iterator = typename StringCacheEntries<StringType>::const_iterator; using CacheEnties = StringCacheEntries<StringType, IndexType>;
using const_iterator = typename CacheEnties::const_iterator;
class Found class Found
{ {
public: public:
typename StringCacheEntries<StringType>::const_iterator iterator; typename CacheEnties::const_iterator iterator;
bool wasFound; bool wasFound;
}; };
@@ -103,14 +110,14 @@ public:
m_indices.reserve(1024); m_indices.reserve(1024);
} }
void populate(StringCacheEntries<StringType> &&entries) void populate(CacheEnties &&entries)
{ {
uncheckedPopulate(std::move(entries)); uncheckedPopulate(std::move(entries));
checkEntries(); checkEntries();
} }
void uncheckedPopulate(StringCacheEntries<StringType> &&entries) void uncheckedPopulate(CacheEnties &&entries)
{ {
std::sort(entries.begin(), entries.end()); std::sort(entries.begin(), entries.end());
@@ -123,7 +130,7 @@ public:
} }
uint stringId(Utils::SmallStringView stringView) IndexType stringId(Utils::SmallStringView stringView)
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
@@ -136,11 +143,11 @@ public:
} }
template <typename Container> template <typename Container>
std::vector<uint> stringIds(const Container &strings) std::vector<IndexType> stringIds(const Container &strings)
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
std::vector<uint> ids; std::vector<IndexType> ids;
ids.reserve(strings.size()); ids.reserve(strings.size());
std::transform(strings.begin(), std::transform(strings.begin(),
@@ -151,19 +158,19 @@ public:
return ids; return ids;
} }
std::vector<uint> stringIds(std::initializer_list<StringType> strings) std::vector<IndexType> stringIds(std::initializer_list<StringType> strings)
{ {
return stringIds<std::initializer_list<StringType>>(strings); return stringIds<std::initializer_list<StringType>>(strings);
} }
Utils::SmallStringView string(uint id) const Utils::SmallStringView string(IndexType id) const
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
return m_strings.at(m_indices.at(id)).string; return m_strings.at(m_indices.at(id)).string;
} }
std::vector<StringType> strings(const std::vector<uint> &ids) const std::vector<StringType> strings(const std::vector<IndexType> &ids) const
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
@@ -173,7 +180,7 @@ public:
std::transform(ids.begin(), std::transform(ids.begin(),
ids.end(), ids.end(),
std::back_inserter(strings), std::back_inserter(strings),
[&] (uint id) { return m_strings.at(m_indices.at(id)).string; }); [&] (IndexType id) { return m_strings.at(m_indices.at(id)).string; });
return strings; return strings;
} }
@@ -191,24 +198,24 @@ private:
return {range.first, range.first != range.second}; return {range.first, range.first != range.second};
} }
void incrementLargerOrEqualIndicesByOne(uint newIndex) void incrementLargerOrEqualIndicesByOne(IndexType newIndex)
{ {
std::transform(m_indices.begin(), std::transform(m_indices.begin(),
m_indices.end(), m_indices.end(),
m_indices.begin(), m_indices.begin(),
[&] (uint index) { [&] (IndexType index) {
return index >= newIndex ? ++index : index; return index >= newIndex ? ++index : index;
}); });
} }
uint insertString(const_iterator beforeIterator, IndexType insertString(const_iterator beforeIterator,
Utils::SmallStringView stringView) Utils::SmallStringView stringView)
{ {
auto id = uint(m_indices.size()); auto id = IndexType(m_indices.size());
auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id); auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id);
auto newIndex = uint(std::distance(m_strings.begin(), inserted)); auto newIndex = IndexType(std::distance(m_strings.begin(), inserted));
incrementLargerOrEqualIndicesByOne(newIndex); incrementLargerOrEqualIndicesByOne(newIndex);
@@ -226,12 +233,13 @@ private:
} }
private: private:
StringCacheEntries<StringType> m_strings; CacheEnties m_strings;
std::vector<uint> m_indices; std::vector<IndexType> m_indices;
mutable Mutex m_mutex; mutable Mutex m_mutex;
}; };
template <typename Mutex = NonLockingMutex> template <typename Mutex>
using FilePathCache = StringCache<Utils::PathString, Mutex>; using FilePathCache = StringCache<Utils::PathString, FilePathIndex, Mutex>;
using FilePathIndices = std::vector<FilePathIndex>;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,14 +29,17 @@
namespace ClangBackEnd { namespace ClangBackEnd {
using FilePathIndex = long long int;
class NonLockingMutex; class NonLockingMutex;
template <typename StringType, template <typename StringType,
typename IndexType,
typename Mutex> typename Mutex>
class StringCache; class StringCache;
template <typename Mutex = NonLockingMutex> template <typename Mutex = NonLockingMutex>
using FilePathCache = StringCache<Utils::PathString, Mutex>; using FilePathCache = StringCache<Utils::PathString, FilePathIndex, Mutex>;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -83,27 +83,27 @@ protected:
{ {
} }
template<typename... Values> template<typename... ValueType>
void bindValues(Values... values) void bindValues(ValueType... values)
{ {
bindValuesByIndex(1, values...); bindValuesByIndex(1, values...);
} }
template<typename... Values> template<typename... ValueType>
void write(Values... values) void write(ValueType... values)
{ {
bindValuesByIndex(1, values...); bindValuesByIndex(1, values...);
execute(); execute();
} }
template<typename... Values> template<typename... ValueType>
void bindNameValues(Values... values) void bindNameValues(ValueType... values)
{ {
bindValuesByName(values...); bindValuesByName(values...);
} }
template<typename... Values> template<typename... ValueType>
void writeNamed(Values... values) void writeNamed(ValueType... values)
{ {
bindValuesByName(values...); bindValuesByName(values...);
execute(); execute();
@@ -117,45 +117,45 @@ protected:
void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames); void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames);
const Utils::SmallStringVector &bindingColumnNames() const; const Utils::SmallStringVector &bindingColumnNames() const;
template <typename... ResultType> template <typename... ResultTypes>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize) std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize)
{ {
using Container = std::vector<std::tuple<ResultType...>>; using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues; Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
while (next()) while (next())
emplaceTupleValues<Container, ResultType...>(resultValues); emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset(); reset();
return resultValues; return resultValues;
} }
template <typename... ResultType, template <typename... ResultTypes,
typename... QueryType> typename... QueryTypes>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, const QueryType&... queryValues) std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize, const QueryTypes&... queryValues)
{ {
using Container = std::vector<std::tuple<ResultType...>>; using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues; Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
bindValues(queryValues...); bindValues(queryValues...);
while (next()) while (next())
emplaceTupleValues<Container, ResultType...>(resultValues); emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset(); reset();
return resultValues; return resultValues;
} }
template <typename... ResultType, template <typename... ResultTypes,
typename... ElementType> typename... QueryElementTypes>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize,
const std::vector<std::tuple<ElementType...>> &queryTuples) const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{ {
using Container = std::vector<std::tuple<ResultType...>>; using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues; Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
@@ -163,7 +163,7 @@ protected:
bindTupleValues(queryTuple); bindTupleValues(queryTuple);
while (next()) while (next())
emplaceTupleValues<Container, ResultType...>(resultValues); emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset(); reset();
} }
@@ -171,12 +171,12 @@ protected:
return resultValues; return resultValues;
} }
template <typename... ResultType, template <typename... ResultTypes,
typename QueryElementType> typename QueryElementType>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues) const std::vector<QueryElementType> &queryValues)
{ {
using Container = std::vector<std::tuple<ResultType...>>; using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues; Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
@@ -184,7 +184,7 @@ protected:
bindValues(queryValue); bindValues(queryValue);
while (next()) while (next())
emplaceTupleValues<Container, ResultType...>(resultValues); emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset(); reset();
} }
@@ -193,7 +193,7 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... ResultEntryType> typename... ResultEntryTypes>
std::vector<ResultType> structValues(std::size_t reserveSize) std::vector<ResultType> structValues(std::size_t reserveSize)
{ {
using Container = std::vector<ResultType>; using Container = std::vector<ResultType>;
@@ -201,7 +201,7 @@ protected:
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
while (next()) while (next())
pushBackStructValues<Container, ResultEntryType...>(resultValues); pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset(); reset();
@@ -209,9 +209,9 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... ResultEntryType, typename... ResultEntryTypes,
typename... QueryType> typename... QueryTypes>
std::vector<ResultType> structValues(std::size_t reserveSize, const QueryType&... queryValues) std::vector<ResultType> structValues(std::size_t reserveSize, const QueryTypes&... queryValues)
{ {
using Container = std::vector<ResultType>; using Container = std::vector<ResultType>;
Container resultValues; Container resultValues;
@@ -220,7 +220,7 @@ protected:
bindValues(queryValues...); bindValues(queryValues...);
while (next()) while (next())
pushBackStructValues<Container, ResultEntryType...>(resultValues); pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset(); reset();
@@ -228,7 +228,7 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... ResultEntryType, typename... ResultEntryTypes,
typename QueryElementType> typename QueryElementType>
std::vector<ResultType> structValues(std::size_t reserveSize, std::vector<ResultType> structValues(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues) const std::vector<QueryElementType> &queryValues)
@@ -241,7 +241,7 @@ protected:
bindValues(queryValue); bindValues(queryValue);
while (next()) while (next())
pushBackStructValues<Container, ResultEntryType...>(resultValues); pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset(); reset();
} }
@@ -250,10 +250,10 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... ResultEntryType, typename... ResultEntryTypes,
typename... QueryElementType> typename... QueryElementTypes>
std::vector<ResultType> structValues(std::size_t reserveSize, std::vector<ResultType> structValues(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementType...>> &queryTuples) const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{ {
using Container = std::vector<ResultType>; using Container = std::vector<ResultType>;
Container resultValues; Container resultValues;
@@ -263,7 +263,7 @@ protected:
bindTupleValues(queryTuple); bindTupleValues(queryTuple);
while (next()) while (next())
pushBackStructValues<Container, ResultEntryType...>(resultValues); pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset(); reset();
} }
@@ -272,7 +272,7 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... ElementType> typename... ElementTypes>
std::vector<ResultType> values(std::size_t reserveSize) std::vector<ResultType> values(std::size_t reserveSize)
{ {
std::vector<ResultType> resultValues; std::vector<ResultType> resultValues;
@@ -327,8 +327,8 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... QueryType> typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues) std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{ {
std::vector<ResultType> resultValues; std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
@@ -379,74 +379,74 @@ protected:
SqliteDatabaseBackend &databaseBackend); SqliteDatabaseBackend &databaseBackend);
private: private:
template <typename Container, template <typename ContainerType,
typename... ResultType, typename... ResultTypes,
int... Index> int... ColumnIndices>
void emplaceTupleValues(Container &container, std::integer_sequence<int, Index...>) void emplaceTupleValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
{ {
container.emplace_back(value<ResultType>(Index)...); container.emplace_back(value<ResultTypes>(ColumnIndices)...);
} }
template <typename Container, template <typename ContainerType,
typename... ResultType> typename... ResultTypes>
void emplaceTupleValues(Container &container) void emplaceTupleValues(ContainerType &container)
{ {
emplaceTupleValues<Container, ResultType...>(container, std::make_integer_sequence<int, sizeof...(ResultType)>{}); emplaceTupleValues<ContainerType, ResultTypes...>(container, std::make_integer_sequence<int, sizeof...(ResultTypes)>{});
} }
template <typename Container, template <typename ContainerType,
typename... ResultEntryType, typename... ResultEntryTypes,
int... Index> int... ColumnIndices>
void pushBackStructValues(Container &container, std::integer_sequence<int, Index...>) void pushBackStructValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
{ {
using ResultType = typename Container::value_type; using ResultType = typename ContainerType::value_type;
container.push_back(ResultType{value<ResultEntryType>(Index)...}); container.push_back(ResultType{value<ResultEntryTypes>(ColumnIndices)...});
} }
template <typename Container, template <typename ContainerType,
typename... ResultEntryType> typename... ResultEntryTypes>
void pushBackStructValues(Container &container) void pushBackStructValues(ContainerType &container)
{ {
pushBackStructValues<Container, ResultEntryType...>(container, std::make_integer_sequence<int, sizeof...(ResultEntryType)>{}); pushBackStructValues<ContainerType, ResultEntryTypes...>(container, std::make_integer_sequence<int, sizeof...(ResultEntryTypes)>{});
} }
template<typename Type> template<typename ValueType>
void bindValuesByIndex(int index, Type value) void bindValuesByIndex(int index, ValueType value)
{ {
bind(index, value); bind(index, value);
} }
template<typename Type, typename... Value> template<typename ValueType, typename... ValueTypes>
void bindValuesByIndex(int index, Type value, Value... values) void bindValuesByIndex(int index, ValueType value, ValueTypes... values)
{ {
bind(index, value); bind(index, value);
bindValuesByIndex(index + 1, values...); bindValuesByIndex(index + 1, values...);
} }
template<typename Type> template<typename ValueType>
void bindValuesByName(Utils::SmallStringView name, Type value) void bindValuesByName(Utils::SmallStringView name, ValueType value)
{ {
bind(bindingIndexForName(name), value); bind(bindingIndexForName(name), value);
} }
template<typename Type, typename... Values> template<typename ValueType, typename... ValueTypes>
void bindValuesByName(Utils::SmallStringView name, Type value, Values... values) void bindValuesByName(Utils::SmallStringView name, ValueType value, ValueTypes... values)
{ {
bind(bindingIndexForName(name), value); bind(bindingIndexForName(name), value);
bindValuesByName(values...); bindValuesByName(values...);
} }
template <typename TupleType, std::size_t... Index> template <typename TupleType, std::size_t... ColumnIndices>
void bindTupleValuesElement(const TupleType &tuple, std::index_sequence<Index...>) void bindTupleValuesElement(const TupleType &tuple, std::index_sequence<ColumnIndices...>)
{ {
bindValues(std::get<Index>(tuple)...); bindValues(std::get<ColumnIndices>(tuple)...);
} }
template <typename TupleType, template <typename TupleType,
typename Indices = std::make_index_sequence<std::tuple_size<TupleType>::value>> typename ColumnIndices = std::make_index_sequence<std::tuple_size<TupleType>::value>>
void bindTupleValues(const TupleType &element) void bindTupleValues(const TupleType &element)
{ {
bindTupleValuesElement(element, Indices()); bindTupleValuesElement(element, ColumnIndices());
} }
private: private:

View File

@@ -140,6 +140,8 @@ public:
return m_pointer[0] == characterToSearch; return m_pointer[0] == characterToSearch;
} }
private: private:
const char *m_pointer; const char *m_pointer;
size_type m_size; size_type m_size;

View File

@@ -50,7 +50,7 @@ using ClangBackEnd::PchGenerator;
using ClangBackEnd::PchManagerClientProxy; using ClangBackEnd::PchManagerClientProxy;
using ClangBackEnd::PchManagerServer; using ClangBackEnd::PchManagerServer;
using ClangBackEnd::ProjectParts; using ClangBackEnd::ProjectParts;
using ClangBackEnd::StringCache; using ClangBackEnd::FilePathCache;
class ApplicationEnvironment : public ClangBackEnd::Environment class ApplicationEnvironment : public ClangBackEnd::Environment
{ {
@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
const QString connection = processArguments(application); const QString connection = processArguments(application);
StringCache<Utils::PathString> filePathCache; FilePathCache<> filePathCache;
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache); ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache);
ApplicationEnvironment environment; ApplicationEnvironment environment;
PchGenerator<QProcess> pchGenerator(environment); PchGenerator<QProcess> pchGenerator(environment);

View File

@@ -37,8 +37,8 @@ namespace ClangBackEnd {
class WatcherEntry class WatcherEntry
{ {
public: public:
uint id; FilePathIndex id;
uint path; FilePathIndex path;
friend bool operator==(const WatcherEntry &first, const WatcherEntry &second) friend bool operator==(const WatcherEntry &first, const WatcherEntry &second)
{ {
@@ -50,12 +50,12 @@ public:
return std::tie(first.path, first.id) < std::tie(second.path, second.id); return std::tie(first.path, first.id) < std::tie(second.path, second.id);
} }
friend bool operator<(const WatcherEntry &entry, uint path) friend bool operator<(const WatcherEntry &entry, FilePathIndex path)
{ {
return entry.path < path; return entry.path < path;
} }
friend bool operator<(uint path, const WatcherEntry &entry) friend bool operator<(FilePathIndex path, const WatcherEntry &entry)
{ {
return path < entry.path; return path < entry.path;
} }
@@ -63,12 +63,14 @@ public:
using WatcherEntries = std::vector<WatcherEntry>; using WatcherEntries = std::vector<WatcherEntry>;
using IdCache = StringCache<Utils::SmallString, FilePathIndex, NonLockingMutex>;
template <typename FileSystemWatcher, template <typename FileSystemWatcher,
typename Timer> typename Timer>
class ClangPathWatcher : public ClangPathWatcherInterface class ClangPathWatcher : public ClangPathWatcherInterface
{ {
public: public:
ClangPathWatcher(StringCache<Utils::PathString> &pathCache, ClangPathWatcher(FilePathCache<> &pathCache,
ClangPathWatcherNotifier *notifier=nullptr) ClangPathWatcherNotifier *notifier=nullptr)
: m_pathCache(pathCache), : m_pathCache(pathCache),
m_notifier(notifier) m_notifier(notifier)
@@ -130,9 +132,9 @@ unittest_public:
return ids; return ids;
} }
std::vector<uint> convertToIdNumbers(const Utils::SmallStringVector &ids) std::vector<FilePathIndex> convertToIdNumbers(const Utils::SmallStringVector &ids)
{ {
std::vector<uint> idNumbers = m_idCache.stringIds(ids); std::vector<FilePathIndex> idNumbers = m_idCache.stringIds(ids);
std::sort(idNumbers.begin(), idNumbers.end()); std::sort(idNumbers.begin(), idNumbers.end());
@@ -149,19 +151,19 @@ unittest_public:
} }
std::pair<WatcherEntries,std::vector<uint>> std::pair<WatcherEntries,std::vector<FilePathIndex>>
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths) convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
{ {
WatcherEntries entries; WatcherEntries entries;
entries.reserve(sizeOfIdPaths(idPaths)); entries.reserve(sizeOfIdPaths(idPaths));
std::vector<uint> ids; std::vector<FilePathIndex> ids;
ids.reserve(ids.size()); ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries); auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths) for (const IdPaths &idPath : idPaths)
{ {
uint id = m_idCache.stringId(idPath.id); FilePathIndex id = m_idCache.stringId(idPath.id);
ids.push_back(id); ids.push_back(id);
@@ -190,7 +192,7 @@ unittest_public:
} }
void removeUnusedEntries(const WatcherEntries &entries, void removeUnusedEntries(const WatcherEntries &entries,
const std::vector<uint> &ids) const std::vector<FilePathIndex> &ids)
{ {
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
@@ -272,7 +274,7 @@ unittest_public:
WatcherEntries notAnymoreWatchedEntriesWithIds( WatcherEntries notAnymoreWatchedEntriesWithIds(
const WatcherEntries &newEntries, const WatcherEntries &newEntries,
const std::vector<uint> &ids) const const std::vector<FilePathIndex> &ids) const
{ {
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>()); auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
@@ -328,7 +330,7 @@ unittest_public:
return m_watchedEntries; return m_watchedEntries;
} }
WatcherEntries removeIdsFromWatchedEntries(const std::vector<uint> &ids) WatcherEntries removeIdsFromWatchedEntries(const std::vector<FilePathIndex> &ids)
{ {
auto keep = [&] (const WatcherEntry &entry) { auto keep = [&] (const WatcherEntry &entry) {
@@ -368,7 +370,7 @@ unittest_public:
WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths) WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths)
{ {
std::vector<uint> pathIds = m_pathCache.stringIds(filePaths); std::vector<FilePathIndex> pathIds = m_pathCache.stringIds(filePaths);
WatcherEntries foundEntries; WatcherEntries foundEntries;
@@ -414,22 +416,22 @@ unittest_public:
} }
} }
StringCache<Utils::PathString> &pathCache() FilePathCache<> &pathCache()
{ {
return m_pathCache; return m_pathCache;
} }
StringCache<Utils::SmallString> &idCache() IdCache &idCache()
{ {
return m_idCache; return m_idCache;
} }
private: private:
StringCache<Utils::SmallString> m_idCache; IdCache m_idCache;
WatcherEntries m_watchedEntries; WatcherEntries m_watchedEntries;
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor; ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
FileSystemWatcher m_fileSystemWatcher; FileSystemWatcher m_fileSystemWatcher;
StringCache<Utils::PathString> &m_pathCache; FilePathCache<> &m_pathCache;
ClangPathWatcherNotifier *m_notifier; ClangPathWatcherNotifier *m_notifier;
}; };

View File

@@ -38,10 +38,10 @@ namespace ClangBackEnd {
class CollectIncludesAction final : public clang::PreprocessOnlyAction class CollectIncludesAction final : public clang::PreprocessOnlyAction
{ {
public: public:
CollectIncludesAction(std::vector<uint> &includeIds, CollectIncludesAction(FilePathIndices &includeIds,
StringCache<Utils::PathString> &filePathCache, FilePathCache<> &filePathCache,
std::vector<uint> &excludedIncludeUID, FilePathIndices &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs) FilePathIndices &alreadyIncludedFileUIDs)
: m_includeIds(includeIds), : m_includeIds(includeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
m_excludedIncludeUID(excludedIncludeUID), m_excludedIncludeUID(excludedIncludeUID),
@@ -78,10 +78,10 @@ public:
} }
private: private:
std::vector<uint> &m_includeIds; FilePathIndices &m_includeIds;
StringCache<Utils::PathString> &m_filePathCache; FilePathCache<> &m_filePathCache;
std::vector<uint> &m_excludedIncludeUID; FilePathIndices &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs; FilePathIndices &m_alreadyIncludedFileUIDs;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -47,10 +47,10 @@ class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks
{ {
public: public:
CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch, CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch,
std::vector<uint> &includeIds, std::vector<FilePathIndex> &includeIds,
StringCache<Utils::PathString> &filePathCache, FilePathCache<> &filePathCache,
const std::vector<uint> &excludedIncludeUID, const std::vector<FilePathIndex> &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs) std::vector<FilePathIndex> &alreadyIncludedFileUIDs)
: m_headerSearch(headerSearch), : m_headerSearch(headerSearch),
m_includeIds(includeIds), m_includeIds(includeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
@@ -78,7 +78,7 @@ public:
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID); m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
Utils::PathString filePath = filePathFromFile(file); Utils::PathString filePath = filePathFromFile(file);
if (!filePath.isEmpty()) { if (!filePath.isEmpty()) {
uint includeId = m_filePathCache.stringId(filePath); FilePathIndex includeId = m_filePathCache.stringId(filePath);
m_includeIds.emplace_back(includeId); m_includeIds.emplace_back(includeId);
} }
} }
@@ -132,7 +132,7 @@ public:
uid); uid);
} }
std::pair<bool, std::vector<uint>::iterator> isNotAlreadyIncluded(uint uid) const std::pair<bool, std::vector<FilePathIndex>::iterator> isNotAlreadyIncluded(FilePathIndex uid) const
{ {
auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(), auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(),
m_alreadyIncludedFileUIDs.end(), m_alreadyIncludedFileUIDs.end(),
@@ -174,10 +174,10 @@ public:
private: private:
clang::HeaderSearch &m_headerSearch; clang::HeaderSearch &m_headerSearch;
std::vector<uint> &m_includeIds; std::vector<FilePathIndex> &m_includeIds;
StringCache<Utils::PathString> &m_filePathCache; FilePathCache<> &m_filePathCache;
const std::vector<uint> &m_excludedIncludeUID; const std::vector<FilePathIndex> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs; std::vector<FilePathIndex> &m_alreadyIncludedFileUIDs;
bool m_skipInclude = false; bool m_skipInclude = false;
}; };

View File

@@ -36,8 +36,8 @@ namespace ClangBackEnd {
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
{ {
public: public:
CollectIncludesToolAction(std::vector<uint> &includeIds, CollectIncludesToolAction(std::vector<FilePathIndex> &includeIds,
StringCache<Utils::PathString> &filePathCache, FilePathCache<> &filePathCache,
const Utils::PathStringVector &excludedIncludes) const Utils::PathStringVector &excludedIncludes)
: m_includeIds(includeIds), : m_includeIds(includeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
@@ -72,9 +72,9 @@ public:
m_alreadyIncludedFileUIDs); m_alreadyIncludedFileUIDs);
} }
std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const std::vector<FilePathIndex> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
{ {
std::vector<uint> fileUIDs; std::vector<FilePathIndex> fileUIDs;
fileUIDs.reserve(m_excludedIncludes.size()); fileUIDs.reserve(m_excludedIncludes.size());
for (const Utils::PathString &filePath : m_excludedIncludes) { for (const Utils::PathString &filePath : m_excludedIncludes) {
@@ -90,10 +90,10 @@ public:
} }
private: private:
std::vector<uint> m_alreadyIncludedFileUIDs; std::vector<FilePathIndex> m_alreadyIncludedFileUIDs;
std::vector<uint> m_excludedIncludeUIDs; std::vector<FilePathIndex> m_excludedIncludeUIDs;
std::vector<uint> &m_includeIds; std::vector<FilePathIndex> &m_includeIds;
StringCache<Utils::PathString> &m_filePathCache; FilePathCache<> &m_filePathCache;
const Utils::PathStringVector &m_excludedIncludes; const Utils::PathStringVector &m_excludedIncludes;
}; };

View File

@@ -29,13 +29,15 @@
#include <iosfwd> #include <iosfwd>
#include <stringcachefwd.h>
namespace ClangBackEnd { namespace ClangBackEnd {
class IdPaths class IdPaths
{ {
public: public:
Utils::SmallString id; Utils::SmallString id;
std::vector<uint> paths; std::vector<FilePathIndex> paths;
friend bool operator==(const IdPaths &first, const IdPaths &second) friend bool operator==(const IdPaths &first, const IdPaths &second)
{ {

View File

@@ -33,7 +33,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
IncludeCollector::IncludeCollector(StringCache<Utils::PathString> &filePathCache) IncludeCollector::IncludeCollector(FilePathCache<> &filePathCache)
: m_filePathCache(filePathCache) : m_filePathCache(filePathCache)
{ {
} }
@@ -69,7 +69,7 @@ void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedInc
#endif #endif
} }
std::vector<uint> IncludeCollector::takeIncludeIds() std::vector<FilePathIndex> IncludeCollector::takeIncludeIds()
{ {
std::sort(m_includeIds.begin(), m_includeIds.end()); std::sort(m_includeIds.begin(), m_includeIds.end());

View File

@@ -34,19 +34,19 @@ namespace ClangBackEnd {
class IncludeCollector : public ClangTool class IncludeCollector : public ClangTool
{ {
public: public:
IncludeCollector(StringCache<Utils::PathString> &filePathCache); IncludeCollector(FilePathCache<> &filePathCache);
void collectIncludes(); void collectIncludes();
void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes); void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes);
std::vector<uint> takeIncludeIds(); std::vector<FilePathIndex> takeIncludeIds();
private: private:
Utils::PathStringVector m_excludedIncludes; Utils::PathStringVector m_excludedIncludes;
std::vector<uint> m_includeIds; std::vector<FilePathIndex> m_includeIds;
Utils::SmallStringVector m_directories; Utils::SmallStringVector m_directories;
StringCache<Utils::PathString> &m_filePathCache; FilePathCache<> &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -37,7 +37,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
PchCreator::PchCreator(Environment &environment, StringCache<Utils::PathString> &filePathCache) PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache)
: m_environment(environment), : m_environment(environment),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
{ {
@@ -45,7 +45,7 @@ PchCreator::PchCreator(Environment &environment, StringCache<Utils::PathString>
PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts, PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment, Environment &environment,
StringCache<Utils::PathString> &filePathCache, FilePathCache<> &filePathCache,
PchGeneratorInterface *pchGenerator, PchGeneratorInterface *pchGenerator,
V2::FileContainers &&generatedFiles) V2::FileContainers &&generatedFiles)
: m_projectParts(std::move(projectsParts)), : m_projectParts(std::move(projectsParts)),
@@ -239,7 +239,7 @@ Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() cons
return compilerArguments; return compilerArguments;
} }
std::vector<uint> PchCreator::generateGlobalPchIncludeIds() const std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const
{ {
IncludeCollector collector(m_filePathCache); IncludeCollector collector(m_filePathCache);
@@ -267,7 +267,7 @@ std::size_t contentSize(const std::vector<Utils::PathString> &includes)
} }
Utils::SmallString PchCreator::generatePchIncludeFileContent( Utils::SmallString PchCreator::generatePchIncludeFileContent(
const std::vector<uint> &includeIds) const const std::vector<FilePathIndex> &includeIds) const
{ {
Utils::SmallString fileContent; Utils::SmallString fileContent;
const std::size_t lineTemplateSize = 12; const std::size_t lineTemplateSize = 12;
@@ -461,7 +461,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaderAndSourcePaths(
return includeAndSources; return includeAndSources;
} }
std::vector<uint> PchCreator::generateProjectPartPchIncludes( std::vector<FilePathIndex> PchCreator::generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const const V2::ProjectPartContainer &projectPart) const
{ {
Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart); Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart);

View File

@@ -48,10 +48,10 @@ class PchCreator final : public PchCreatorInterface
{ {
public: public:
PchCreator(Environment &environment, PchCreator(Environment &environment,
StringCache<Utils::PathString> &filePathCache); FilePathCache<> &filePathCache);
PchCreator(V2::ProjectPartContainers &&projectsParts, PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment, Environment &environment,
StringCache<Utils::PathString> &filePathCache, FilePathCache<> &filePathCache,
PchGeneratorInterface *pchGenerator, PchGeneratorInterface *pchGenerator,
V2::FileContainers &&generatedFiles); V2::FileContainers &&generatedFiles);
@@ -70,9 +70,9 @@ unittest_public:
Utils::SmallStringVector generateGlobalPchCompilerArguments() const; Utils::SmallStringVector generateGlobalPchCompilerArguments() const;
Utils::SmallStringVector generateGlobalClangCompilerArguments() const; Utils::SmallStringVector generateGlobalClangCompilerArguments() const;
std::vector<uint> generateGlobalPchIncludeIds() const; std::vector<FilePathIndex> generateGlobalPchIncludeIds() const;
Utils::SmallString generatePchIncludeFileContent(const std::vector<uint> &includeIds) const; Utils::SmallString generatePchIncludeFileContent(const std::vector<FilePathIndex> &includeIds) const;
Utils::SmallString generateGlobalPchHeaderFileContent() const; Utils::SmallString generateGlobalPchHeaderFileContent() const;
std::unique_ptr<QFile> generateGlobalPchHeaderFile(); std::unique_ptr<QFile> generateGlobalPchHeaderFile();
void generatePch(Utils::SmallStringVector &&commandLineArguments, void generatePch(Utils::SmallStringVector &&commandLineArguments,
@@ -97,7 +97,7 @@ unittest_public:
const V2::ProjectPartContainer &projectPart); const V2::ProjectPartContainer &projectPart);
static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths( static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths(
const V2::ProjectPartContainer &projectPart); const V2::ProjectPartContainer &projectPart);
std::vector<uint> generateProjectPartPchIncludes( std::vector<FilePathIndex> generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPathPchHeaderFilePath( Utils::SmallString generateProjectPathPchHeaderFilePath(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
@@ -127,7 +127,7 @@ private:
std::vector<ProjectPartPch> m_projectPartPchs; std::vector<ProjectPartPch> m_projectPartPchs;
std::vector<IdPaths> m_projectsIncludeIds; std::vector<IdPaths> m_projectsIncludeIds;
Environment &m_environment; Environment &m_environment;
StringCache<Utils::PathString> &m_filePathCache; FilePathCache<> &m_filePathCache;
PchGeneratorInterface *m_pchGenerator = nullptr; PchGeneratorInterface *m_pchGenerator = nullptr;
}; };

View File

@@ -36,7 +36,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
PchManagerServer::PchManagerServer(StringCache<Utils::PathString> &filePathCache, PchManagerServer::PchManagerServer(FilePathCache<> &filePathCache,
ClangPathWatcherInterface &fileSystemWatcher, ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator, PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts) ProjectPartsInterface &projectParts)

View File

@@ -46,7 +46,7 @@ class PchManagerServer : public PchManagerServerInterface,
{ {
public: public:
PchManagerServer(StringCache<Utils::PathString> &filePathCache, PchManagerServer(FilePathCache<> &filePathCache,
ClangPathWatcherInterface &fileSystemWatcher, ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator, PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts); ProjectPartsInterface &projectParts);
@@ -60,7 +60,7 @@ public:
void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override; void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override;
private: private:
StringCache<Utils::PathString> &m_filePathCache; FilePathCache<> &m_filePathCache;
ClangPathWatcherInterface &m_fileSystemWatcher; ClangPathWatcherInterface &m_fileSystemWatcher;
PchCreatorInterface &m_pchCreator; PchCreatorInterface &m_pchCreator;
ProjectPartsInterface &m_projectParts; ProjectPartsInterface &m_projectParts;

View File

@@ -54,7 +54,7 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
} }
}; };
ClangQuery::ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, ClangQuery::ClangQuery(FilePathCache<std::mutex> &filePathCache,
Utils::SmallString &&query) Utils::SmallString &&query)
: query(std::move(query)), : query(std::move(query)),
filePathCache(filePathCache) filePathCache(filePathCache)

View File

@@ -51,7 +51,7 @@ namespace ClangBackEnd {
class ClangQuery : public ClangTool class ClangQuery : public ClangTool
{ {
public: public:
ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, Utils::SmallString &&query={}); ClangQuery(FilePathCache<std::mutex> &filePathCache, Utils::SmallString &&query={});
void setQuery(Utils::SmallString &&query); void setQuery(Utils::SmallString &&query);
@@ -69,7 +69,7 @@ private:
SourceRangesContainer sourceRangesContainer; SourceRangesContainer sourceRangesContainer;
Utils::SmallString query; Utils::SmallString query;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_; std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_;
StringCache<Utils::PathString, std::mutex> &filePathCache; FilePathCache<std::mutex> &filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,7 +29,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache, ClangQueryGatherer::ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)
@@ -43,7 +43,7 @@ ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex
SourceRangesForQueryMessage SourceRangesForQueryMessage
ClangQueryGatherer::createSourceRangesForSource( ClangQueryGatherer::createSourceRangesForSource(
StringCache<Utils::PathString, std::mutex> *filePathCache, FilePathCache<std::mutex> *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)

View File

@@ -41,13 +41,13 @@ public:
using Future = std::future<SourceRangesForQueryMessage>; using Future = std::future<SourceRangesForQueryMessage>;
ClangQueryGatherer() = default; ClangQueryGatherer() = default;
ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache, ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
static SourceRangesForQueryMessage createSourceRangesForSource( static SourceRangesForQueryMessage createSourceRangesForSource(
StringCache<Utils::PathString, std::mutex> *filePathCache, FilePathCache<std::mutex> *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
@@ -69,7 +69,7 @@ protected:
std::vector<Future> finishedFutures(); std::vector<Future> finishedFutures();
private: private:
StringCache<Utils::PathString, std::mutex> *m_filePathCache = nullptr; FilePathCache<std::mutex> *m_filePathCache = nullptr;
SourceRangeFilter m_sourceRangeFilter; SourceRangeFilter m_sourceRangeFilter;
std::vector<V2::FileContainer> m_sources; std::vector<V2::FileContainer> m_sources;
std::vector<V2::FileContainer> m_unsaved; std::vector<V2::FileContainer> m_unsaved;

View File

@@ -12,7 +12,9 @@ HEADERS += \
$$PWD/collectsymbolsastvisitor.h \ $$PWD/collectsymbolsastvisitor.h \
$$PWD/sourcelocationentry.h \ $$PWD/sourcelocationentry.h \
$$PWD/symbolscollectorinterface.h \ $$PWD/symbolscollectorinterface.h \
$$PWD/symbolstorageinterface.h $$PWD/symbolstorageinterface.h \
$$PWD/symbolstorage.h \
$$PWD/storagesqlitestatementfactory.h
!isEmpty(LIBTOOLING_LIBS) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \
@@ -52,4 +54,5 @@ SOURCES += \
$$PWD/collectsymbolsaction.cpp \ $$PWD/collectsymbolsaction.cpp \
$$PWD/collectmacrossourcefilecallbacks.cpp \ $$PWD/collectmacrossourcefilecallbacks.cpp \
$$PWD/symbolentry.cpp \ $$PWD/symbolentry.cpp \
$$PWD/sourcelocationentry.cpp $$PWD/sourcelocationentry.cpp \
$$PWD/symbolstorage.cpp

View File

@@ -60,7 +60,7 @@ public:
bool VisitNamedDecl(const clang::NamedDecl *declaration) bool VisitNamedDecl(const clang::NamedDecl *declaration)
{ {
auto globalId = declaration->getCanonicalDecl()->getLocation().getRawEncoding(); SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
auto sourceLocation = declaration->getLocation(); auto sourceLocation = declaration->getLocation();
auto found = m_symbolEntries.find(globalId); auto found = m_symbolEntries.find(globalId);
@@ -81,7 +81,7 @@ public:
bool VisitDeclRefExpr(const clang::DeclRefExpr *expression) bool VisitDeclRefExpr(const clang::DeclRefExpr *expression)
{ {
auto declaration = expression->getFoundDecl(); auto declaration = expression->getFoundDecl();
auto globalId = declaration->getCanonicalDecl()->getLocation().getRawEncoding(); SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
auto sourceLocation = expression->getLocation(); auto sourceLocation = expression->getLocation();
m_sourceLocationEntries.emplace_back(globalId, m_sourceLocationEntries.emplace_back(globalId,
@@ -92,7 +92,7 @@ public:
return true; return true;
} }
uint filePathId(clang::SourceLocation sourceLocation) FilePathIndex filePathId(clang::SourceLocation sourceLocation)
{ {
auto filePath = m_sourceManager.getFilename(sourceLocation); auto filePath = m_sourceManager.getFilename(sourceLocation);
@@ -114,6 +114,11 @@ public:
return usr; return usr;
} }
static SymbolIndex toSymbolIndex(const void *pointer)
{
return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer));
}
private: private:
SymbolEntries &m_symbolEntries; SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries; SourceLocationEntries &m_sourceLocationEntries;

View File

@@ -75,7 +75,7 @@ private:
Utils::SmallString &&query); Utils::SmallString &&query);
private: private:
StringCache<Utils::PathString, std::mutex> m_filePathCache; FilePathCache<std::mutex> m_filePathCache;
ClangQueryGatherer m_gatherer; ClangQueryGatherer m_gatherer;
QTimer m_pollTimer; QTimer m_pollTimer;
}; };

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include <stringcachefwd.h>
#include <limits> #include <limits>
#include <vector> #include <vector>
#include <iosfwd> #include <iosfwd>
@@ -51,11 +53,13 @@ public:
uint column = 0; uint column = 0;
}; };
using SymbolIndex = long long;
class SourceLocationEntry class SourceLocationEntry
{ {
public: public:
SourceLocationEntry(uint symbolId, SourceLocationEntry(SymbolIndex symbolId,
uint fileId, FilePathIndex fileId,
LineColumn lineColumn, LineColumn lineColumn,
SymbolType symbolType) SymbolType symbolType)
: symbolId(symbolId), : symbolId(symbolId),
@@ -65,8 +69,8 @@ public:
symbolType(symbolType) symbolType(symbolType)
{} {}
uint symbolId = 0; SymbolIndex symbolId = 0;
uint fileId = std::numeric_limits<uint>::max(); FilePathIndex fileId = std::numeric_limits<uint>::max();
uint line = 0; uint line = 0;
uint column = 0; uint column = 0;
SymbolType symbolType; SymbolType symbolType;

View File

@@ -54,7 +54,7 @@ namespace ClangBackEnd {
SourceRangeExtractor::SourceRangeExtractor( SourceRangeExtractor::SourceRangeExtractor(
const clang::SourceManager &sourceManager, const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache, ClangBackEnd::FilePathCache<std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer) SourceRangesContainer &sourceRangesContainer)
: sourceManager(sourceManager), : sourceManager(sourceManager),
languageOptions(languageOptions), languageOptions(languageOptions),
@@ -145,7 +145,7 @@ void SourceRangeExtractor::insertSourceRange(uint fileId,
std::move(lineSnippet)); std::move(lineSnippet));
} }
uint SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const
{ {
auto found = m_fileIdMapping.find(fileId.getHashValue()); auto found = m_fileIdMapping.find(fileId.getHashValue());
if (found != m_fileIdMapping.end()) { if (found != m_fileIdMapping.end()) {

View File

@@ -59,7 +59,7 @@ class SourceRangeExtractor
public: public:
SourceRangeExtractor(const clang::SourceManager &sourceManager, SourceRangeExtractor(const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache, ClangBackEnd::FilePathCache<std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer); SourceRangesContainer &sourceRangesContainer);
void addSourceRange(const clang::SourceRange &sourceRange); void addSourceRange(const clang::SourceRange &sourceRange);
@@ -82,13 +82,13 @@ private:
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet); Utils::SmallString &&lineSnippet);
uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; FilePathIndex findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
private: private:
mutable std::unordered_map<uint, uint> m_fileIdMapping; mutable std::unordered_map<uint, uint> m_fileIdMapping;
const clang::SourceManager &sourceManager; const clang::SourceManager &sourceManager;
const clang::LangOptions &languageOptions; const clang::LangOptions &languageOptions;
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache; ClangBackEnd::FilePathCache<std::mutex> &filePathCache;
SourceRangesContainer &sourceRangesContainer; SourceRangesContainer &sourceRangesContainer;
}; };

View File

@@ -0,0 +1,180 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <createtablesqlstatementbuilder.h>
#include <sqlitetransaction.h>
#include <sqlitetable.h>
namespace ClangBackEnd {
template<typename Database,
typename ReadStatement,
typename WriteStatement>
class StorageSqliteStatementFactory
{
public:
using DatabaseType = Database;
using ReadStatementType = ReadStatement;
using WriteStatementType = WriteStatement;
StorageSqliteStatementFactory(Database &database)
: database(database)
{
}
Sqlite::SqliteTable createSymbolsTable()
{
Sqlite::SqliteTable table;
table.setUseIfNotExists(true);
table.setName("symbols");
table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text);
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::SqliteTable createLocationsTable()
{
Sqlite::SqliteTable table;
table.setUseIfNotExists(true);
table.setName("locations");
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer);
table.addColumn("sourceId", Sqlite::ColumnType::Integer);
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::SqliteTable createSourcesTable()
{
Sqlite::SqliteTable table;
table.setUseIfNotExists(true);
table.setName("sources");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("sourcePath", Sqlite::ColumnType::Text);
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::SqliteTable createNewSymbolsTable() const
{
Sqlite::SqliteTable table;
table.setName("newSymbols");
table.setUseTemporaryTable(true);
table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text);
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::SqliteTable createNewLocationsTable() const
{
Sqlite::SqliteTable table;
table.setName("newLocations");
table.setUseTemporaryTable(true);
table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer);
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer);
table.addColumn("sourceId", Sqlite::ColumnType::Integer);
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
public:
Database &database;
Sqlite::SqliteTable symbolsTable{createSymbolsTable()};
Sqlite::SqliteTable locationsTable{createLocationsTable()};
Sqlite::SqliteTable sourcesTable{createSourcesTable()};
Sqlite::SqliteTable newSymbolsTablet{createNewSymbolsTable()};
Sqlite::SqliteTable newLocationsTable{createNewLocationsTable()};
WriteStatement insertSymbolsToNewSymbolsStatement{
"INSERT INTO newSymbols(temporarySymbolId, usr, symbolName) VALUES(?,?,?)",
database};
WriteStatement insertLocationsToNewLocationsStatement{
"INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)",
database};
// WriteStatement syncNewLocationsToLocationsStatement{
// "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
// database};
ReadStatement selectNewSourceIdsStatement{
"SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)",
database};
WriteStatement addNewSymbolsToSymbolsStatement{
"INSERT INTO symbols(usr, symbolname) "
"SELECT usr, symbolname FROM newsymbols WHERE NOT EXISTS "
"(SELECT usr FROM symbols WHERE usr == newsymbols.usr)",
database};
WriteStatement insertSourcesStatement{
"INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)",
database};
WriteStatement syncNewSymbolsFromSymbolsStatement{
"UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)",
database};
WriteStatement syncSymbolsIntoNewLocationsStatement{
"UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)",
database};
WriteStatement deleteAllLocationsFromUpdatedFilesStatement{
"DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)",
database};
WriteStatement insertNewLocationsInLocationsStatement{
"INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
database};
WriteStatement deleteNewSymbolsTableStatement{
"DELETE FROM newSymbols",
database};
WriteStatement deleteNewLocationsTableStatement{
"DELETE FROM newLocations",
database};
};
} // namespace ClangBackEnd

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include <stringcachefwd.h>
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <llvm/ADT/SmallVector.h> #include <llvm/ADT/SmallVector.h>
@@ -36,6 +38,8 @@
namespace ClangBackEnd { namespace ClangBackEnd {
using SymbolIndex = long long;
class SymbolEntry class SymbolEntry
{ {
public: public:
@@ -60,7 +64,7 @@ public:
} }
}; };
using SymbolEntries = std::unordered_map<uint, SymbolEntry>; using SymbolEntries = std::unordered_map<SymbolIndex, SymbolEntry>;
std::ostream &operator<<(std::ostream &out, const SymbolEntry &entry); std::ostream &operator<<(std::ostream &out, const SymbolEntry &entry);

View File

@@ -0,0 +1,30 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "symbolstorage.h"
namespace ClangBackEnd {
} // namespace ClangBackEnd

View File

@@ -0,0 +1,155 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "symbolstorageinterface.h"
#include <sqlitetransaction.h>
#include <stringcache.h>
namespace ClangBackEnd {
template <typename StatementFactory>
class SymbolStorage : public SymbolStorageInterface
{
using Transaction = Sqlite::SqliteImmediateTransaction<typename StatementFactory::DatabaseType>;
using ReadStatement = typename StatementFactory::ReadStatementType;
using WriteStatement = typename StatementFactory::WriteStatementType;
using Database = typename StatementFactory::DatabaseType;
public:
SymbolStorage(StatementFactory &statementFactory,
FilePathCache<> &filePathCache)
: m_statementFactory(statementFactory),
m_filePathCache(filePathCache)
{
}
void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations) override
{
Transaction transaction{m_statementFactory.database};
fillTemporarySymbolsTable(symbolEntries);
fillTemporaryLocationsTable(sourceLocations);
addNewSymbolsToSymbols();
syncNewSymbolsFromSymbols();
syncSymbolsIntoNewLocations();
insertNewSources();
deleteAllLocationsFromUpdatedFiles();
insertNewLocationsInLocations();
deleteNewSymbolsTable();
deleteNewLocationsTable();
transaction.commit();
}
void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries)
{
WriteStatement &statement = m_statementFactory.insertSymbolsToNewSymbolsStatement;
for (const auto &symbolEntry : symbolEntries) {
statement.write(symbolEntry.first,
symbolEntry.second.usr,
symbolEntry.second.symbolName);
}
}
void fillTemporaryLocationsTable(const SourceLocationEntries &sourceLocations)
{
WriteStatement &statement = m_statementFactory.insertLocationsToNewLocationsStatement;
for (const auto &locationsEntry : sourceLocations) {
statement.write(locationsEntry.symbolId,
locationsEntry.line,
locationsEntry.column,
locationsEntry.fileId);
}
}
void addNewSymbolsToSymbols()
{
m_statementFactory.addNewSymbolsToSymbolsStatement.execute();
}
void syncNewSymbolsFromSymbols()
{
m_statementFactory.syncNewSymbolsFromSymbolsStatement.execute();
}
void syncSymbolsIntoNewLocations()
{
m_statementFactory.syncSymbolsIntoNewLocationsStatement.execute();
}
void deleteAllLocationsFromUpdatedFiles()
{
m_statementFactory.deleteAllLocationsFromUpdatedFilesStatement.execute();
}
void insertNewLocationsInLocations()
{
m_statementFactory.insertNewLocationsInLocationsStatement.execute();
}
FilePathIndices selectNewSourceIds() const
{
ReadStatement &statement = m_statementFactory.selectNewSourceIdsStatement;
return statement.template values<FilePathIndex>(16);
}
void insertNewSources()
{
WriteStatement &statement = m_statementFactory.insertSourcesStatement;
FilePathIndices newSourceIds = selectNewSourceIds();
for (FilePathIndex sourceId : newSourceIds)
statement.write(sourceId, m_filePathCache.string(sourceId));
}
void deleteNewSymbolsTable()
{
m_statementFactory.deleteNewSymbolsTableStatement.execute();
}
void deleteNewLocationsTable()
{
m_statementFactory.deleteNewLocationsTableStatement.execute();
}
SourceLocationEntries sourceLocations() const
{
return SourceLocationEntries();
}
private:
StatementFactory &m_statementFactory;
FilePathCache<> &m_filePathCache;
};
} // namespace ClangBackEnd

View File

@@ -33,7 +33,7 @@ namespace ClangBackEnd {
class SymbolStorageInterface class SymbolStorageInterface
{ {
public: public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEentries, virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations) = 0; const SourceLocationEntries &sourceLocations) = 0;
}; };

View File

@@ -42,11 +42,12 @@ using testing::NiceMock;
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>; using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>;
using ClangBackEnd::WatcherEntry; using ClangBackEnd::WatcherEntry;
using ClangBackEnd::FilePathIndices;
class ClangPathWatcher : public testing::Test class ClangPathWatcher : public testing::Test
{ {
protected: protected:
ClangBackEnd::StringCache<Utils::PathString> pathCache; ClangBackEnd::FilePathCache<> pathCache;
NiceMock<MockClangPathWatcherNotifier> notifier; NiceMock<MockClangPathWatcherNotifier> notifier;
Watcher watcher{pathCache, &notifier}; Watcher watcher{pathCache, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
@@ -55,8 +56,8 @@ protected:
Utils::SmallString id3{"id3"}; Utils::SmallString id3{"id3"};
Utils::PathString path1{"/path/path1"}; Utils::PathString path1{"/path/path1"};
Utils::PathString path2{"/path/path2"}; Utils::PathString path2{"/path/path2"};
std::vector<uint> paths = watcher.pathCache().stringIds({path1, path2}); FilePathIndices paths{watcher.pathCache().stringIds({path1, path2})};
std::vector<uint> ids = watcher.idCache().stringIds({id1, id2, id3}); FilePathIndices ids{watcher.idCache().stringIds({id1, id2, id3})};
WatcherEntry watcherEntry1{ids[0], paths[0]}; WatcherEntry watcherEntry1{ids[0], paths[0]};
WatcherEntry watcherEntry2{ids[1], paths[0]}; WatcherEntry watcherEntry2{ids[1], paths[0]};
WatcherEntry watcherEntry3{ids[0], paths[1]}; WatcherEntry watcherEntry3{ids[0], paths[1]};

View File

@@ -33,7 +33,7 @@
#include <mutex> #include <mutex>
using ClangBackEnd::ClangQuery; using ClangBackEnd::ClangQuery;
using ClangBackEnd::StringCache; using ClangBackEnd::FilePathCache;
using testing::AllOf; using testing::AllOf;
using testing::Contains; using testing::Contains;
@@ -48,7 +48,7 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
StringCache<Utils::PathString, std::mutex> filePathCache; FilePathCache<std::mutex> filePathCache;
::ClangQuery simpleFunctionQuery{filePathCache}; ::ClangQuery simpleFunctionQuery{filePathCache};
::ClangQuery simpleClassQuery{filePathCache}; ::ClangQuery simpleClassQuery{filePathCache};
}; };

View File

@@ -75,7 +75,7 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache; ClangBackEnd::FilePathCache<std::mutex> filePathCache;
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(), sourceContent.clone(),

View File

@@ -43,7 +43,7 @@ protected:
uint id(const Utils::SmallString &path); uint id(const Utils::SmallString &path);
protected: protected:
ClangBackEnd::StringCache<Utils::PathString> filePathCache; ClangBackEnd::FilePathCache<> filePathCache;
ClangBackEnd::IncludeCollector collector{filePathCache}; ClangBackEnd::IncludeCollector collector{filePathCache};
ClangBackEnd::IncludeCollector emptyCollector{filePathCache}; ClangBackEnd::IncludeCollector emptyCollector{filePathCache};
Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector_main.h", Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector_main.h",

View File

@@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <sqlitetable.h>
#include <utils/smallstringview.h>
class MockSqliteDatabase
{
public:
MOCK_METHOD1(execute,
void (Utils::SmallStringView sqlStatement));
};

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "mocksqlitereadstatement.h"
template <typename ResultType,
typename... QueryType>
std::vector<ResultType> values(std::size_t, QueryType...)
{
FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload.";
}
template <typename... ResultType>
std::vector<std::tuple<ResultType...>> values(std::size_t,
Utils::SmallStringView,
uint,
uint)
{
FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload.";
}
template <typename... ResultType,
template <typename...> class ContainerType,
typename ElementType>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t,
const ContainerType<ElementType> &)
{
FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload.";
}
template <>
std::vector<FilePathIndex> MockSqliteReadStatement::values<FilePathIndex>(std::size_t reserveSize)
{
return valuesReturnStdVectorInt(reserveSize);
}
template <>
std::vector<std::tuple<int64_t, int64_t, int64_t>>
MockSqliteReadStatement::tupleValues<int64_t, int64_t, int64_t>(
std::size_t reserveSize,
const Utils::PathString &sourcePath,
const uint &line,
const uint &column)
{
return valuesReturnStdVectorTupleInt64Int64Int64(reserveSize, sourcePath, line, column);
}
template <>
std::vector<std::tuple<int64_t, Utils::PathString>>
MockSqliteReadStatement::tupleValues<int64_t, Utils::PathString>(std::size_t reserveSize,
const std::vector<int64_t> &sourceIds)
{
return valuesReturnStdVectorTupleInt64PathString(reserveSize, sourceIds);
}

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <stringcachefwd.h>
#include "mocksqlitedatabase.h"
#include <utils/smallstring.h>
#include <cstdint>
#include <tuple>
#include <vector>
using std::int64_t;
using ClangBackEnd::FilePathIndex;
class MockSqliteReadStatement
{
public:
MockSqliteReadStatement() = default;
MockSqliteReadStatement(Utils::SmallStringView sqlStatement, MockSqliteDatabase &)
: sqlStatement(sqlStatement)
{}
MOCK_CONST_METHOD1(valuesReturnStdVectorInt,
std::vector<FilePathIndex>(std::size_t));
MOCK_CONST_METHOD4(valuesReturnStdVectorTupleInt64Int64Int64,
std::vector<std::tuple<int64_t, int64_t, int64_t>>(std::size_t, Utils::SmallStringView, int64_t, int64_t));
MOCK_CONST_METHOD2(valuesReturnStdVectorTupleInt64PathString,
std::vector<std::tuple<int64_t, Utils::PathString>>(std::size_t, const std::vector<int64_t> &));
template <typename ResultType,
typename... QueryType>
std::vector<ResultType> values(std::size_t, QueryType...);
template <typename... ResultType,
typename... QueryType>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, const QueryType&... queryValues);
template <typename... ResultType,
template <typename...> class ContainerType,
typename ElementType>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, const ContainerType<ElementType> &queryValues);
public:
Utils::SmallString sqlStatement;
};
template <>
std::vector<int> MockSqliteReadStatement::values<int>(std::size_t reserveSize);
template <>
std::vector<std::tuple<int64_t, int64_t, int64_t>>
MockSqliteReadStatement::tupleValues<int64_t, int64_t, int64_t>(
std::size_t reserveSize,
const Utils::PathString &sourcePath,
const uint &line,
const uint &column);
template <>
std::vector<std::tuple<int64_t, Utils::PathString>>
MockSqliteReadStatement::tupleValues<int64_t, Utils::PathString>(std::size_t reserveSize,
const std::vector<int64_t> &);

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "mocksqlitedatabase.h"
#include <utils/smallstring.h>
class MockSqliteWriteStatement
{
public:
MockSqliteWriteStatement() = default;
MockSqliteWriteStatement(Utils::SmallStringView sqlStatement, MockSqliteDatabase &)
: sqlStatement(sqlStatement)
{}
MOCK_METHOD0(execute,
void ());
MOCK_METHOD2(bind,
void (int index, Utils::SmallStringView value));
MOCK_METHOD2(bindValues,
void (Utils::SmallStringView, Utils::SmallStringView));
MOCK_METHOD3(write,
void (uint, Utils::SmallStringView, Utils::SmallStringView));
MOCK_METHOD4(write,
void (uint, uint, uint, uint));
MOCK_METHOD2(write,
void (uint, Utils::SmallStringView));
Utils::SmallString sqlStatement;
};

View File

@@ -68,7 +68,7 @@ protected:
uint id(const Utils::PathString &path); uint id(const Utils::PathString &path);
protected: protected:
ClangBackEnd::StringCache<Utils::PathString> filePathCache; ClangBackEnd::FilePathCache<> filePathCache;
PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp"; PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp";
PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h";

View File

@@ -59,7 +59,7 @@ protected:
NiceMock<MockPchCreator> mockPchCreator; NiceMock<MockPchCreator> mockPchCreator;
NiceMock<MockClangPathWatcher> mockClangPathWatcher; NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockProjectParts> mockProjectParts; NiceMock<MockProjectParts> mockProjectParts;
ClangBackEnd::StringCache<Utils::PathString> filePathCache; ClangBackEnd::FilePathCache<> filePathCache;
ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts}; ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts};
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
SmallString projectPartId1 = "project1"; SmallString projectPartId1 = "project1";

View File

@@ -54,7 +54,7 @@ protected:
TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}};
ClangBackEnd::SourceRangesContainer sourceRangesContainer; ClangBackEnd::SourceRangesContainer sourceRangesContainer;
const clang::SourceManager &sourceManager{clangTool.sourceManager()}; const clang::SourceManager &sourceManager{clangTool.sourceManager()};
ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache; ClangBackEnd::FilePathCache<std::mutex> filePathCache;
ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer}; ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer};
clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID());
clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4);

View File

@@ -340,7 +340,6 @@ TEST_F(SqliteStatement, GetStructValuesWithoutArguments)
Output{"poo", "40", 3})); Output{"poo", "40", 3}));
} }
TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes) TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes)
{ {
SqliteReadStatement statement("SELECT name FROM test WHERE number=?", database); SqliteReadStatement statement("SELECT name FROM test WHERE number=?", database);

View File

@@ -0,0 +1,186 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mocksqlitedatabase.h"
#include "mocksqlitereadstatement.h"
#include "mocksqlitewritestatement.h"
#include <storagesqlitestatementfactory.h>
namespace {
using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>,
MockSqliteReadStatement,
MockSqliteWriteStatement>;
using Sqlite::SqliteTable;
class StorageSqliteStatementFactory : public testing::Test
{
protected:
NiceMock<MockSqliteDatabase> mockDatabase;
StatementFactory factory{mockDatabase};
};
TEST_F(StorageSqliteStatementFactory, AddSymbolsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createSymbolsTable();
}
TEST_F(StorageSqliteStatementFactory, AddLocationsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createLocationsTable();
}
TEST_F(StorageSqliteStatementFactory, AddSourcesTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createSourcesTable();
}
TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createNewSymbolsTable();
}
TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createNewLocationsTable();
}
TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor)
{
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(5);
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
StatementFactory factory{mockDatabase};
}
TEST_F(StorageSqliteStatementFactory, InsertNewSymbolsStatement)
{
ASSERT_THAT(factory.insertSymbolsToNewSymbolsStatement.sqlStatement,
Eq("INSERT INTO newSymbols(temporarySymbolId, usr, symbolName) VALUES(?,?,?)"));
}
TEST_F(StorageSqliteStatementFactory, InsertNewLocationsToLocations)
{
ASSERT_THAT(factory.insertLocationsToNewLocationsStatement.sqlStatement,
Eq("INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)"));
}
TEST_F(StorageSqliteStatementFactory, SelectNewSourceIdsStatement)
{
ASSERT_THAT(factory.selectNewSourceIdsStatement.sqlStatement,
Eq("SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)"));
}
TEST_F(StorageSqliteStatementFactory, AddNewSymbolsToSymbolsStatement)
{
ASSERT_THAT(factory.addNewSymbolsToSymbolsStatement.sqlStatement,
Eq("INSERT INTO symbols(usr, symbolname) SELECT usr, symbolname FROM newsymbols WHERE NOT EXISTS (SELECT usr FROM symbols WHERE usr == newsymbols.usr)"));
}
TEST_F(StorageSqliteStatementFactory, InsertSourcesStatement)
{
ASSERT_THAT(factory.insertSourcesStatement.sqlStatement,
Eq("INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)"));
}
TEST_F(StorageSqliteStatementFactory, SyncNewSymbolsFromSymbolsStatement)
{
ASSERT_THAT(factory.syncNewSymbolsFromSymbolsStatement.sqlStatement,
Eq("UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)"));
}
TEST_F(StorageSqliteStatementFactory, SyncSymbolsIntoNewLocations)
{
ASSERT_THAT(factory.syncSymbolsIntoNewLocationsStatement.sqlStatement,
Eq("UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)"));
}
TEST_F(StorageSqliteStatementFactory, DeleteAllLocationsFromUpdatedFiles)
{
ASSERT_THAT(factory.deleteAllLocationsFromUpdatedFilesStatement.sqlStatement,
Eq("DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)"));
}
TEST_F(StorageSqliteStatementFactory, InsertNewLocationsInLocations)
{
ASSERT_THAT(factory.insertNewLocationsInLocationsStatement.sqlStatement,
Eq("INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations"));
}
TEST_F(StorageSqliteStatementFactory, DeleteNewSymbolsTableStatement)
{
ASSERT_THAT(factory.deleteNewSymbolsTableStatement.sqlStatement,
Eq("DELETE FROM newSymbols"));
}
TEST_F(StorageSqliteStatementFactory, DeleteNewLocationsTableStatement)
{
ASSERT_THAT(factory.deleteNewLocationsTableStatement.sqlStatement,
Eq("DELETE FROM newLocations"));
}
}

View File

@@ -31,13 +31,16 @@
namespace { namespace {
using ClangBackEnd::StringCacheEntries;
using ClangBackEnd::StringCacheException; using ClangBackEnd::StringCacheException;
using uint64 = unsigned long long;
using CacheEntries = ClangBackEnd::FileCacheCacheEntries;
class StringCache : public testing::Test class StringCache : public testing::Test
{ {
protected: protected:
ClangBackEnd::StringCache<Utils::PathString> cache; ClangBackEnd::FilePathCache<> cache;
Utils::PathString filePath1{"/file/pathOne"}; Utils::PathString filePath1{"/file/pathOne"};
Utils::PathString filePath2{"/file/pathTwo"}; Utils::PathString filePath2{"/file/pathTwo"};
Utils::PathString filePath3{"/file/pathThree"}; Utils::PathString filePath3{"/file/pathThree"};
@@ -144,7 +147,7 @@ TEST_F(StringCache, IsNotEmpty)
TEST_F(StringCache, PopulateWithEmptyVector) TEST_F(StringCache, PopulateWithEmptyVector)
{ {
StringCacheEntries<Utils::PathString> entries; CacheEntries entries;
cache.uncheckedPopulate(std::move(entries)); cache.uncheckedPopulate(std::move(entries));
@@ -153,10 +156,10 @@ TEST_F(StringCache, PopulateWithEmptyVector)
TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries) TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries)
{ {
StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1}, {filePath2.clone(), 1},
{filePath3.clone(), 2}, {filePath3.clone(), 2},
{filePath4.clone(), 3}}; {filePath4.clone(), 3}};
cache.uncheckedPopulate(std::move(entries)); cache.uncheckedPopulate(std::move(entries));
@@ -165,10 +168,10 @@ TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries)
TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries) TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries)
{ {
StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1}, {filePath2.clone(), 1},
{filePath3.clone(), 2}, {filePath3.clone(), 2},
{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(2);
@@ -178,30 +181,30 @@ TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries)
TEST_F(StringCache, EntriesHaveUniqueIds) TEST_F(StringCache, EntriesHaveUniqueIds)
{ {
StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1}, {filePath2.clone(), 1},
{filePath3.clone(), 2}, {filePath3.clone(), 2},
{filePath4.clone(), 2}}; {filePath4.clone(), 2}};
ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException); ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException);
} }
TEST_F(StringCache, IdsAreHigherLowerEntriesSize) TEST_F(StringCache, IdsAreHigherLowerEntriesSize)
{ {
StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath2.clone(), 1}, {filePath2.clone(), 1},
{filePath3.clone(), 4}, {filePath3.clone(), 4},
{filePath4.clone(), 3}}; {filePath4.clone(), 3}};
ASSERT_THROW(cache.populate(std::move(entries)), std::out_of_range); ASSERT_THROW(cache.populate(std::move(entries)), std::out_of_range);
} }
TEST_F(StringCache, MultipleEntries) TEST_F(StringCache, MultipleEntries)
{ {
StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, CacheEntries entries{{filePath1.clone(), 0},
{filePath1.clone(), 1}, {filePath1.clone(), 1},
{filePath3.clone(), 2}, {filePath3.clone(), 2},
{filePath4.clone(), 3}}; {filePath4.clone(), 3}};
ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException); ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException);
} }

View File

@@ -42,6 +42,7 @@ using testing::_;
using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::SymbolEntry; using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SymbolType; using ClangBackEnd::SymbolType;
using ClangBackEnd::SymbolIndex;
namespace { namespace {
@@ -53,7 +54,7 @@ protected:
return filePathCache.stringId(string); return filePathCache.stringId(string);
} }
uint symbolIdForSymbolName(const Utils::SmallString &symbolName); SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName);
protected: protected:
ClangBackEnd::FilePathCache<> filePathCache; ClangBackEnd::FilePathCache<> filePathCache;
@@ -149,7 +150,7 @@ TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation)
Field(&SourceLocationEntry::column, 5)))); Field(&SourceLocationEntry::column, 5))));
} }
uint SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName) SymbolIndex SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName)
{ {
for (const auto &entry : collector.symbols()) { for (const auto &entry : collector.symbols()) {
if (entry.second.symbolName == symbolName) if (entry.second.symbolName == symbolName)

View File

@@ -0,0 +1,203 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mocksqlitereadstatement.h"
#include "mocksqlitewritestatement.h"
#include <storagesqlitestatementfactory.h>
#include <symbolstorage.h>
#include <sqlitedatabase.h>
#include <storagesqlitestatementfactory.h>
namespace {
using Utils::PathString;
using ClangBackEnd::FilePathCache;
using ClangBackEnd::SymbolEntries;
using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SourceLocationEntries;
using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::StorageSqliteStatementFactory;
using ClangBackEnd::SymbolType;
using Sqlite::SqliteDatabase;
using Sqlite::SqliteTable;
using StatementFactory = StorageSqliteStatementFactory<MockSqliteDatabase,
MockSqliteReadStatement,
MockSqliteWriteStatement>;
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
class SymbolStorage : public testing::Test
{
protected:
void SetUp();
protected:
FilePathCache<> filePathCache;
NiceMock<MockSqliteDatabase> mockDatabase;
StatementFactory statementFactory{mockDatabase};
MockSqliteWriteStatement &insertSymbolsToNewSymbolsStatement = statementFactory.insertSymbolsToNewSymbolsStatement;
MockSqliteWriteStatement &insertLocationsToNewLocationsStatement = statementFactory.insertLocationsToNewLocationsStatement;
MockSqliteWriteStatement &insertSourcesStatement = statementFactory.insertSourcesStatement;
MockSqliteReadStatement &selectNewSourceIdsStatement = statementFactory.selectNewSourceIdsStatement;
MockSqliteWriteStatement &addNewSymbolsToSymbolsStatement = statementFactory.addNewSymbolsToSymbolsStatement;
MockSqliteWriteStatement &syncNewSymbolsFromSymbolsStatement = statementFactory.syncNewSymbolsFromSymbolsStatement;
MockSqliteWriteStatement &syncSymbolsIntoNewLocationsStatement = statementFactory.syncSymbolsIntoNewLocationsStatement;
MockSqliteWriteStatement &deleteAllLocationsFromUpdatedFilesStatement = statementFactory.deleteAllLocationsFromUpdatedFilesStatement;
MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = statementFactory.insertNewLocationsInLocationsStatement;
MockSqliteWriteStatement &deleteNewSymbolsTableStatement = statementFactory.deleteNewSymbolsTableStatement;
MockSqliteWriteStatement &deleteNewLocationsTableStatement = statementFactory.deleteNewLocationsTableStatement;
SymbolEntries symbolEntries{{1, {"functionUSR", "function"}},
{2, {"function2USR", "function2"}}};
SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SymbolType::Declaration},
{2, 4, {7, 11}, SymbolType::Declaration}};
Storage storage{statementFactory, filePathCache};
};
TEST_F(SymbolStorage, CreateAndFillTemporaryLocationsTable)
{
InSequence sequence;
EXPECT_CALL(insertLocationsToNewLocationsStatement, write(1, 42, 23, 3));
EXPECT_CALL(insertLocationsToNewLocationsStatement, write(2, 7, 11, 4));
storage.fillTemporaryLocationsTable(sourceLocations);
}
TEST_F(SymbolStorage, AddNewSymbolsToSymbols)
{
EXPECT_CALL(addNewSymbolsToSymbolsStatement, execute());
storage.addNewSymbolsToSymbols();
}
TEST_F(SymbolStorage, SyncNewSymbolsFromSymbols)
{
EXPECT_CALL(syncNewSymbolsFromSymbolsStatement, execute());
storage.syncNewSymbolsFromSymbols();
}
TEST_F(SymbolStorage, SyncSymbolsIntoNewLocations)
{
EXPECT_CALL(syncSymbolsIntoNewLocationsStatement, execute());
storage.syncSymbolsIntoNewLocations();
}
TEST_F(SymbolStorage, DeleteAllLocationsFromUpdatedFiles)
{
EXPECT_CALL(deleteAllLocationsFromUpdatedFilesStatement, execute());
storage.deleteAllLocationsFromUpdatedFiles();
}
TEST_F(SymbolStorage, InsertNewLocationsInLocations)
{
EXPECT_CALL(insertNewLocationsInLocationsStatement, execute());
storage.insertNewLocationsInLocations();
}
TEST_F(SymbolStorage, SelectNewSourceIdsCalls)
{
EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
storage.selectNewSourceIds();
}
TEST_F(SymbolStorage, SelectNewSourceIds)
{
EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
auto sourceIds = storage.selectNewSourceIds();
ASSERT_THAT(sourceIds, ElementsAre(0, 1, 2));
}
TEST_F(SymbolStorage, InserNewSources)
{
InSequence sequence;
EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
EXPECT_CALL(insertSourcesStatement, write(0, Eq("/path/to/source1")));
EXPECT_CALL(insertSourcesStatement, write(1, Eq("/path/to/source2")));
EXPECT_CALL(insertSourcesStatement, write(2, Eq("/path/to/source3")));
storage.insertNewSources();
}
TEST_F(SymbolStorage, DropNewSymbolsTable)
{
EXPECT_CALL(deleteNewSymbolsTableStatement, execute());
storage.deleteNewSymbolsTable();
}
TEST_F(SymbolStorage, DropNewLocationsTable)
{
EXPECT_CALL(deleteNewLocationsTableStatement, execute());
storage.deleteNewLocationsTable();
}
TEST_F(SymbolStorage, AddSymbolsAndSourceLocationsCallsWrite)
{
InSequence sequence;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(insertSymbolsToNewSymbolsStatement, write(_, _, _)).Times(2);
EXPECT_CALL(insertLocationsToNewLocationsStatement, write(1, 42, 23, 3));
EXPECT_CALL(insertLocationsToNewLocationsStatement, write(2, 7, 11, 4));
EXPECT_CALL(addNewSymbolsToSymbolsStatement, execute());
EXPECT_CALL(syncNewSymbolsFromSymbolsStatement, execute());
EXPECT_CALL(syncSymbolsIntoNewLocationsStatement, execute());
EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
EXPECT_CALL(insertSourcesStatement, write(0, Eq("/path/to/source1")));
EXPECT_CALL(insertSourcesStatement, write(1, Eq("/path/to/source2")));
EXPECT_CALL(insertSourcesStatement, write(2, Eq("/path/to/source3")));
EXPECT_CALL(deleteAllLocationsFromUpdatedFilesStatement, execute());
EXPECT_CALL(insertNewLocationsInLocationsStatement, execute());
EXPECT_CALL(deleteNewSymbolsTableStatement, execute());
EXPECT_CALL(deleteNewLocationsTableStatement, execute());
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.addSymbolsAndSourceLocations(symbolEntries, sourceLocations);
}
void SymbolStorage::SetUp()
{
ON_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_))
.WillByDefault(Return(std::vector<FilePathIndex>{0, 1, 2}));
filePathCache.stringIds({"/path/to/source1", "/path/to/source2", "/path/to/source3"});
}
}

View File

@@ -69,7 +69,10 @@ SOURCES += \
symbolindexer-test.cpp \ symbolindexer-test.cpp \
stringcache-test.cpp \ stringcache-test.cpp \
unittests-main.cpp \ unittests-main.cpp \
utf8-test.cpp utf8-test.cpp \
symbolstorage-test.cpp \
storagesqlitestatementfactory-test.cpp \
mocksqlitereadstatement.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \
@@ -188,7 +191,11 @@ HEADERS += \
spydummy.h \ spydummy.h \
testenvironment.h \ testenvironment.h \
mocksymbolscollector.h \ mocksymbolscollector.h \
mocksymbolstorage.h mocksymbolstorage.h \
mocksqlitewritestatement.h \
mocksqlitedatabase.h \
mocksqlitereadstatement.h \
google-using-directive.h
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
HEADERS += \ HEADERS += \