From f49a1d721c8be7d49bc0831ffa7316f2ec4f383f Mon Sep 17 00:00:00 2001 From: Marco Bubke <marco.bubke@qt.io> Date: Mon, 21 Aug 2017 12:00:27 +0200 Subject: [PATCH] Clang: Add symbol storage Extend file path cache to 64 bit integer. Change-Id: I5627f13d59a3214f389087038482cbcc8d0eb484 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io> --- src/libs/clangsupport/stringcache.h | 60 +++--- src/libs/clangsupport/stringcachefwd.h | 5 +- src/libs/sqlite/sqlitestatement.h | 148 ++++++------- src/libs/utils/smallstringview.h | 2 + .../clangpchmanagerbackendmain.cpp | 4 +- .../source/clangpathwatcher.h | 38 ++-- .../source/collectincludesaction.h | 16 +- .../collectincludespreprocessorcallbacks.h | 20 +- .../source/collectincludestoolaction.h | 16 +- .../clangpchmanagerbackend/source/idpaths.h | 4 +- .../source/includecollector.cpp | 4 +- .../source/includecollector.h | 8 +- .../source/pchcreator.cpp | 10 +- .../source/pchcreator.h | 12 +- .../source/pchmanagerserver.cpp | 2 +- .../source/pchmanagerserver.h | 4 +- .../source/clangquery.cpp | 2 +- .../source/clangquery.h | 4 +- .../source/clangquerygatherer.cpp | 4 +- .../source/clangquerygatherer.h | 6 +- .../source/clangrefactoringbackend-source.pri | 7 +- .../source/collectsymbolsastvisitor.h | 11 +- .../source/refactoringserver.h | 2 +- .../source/sourcelocationentry.h | 12 +- .../source/sourcerangeextractor.cpp | 4 +- .../source/sourcerangeextractor.h | 6 +- .../source/storagesqlitestatementfactory.h | 180 ++++++++++++++++ .../source/symbolentry.h | 6 +- .../source/symbolstorage.cpp | 30 +++ .../source/symbolstorage.h | 155 +++++++++++++ .../source/symbolstorageinterface.h | 2 +- tests/unit/unittest/clangpathwatcher-test.cpp | 7 +- tests/unit/unittest/clangquery-test.cpp | 4 +- .../unit/unittest/clangquerygatherer-test.cpp | 2 +- tests/unit/unittest/includecollector-test.cpp | 2 +- tests/unit/unittest/mocksqlitedatabase.h | 41 ++++ .../unit/unittest/mocksqlitereadstatement.cpp | 76 +++++++ tests/unit/unittest/mocksqlitereadstatement.h | 92 ++++++++ .../unit/unittest/mocksqlitewritestatement.h | 59 +++++ tests/unit/unittest/pchcreator-test.cpp | 2 +- tests/unit/unittest/pchmanagerserver-test.cpp | 2 +- .../unittest/sourcerangeextractor-test.cpp | 2 +- tests/unit/unittest/sqlitestatement-test.cpp | 1 - .../storagesqlitestatementfactory-test.cpp | 186 ++++++++++++++++ tests/unit/unittest/stringcache-test.cpp | 49 +++-- tests/unit/unittest/symbolscollector-test.cpp | 5 +- tests/unit/unittest/symbolstorage-test.cpp | 203 ++++++++++++++++++ tests/unit/unittest/unittest.pro | 11 +- 48 files changed, 1297 insertions(+), 231 deletions(-) create mode 100644 src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h create mode 100644 src/tools/clangrefactoringbackend/source/symbolstorage.cpp create mode 100644 src/tools/clangrefactoringbackend/source/symbolstorage.h create mode 100644 tests/unit/unittest/mocksqlitedatabase.h create mode 100644 tests/unit/unittest/mocksqlitereadstatement.cpp create mode 100644 tests/unit/unittest/mocksqlitereadstatement.h create mode 100644 tests/unit/unittest/mocksqlitewritestatement.h create mode 100644 tests/unit/unittest/storagesqlitestatementfactory-test.cpp create mode 100644 tests/unit/unittest/symbolstorage-test.cpp diff --git a/src/libs/clangsupport/stringcache.h b/src/libs/clangsupport/stringcache.h index a6f8d4633e5..804be33541f 100644 --- a/src/libs/clangsupport/stringcache.h +++ b/src/libs/clangsupport/stringcache.h @@ -25,6 +25,8 @@ #pragma once +#include "stringcachefwd.h" + #include <utils/smallstringview.h> #include <utils/smallstringfwd.h> @@ -52,11 +54,11 @@ public: void unlock() {} }; -template <typename StringType> +template <typename StringType, typename IndexType> class StringCacheEntry { public: - StringCacheEntry(StringType &&string, uint id) + StringCacheEntry(StringType &&string, IndexType id) : string(std::move(string)), id(id) {} @@ -77,22 +79,27 @@ public: } StringType string; - uint id; + IndexType id; }; -template <typename StringType> -using StringCacheEntries = std::vector<StringCacheEntry<StringType>>; +template <typename StringType, typename IndexType> +using StringCacheEntries = std::vector<StringCacheEntry<StringType, IndexType>>; + +using FileCacheCacheEntry = StringCacheEntry<Utils::PathString, FilePathIndex>; +using FileCacheCacheEntries = std::vector<FileCacheCacheEntry>; template <typename StringType, - typename Mutex = NonLockingMutex> + typename IndexType, + typename Mutex> class StringCache { - using const_iterator = typename StringCacheEntries<StringType>::const_iterator; + using CacheEnties = StringCacheEntries<StringType, IndexType>; + using const_iterator = typename CacheEnties::const_iterator; class Found { public: - typename StringCacheEntries<StringType>::const_iterator iterator; + typename CacheEnties::const_iterator iterator; bool wasFound; }; @@ -103,14 +110,14 @@ public: m_indices.reserve(1024); } - void populate(StringCacheEntries<StringType> &&entries) + void populate(CacheEnties &&entries) { uncheckedPopulate(std::move(entries)); checkEntries(); } - void uncheckedPopulate(StringCacheEntries<StringType> &&entries) + void uncheckedPopulate(CacheEnties &&entries) { 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); @@ -136,11 +143,11 @@ public: } 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::vector<uint> ids; + std::vector<IndexType> ids; ids.reserve(strings.size()); std::transform(strings.begin(), @@ -151,19 +158,19 @@ public: 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); } - Utils::SmallStringView string(uint id) const + Utils::SmallStringView string(IndexType id) const { std::lock_guard<Mutex> lock(m_mutex); 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); @@ -173,7 +180,7 @@ public: std::transform(ids.begin(), ids.end(), 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; } @@ -191,24 +198,24 @@ private: return {range.first, range.first != range.second}; } - void incrementLargerOrEqualIndicesByOne(uint newIndex) + void incrementLargerOrEqualIndicesByOne(IndexType newIndex) { std::transform(m_indices.begin(), m_indices.end(), m_indices.begin(), - [&] (uint index) { + [&] (IndexType index) { return index >= newIndex ? ++index : index; }); } - uint insertString(const_iterator beforeIterator, + IndexType insertString(const_iterator beforeIterator, 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 newIndex = uint(std::distance(m_strings.begin(), inserted)); + auto newIndex = IndexType(std::distance(m_strings.begin(), inserted)); incrementLargerOrEqualIndicesByOne(newIndex); @@ -226,12 +233,13 @@ private: } private: - StringCacheEntries<StringType> m_strings; - std::vector<uint> m_indices; + CacheEnties m_strings; + std::vector<IndexType> m_indices; mutable Mutex m_mutex; }; -template <typename Mutex = NonLockingMutex> -using FilePathCache = StringCache<Utils::PathString, Mutex>; +template <typename Mutex> +using FilePathCache = StringCache<Utils::PathString, FilePathIndex, Mutex>; +using FilePathIndices = std::vector<FilePathIndex>; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/stringcachefwd.h b/src/libs/clangsupport/stringcachefwd.h index 35b8534254e..4a12bfee691 100644 --- a/src/libs/clangsupport/stringcachefwd.h +++ b/src/libs/clangsupport/stringcachefwd.h @@ -29,14 +29,17 @@ namespace ClangBackEnd { +using FilePathIndex = long long int; + class NonLockingMutex; template <typename StringType, + typename IndexType, typename Mutex> class StringCache; template <typename Mutex = NonLockingMutex> -using FilePathCache = StringCache<Utils::PathString, Mutex>; +using FilePathCache = StringCache<Utils::PathString, FilePathIndex, Mutex>; } // namespace ClangBackEnd diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h index 09c75c16d97..d9bd87a2ee4 100644 --- a/src/libs/sqlite/sqlitestatement.h +++ b/src/libs/sqlite/sqlitestatement.h @@ -83,27 +83,27 @@ protected: { } - template<typename... Values> - void bindValues(Values... values) + template<typename... ValueType> + void bindValues(ValueType... values) { bindValuesByIndex(1, values...); } - template<typename... Values> - void write(Values... values) + template<typename... ValueType> + void write(ValueType... values) { bindValuesByIndex(1, values...); execute(); } - template<typename... Values> - void bindNameValues(Values... values) + template<typename... ValueType> + void bindNameValues(ValueType... values) { bindValuesByName(values...); } - template<typename... Values> - void writeNamed(Values... values) + template<typename... ValueType> + void writeNamed(ValueType... values) { bindValuesByName(values...); execute(); @@ -117,45 +117,45 @@ protected: void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames); const Utils::SmallStringVector &bindingColumnNames() const; - template <typename... ResultType> - std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize) + template <typename... ResultTypes> + 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; resultValues.reserve(reserveSize); while (next()) - emplaceTupleValues<Container, ResultType...>(resultValues); + emplaceTupleValues<Container, ResultTypes...>(resultValues); reset(); return resultValues; } - template <typename... ResultType, - typename... QueryType> - std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, const QueryType&... queryValues) + template <typename... ResultTypes, + typename... QueryTypes> + 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; resultValues.reserve(reserveSize); bindValues(queryValues...); while (next()) - emplaceTupleValues<Container, ResultType...>(resultValues); + emplaceTupleValues<Container, ResultTypes...>(resultValues); reset(); return resultValues; } - template <typename... ResultType, - typename... ElementType> - std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, - const std::vector<std::tuple<ElementType...>> &queryTuples) + template <typename... ResultTypes, + typename... QueryElementTypes> + std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize, + const std::vector<std::tuple<QueryElementTypes...>> &queryTuples) { - using Container = std::vector<std::tuple<ResultType...>>; + using Container = std::vector<std::tuple<ResultTypes...>>; Container resultValues; resultValues.reserve(reserveSize); @@ -163,7 +163,7 @@ protected: bindTupleValues(queryTuple); while (next()) - emplaceTupleValues<Container, ResultType...>(resultValues); + emplaceTupleValues<Container, ResultTypes...>(resultValues); reset(); } @@ -171,12 +171,12 @@ protected: return resultValues; } - template <typename... ResultType, + template <typename... ResultTypes, 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) { - using Container = std::vector<std::tuple<ResultType...>>; + using Container = std::vector<std::tuple<ResultTypes...>>; Container resultValues; resultValues.reserve(reserveSize); @@ -184,7 +184,7 @@ protected: bindValues(queryValue); while (next()) - emplaceTupleValues<Container, ResultType...>(resultValues); + emplaceTupleValues<Container, ResultTypes...>(resultValues); reset(); } @@ -193,7 +193,7 @@ protected: } template <typename ResultType, - typename... ResultEntryType> + typename... ResultEntryTypes> std::vector<ResultType> structValues(std::size_t reserveSize) { using Container = std::vector<ResultType>; @@ -201,7 +201,7 @@ protected: resultValues.reserve(reserveSize); while (next()) - pushBackStructValues<Container, ResultEntryType...>(resultValues); + pushBackStructValues<Container, ResultEntryTypes...>(resultValues); reset(); @@ -209,9 +209,9 @@ protected: } template <typename ResultType, - typename... ResultEntryType, - typename... QueryType> - std::vector<ResultType> structValues(std::size_t reserveSize, const QueryType&... queryValues) + typename... ResultEntryTypes, + typename... QueryTypes> + std::vector<ResultType> structValues(std::size_t reserveSize, const QueryTypes&... queryValues) { using Container = std::vector<ResultType>; Container resultValues; @@ -220,7 +220,7 @@ protected: bindValues(queryValues...); while (next()) - pushBackStructValues<Container, ResultEntryType...>(resultValues); + pushBackStructValues<Container, ResultEntryTypes...>(resultValues); reset(); @@ -228,7 +228,7 @@ protected: } template <typename ResultType, - typename... ResultEntryType, + typename... ResultEntryTypes, typename QueryElementType> std::vector<ResultType> structValues(std::size_t reserveSize, const std::vector<QueryElementType> &queryValues) @@ -241,7 +241,7 @@ protected: bindValues(queryValue); while (next()) - pushBackStructValues<Container, ResultEntryType...>(resultValues); + pushBackStructValues<Container, ResultEntryTypes...>(resultValues); reset(); } @@ -250,10 +250,10 @@ protected: } template <typename ResultType, - typename... ResultEntryType, - typename... QueryElementType> + typename... ResultEntryTypes, + typename... QueryElementTypes> 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>; Container resultValues; @@ -263,7 +263,7 @@ protected: bindTupleValues(queryTuple); while (next()) - pushBackStructValues<Container, ResultEntryType...>(resultValues); + pushBackStructValues<Container, ResultEntryTypes...>(resultValues); reset(); } @@ -272,7 +272,7 @@ protected: } template <typename ResultType, - typename... ElementType> + typename... ElementTypes> std::vector<ResultType> values(std::size_t reserveSize) { std::vector<ResultType> resultValues; @@ -327,8 +327,8 @@ protected: } template <typename ResultType, - typename... QueryType> - std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues) + typename... QueryTypes> + std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues) { std::vector<ResultType> resultValues; resultValues.reserve(reserveSize); @@ -379,74 +379,74 @@ protected: SqliteDatabaseBackend &databaseBackend); private: - template <typename Container, - typename... ResultType, - int... Index> - void emplaceTupleValues(Container &container, std::integer_sequence<int, Index...>) + template <typename ContainerType, + typename... ResultTypes, + int... ColumnIndices> + void emplaceTupleValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>) { - container.emplace_back(value<ResultType>(Index)...); + container.emplace_back(value<ResultTypes>(ColumnIndices)...); } - template <typename Container, - typename... ResultType> - void emplaceTupleValues(Container &container) + template <typename ContainerType, + typename... ResultTypes> + 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, - typename... ResultEntryType, - int... Index> - void pushBackStructValues(Container &container, std::integer_sequence<int, Index...>) + template <typename ContainerType, + typename... ResultEntryTypes, + int... ColumnIndices> + void pushBackStructValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>) { - using ResultType = typename Container::value_type; - container.push_back(ResultType{value<ResultEntryType>(Index)...}); + using ResultType = typename ContainerType::value_type; + container.push_back(ResultType{value<ResultEntryTypes>(ColumnIndices)...}); } - template <typename Container, - typename... ResultEntryType> - void pushBackStructValues(Container &container) + template <typename ContainerType, + typename... ResultEntryTypes> + 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> - void bindValuesByIndex(int index, Type value) + template<typename ValueType> + void bindValuesByIndex(int index, ValueType value) { bind(index, value); } - template<typename Type, typename... Value> - void bindValuesByIndex(int index, Type value, Value... values) + template<typename ValueType, typename... ValueTypes> + void bindValuesByIndex(int index, ValueType value, ValueTypes... values) { bind(index, value); bindValuesByIndex(index + 1, values...); } - template<typename Type> - void bindValuesByName(Utils::SmallStringView name, Type value) + template<typename ValueType> + void bindValuesByName(Utils::SmallStringView name, ValueType value) { bind(bindingIndexForName(name), value); } - template<typename Type, typename... Values> - void bindValuesByName(Utils::SmallStringView name, Type value, Values... values) + template<typename ValueType, typename... ValueTypes> + void bindValuesByName(Utils::SmallStringView name, ValueType value, ValueTypes... values) { bind(bindingIndexForName(name), value); bindValuesByName(values...); } - template <typename TupleType, std::size_t... Index> - void bindTupleValuesElement(const TupleType &tuple, std::index_sequence<Index...>) + template <typename TupleType, std::size_t... ColumnIndices> + void bindTupleValuesElement(const TupleType &tuple, std::index_sequence<ColumnIndices...>) { - bindValues(std::get<Index>(tuple)...); + bindValues(std::get<ColumnIndices>(tuple)...); } 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) { - bindTupleValuesElement(element, Indices()); + bindTupleValuesElement(element, ColumnIndices()); } private: diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 194616b2b44..3798cb6e4e8 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -140,6 +140,8 @@ public: return m_pointer[0] == characterToSearch; } + + private: const char *m_pointer; size_type m_size; diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index a8eb4ce09a1..5622179272b 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -50,7 +50,7 @@ using ClangBackEnd::PchGenerator; using ClangBackEnd::PchManagerClientProxy; using ClangBackEnd::PchManagerServer; using ClangBackEnd::ProjectParts; -using ClangBackEnd::StringCache; +using ClangBackEnd::FilePathCache; class ApplicationEnvironment : public ClangBackEnd::Environment { @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) const QString connection = processArguments(application); - StringCache<Utils::PathString> filePathCache; + FilePathCache<> filePathCache; ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache); ApplicationEnvironment environment; PchGenerator<QProcess> pchGenerator(environment); diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h index a02d09f3f7f..10dbbb12471 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h +++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h @@ -37,8 +37,8 @@ namespace ClangBackEnd { class WatcherEntry { public: - uint id; - uint path; + FilePathIndex id; + FilePathIndex path; 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); } - friend bool operator<(const WatcherEntry &entry, uint path) + friend bool operator<(const WatcherEntry &entry, FilePathIndex 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; } @@ -63,12 +63,14 @@ public: using WatcherEntries = std::vector<WatcherEntry>; +using IdCache = StringCache<Utils::SmallString, FilePathIndex, NonLockingMutex>; + template <typename FileSystemWatcher, typename Timer> class ClangPathWatcher : public ClangPathWatcherInterface { public: - ClangPathWatcher(StringCache<Utils::PathString> &pathCache, + ClangPathWatcher(FilePathCache<> &pathCache, ClangPathWatcherNotifier *notifier=nullptr) : m_pathCache(pathCache), m_notifier(notifier) @@ -130,9 +132,9 @@ unittest_public: 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()); @@ -149,19 +151,19 @@ unittest_public: } - std::pair<WatcherEntries,std::vector<uint>> + std::pair<WatcherEntries,std::vector<FilePathIndex>> convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths) { WatcherEntries entries; entries.reserve(sizeOfIdPaths(idPaths)); - std::vector<uint> ids; + std::vector<FilePathIndex> ids; ids.reserve(ids.size()); auto outputIterator = std::back_inserter(entries); for (const IdPaths &idPath : idPaths) { - uint id = m_idCache.stringId(idPath.id); + FilePathIndex id = m_idCache.stringId(idPath.id); ids.push_back(id); @@ -190,7 +192,7 @@ unittest_public: } void removeUnusedEntries(const WatcherEntries &entries, - const std::vector<uint> &ids) + const std::vector<FilePathIndex> &ids) { auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); @@ -272,7 +274,7 @@ unittest_public: WatcherEntries notAnymoreWatchedEntriesWithIds( const WatcherEntries &newEntries, - const std::vector<uint> &ids) const + const std::vector<FilePathIndex> &ids) const { auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>()); @@ -328,7 +330,7 @@ unittest_public: return m_watchedEntries; } - WatcherEntries removeIdsFromWatchedEntries(const std::vector<uint> &ids) + WatcherEntries removeIdsFromWatchedEntries(const std::vector<FilePathIndex> &ids) { auto keep = [&] (const WatcherEntry &entry) { @@ -368,7 +370,7 @@ unittest_public: WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths) { - std::vector<uint> pathIds = m_pathCache.stringIds(filePaths); + std::vector<FilePathIndex> pathIds = m_pathCache.stringIds(filePaths); WatcherEntries foundEntries; @@ -414,22 +416,22 @@ unittest_public: } } - StringCache<Utils::PathString> &pathCache() + FilePathCache<> &pathCache() { return m_pathCache; } - StringCache<Utils::SmallString> &idCache() + IdCache &idCache() { return m_idCache; } private: - StringCache<Utils::SmallString> m_idCache; + IdCache m_idCache; WatcherEntries m_watchedEntries; ChangedFilePathCompressor<Timer> m_changedFilePathCompressor; FileSystemWatcher m_fileSystemWatcher; - StringCache<Utils::PathString> &m_pathCache; + FilePathCache<> &m_pathCache; ClangPathWatcherNotifier *m_notifier; }; diff --git a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h index 5b8b8ad5e6b..339d491848d 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h @@ -38,10 +38,10 @@ namespace ClangBackEnd { class CollectIncludesAction final : public clang::PreprocessOnlyAction { public: - CollectIncludesAction(std::vector<uint> &includeIds, - StringCache<Utils::PathString> &filePathCache, - std::vector<uint> &excludedIncludeUID, - std::vector<uint> &alreadyIncludedFileUIDs) + CollectIncludesAction(FilePathIndices &includeIds, + FilePathCache<> &filePathCache, + FilePathIndices &excludedIncludeUID, + FilePathIndices &alreadyIncludedFileUIDs) : m_includeIds(includeIds), m_filePathCache(filePathCache), m_excludedIncludeUID(excludedIncludeUID), @@ -78,10 +78,10 @@ public: } private: - std::vector<uint> &m_includeIds; - StringCache<Utils::PathString> &m_filePathCache; - std::vector<uint> &m_excludedIncludeUID; - std::vector<uint> &m_alreadyIncludedFileUIDs; + FilePathIndices &m_includeIds; + FilePathCache<> &m_filePathCache; + FilePathIndices &m_excludedIncludeUID; + FilePathIndices &m_alreadyIncludedFileUIDs; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h index ba86822fce3..a57d72adfcb 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h @@ -47,10 +47,10 @@ class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks { public: CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch, - std::vector<uint> &includeIds, - StringCache<Utils::PathString> &filePathCache, - const std::vector<uint> &excludedIncludeUID, - std::vector<uint> &alreadyIncludedFileUIDs) + std::vector<FilePathIndex> &includeIds, + FilePathCache<> &filePathCache, + const std::vector<FilePathIndex> &excludedIncludeUID, + std::vector<FilePathIndex> &alreadyIncludedFileUIDs) : m_headerSearch(headerSearch), m_includeIds(includeIds), m_filePathCache(filePathCache), @@ -78,7 +78,7 @@ public: m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID); Utils::PathString filePath = filePathFromFile(file); if (!filePath.isEmpty()) { - uint includeId = m_filePathCache.stringId(filePath); + FilePathIndex includeId = m_filePathCache.stringId(filePath); m_includeIds.emplace_back(includeId); } } @@ -132,7 +132,7 @@ public: 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(), m_alreadyIncludedFileUIDs.end(), @@ -174,10 +174,10 @@ public: private: clang::HeaderSearch &m_headerSearch; - std::vector<uint> &m_includeIds; - StringCache<Utils::PathString> &m_filePathCache; - const std::vector<uint> &m_excludedIncludeUID; - std::vector<uint> &m_alreadyIncludedFileUIDs; + std::vector<FilePathIndex> &m_includeIds; + FilePathCache<> &m_filePathCache; + const std::vector<FilePathIndex> &m_excludedIncludeUID; + std::vector<FilePathIndex> &m_alreadyIncludedFileUIDs; bool m_skipInclude = false; }; diff --git a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h index 87e92c1df3e..42b8a62cea7 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h @@ -36,8 +36,8 @@ namespace ClangBackEnd { class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory { public: - CollectIncludesToolAction(std::vector<uint> &includeIds, - StringCache<Utils::PathString> &filePathCache, + CollectIncludesToolAction(std::vector<FilePathIndex> &includeIds, + FilePathCache<> &filePathCache, const Utils::PathStringVector &excludedIncludes) : m_includeIds(includeIds), m_filePathCache(filePathCache), @@ -72,9 +72,9 @@ public: 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()); for (const Utils::PathString &filePath : m_excludedIncludes) { @@ -90,10 +90,10 @@ public: } private: - std::vector<uint> m_alreadyIncludedFileUIDs; - std::vector<uint> m_excludedIncludeUIDs; - std::vector<uint> &m_includeIds; - StringCache<Utils::PathString> &m_filePathCache; + std::vector<FilePathIndex> m_alreadyIncludedFileUIDs; + std::vector<FilePathIndex> m_excludedIncludeUIDs; + std::vector<FilePathIndex> &m_includeIds; + FilePathCache<> &m_filePathCache; const Utils::PathStringVector &m_excludedIncludes; }; diff --git a/src/tools/clangpchmanagerbackend/source/idpaths.h b/src/tools/clangpchmanagerbackend/source/idpaths.h index f6f312f05fd..a407e24530f 100644 --- a/src/tools/clangpchmanagerbackend/source/idpaths.h +++ b/src/tools/clangpchmanagerbackend/source/idpaths.h @@ -29,13 +29,15 @@ #include <iosfwd> +#include <stringcachefwd.h> + namespace ClangBackEnd { class IdPaths { public: Utils::SmallString id; - std::vector<uint> paths; + std::vector<FilePathIndex> paths; friend bool operator==(const IdPaths &first, const IdPaths &second) { diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.cpp b/src/tools/clangpchmanagerbackend/source/includecollector.cpp index b380fa2b8b6..421123b3a7c 100644 --- a/src/tools/clangpchmanagerbackend/source/includecollector.cpp +++ b/src/tools/clangpchmanagerbackend/source/includecollector.cpp @@ -33,7 +33,7 @@ namespace ClangBackEnd { -IncludeCollector::IncludeCollector(StringCache<Utils::PathString> &filePathCache) +IncludeCollector::IncludeCollector(FilePathCache<> &filePathCache) : m_filePathCache(filePathCache) { } @@ -69,7 +69,7 @@ void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedInc #endif } -std::vector<uint> IncludeCollector::takeIncludeIds() +std::vector<FilePathIndex> IncludeCollector::takeIncludeIds() { std::sort(m_includeIds.begin(), m_includeIds.end()); diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.h b/src/tools/clangpchmanagerbackend/source/includecollector.h index ba485ea33d7..73f9b948afa 100644 --- a/src/tools/clangpchmanagerbackend/source/includecollector.h +++ b/src/tools/clangpchmanagerbackend/source/includecollector.h @@ -34,19 +34,19 @@ namespace ClangBackEnd { class IncludeCollector : public ClangTool { public: - IncludeCollector(StringCache<Utils::PathString> &filePathCache); + IncludeCollector(FilePathCache<> &filePathCache); void collectIncludes(); void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes); - std::vector<uint> takeIncludeIds(); + std::vector<FilePathIndex> takeIncludeIds(); private: Utils::PathStringVector m_excludedIncludes; - std::vector<uint> m_includeIds; + std::vector<FilePathIndex> m_includeIds; Utils::SmallStringVector m_directories; - StringCache<Utils::PathString> &m_filePathCache; + FilePathCache<> &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp index 4c685dc34e1..d8551d77677 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp @@ -37,7 +37,7 @@ namespace ClangBackEnd { -PchCreator::PchCreator(Environment &environment, StringCache<Utils::PathString> &filePathCache) +PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache) : m_environment(environment), m_filePathCache(filePathCache) { @@ -45,7 +45,7 @@ PchCreator::PchCreator(Environment &environment, StringCache<Utils::PathString> PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts, Environment &environment, - StringCache<Utils::PathString> &filePathCache, + FilePathCache<> &filePathCache, PchGeneratorInterface *pchGenerator, V2::FileContainers &&generatedFiles) : m_projectParts(std::move(projectsParts)), @@ -239,7 +239,7 @@ Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() cons return compilerArguments; } -std::vector<uint> PchCreator::generateGlobalPchIncludeIds() const +std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const { IncludeCollector collector(m_filePathCache); @@ -267,7 +267,7 @@ std::size_t contentSize(const std::vector<Utils::PathString> &includes) } Utils::SmallString PchCreator::generatePchIncludeFileContent( - const std::vector<uint> &includeIds) const + const std::vector<FilePathIndex> &includeIds) const { Utils::SmallString fileContent; const std::size_t lineTemplateSize = 12; @@ -461,7 +461,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaderAndSourcePaths( return includeAndSources; } -std::vector<uint> PchCreator::generateProjectPartPchIncludes( +std::vector<FilePathIndex> PchCreator::generateProjectPartPchIncludes( const V2::ProjectPartContainer &projectPart) const { Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart); diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h index 1b418ad3db2..5548ec7acd2 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.h +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h @@ -48,10 +48,10 @@ class PchCreator final : public PchCreatorInterface { public: PchCreator(Environment &environment, - StringCache<Utils::PathString> &filePathCache); + FilePathCache<> &filePathCache); PchCreator(V2::ProjectPartContainers &&projectsParts, Environment &environment, - StringCache<Utils::PathString> &filePathCache, + FilePathCache<> &filePathCache, PchGeneratorInterface *pchGenerator, V2::FileContainers &&generatedFiles); @@ -70,9 +70,9 @@ unittest_public: Utils::SmallStringVector generateGlobalPchCompilerArguments() 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; std::unique_ptr<QFile> generateGlobalPchHeaderFile(); void generatePch(Utils::SmallStringVector &&commandLineArguments, @@ -97,7 +97,7 @@ unittest_public: const V2::ProjectPartContainer &projectPart); static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths( const V2::ProjectPartContainer &projectPart); - std::vector<uint> generateProjectPartPchIncludes( + std::vector<FilePathIndex> generateProjectPartPchIncludes( const V2::ProjectPartContainer &projectPart) const; Utils::SmallString generateProjectPathPchHeaderFilePath( const V2::ProjectPartContainer &projectPart) const; @@ -127,7 +127,7 @@ private: std::vector<ProjectPartPch> m_projectPartPchs; std::vector<IdPaths> m_projectsIncludeIds; Environment &m_environment; - StringCache<Utils::PathString> &m_filePathCache; + FilePathCache<> &m_filePathCache; PchGeneratorInterface *m_pchGenerator = nullptr; }; diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index f22458c8b3d..03261ae164c 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -36,7 +36,7 @@ namespace ClangBackEnd { -PchManagerServer::PchManagerServer(StringCache<Utils::PathString> &filePathCache, +PchManagerServer::PchManagerServer(FilePathCache<> &filePathCache, ClangPathWatcherInterface &fileSystemWatcher, PchCreatorInterface &pchCreator, ProjectPartsInterface &projectParts) diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index b9df33f8b9f..7be9c759669 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -46,7 +46,7 @@ class PchManagerServer : public PchManagerServerInterface, { public: - PchManagerServer(StringCache<Utils::PathString> &filePathCache, + PchManagerServer(FilePathCache<> &filePathCache, ClangPathWatcherInterface &fileSystemWatcher, PchCreatorInterface &pchCreator, ProjectPartsInterface &projectParts); @@ -60,7 +60,7 @@ public: void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override; private: - StringCache<Utils::PathString> &m_filePathCache; + FilePathCache<> &m_filePathCache; ClangPathWatcherInterface &m_fileSystemWatcher; PchCreatorInterface &m_pchCreator; ProjectPartsInterface &m_projectParts; diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp index b625e9e197f..620a7ebaab0 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp @@ -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) : query(std::move(query)), filePathCache(filePathCache) diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h index faa5821ca3b..7d99766008d 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.h +++ b/src/tools/clangrefactoringbackend/source/clangquery.h @@ -51,7 +51,7 @@ namespace ClangBackEnd { class ClangQuery : public ClangTool { public: - ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, Utils::SmallString &&query={}); + ClangQuery(FilePathCache<std::mutex> &filePathCache, Utils::SmallString &&query={}); void setQuery(Utils::SmallString &&query); @@ -69,7 +69,7 @@ private: SourceRangesContainer sourceRangesContainer; Utils::SmallString query; std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_; - StringCache<Utils::PathString, std::mutex> &filePathCache; + FilePathCache<std::mutex> &filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp index 32c8e8694e2..692065a9e79 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp @@ -29,7 +29,7 @@ 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> &&unsaved, Utils::SmallString &&query) @@ -43,7 +43,7 @@ ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex SourceRangesForQueryMessage ClangQueryGatherer::createSourceRangesForSource( - StringCache<Utils::PathString, std::mutex> *filePathCache, + FilePathCache<std::mutex> *filePathCache, V2::FileContainer &&source, const std::vector<V2::FileContainer> &unsaved, Utils::SmallString &&query) diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h index 7d93560eecf..c1fd6341fab 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h @@ -41,13 +41,13 @@ public: using Future = std::future<SourceRangesForQueryMessage>; ClangQueryGatherer() = default; - ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache, + ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache, std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&unsaved, Utils::SmallString &&query); static SourceRangesForQueryMessage createSourceRangesForSource( - StringCache<Utils::PathString, std::mutex> *filePathCache, + FilePathCache<std::mutex> *filePathCache, V2::FileContainer &&source, const std::vector<V2::FileContainer> &unsaved, Utils::SmallString &&query); @@ -69,7 +69,7 @@ protected: std::vector<Future> finishedFutures(); private: - StringCache<Utils::PathString, std::mutex> *m_filePathCache = nullptr; + FilePathCache<std::mutex> *m_filePathCache = nullptr; SourceRangeFilter m_sourceRangeFilter; std::vector<V2::FileContainer> m_sources; std::vector<V2::FileContainer> m_unsaved; diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index d8e81a9044f..a342ff8478b 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -12,7 +12,9 @@ HEADERS += \ $$PWD/collectsymbolsastvisitor.h \ $$PWD/sourcelocationentry.h \ $$PWD/symbolscollectorinterface.h \ - $$PWD/symbolstorageinterface.h + $$PWD/symbolstorageinterface.h \ + $$PWD/symbolstorage.h \ + $$PWD/storagesqlitestatementfactory.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -52,4 +54,5 @@ SOURCES += \ $$PWD/collectsymbolsaction.cpp \ $$PWD/collectmacrossourcefilecallbacks.cpp \ $$PWD/symbolentry.cpp \ - $$PWD/sourcelocationentry.cpp + $$PWD/sourcelocationentry.cpp \ + $$PWD/symbolstorage.cpp diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h index 11fd41900fd..73fe3c5b138 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h @@ -60,7 +60,7 @@ public: bool VisitNamedDecl(const clang::NamedDecl *declaration) { - auto globalId = declaration->getCanonicalDecl()->getLocation().getRawEncoding(); + SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl()); auto sourceLocation = declaration->getLocation(); auto found = m_symbolEntries.find(globalId); @@ -81,7 +81,7 @@ public: bool VisitDeclRefExpr(const clang::DeclRefExpr *expression) { auto declaration = expression->getFoundDecl(); - auto globalId = declaration->getCanonicalDecl()->getLocation().getRawEncoding(); + SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl()); auto sourceLocation = expression->getLocation(); m_sourceLocationEntries.emplace_back(globalId, @@ -92,7 +92,7 @@ public: return true; } - uint filePathId(clang::SourceLocation sourceLocation) + FilePathIndex filePathId(clang::SourceLocation sourceLocation) { auto filePath = m_sourceManager.getFilename(sourceLocation); @@ -114,6 +114,11 @@ public: return usr; } + static SymbolIndex toSymbolIndex(const void *pointer) + { + return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer)); + } + private: SymbolEntries &m_symbolEntries; SourceLocationEntries &m_sourceLocationEntries; diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h index d988ea5b806..33eaee2a0a4 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.h +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h @@ -75,7 +75,7 @@ private: Utils::SmallString &&query); private: - StringCache<Utils::PathString, std::mutex> m_filePathCache; + FilePathCache<std::mutex> m_filePathCache; ClangQueryGatherer m_gatherer; QTimer m_pollTimer; }; diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationentry.h b/src/tools/clangrefactoringbackend/source/sourcelocationentry.h index 20f506c8b1f..dbe70123883 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationentry.h +++ b/src/tools/clangrefactoringbackend/source/sourcelocationentry.h @@ -25,6 +25,8 @@ #pragma once +#include <stringcachefwd.h> + #include <limits> #include <vector> #include <iosfwd> @@ -51,11 +53,13 @@ public: uint column = 0; }; +using SymbolIndex = long long; + class SourceLocationEntry { public: - SourceLocationEntry(uint symbolId, - uint fileId, + SourceLocationEntry(SymbolIndex symbolId, + FilePathIndex fileId, LineColumn lineColumn, SymbolType symbolType) : symbolId(symbolId), @@ -65,8 +69,8 @@ public: symbolType(symbolType) {} - uint symbolId = 0; - uint fileId = std::numeric_limits<uint>::max(); + SymbolIndex symbolId = 0; + FilePathIndex fileId = std::numeric_limits<uint>::max(); uint line = 0; uint column = 0; SymbolType symbolType; diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp index e83f6a3c383..6d9d4982273 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp @@ -54,7 +54,7 @@ namespace ClangBackEnd { SourceRangeExtractor::SourceRangeExtractor( const clang::SourceManager &sourceManager, const clang::LangOptions &languageOptions, - ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache, + ClangBackEnd::FilePathCache<std::mutex> &filePathCache, SourceRangesContainer &sourceRangesContainer) : sourceManager(sourceManager), languageOptions(languageOptions), @@ -145,7 +145,7 @@ void SourceRangeExtractor::insertSourceRange(uint fileId, 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()); if (found != m_fileIdMapping.end()) { diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h index 7a07e5c3f87..30646429747 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h @@ -59,7 +59,7 @@ class SourceRangeExtractor public: SourceRangeExtractor(const clang::SourceManager &sourceManager, const clang::LangOptions &languageOptions, - ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache, + ClangBackEnd::FilePathCache<std::mutex> &filePathCache, SourceRangesContainer &sourceRangesContainer); void addSourceRange(const clang::SourceRange &sourceRange); @@ -82,13 +82,13 @@ private: uint endOffset, Utils::SmallString &&lineSnippet); - uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; + FilePathIndex findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; private: mutable std::unordered_map<uint, uint> m_fileIdMapping; const clang::SourceManager &sourceManager; const clang::LangOptions &languageOptions; - ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache; + ClangBackEnd::FilePathCache<std::mutex> &filePathCache; SourceRangesContainer &sourceRangesContainer; }; diff --git a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h new file mode 100644 index 00000000000..22bd7cf5f5c --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h @@ -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 diff --git a/src/tools/clangrefactoringbackend/source/symbolentry.h b/src/tools/clangrefactoringbackend/source/symbolentry.h index 1b97d2f22bb..432367e3c4b 100644 --- a/src/tools/clangrefactoringbackend/source/symbolentry.h +++ b/src/tools/clangrefactoringbackend/source/symbolentry.h @@ -25,6 +25,8 @@ #pragma once +#include <stringcachefwd.h> + #include <utils/smallstring.h> #include <llvm/ADT/SmallVector.h> @@ -36,6 +38,8 @@ namespace ClangBackEnd { +using SymbolIndex = long long; + class SymbolEntry { 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); diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.cpp b/src/tools/clangrefactoringbackend/source/symbolstorage.cpp new file mode 100644 index 00000000000..793f06f882b --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolstorage.cpp @@ -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 diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h new file mode 100644 index 00000000000..12163b0f25c --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h @@ -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 diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h index cea0ec8d7a4..05d449748c2 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h @@ -33,7 +33,7 @@ namespace ClangBackEnd { class SymbolStorageInterface { public: - virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEentries, + virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries, const SourceLocationEntries &sourceLocations) = 0; }; diff --git a/tests/unit/unittest/clangpathwatcher-test.cpp b/tests/unit/unittest/clangpathwatcher-test.cpp index ebe57c3a3d8..4bbadca3a3c 100644 --- a/tests/unit/unittest/clangpathwatcher-test.cpp +++ b/tests/unit/unittest/clangpathwatcher-test.cpp @@ -42,11 +42,12 @@ using testing::NiceMock; using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>; using ClangBackEnd::WatcherEntry; +using ClangBackEnd::FilePathIndices; class ClangPathWatcher : public testing::Test { protected: - ClangBackEnd::StringCache<Utils::PathString> pathCache; + ClangBackEnd::FilePathCache<> pathCache; NiceMock<MockClangPathWatcherNotifier> notifier; Watcher watcher{pathCache, ¬ifier}; NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); @@ -55,8 +56,8 @@ protected: Utils::SmallString id3{"id3"}; Utils::PathString path1{"/path/path1"}; Utils::PathString path2{"/path/path2"}; - std::vector<uint> paths = watcher.pathCache().stringIds({path1, path2}); - std::vector<uint> ids = watcher.idCache().stringIds({id1, id2, id3}); + FilePathIndices paths{watcher.pathCache().stringIds({path1, path2})}; + FilePathIndices ids{watcher.idCache().stringIds({id1, id2, id3})}; WatcherEntry watcherEntry1{ids[0], paths[0]}; WatcherEntry watcherEntry2{ids[1], paths[0]}; WatcherEntry watcherEntry3{ids[0], paths[1]}; diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp index 3b1a196e94d..792c234570a 100644 --- a/tests/unit/unittest/clangquery-test.cpp +++ b/tests/unit/unittest/clangquery-test.cpp @@ -33,7 +33,7 @@ #include <mutex> using ClangBackEnd::ClangQuery; -using ClangBackEnd::StringCache; +using ClangBackEnd::FilePathCache; using testing::AllOf; using testing::Contains; @@ -48,7 +48,7 @@ protected: void SetUp() override; protected: - StringCache<Utils::PathString, std::mutex> filePathCache; + FilePathCache<std::mutex> filePathCache; ::ClangQuery simpleFunctionQuery{filePathCache}; ::ClangQuery simpleClassQuery{filePathCache}; }; diff --git a/tests/unit/unittest/clangquerygatherer-test.cpp b/tests/unit/unittest/clangquerygatherer-test.cpp index 47719f031de..a9a191383c1 100644 --- a/tests/unit/unittest/clangquerygatherer-test.cpp +++ b/tests/unit/unittest/clangquerygatherer-test.cpp @@ -75,7 +75,7 @@ protected: void SetUp() override; protected: - ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache; + ClangBackEnd::FilePathCache<std::mutex> filePathCache; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), diff --git a/tests/unit/unittest/includecollector-test.cpp b/tests/unit/unittest/includecollector-test.cpp index d2c0d06b710..ad405e55d7d 100644 --- a/tests/unit/unittest/includecollector-test.cpp +++ b/tests/unit/unittest/includecollector-test.cpp @@ -43,7 +43,7 @@ protected: uint id(const Utils::SmallString &path); protected: - ClangBackEnd::StringCache<Utils::PathString> filePathCache; + ClangBackEnd::FilePathCache<> filePathCache; ClangBackEnd::IncludeCollector collector{filePathCache}; ClangBackEnd::IncludeCollector emptyCollector{filePathCache}; Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector_main.h", diff --git a/tests/unit/unittest/mocksqlitedatabase.h b/tests/unit/unittest/mocksqlitedatabase.h new file mode 100644 index 00000000000..55c06cb81e4 --- /dev/null +++ b/tests/unit/unittest/mocksqlitedatabase.h @@ -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)); + +}; + diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp new file mode 100644 index 00000000000..a1813b52c70 --- /dev/null +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -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); +} diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h new file mode 100644 index 00000000000..7e45bd39527 --- /dev/null +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -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> &); + + diff --git a/tests/unit/unittest/mocksqlitewritestatement.h b/tests/unit/unittest/mocksqlitewritestatement.h new file mode 100644 index 00000000000..98ea4e7e249 --- /dev/null +++ b/tests/unit/unittest/mocksqlitewritestatement.h @@ -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; +}; diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp index 12cd50b8e5f..f03b0cd25e1 100644 --- a/tests/unit/unittest/pchcreator-test.cpp +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -68,7 +68,7 @@ protected: uint id(const Utils::PathString &path); protected: - ClangBackEnd::StringCache<Utils::PathString> filePathCache; + ClangBackEnd::FilePathCache<> filePathCache; PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp"; PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp index 8ac039b16ab..b9b170e3dc8 100644 --- a/tests/unit/unittest/pchmanagerserver-test.cpp +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -59,7 +59,7 @@ protected: NiceMock<MockPchCreator> mockPchCreator; NiceMock<MockClangPathWatcher> mockClangPathWatcher; NiceMock<MockProjectParts> mockProjectParts; - ClangBackEnd::StringCache<Utils::PathString> filePathCache; + ClangBackEnd::FilePathCache<> filePathCache; ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts}; NiceMock<MockPchManagerClient> mockPchManagerClient; SmallString projectPartId1 = "project1"; diff --git a/tests/unit/unittest/sourcerangeextractor-test.cpp b/tests/unit/unittest/sourcerangeextractor-test.cpp index 42f2f0f7246..d20cd9bb93d 100644 --- a/tests/unit/unittest/sourcerangeextractor-test.cpp +++ b/tests/unit/unittest/sourcerangeextractor-test.cpp @@ -54,7 +54,7 @@ protected: TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; ClangBackEnd::SourceRangesContainer sourceRangesContainer; 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}; clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index b3523bdc770..c052367a8bd 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -340,7 +340,6 @@ TEST_F(SqliteStatement, GetStructValuesWithoutArguments) Output{"poo", "40", 3})); } - TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes) { SqliteReadStatement statement("SELECT name FROM test WHERE number=?", database); diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp new file mode 100644 index 00000000000..98c99d908e2 --- /dev/null +++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp @@ -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")); +} + +} + diff --git a/tests/unit/unittest/stringcache-test.cpp b/tests/unit/unittest/stringcache-test.cpp index 265555f35c5..a4f989ba023 100644 --- a/tests/unit/unittest/stringcache-test.cpp +++ b/tests/unit/unittest/stringcache-test.cpp @@ -31,13 +31,16 @@ namespace { -using ClangBackEnd::StringCacheEntries; using ClangBackEnd::StringCacheException; +using uint64 = unsigned long long; + +using CacheEntries = ClangBackEnd::FileCacheCacheEntries; + class StringCache : public testing::Test { protected: - ClangBackEnd::StringCache<Utils::PathString> cache; + ClangBackEnd::FilePathCache<> cache; Utils::PathString filePath1{"/file/pathOne"}; Utils::PathString filePath2{"/file/pathTwo"}; Utils::PathString filePath3{"/file/pathThree"}; @@ -144,7 +147,7 @@ TEST_F(StringCache, IsNotEmpty) TEST_F(StringCache, PopulateWithEmptyVector) { - StringCacheEntries<Utils::PathString> entries; + CacheEntries entries; cache.uncheckedPopulate(std::move(entries)); @@ -153,10 +156,10 @@ TEST_F(StringCache, PopulateWithEmptyVector) TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries) { - StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, - {filePath2.clone(), 1}, - {filePath3.clone(), 2}, - {filePath4.clone(), 3}}; + CacheEntries entries{{filePath1.clone(), 0}, + {filePath2.clone(), 1}, + {filePath3.clone(), 2}, + {filePath4.clone(), 3}}; cache.uncheckedPopulate(std::move(entries)); @@ -165,10 +168,10 @@ TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries) TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries) { - StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, - {filePath2.clone(), 1}, - {filePath3.clone(), 2}, - {filePath4.clone(), 3}}; + CacheEntries entries{{filePath1.clone(), 0}, + {filePath2.clone(), 1}, + {filePath3.clone(), 2}, + {filePath4.clone(), 3}}; cache.uncheckedPopulate(std::move(entries)); auto string = cache.string(2); @@ -178,30 +181,30 @@ TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries) TEST_F(StringCache, EntriesHaveUniqueIds) { - StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, - {filePath2.clone(), 1}, - {filePath3.clone(), 2}, - {filePath4.clone(), 2}}; + CacheEntries entries{{filePath1.clone(), 0}, + {filePath2.clone(), 1}, + {filePath3.clone(), 2}, + {filePath4.clone(), 2}}; ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException); } TEST_F(StringCache, IdsAreHigherLowerEntriesSize) { - StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, - {filePath2.clone(), 1}, - {filePath3.clone(), 4}, - {filePath4.clone(), 3}}; + CacheEntries entries{{filePath1.clone(), 0}, + {filePath2.clone(), 1}, + {filePath3.clone(), 4}, + {filePath4.clone(), 3}}; ASSERT_THROW(cache.populate(std::move(entries)), std::out_of_range); } TEST_F(StringCache, MultipleEntries) { - StringCacheEntries<Utils::PathString> entries{{filePath1.clone(), 0}, - {filePath1.clone(), 1}, - {filePath3.clone(), 2}, - {filePath4.clone(), 3}}; + CacheEntries entries{{filePath1.clone(), 0}, + {filePath1.clone(), 1}, + {filePath3.clone(), 2}, + {filePath4.clone(), 3}}; ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException); } diff --git a/tests/unit/unittest/symbolscollector-test.cpp b/tests/unit/unittest/symbolscollector-test.cpp index 15e15ba5f14..4543c61e446 100644 --- a/tests/unit/unittest/symbolscollector-test.cpp +++ b/tests/unit/unittest/symbolscollector-test.cpp @@ -42,6 +42,7 @@ using testing::_; using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SymbolEntry; using ClangBackEnd::SymbolType; +using ClangBackEnd::SymbolIndex; namespace { @@ -53,7 +54,7 @@ protected: return filePathCache.stringId(string); } - uint symbolIdForSymbolName(const Utils::SmallString &symbolName); + SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName); protected: ClangBackEnd::FilePathCache<> filePathCache; @@ -149,7 +150,7 @@ TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation) Field(&SourceLocationEntry::column, 5)))); } -uint SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName) +SymbolIndex SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName) { for (const auto &entry : collector.symbols()) { if (entry.second.symbolName == symbolName) diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp new file mode 100644 index 00000000000..ec30b9289df --- /dev/null +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -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"}); +} +} + diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 7c44c4f4ad9..667aeaa5d70 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -69,7 +69,10 @@ SOURCES += \ symbolindexer-test.cpp \ stringcache-test.cpp \ unittests-main.cpp \ - utf8-test.cpp + utf8-test.cpp \ + symbolstorage-test.cpp \ + storagesqlitestatementfactory-test.cpp \ + mocksqlitereadstatement.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -188,7 +191,11 @@ HEADERS += \ spydummy.h \ testenvironment.h \ mocksymbolscollector.h \ - mocksymbolstorage.h + mocksymbolstorage.h \ + mocksqlitewritestatement.h \ + mocksqlitedatabase.h \ + mocksqlitereadstatement.h \ + google-using-directive.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ -- GitLab