From d2e15e5f1efa1ef160a2d4f40ab61180477d1f14 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 21 Sep 2017 11:43:59 +0200 Subject: [PATCH] Clang: Add file cache The database is using file path integer ids to handle file paths because otherwise we would save many redundant data. This patch is improving it further with the introduction of a database based file path cache. The entries are now divided in a directory path and file name. This is quite handy for directory based file watching. Change-Id: I03f2e388e43f3d521d6bf8e39dfb95eb2309dc73 Reviewed-by: Tim Jenssen --- src/libs/clangsupport/clangsupport-lib.pri | 17 +- ...amicastmatcherdiagnosticmessagecontainer.h | 4 +- src/libs/clangsupport/filepath.h | 36 +- src/libs/clangsupport/filepathcache.h | 128 ++++++ .../clangsupport/filepathcaching.cpp} | 16 +- src/libs/clangsupport/filepathcaching.h | 62 +++ ...containerbase.cpp => filepathcachingfwd.h} | 6 +- .../clangsupport/filepathcachinginterface.h | 73 ++++ src/libs/clangsupport/filepathexceptions.h | 59 +++ .../clangsupport/filepathid.cpp} | 14 +- src/libs/clangsupport/filepathid.h | 113 +++++ src/libs/clangsupport/filepathstorage.h | 187 ++++++++ ...ntainerbase.h => filepathstoragesources.h} | 63 +-- .../filepathstoragesqlitestatementfactory.h | 85 ++++ .../refactoringdatabaseinitializer.h | 24 +- .../sourcelocationcontainerv2.cpp | 6 +- .../clangsupport/sourcelocationcontainerv2.h | 23 +- .../clangsupport/sourcelocationscontainer.cpp | 6 +- .../clangsupport/sourcelocationscontainer.h | 27 +- .../clangsupport/sourcerangecontainerv2.h | 12 +- .../clangsupport/sourcerangescontainer.cpp | 5 +- src/libs/clangsupport/sourcerangescontainer.h | 23 +- .../sourcerangewithtextcontainer.h | 6 +- src/libs/clangsupport/stringcache.h | 89 +++- src/libs/clangsupport/stringcachefwd.h | 10 - src/libs/sqlite/sqlite-lib.pri | 8 +- ...estatement.cpp => sqlitebasestatement.cpp} | 175 +++----- ...qlitestatement.h => sqlitebasestatement.h} | 352 +++++++-------- src/libs/sqlite/sqlitedatabasebackend.cpp | 2 +- src/libs/sqlite/sqliteexception.h | 4 +- src/libs/sqlite/sqlitereadstatement.cpp | 2 +- src/libs/sqlite/sqlitereadstatement.h | 11 +- src/libs/sqlite/sqlitereadwritestatement.cpp | 2 +- src/libs/sqlite/sqlitereadwritestatement.h | 17 +- src/libs/sqlite/sqlitewritestatement.cpp | 2 +- src/libs/sqlite/sqlitewritestatement.h | 12 +- src/libs/utils/smallstring.h | 48 +- src/libs/utils/smallstringview.h | 9 +- .../clangrefactoringplugin.cpp | 12 +- .../querysqlitestatementfactory.h | 9 +- .../clangrefactoring/refactoringclient.cpp | 52 +-- .../clangrefactoring/refactoringclient.h | 6 +- .../clangrefactoring/refactoringengine.cpp | 16 +- .../clangrefactoring/refactoringengine.h | 18 +- .../clangrefactoring/sourcelocations.h | 41 +- src/plugins/clangrefactoring/symbolquery.h | 59 +-- .../clangpchmanagerbackendmain.cpp | 11 +- .../source/clangpathwatcher.h | 66 +-- .../source/clangpchmanagerbackend-source.pri | 2 - .../source/collectincludesaction.h | 21 +- .../collectincludespreprocessorcallbacks.h | 27 +- .../source/collectincludestoolaction.h | 21 +- .../clangpchmanagerbackend/source/idpaths.h | 10 +- .../source/includecollector.cpp | 4 +- .../source/includecollector.h | 12 +- .../source/pchcreator.cpp | 23 +- .../source/pchcreator.h | 14 +- .../source/pchmanagerserver.cpp | 6 +- .../source/pchmanagerserver.h | 5 +- .../clangrefactoringbackendmain.cpp | 11 +- .../source/clangquery.cpp | 24 +- .../source/clangquery.h | 14 +- .../source/clangquerygatherer.cpp | 4 +- .../source/clangquerygatherer.h | 8 +- .../source/clangrefactoringbackend-source.pri | 3 +- .../source/collectsymbolsaction.h | 6 +- .../source/collectsymbolsastvisitor.h | 16 +- .../source/collectsymbolsconsumer.h | 6 +- .../source/locationsourcefilecallbacks.cpp | 28 +- .../source/locationsourcefilecallbacks.h | 14 +- .../source/macropreprocessorcallbacks.cpp | 12 +- .../source/macropreprocessorcallbacks.h | 112 +++-- .../source/refactoringserver.cpp | 4 +- .../source/refactoringserver.h | 9 +- .../source/sourcelocationentry.h | 13 +- .../source/sourcelocationsutils.h | 23 +- .../source/sourcerangeextractor.cpp | 29 +- .../source/sourcerangeextractor.h | 14 +- .../source/storagesqlitestatementfactory.h | 9 - .../source/symbolfinder.cpp | 31 +- .../source/symbolfinder.h | 14 +- .../source/symbolindexing.h | 21 +- .../source/symbollocationfinderaction.cpp | 17 +- .../source/symbollocationfinderaction.h | 35 +- .../source/symbolscollector.cpp | 2 +- .../source/symbolscollector.h | 5 +- .../source/symbolstorage.h | 28 +- .../unittest/clangdocumentprocessor-test.cpp | 7 +- .../unittest/clangdocumentprocessors-test.cpp | 7 +- tests/unit/unittest/clangpathwatcher-test.cpp | 100 +++-- tests/unit/unittest/clangquery-test.cpp | 14 +- .../clangqueryexamplehighlightmarker-test.cpp | 34 +- .../unit/unittest/clangquerygatherer-test.cpp | 10 +- .../clangqueryhighlightmarker-test.cpp | 58 +-- ...portivetranslationunitinitializer-test.cpp | 7 +- .../unittest/clangtranslationunit-test.cpp | 7 +- .../unittest/clangtranslationunits-test.cpp | 7 +- tests/unit/unittest/filepathcache-test.cpp | 286 ++++++++++++ tests/unit/unittest/filepathstorage-test.cpp | 409 ++++++++++++++++++ ...pathstoragesqlitestatementfactory-test.cpp | 97 +++++ .../unit/unittest/google-using-declarations.h | 5 + tests/unit/unittest/gtest-clang-printing.cpp | 14 - .../unit/unittest/gtest-creator-printing.cpp | 75 +++- tests/unit/unittest/gtest-creator-printing.h | 32 +- tests/unit/unittest/gtest-qt-printing.cpp | 5 + tests/unit/unittest/gtest-qt-printing.h | 2 + tests/unit/unittest/includecollector-test.cpp | 23 +- .../unit/unittest/mockfilepathcaching.h | 24 +- tests/unit/unittest/mockfilepathstorage.h | 42 ++ tests/unit/unittest/mocksqlitedatabase.h | 3 + .../unit/unittest/mocksqlitereadstatement.cpp | 48 +- tests/unit/unittest/mocksqlitereadstatement.h | 81 ++-- tests/unit/unittest/mocksqlitestatement.h | 106 +++++ .../unit/unittest/mocksqlitewritestatement.h | 3 + tests/unit/unittest/pchcreator-test.cpp | 45 +- tests/unit/unittest/pchmanagerserver-test.cpp | 8 +- .../querysqlitestatementfactory-test.cpp | 12 +- .../unit/unittest/refactoringclient-test.cpp | 36 +- .../refactoringdatabaseinitializer-test.cpp | 21 +- .../unit/unittest/refactoringengine-test.cpp | 13 +- .../unit/unittest/refactoringserver-test.cpp | 15 +- tests/unit/unittest/smallstring-test.cpp | 35 +- .../unittest/sourcerangeextractor-test.cpp | 17 +- .../unit/unittest/sourcerangefilter-test.cpp | 30 +- tests/unit/unittest/sqlitestatement-test.cpp | 128 +++++- tests/unit/unittest/sqliteteststatement.h | 23 +- .../storagesqlitestatementfactory-test.cpp | 6 - tests/unit/unittest/stringcache-test.cpp | 134 +++++- tests/unit/unittest/symbolfinder-test.cpp | 82 ++-- tests/unit/unittest/symbolindexer-test.cpp | 2 +- tests/unit/unittest/symbolindexing-test.cpp | 59 +-- tests/unit/unittest/symbolquery-test.cpp | 40 +- tests/unit/unittest/symbolscollector-test.cpp | 21 +- tests/unit/unittest/symbolstorage-test.cpp | 47 +- tests/unit/unittest/unittest.pro | 10 +- 135 files changed, 3458 insertions(+), 1517 deletions(-) create mode 100644 src/libs/clangsupport/filepathcache.h rename src/{tools/clangrefactoringbackend/source/sourcelocationentry.cpp => libs/clangsupport/filepathcaching.cpp} (82%) create mode 100644 src/libs/clangsupport/filepathcaching.h rename src/libs/clangsupport/{sourcefilepathcontainerbase.cpp => filepathcachingfwd.h} (93%) create mode 100644 src/libs/clangsupport/filepathcachinginterface.h create mode 100644 src/libs/clangsupport/filepathexceptions.h rename src/{tools/clangpchmanagerbackend/source/idpaths.cpp => libs/clangsupport/filepathid.cpp} (82%) create mode 100644 src/libs/clangsupport/filepathid.h create mode 100644 src/libs/clangsupport/filepathstorage.h rename src/libs/clangsupport/{sourcefilepathcontainerbase.h => filepathstoragesources.h} (57%) create mode 100644 src/libs/clangsupport/filepathstoragesqlitestatementfactory.h rename src/libs/sqlite/{sqlitestatement.cpp => sqlitebasestatement.cpp} (68%) rename src/libs/sqlite/{sqlitestatement.h => sqlitebasestatement.h} (77%) create mode 100644 tests/unit/unittest/filepathcache-test.cpp create mode 100644 tests/unit/unittest/filepathstorage-test.cpp create mode 100644 tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp rename src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp => tests/unit/unittest/mockfilepathcaching.h (72%) create mode 100644 tests/unit/unittest/mockfilepathstorage.h create mode 100644 tests/unit/unittest/mocksqlitestatement.h diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index 25b48dfc075..30c1d03446d 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -67,7 +67,6 @@ SOURCES += \ $$PWD/requestsourcelocationforrenamingmessage.cpp \ $$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \ $$PWD/requestsourcerangesforquerymessage.cpp \ - $$PWD/sourcefilepathcontainerbase.cpp \ $$PWD/sourcelocationcontainer.cpp \ $$PWD/sourcelocationcontainerv2.cpp \ $$PWD/sourcelocationscontainer.cpp \ @@ -82,7 +81,9 @@ SOURCES += \ $$PWD/updatepchprojectpartsmessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \ $$PWD/updatevisibletranslationunitsmessage.cpp \ - $$PWD/writemessageblock.cpp + $$PWD/writemessageblock.cpp \ + $$PWD/filepathcaching.cpp \ + $$PWD/filepathid.cpp HEADERS += \ $$PWD/cancelmessage.h \ @@ -150,7 +151,6 @@ HEADERS += \ $$PWD/requestsourcelocationforrenamingmessage.h \ $$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \ $$PWD/requestsourcerangesforquerymessage.h \ - $$PWD/sourcefilepathcontainerbase.h \ $$PWD/sourcelocationcontainer.h \ $$PWD/sourcelocationcontainerv2.h \ $$PWD/sourcelocationscontainer.h \ @@ -172,6 +172,15 @@ HEADERS += \ $$PWD/stringcachefwd.h \ $$PWD/stringcachealgorithms.h \ $$PWD/projectmanagementserverinterface.h \ - $$PWD/refactoringdatabaseinitializer.h + $$PWD/refactoringdatabaseinitializer.h \ + $$PWD/filepathcache.h \ + $$PWD/filepathid.h \ + $$PWD/filepathstorage.h \ + $$PWD/filepathstoragesqlitestatementfactory.h \ + $$PWD/filepathstoragesources.h \ + $$PWD/filepathexceptions.h \ + $$PWD/filepathcachinginterface.h \ + $$PWD/filepathcaching.h \ + $$PWD/filepathcachingfwd.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h b/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h index 07a21af605f..51e1f129492 100644 --- a/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h +++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h @@ -94,9 +94,7 @@ public: DynamicASTMatcherDiagnosticMessageContainer clone() const { - return DynamicASTMatcherDiagnosticMessageContainer(m_sourceRange.clone(), - m_errorType, - m_arguments.clone()); + return *this; } private: diff --git a/src/libs/clangsupport/filepath.h b/src/libs/clangsupport/filepath.h index c57da408bc0..96387412c11 100644 --- a/src/libs/clangsupport/filepath.h +++ b/src/libs/clangsupport/filepath.h @@ -63,22 +63,27 @@ public: { } - FilePath(const Utils::PathString &directory, const Utils::PathString &name) - : m_path({std::move(directory), "/", std::move(name)}), + FilePath(Utils::SmallStringView directory, Utils::SmallStringView name) + : m_path({directory, "/", name}), m_slashIndex(directory.size()) {} - Utils::SmallStringView directory() const + Utils::SmallStringView directory() const noexcept { return m_path.mid(0, m_slashIndex); } - Utils::SmallStringView name() const + Utils::SmallStringView name() const noexcept { return m_path.mid(m_slashIndex + 1, m_path.size() - m_slashIndex - 1); } - const Utils::PathString &path() const + const Utils::PathString &path() const noexcept + { + return m_path; + } + + operator Utils::PathString() const noexcept { return m_path; } @@ -105,9 +110,7 @@ public: friend std::ostream &operator<<(std::ostream &out, const FilePath &filePath) { - out << filePath.directory() << "/" << filePath.name(); - - return out; + return out << "(" << filePath.path() << ", " << filePath.slashIndex() << ")"; } friend bool operator==(const FilePath &first, const FilePath &second) @@ -115,6 +118,16 @@ public: return first.m_path == second.m_path; } + friend bool operator==(const FilePath &first, const Utils::SmallStringView &second) + { + return first.path() == second; + } + + friend bool operator==(const Utils::SmallStringView &first, const FilePath&second) + { + return second == first; + } + friend bool operator<(const FilePath &first, const FilePath &second) { return first.m_path < second.m_path; @@ -125,11 +138,18 @@ public: return *this; } + std::size_t slashIndex() const + { + return m_slashIndex; + } + private: Utils::PathString m_path = "/"; std::size_t m_slashIndex = 0; }; +using FilePaths = std::vector; + CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath); } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathcache.h b/src/libs/clangsupport/filepathcache.h new file mode 100644 index 00000000000..61e86809653 --- /dev/null +++ b/src/libs/clangsupport/filepathcache.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 "filepathexceptions.h" +#include "filepathid.h" +#include "filepath.h" +#include "stringcache.h" + +#include + +#include + +namespace ClangBackEnd { + +class FilePathCacheBase +{ +public: + static + std::ptrdiff_t lastSlashIndex(Utils::SmallStringView filePath) + { + auto foundReverse = std::find(filePath.rbegin(), filePath.rend(), '/'); + auto found = foundReverse.base(); + --found; + + return std::distance(filePath.begin(), found); + } + + static + Utils::SmallStringView directoryPath(Utils::SmallStringView filePath, std::ptrdiff_t slashIndex) + { + return {filePath.data(), std::size_t(std::max(std::ptrdiff_t(0), slashIndex))}; + } + + static + Utils::SmallStringView fileName(Utils::SmallStringView filePath, std::ptrdiff_t slashIndex) + { + return {filePath.data() + slashIndex + 1, filePath.size() - std::size_t(slashIndex) - 1}; + } +}; + +template +class FilePathCache final : private FilePathCacheBase +{ + using DirectoryPathCache = StringCache; + using FileNameCache = StringCache; +public: + FilePathCache(FilePathStorage &filePathStorage) + : m_filePathStorage(filePathStorage) + {} + + FilePathId filePathId(Utils::SmallStringView filePath) const + { + std::ptrdiff_t slashIndex = lastSlashIndex(filePath); + + Utils::SmallStringView directoryPath = this->directoryPath(filePath, slashIndex); + int directoryId = m_directyPathCache.stringId(directoryPath, + [&] (const Utils::SmallStringView) { + return m_filePathStorage.fetchDirectoryId(directoryPath); + }); + + Utils::SmallStringView fileName = this->fileName(filePath, slashIndex); + + int fileNameId = m_fileNameCache.stringId(fileName, + [&] (const Utils::SmallStringView) { + return m_filePathStorage.fetchSourceId(directoryId, fileName); + }); + + return {directoryId, fileNameId}; + } + + FilePath filePath(FilePathId filePathId) const + { + if (Q_UNLIKELY(!filePathId.isValid())) + throw NoFilePathForInvalidFilePathId(); + + auto fetchFilePath = [&] (int id) { return m_filePathStorage.fetchDirectoryPath(id); }; + + Utils::PathString directoryPath = m_directyPathCache.string(filePathId.directoryId, + fetchFilePath); + + + auto fetchSoureName = [&] (int id) { return m_filePathStorage.fetchSourceName(id); }; + + Utils::SmallString fileName = m_fileNameCache.string(filePathId.fileNameId, + fetchSoureName); + + return {directoryPath, fileName}; + } + +private: + mutable DirectoryPathCache m_directyPathCache; + mutable FileNameCache m_fileNameCache; + FilePathStorage &m_filePathStorage; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp b/src/libs/clangsupport/filepathcaching.cpp similarity index 82% rename from src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp rename to src/libs/clangsupport/filepathcaching.cpp index 9cea242fa87..1956a4718c4 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp +++ b/src/libs/clangsupport/filepathcaching.cpp @@ -23,20 +23,18 @@ ** ****************************************************************************/ -#include "sourcelocationentry.h" - -#include +#include "filepathcaching.h" namespace ClangBackEnd { -std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry) +FilePathId FilePathCaching::filePathId(Utils::SmallStringView filePath) const { - out << "(" - << entry.fileId << ", " - << entry.line << ", " - << entry.column << ")"; + return m_cache.filePathId(filePath); +} - return out; +FilePath FilePathCaching::filePath(FilePathId filePathId) const +{ + return m_cache.filePath(filePathId); } } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathcaching.h b/src/libs/clangsupport/filepathcaching.h new file mode 100644 index 00000000000..573ce816105 --- /dev/null +++ b/src/libs/clangsupport/filepathcaching.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 "clangsupport_global.h" + +#include "filepathcachinginterface.h" +#include "filepathcache.h" +#include "filepathstoragesqlitestatementfactory.h" +#include "filepathstorage.h" + +#include +#include +#include + +namespace ClangBackEnd { + +class CMBIPC_EXPORT FilePathCaching final : public FilePathCachingInterface +{ + using Factory = FilePathStorageSqliteStatementFactory; + using Storage = FilePathStorage; + using Cache = FilePathCache; +public: + FilePathCaching(Sqlite::Database &database) + : m_factory(database) + {} + + FilePathId filePathId(Utils::SmallStringView filePath) const override; + FilePath filePath(FilePathId filePathId) const override; + +private: + Factory m_factory; + Storage m_storage{m_factory}; + Cache m_cache{m_storage}; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/sourcefilepathcontainerbase.cpp b/src/libs/clangsupport/filepathcachingfwd.h similarity index 93% rename from src/libs/clangsupport/sourcefilepathcontainerbase.cpp rename to src/libs/clangsupport/filepathcachingfwd.h index 66d44d88274..7519dde634f 100644 --- a/src/libs/clangsupport/sourcefilepathcontainerbase.cpp +++ b/src/libs/clangsupport/filepathcachingfwd.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,10 +23,10 @@ ** ****************************************************************************/ -#include "sourcefilepathcontainerbase.h" +#pragma once namespace ClangBackEnd { - +class FilePathCachingInterface; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathcachinginterface.h b/src/libs/clangsupport/filepathcachinginterface.h new file mode 100644 index 00000000000..9f53e57610d --- /dev/null +++ b/src/libs/clangsupport/filepathcachinginterface.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 "filepath.h" +#include "filepathid.h" + +namespace ClangBackEnd { + +class FilePathCachingInterface +{ +public: + virtual FilePathId filePathId(Utils::SmallStringView filePath) const = 0; + virtual FilePath filePath(FilePathId filePathId) const = 0; + + template + FilePathIds filePathIds(Container &&filePaths) const + { + FilePathIds filePathIds; + filePathIds.reserve(filePaths.size()); + + std::transform(filePaths.begin(), + filePaths.end(), + std::back_inserter(filePathIds), + [&] (const auto &filePath) { return this->filePathId(filePath); }); + + return filePathIds; + } + + template + FilePathIds filePathIds(std::initializer_list filePaths) const + { + return filePathIds(std::vector(filePaths)); + } + + FilePaths filePaths(const FilePathIds &filePathIds) const + { + FilePaths filePaths; + filePaths.reserve(filePathIds.size()); + + std::transform(filePathIds.begin(), + filePathIds.end(), + std::back_inserter(filePaths), + [&] (auto filePathId) { return this->filePath(filePathId); }); + + return filePaths; + } +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathexceptions.h b/src/libs/clangsupport/filepathexceptions.h new file mode 100644 index 00000000000..32142c084c6 --- /dev/null +++ b/src/libs/clangsupport/filepathexceptions.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 + +namespace ClangBackEnd { + +class NoFilePathForInvalidFilePathId : std::exception +{ +public: + const char *what() const noexcept override + { + return "You cannot get a file path for an invalid file path id!"; + } +}; + +class SourceNameIdDoesNotExists : std::exception +{ +public: + const char *what() const noexcept override + { + return "The source name id does not exists in the database!"; + } +}; + +class DirectoryPathIdDoesNotExists : std::exception +{ +public: + const char *what() const noexcept override + { + return "The directory path id does not exists in the database!"; + } +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/idpaths.cpp b/src/libs/clangsupport/filepathid.cpp similarity index 82% rename from src/tools/clangpchmanagerbackend/source/idpaths.cpp rename to src/libs/clangsupport/filepathid.cpp index f1dba02e4e9..0ed77ef77a1 100644 --- a/src/tools/clangpchmanagerbackend/source/idpaths.cpp +++ b/src/libs/clangsupport/filepathid.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,19 +23,17 @@ ** ****************************************************************************/ -#include "idpaths.h" +#include "filepathid.h" -#include +#include namespace ClangBackEnd { -std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths) +QDebug operator<<(QDebug debug, const FilePathId &filePathId) { - out << "(" - << idPaths.id << ", " - << idPaths.paths << ")"; + debug.nospace() << "(" << filePathId.directoryId << ", " << filePathId.fileNameId << ")"; - return out; + return debug; } } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathid.h b/src/libs/clangsupport/filepathid.h new file mode 100644 index 00000000000..34bd66dbe32 --- /dev/null +++ b/src/libs/clangsupport/filepathid.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 "clangsupport_global.h" + +#include + +#include +#include +#include + +namespace ClangBackEnd { + +class FilePathId +{ +public: + FilePathId() = default; + FilePathId(int directoryId, int fileNameId) + : directoryId(directoryId), + fileNameId(fileNameId) + {} + + bool isValid() const + { + return directoryId >= 0 && fileNameId >= 0; + } + + friend bool operator==(FilePathId first, FilePathId second) + { + return first.isValid() + && second.isValid() + && first.directoryId == second.directoryId + && first.fileNameId == second.fileNameId; + } + + friend bool operator!=(FilePathId first, FilePathId second) + { + return !(first==second); + } + + friend bool operator<(FilePathId first, FilePathId second) + { + return std::tie(first.directoryId, first.fileNameId) + < std::tie(second.directoryId, second.fileNameId); + } + + friend QDataStream &operator<<(QDataStream &out, const FilePathId &filePathId) + { + out << filePathId.directoryId; + out << filePathId.fileNameId; + + return out; + } + + friend QDataStream &operator>>(QDataStream &in, FilePathId &filePathId) + { + in >> filePathId.directoryId; + in >> filePathId.fileNameId; + + return in; + } + + +public: + int directoryId = -1; + int fileNameId = -1; +}; + +using FilePathIds = std::vector; + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePathId &filePathId); +} // namespace ClangBackEnd + +namespace std { +template<> struct hash +{ + using argument_type = ClangBackEnd::FilePathId; + using result_type = std::size_t; + result_type operator()(const argument_type& filePathId) const + { + long long hash = filePathId.directoryId; + hash = hash << 32; + hash += filePathId.fileNameId; + + return std::hash{}(hash); + } +}; + +} // namespace std diff --git a/src/libs/clangsupport/filepathstorage.h b/src/libs/clangsupport/filepathstorage.h new file mode 100644 index 00000000000..d8279c9c0b8 --- /dev/null +++ b/src/libs/clangsupport/filepathstorage.h @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** 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 "filepathexceptions.h" +#include "filepathid.h" +#include "filepathstoragesources.h" + +#include +#include + +#include + +namespace ClangBackEnd { + +template +class FilePathStorage +{ + using DeferredTransaction = Sqlite::DeferredTransaction; + using ImmediateTransaction = Sqlite::ImmediateTransaction; + using ReadStatement = typename StatementFactory::ReadStatementType; + using WriteStatement = typename StatementFactory::WriteStatementType; + using Database = typename StatementFactory::DatabaseType; + +public: + FilePathStorage(StatementFactory &statementFactory) + : m_statementFactory(statementFactory) + {} + + int fetchDirectoryId(Utils::SmallStringView directoryPath) + try { + DeferredTransaction transaction{m_statementFactory.database}; + + Utils::optional optionalDirectoryId = readDirectoryId(directoryPath); + + int directoryId = -1; + + if (optionalDirectoryId) + directoryId = optionalDirectoryId.value(); + else + directoryId = writeDirectoryId(directoryPath); + + transaction.commit(); + + return directoryId; + } catch (Sqlite::StatementIsBusy &) { + return fetchDirectoryId(directoryPath); + } + + Utils::optional readDirectoryId(Utils::SmallStringView directoryPath) + { + ReadStatement &statement = m_statementFactory.selectDirectoryIdFromDirectoriesByDirectoryPath; + + return statement.template value(directoryPath); + } + + int writeDirectoryId(Utils::SmallStringView directoryPath) + { + WriteStatement &statement = m_statementFactory.insertIntoDirectories; + + statement.write(directoryPath); + + return int(m_statementFactory.database.lastInsertedRowId()); + } + + Utils::PathString fetchDirectoryPath(int directoryPathId) + { + DeferredTransaction transaction{m_statementFactory.database}; + + ReadStatement &statement = m_statementFactory.selectDirectoryPathFromDirectoriesByDirectoryId; + + auto optionalDirectoryPath = statement.template value(directoryPathId); + + if (!optionalDirectoryPath) + throw DirectoryPathIdDoesNotExists(); + + transaction.commit(); + + return optionalDirectoryPath.value(); + } + + std::vector fetchAllDirectories() + { + DeferredTransaction transaction{m_statementFactory.database}; + + ReadStatement &statement = m_statementFactory.selectAllDirectories; + + auto directories = statement.template values(256); + + transaction.commit(); + + return directories; + } + + int fetchSourceId(int directoryId, Utils::SmallStringView sourceName) + try { + DeferredTransaction transaction{m_statementFactory.database}; + + Utils::optional optionalSourceId = readSourceId(directoryId, sourceName); + + int sourceId = -1; + + if (optionalSourceId) + sourceId = optionalSourceId.value(); + else + sourceId = writeSourceId(directoryId, sourceName); + + transaction.commit(); + + return sourceId; + } catch (Sqlite::StatementIsBusy &) { + return fetchSourceId(directoryId, sourceName); + } + + int writeSourceId(int directoryId, Utils::SmallStringView sourceName) + { + WriteStatement &statement = m_statementFactory.insertIntoSources; + + statement.write(directoryId, sourceName); + + return int(m_statementFactory.database.lastInsertedRowId()); + } + + Utils::optional readSourceId(int directoryId, Utils::SmallStringView sourceName) + { + ReadStatement &statement = m_statementFactory.selectSourceIdFromSourcesByDirectoryIdAndSourceName; + + return statement.template value(directoryId, sourceName); + } + + Utils::SmallString fetchSourceName(int sourceId) + { + DeferredTransaction transaction{m_statementFactory.database}; + + ReadStatement &statement = m_statementFactory.selectSourceNameFromSourcesBySourceId; + + auto optionalSourceName = statement.template value(sourceId); + + if (!optionalSourceName) + throw SourceNameIdDoesNotExists(); + + transaction.commit(); + + return optionalSourceName.value(); + } + + std::vector fetchAllSources() + { + DeferredTransaction transaction{m_statementFactory.database}; + + ReadStatement &statement = m_statementFactory.selectAllSources; + + auto sources = statement.template values(8192); + + transaction.commit(); + + return sources; + } + +private: + StatementFactory &m_statementFactory; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/sourcefilepathcontainerbase.h b/src/libs/clangsupport/filepathstoragesources.h similarity index 57% rename from src/libs/clangsupport/sourcefilepathcontainerbase.h rename to src/libs/clangsupport/filepathstoragesources.h index ebf717f15e6..7561aca908e 100644 --- a/src/libs/clangsupport/sourcefilepathcontainerbase.h +++ b/src/libs/clangsupport/filepathstoragesources.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,41 +25,50 @@ #pragma once -#include "filepath.h" +#include +#include +#include +#include #include namespace ClangBackEnd { - -using FilePathDict = std::unordered_map; - -class SourceFilePathContainerBase +namespace Sources { +class Directory { public: - SourceFilePathContainerBase() = default; - SourceFilePathContainerBase(std::unordered_map &&filePathHash) - : m_filePathHash(std::move(filePathHash)) + Directory(int directoryId, Utils::PathString &&directoryPath) + : directoryId(directoryId), directoryPath(std::move(directoryPath)) + {} + + friend + bool operator==(const Directory &first, const Directory &second) { + return first.directoryId == second.directoryId && first.directoryPath == second.directoryPath; } - void insertFilePath(uint fileId, Utils::PathString &&filePath) - { - if (m_filePathHash.find(fileId) == m_filePathHash.end()) - m_filePathHash.emplace(fileId, FilePath(std::move(filePath))); - } - - void reserve(std::size_t size) - { - m_filePathHash.reserve(size / 3); - } - - const FilePathDict &filePaths() const - { - return m_filePathHash; - } - -protected: - FilePathDict m_filePathHash; +public: + int directoryId; + Utils::PathString directoryPath; }; +class Source +{ +public: + Source(int sourceId, Utils::PathString &&sourceName) + : sourceId(sourceId), sourceName(std::move(sourceName)) + {} + + friend + bool operator==(const Source &first, const Source &second) + { + return first.sourceId == second.sourceId && first.sourceName == second.sourceName; + } + +public: + int sourceId; + Utils::PathString sourceName; +}; +} // namespace ClangBackEnd + } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h b/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h new file mode 100644 index 00000000000..6c4c48302ad --- /dev/null +++ b/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 +#include + +namespace ClangBackEnd { + +template +class FilePathStorageSqliteStatementFactory +{ +public: + using DatabaseType = Database; + using ReadStatementType = ReadStatement; + using WriteStatementType = WriteStatement; + + FilePathStorageSqliteStatementFactory(Database &database) + : database(database) + { + } + +public: + Database &database; + ReadStatement selectDirectoryIdFromDirectoriesByDirectoryPath{ + "SELECT directoryId FROM directories WHERE directoryPath = ?", + database + }; + ReadStatement selectDirectoryPathFromDirectoriesByDirectoryId{ + "SELECT directoryPath FROM directories WHERE directoryId = ?", + database + }; + ReadStatement selectAllDirectories{ + "SELECT directoryId, directoryPath FROM directories", + database + }; + WriteStatement insertIntoDirectories{ + "INSERT INTO directories(directoryPath) VALUES (?)", + database + }; + ReadStatement selectSourceIdFromSourcesByDirectoryIdAndSourceName{ + "SELECT sourceId FROM sources WHERE directoryId = ? AND sourceName = ?", + database + }; + ReadStatement selectSourceNameFromSourcesBySourceId{ + "SELECT sourceName FROM sources WHERE sourceId = ?", + database + }; + WriteStatement insertIntoSources{ + "INSERT INTO sources(directoryId, sourceName) VALUES (?,?)", + database + }; + ReadStatement selectAllSources{ + "SELECT sourceId, sourceName FROM sources", + database + }; +}; + +} // namespace ClangBackEnd + diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h index 29f41d621e9..c1696d0ecf8 100644 --- a/src/libs/clangsupport/refactoringdatabaseinitializer.h +++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h @@ -44,6 +44,7 @@ public: createSymbolsTable(); createLocationsTable(); createSourcesTable(); + createDirectoriesTable(); transaction.commit(); } @@ -67,10 +68,10 @@ public: table.setUseIfNotExists(true); table.setName("locations"); table.addColumn("symbolId", Sqlite::ColumnType::Integer); - table.addColumn("line", Sqlite::ColumnType::Integer); - table.addColumn("column", Sqlite::ColumnType::Integer); + const Sqlite::Column &lineColumn = table.addColumn("line", Sqlite::ColumnType::Integer); + const Sqlite::Column &columnColumn = table.addColumn("column", Sqlite::ColumnType::Integer); const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); - table.addIndex({sourceIdColumn}); + table.addIndex({sourceIdColumn, lineColumn, columnColumn}); table.initialize(database); } @@ -81,7 +82,22 @@ public: table.setUseIfNotExists(true); table.setName("sources"); table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); - table.addColumn("sourcePath", Sqlite::ColumnType::Text); + table.addColumn("directoryId", Sqlite::ColumnType::Integer); + const Sqlite::Column &sourceNameColumn = table.addColumn("sourceName", Sqlite::ColumnType::Text); + table.addColumn("sourceType", Sqlite::ColumnType::Integer); + table.addIndex({sourceNameColumn}); + + table.initialize(database); + } + + void createDirectoriesTable() + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("directories"); + table.addColumn("directoryId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); + const Sqlite::Column &directoryPathColumn = table.addColumn("directoryPath", Sqlite::ColumnType::Text); + table.addIndex({directoryPathColumn}); table.initialize(database); } diff --git a/src/libs/clangsupport/sourcelocationcontainerv2.cpp b/src/libs/clangsupport/sourcelocationcontainerv2.cpp index 3206daf2b58..2aa2d1a3cf5 100644 --- a/src/libs/clangsupport/sourcelocationcontainerv2.cpp +++ b/src/libs/clangsupport/sourcelocationcontainerv2.cpp @@ -38,15 +38,15 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container) << container.line() << ", " << container.column() << ", " << container.offset() << ", " - << container.fileHash() + << container.filePathId().fileNameId << ")"; return debug; } std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container) { - os << "(" - << container.fileHash() << ", " + os << "((" + << container.filePathId().directoryId << ", " << container.filePathId().fileNameId << "), " << container.line() << ", " << container.column() << ", " << container.offset() diff --git a/src/libs/clangsupport/sourcelocationcontainerv2.h b/src/libs/clangsupport/sourcelocationcontainerv2.h index def1c389fa2..70327f371ad 100644 --- a/src/libs/clangsupport/sourcelocationcontainerv2.h +++ b/src/libs/clangsupport/sourcelocationcontainerv2.h @@ -26,6 +26,7 @@ #pragma once #include "clangsupport_global.h" +#include "filepathid.h" #include @@ -37,20 +38,20 @@ class SourceLocationContainer { public: SourceLocationContainer() = default; - SourceLocationContainer(uint fileHash, + SourceLocationContainer(FilePathId filePathId, uint line, uint column, uint offset) - : m_fileHash(fileHash), + : m_filePathId(filePathId), m_line(line), m_column(column), m_offset(offset) { } - uint fileHash() const + FilePathId filePathId() const { - return m_fileHash; + return m_filePathId; } uint line() const @@ -70,7 +71,7 @@ public: friend QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container) { - out << container.m_fileHash; + out << container.m_filePathId; out << container.m_line; out << container.m_column; out << container.m_offset; @@ -80,7 +81,7 @@ public: friend QDataStream &operator>>(QDataStream &in, SourceLocationContainer &container) { - in >> container.m_fileHash; + in >> container.m_filePathId; in >> container.m_line; in >> container.m_column; in >> container.m_offset; @@ -97,23 +98,23 @@ public: { return first.m_line != second.m_line || first.m_column != second.m_column - || first.m_fileHash != second.m_fileHash; + || first.m_filePathId != second.m_filePathId; } friend bool operator<(const SourceLocationContainer &first, const SourceLocationContainer &second) { - return std::tie(first.m_fileHash, first.m_line, first.m_column) - < std::tie(second.m_fileHash, second.m_line, second.m_column); + return std::tie(first.m_filePathId, first.m_line, first.m_column) + < std::tie(second.m_filePathId, second.m_line, second.m_column); } SourceLocationContainer clone() const { - return SourceLocationContainer(m_fileHash, m_line, m_column, m_offset); + return *this; } private: - uint m_fileHash = 0; + FilePathId m_filePathId; uint m_line = 1; uint m_column = 1; uint m_offset = 0; diff --git a/src/libs/clangsupport/sourcelocationscontainer.cpp b/src/libs/clangsupport/sourcelocationscontainer.cpp index c5775e6a761..7e4bc79a5b8 100644 --- a/src/libs/clangsupport/sourcelocationscontainer.cpp +++ b/src/libs/clangsupport/sourcelocationscontainer.cpp @@ -33,10 +33,10 @@ QDebug operator<<(QDebug debug, const SourceLocationsContainer &container) { debug.nospace() << "SourceLocationsContainer(["; for (const auto &sourceLocation: container.sourceLocationContainers()) { - debug.nospace() << "[" - << container.filePathForSourceLocation(sourceLocation).name() << "," + debug.nospace() << "(" + << sourceLocation.filePathId() << "," << sourceLocation.line() << "," - << sourceLocation.column() << "], "; + << sourceLocation.column() << "), "; } debug.nospace() << "])"; diff --git a/src/libs/clangsupport/sourcelocationscontainer.h b/src/libs/clangsupport/sourcelocationscontainer.h index 731ad16906b..c33564c304f 100644 --- a/src/libs/clangsupport/sourcelocationscontainer.h +++ b/src/libs/clangsupport/sourcelocationscontainer.h @@ -25,30 +25,20 @@ #pragma once -#include "sourcefilepathcontainerbase.h" #include "sourcelocationcontainerv2.h" -#include +#include namespace ClangBackEnd { -class SourceLocationsContainer : public SourceFilePathContainerBase +class SourceLocationsContainer { public: SourceLocationsContainer() = default; - SourceLocationsContainer(std::unordered_map &&filePathHash, - std::vector &&sourceLocationContainers) - : SourceFilePathContainerBase(std::move(filePathHash)), - m_sourceLocationContainers(std::move(sourceLocationContainers)) + SourceLocationsContainer(std::vector &&sourceLocationContainers) + : m_sourceLocationContainers(std::move(sourceLocationContainers)) {} - const FilePath &filePathForSourceLocation(const V2::SourceLocationContainer &sourceLocation) const - { - auto found = m_filePathHash.find(sourceLocation.fileHash()); - - return found->second; - } - const std::vector &sourceLocationContainers() const { return m_sourceLocationContainers; @@ -59,20 +49,18 @@ public: return !m_sourceLocationContainers.empty(); } - void insertSourceLocation(uint fileId, uint line, uint column, uint offset) + void insertSourceLocation(FilePathId filePathId, uint line, uint column, uint offset) { - m_sourceLocationContainers.emplace_back(fileId, line, column, offset); + m_sourceLocationContainers.emplace_back(filePathId, line, column, offset); } void reserve(std::size_t size) { - SourceFilePathContainerBase::reserve(size); m_sourceLocationContainers.reserve(size); } friend QDataStream &operator<<(QDataStream &out, const SourceLocationsContainer &container) { - out << container.m_filePathHash; out << container.m_sourceLocationContainers; return out; @@ -80,7 +68,6 @@ public: friend QDataStream &operator>>(QDataStream &in, SourceLocationsContainer &container) { - in >> container.m_filePathHash; in >> container.m_sourceLocationContainers; return in; @@ -93,7 +80,7 @@ public: SourceLocationsContainer clone() const { - return SourceLocationsContainer(Utils::clone(m_filePathHash), Utils::clone(m_sourceLocationContainers)); + return *this; } std::vector m_sourceLocationContainers; diff --git a/src/libs/clangsupport/sourcerangecontainerv2.h b/src/libs/clangsupport/sourcerangecontainerv2.h index a5dba3ddf15..50d0b966825 100644 --- a/src/libs/clangsupport/sourcerangecontainerv2.h +++ b/src/libs/clangsupport/sourcerangecontainerv2.h @@ -43,15 +43,15 @@ public: { } - SourceRangeContainer(uint fileHash, + SourceRangeContainer(FilePathId filePathId, uint startLine, uint startColumn, uint startOffset, uint endLine, uint endColumn, uint endOffset) - : m_start(fileHash, startLine, startColumn, startOffset), - m_end(fileHash, endLine, endColumn, endOffset) + : m_start(filePathId, startLine, startColumn, startOffset), + m_end(filePathId, endLine, endColumn, endOffset) { } @@ -65,9 +65,9 @@ public: return m_end; } - uint fileHash() const + FilePathId filePathId() const { - return m_start.fileHash(); + return m_start.filePathId(); } friend QDataStream &operator<<(QDataStream &out, const SourceRangeContainer &container) @@ -99,7 +99,7 @@ public: SourceRangeContainer clone() const { - return SourceRangeContainer(m_start.clone(), m_end.clone()); + return *this; } private: diff --git a/src/libs/clangsupport/sourcerangescontainer.cpp b/src/libs/clangsupport/sourcerangescontainer.cpp index ff833be8749..9f2752f2866 100644 --- a/src/libs/clangsupport/sourcerangescontainer.cpp +++ b/src/libs/clangsupport/sourcerangescontainer.cpp @@ -31,12 +31,11 @@ QDebug operator<<(QDebug debug, const SourceRangesContainer &container) { debug.nospace() << "SourceRangesContainer(["; for (const auto &sourceRangeWithText: container.sourceRangeWithTextContainers()) { - debug.nospace() << "[" - << container.filePathForSourceRange(sourceRangeWithText).name() << ", (" + debug.nospace() << "(" << sourceRangeWithText.start().line() << "," << sourceRangeWithText.start().column() << "), (" << sourceRangeWithText.end().line() << "," - << sourceRangeWithText.end().column() << ")], "; + << sourceRangeWithText.end().column() << "), "; } debug.nospace() << "])"; diff --git a/src/libs/clangsupport/sourcerangescontainer.h b/src/libs/clangsupport/sourcerangescontainer.h index 6968830a6d8..dfb5d44bd45 100644 --- a/src/libs/clangsupport/sourcerangescontainer.h +++ b/src/libs/clangsupport/sourcerangescontainer.h @@ -25,30 +25,20 @@ #pragma once -#include "sourcefilepathcontainerbase.h" #include "sourcerangewithtextcontainer.h" #include namespace ClangBackEnd { -class SourceRangesContainer : public SourceFilePathContainerBase +class SourceRangesContainer { public: SourceRangesContainer() = default; - SourceRangesContainer(std::unordered_map &&filePathHash, - SourceRangeWithTextContainers &&sourceRangeWithTextContainers) - : SourceFilePathContainerBase(std::move(filePathHash)), - m_sourceRangeWithTextContainers(std::move(sourceRangeWithTextContainers)) + SourceRangesContainer(SourceRangeWithTextContainers &&sourceRangeWithTextContainers) + : m_sourceRangeWithTextContainers(std::move(sourceRangeWithTextContainers)) {} - const FilePath &filePathForSourceRange(const SourceRangeWithTextContainer &sourceRange) const - { - auto found = m_filePathHash.find(sourceRange.fileHash()); - - return found->second; - } - const SourceRangeWithTextContainers &sourceRangeWithTextContainers() const { return m_sourceRangeWithTextContainers; @@ -69,7 +59,7 @@ public: return !m_sourceRangeWithTextContainers.empty(); } - void insertSourceRange(uint fileId, + void insertSourceRange(FilePathId filePathId, uint startLine, uint startColumn, uint startOffset, @@ -78,7 +68,7 @@ public: uint endOffset, Utils::SmallString &&text) { - m_sourceRangeWithTextContainers.emplace_back(fileId, + m_sourceRangeWithTextContainers.emplace_back(filePathId, startLine, startColumn, startOffset, @@ -90,13 +80,11 @@ public: void reserve(std::size_t size) { - SourceFilePathContainerBase::reserve(size); m_sourceRangeWithTextContainers.reserve(size); } friend QDataStream &operator<<(QDataStream &out, const SourceRangesContainer &container) { - out << container.m_filePathHash; out << container.m_sourceRangeWithTextContainers; return out; @@ -104,7 +92,6 @@ public: friend QDataStream &operator>>(QDataStream &in, SourceRangesContainer &container) { - in >> container.m_filePathHash; in >> container.m_sourceRangeWithTextContainers; return in; diff --git a/src/libs/clangsupport/sourcerangewithtextcontainer.h b/src/libs/clangsupport/sourcerangewithtextcontainer.h index 4edb2315509..dd2d66cb7e4 100644 --- a/src/libs/clangsupport/sourcerangewithtextcontainer.h +++ b/src/libs/clangsupport/sourcerangewithtextcontainer.h @@ -35,7 +35,7 @@ class SourceRangeWithTextContainer : public V2::SourceRangeContainer { public: SourceRangeWithTextContainer() = default; - SourceRangeWithTextContainer(uint fileHash, + SourceRangeWithTextContainer(FilePathId filePathId, uint startLine, uint startColumn, uint startOffset, @@ -43,7 +43,7 @@ public: uint endColumn, uint endOffset, Utils::SmallString &&text) - : V2::SourceRangeContainer(fileHash, + : V2::SourceRangeContainer(filePathId, startLine, startColumn, startOffset, @@ -67,7 +67,7 @@ public: using V2::SourceRangeContainer::start; using V2::SourceRangeContainer::end; - using V2::SourceRangeContainer::fileHash; + using V2::SourceRangeContainer::filePathId; friend QDataStream &operator<<(QDataStream &out, const SourceRangeWithTextContainer &container) { diff --git a/src/libs/clangsupport/stringcache.h b/src/libs/clangsupport/stringcache.h index 6d5f4e986b2..d3de7fe4ddd 100644 --- a/src/libs/clangsupport/stringcache.h +++ b/src/libs/clangsupport/stringcache.h @@ -28,6 +28,7 @@ #include "stringcachealgorithms.h" #include "stringcachefwd.h" +#include #include #include @@ -70,15 +71,12 @@ public: } StringType string; - uint id; + IndexType id; }; template using StringCacheEntries = std::vector>; -using FileCacheCacheEntry = StringCacheEntry; -using FileCacheCacheEntries = std::vector; - template class StringCache { - using CacheEntry = StringCacheEntry; - using CacheEnties = StringCacheEntries; - using const_iterator = typename CacheEnties::const_iterator; - using Found = ClangBackEnd::Found; public: - StringCache() + using CacheEntry = StringCacheEntry; + using CacheEntries = StringCacheEntries; + using const_iterator = typename CacheEntries::const_iterator; + using Found = ClangBackEnd::Found; + + StringCache(std::size_t reserveSize = 1024) { - m_strings.reserve(1024); - m_indices.reserve(1024); + m_strings.reserve(reserveSize); + m_indices.reserve(reserveSize); } - void populate(CacheEnties &&entries) + void populate(CacheEntries &&entries) { uncheckedPopulate(std::move(entries)); checkEntries(); } - void uncheckedPopulate(CacheEnties &&entries) + void uncheckedPopulate(CacheEntries &&entries) { std::sort(entries.begin(), entries.end(), @@ -149,13 +148,35 @@ public: return stringIds>(strings); } - Utils::SmallStringView string(IndexType id) const + StringType string(IndexType id) const { std::lock_guard lock(m_mutex); return m_strings.at(m_indices.at(id)).string; } + template + StringType string(IndexType id, Function storageFunction) + { + std::lock_guard lock(m_mutex); + + IndexType index; + + if (IndexType(m_indices.size()) <= id) { + StringType string{storageFunction(id)}; + index = insertString(find(string).iterator, string, id); + } else { + index = m_indices.at(id); + + if (index < 0) { + StringType string{storageFunction(id)}; + index = insertString(find(string).iterator, string, id); + } + } + + return m_strings.at(index).string; + } + std::vector strings(const std::vector &ids) const { std::lock_guard lock(m_mutex); @@ -176,13 +197,31 @@ public: return m_strings.empty() && m_indices.empty(); } + template + IndexType stringId(Utils::SmallStringView stringView, Function storageFunction) + { + std::lock_guard lock(m_mutex); + + Found found = find(stringView); + + if (!found.wasFound) + insertString(found.iterator, stringView, storageFunction(stringView)); + + return found.iterator->id; + } + + Mutex &mutex() const + { + return m_mutex; + } + private: IndexType ungardedStringId(Utils::SmallStringView stringView) { Found found = find(stringView); if (!found.wasFound) - return insertString(found.iterator, stringView); + insertString(found.iterator, stringView, IndexType(m_indices.size())); return found.iterator->id; } @@ -202,20 +241,26 @@ private: }); } - IndexType insertString(const_iterator beforeIterator, - Utils::SmallStringView stringView) + void ensureSize(IndexType id) { - auto id = IndexType(m_indices.size()); + if (m_indices.size() <= std::size_t(id)) + m_indices.resize(id + 1, -1); + } + IndexType insertString(const_iterator beforeIterator, + Utils::SmallStringView stringView, + IndexType id) + { auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id); auto newIndex = IndexType(std::distance(m_strings.begin(), inserted)); incrementLargerOrEqualIndicesByOne(newIndex); - m_indices.push_back(newIndex); + ensureSize(id); + m_indices.at(id) = newIndex; - return id; + return newIndex; } void checkEntries() @@ -227,11 +272,9 @@ private: } private: - CacheEnties m_strings; + CacheEntries m_strings; std::vector m_indices; mutable Mutex m_mutex; }; -using FilePathIndices = std::vector; - } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/stringcachefwd.h b/src/libs/clangsupport/stringcachefwd.h index 66448411e12..75f03056b20 100644 --- a/src/libs/clangsupport/stringcachefwd.h +++ b/src/libs/clangsupport/stringcachefwd.h @@ -29,8 +29,6 @@ namespace ClangBackEnd { -using FilePathIndex = long long int; - class NonLockingMutex; template class StringCache; - -template -using FilePathCache = StringCache; - } // namespace ClangBackEnd diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri index 67c8c6b9372..28f159a0d54 100644 --- a/src/libs/sqlite/sqlite-lib.pri +++ b/src/libs/sqlite/sqlite-lib.pri @@ -17,7 +17,6 @@ SOURCES += \ $$PWD/sqliteglobal.cpp \ $$PWD/sqlitereadstatement.cpp \ $$PWD/sqlitereadwritestatement.cpp \ - $$PWD/sqlitestatement.cpp \ $$PWD/sqlitetransaction.cpp \ $$PWD/sqlitewritestatement.cpp \ $$PWD/sqlstatementbuilder.cpp \ @@ -26,7 +25,8 @@ SOURCES += \ $$PWD/utf8stringvector.cpp \ $$PWD/sqlitedatabase.cpp \ $$PWD/sqlitetable.cpp \ - $$PWD/sqlitecolumn.cpp + $$PWD/sqlitecolumn.cpp \ + $$PWD/sqlitebasestatement.cpp HEADERS += \ $$PWD/createtablesqlstatementbuilder.h \ $$PWD/sqlitedatabasebackend.h \ @@ -34,7 +34,6 @@ HEADERS += \ $$PWD/sqliteglobal.h \ $$PWD/sqlitereadstatement.h \ $$PWD/sqlitereadwritestatement.h \ - $$PWD/sqlitestatement.h \ $$PWD/sqlitetransaction.h \ $$PWD/sqlitewritestatement.h \ $$PWD/sqlstatementbuilder.h \ @@ -44,7 +43,8 @@ HEADERS += \ $$PWD/sqlitedatabase.h \ $$PWD/sqlitetable.h \ $$PWD/sqlitecolumn.h \ - $$PWD/sqliteindex.h + $$PWD/sqliteindex.h \ + $$PWD/sqlitebasestatement.h DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp similarity index 68% rename from src/libs/sqlite/sqlitestatement.cpp rename to src/libs/sqlite/sqlitebasestatement.cpp index 0e70b5aaca6..3f41c04a11e 100644 --- a/src/libs/sqlite/sqlitestatement.cpp +++ b/src/libs/sqlite/sqlitebasestatement.cpp @@ -23,7 +23,7 @@ ** ****************************************************************************/ -#include "sqlitestatement.h" +#include "sqlitebasestatement.h" #include "sqlitedatabase.h" #include "sqlitedatabasebackend.h" @@ -40,7 +40,7 @@ namespace Sqlite { -Statement::Statement(Utils::SmallStringView sqlStatement, Database &database) +BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database) : m_compiledStatement(nullptr, deleteCompiledStatement), m_database(database), m_bindingParameterCount(0), @@ -49,11 +49,10 @@ Statement::Statement(Utils::SmallStringView sqlStatement, Database &database) { prepare(sqlStatement); setBindingParameterCount(); - setBindingColumnNamesFromStatement(); setColumnCount(); } -void Statement::deleteCompiledStatement(sqlite3_stmt *compiledStatement) +void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement) { if (compiledStatement) sqlite3_finalize(compiledStatement); @@ -92,7 +91,7 @@ private: std::mutex m_mutex; }; -void Statement::waitForUnlockNotify() const +void BaseStatement::waitForUnlockNotify() const { UnlockNotification unlockNotification; int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), @@ -105,7 +104,7 @@ void Statement::waitForUnlockNotify() const unlockNotification.wait(); } -void Statement::reset() const +void BaseStatement::reset() const { int resultCode = sqlite3_reset(m_compiledStatement.get()); switch (resultCode) { @@ -119,7 +118,7 @@ void Statement::reset() const m_isReadyToFetchValues = false; } -bool Statement::next() const +bool BaseStatement::next() const { int resultCode; @@ -137,26 +136,26 @@ bool Statement::next() const return checkForStepError(resultCode); } -void Statement::step() const +void BaseStatement::step() const { next(); } -void Statement::execute() const +void BaseStatement::execute() const { next(); reset(); } -int Statement::columnCount() const +int BaseStatement::columnCount() const { return m_columnCount; } -Utils::SmallStringVector Statement::columnNames() const +Utils::SmallStringVector BaseStatement::columnNames() const { Utils::SmallStringVector columnNames; - int columnCount = Statement::columnCount(); + int columnCount = BaseStatement::columnCount(); columnNames.reserve(std::size_t(columnCount)); for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) columnNames.emplace_back(sqlite3_column_origin_name(m_compiledStatement.get(), columnIndex)); @@ -164,25 +163,25 @@ Utils::SmallStringVector Statement::columnNames() const return columnNames; } -void Statement::bind(int index, int value) +void BaseStatement::bind(int index, int value) { int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); checkForBindingError(resultCode); } -void Statement::bind(int index, long long value) +void BaseStatement::bind(int index, long long value) { int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); checkForBindingError(resultCode); } -void Statement::bind(int index, double value) +void BaseStatement::bind(int index, double value) { int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value); checkForBindingError(resultCode); } -void Statement::bind(int index, Utils::SmallStringView text) +void BaseStatement::bind(int index, Utils::SmallStringView text) { int resultCode = sqlite3_bind_text(m_compiledStatement.get(), index, @@ -193,35 +192,25 @@ void Statement::bind(int index, Utils::SmallStringView text) } template -void Statement::bind(Utils::SmallStringView name, Type value) +void BaseStatement::bind(Utils::SmallStringView name, Type value) { int index = bindingIndexForName(name); checkBindingName(index); bind(index, value); } -template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value); -template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value); -template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value); -template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value); -template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text); +template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, int value); +template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value); +template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value); +template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value); +template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text); -int Statement::bindingIndexForName(Utils::SmallStringView name) const +int BaseStatement::bindingIndexForName(Utils::SmallStringView name) const { return sqlite3_bind_parameter_index(m_compiledStatement.get(), name.data()); } -void Statement::setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames) -{ - m_bindingColumnNames = bindingColumnNames; -} - -const Utils::SmallStringVector &Statement::bindingColumnNames() const -{ - return m_bindingColumnNames; -} - -void Statement::prepare(Utils::SmallStringView sqlStatement) +void BaseStatement::prepare(Utils::SmallStringView sqlStatement) { int resultCode; @@ -242,17 +231,17 @@ void Statement::prepare(Utils::SmallStringView sqlStatement) checkForPrepareError(resultCode); } -sqlite3 *Statement::sqliteDatabaseHandle() const +sqlite3 *BaseStatement::sqliteDatabaseHandle() const { return m_database.backend().sqliteDatabaseHandle(); } -TextEncoding Statement::databaseTextEncoding() +TextEncoding BaseStatement::databaseTextEncoding() { return m_database.backend().textEncoding(); } -bool Statement::checkForStepError(int resultCode) const +bool BaseStatement::checkForStepError(int resultCode) const { switch (resultCode) { case SQLITE_ROW: return true; @@ -268,7 +257,7 @@ bool Statement::checkForStepError(int resultCode) const Q_UNREACHABLE(); } -void Statement::checkForPrepareError(int resultCode) const +void BaseStatement::checkForPrepareError(int resultCode) const { switch (resultCode) { case SQLITE_OK: return; @@ -280,7 +269,7 @@ void Statement::checkForPrepareError(int resultCode) const throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened"); } -void Statement::checkForBindingError(int resultCode) const +void BaseStatement::checkForBindingError(int resultCode) const { switch (resultCode) { case SQLITE_OK: return; @@ -292,7 +281,7 @@ void Statement::checkForBindingError(int resultCode) const throwUnknowError("SqliteStatement::bind: unknown error has happened"); } -void Statement::setIfIsReadyToFetchValues(int resultCode) const +void BaseStatement::setIfIsReadyToFetchValues(int resultCode) const { if (resultCode == SQLITE_ROW) m_isReadyToFetchValues = true; @@ -301,13 +290,13 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const } -void Statement::checkIfIsReadyToFetchValues() const +void BaseStatement::checkIfIsReadyToFetchValues() const { if (!m_isReadyToFetchValues) throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!"); } -void Statement::checkColumnsAreValid(const std::vector &columns) const +void BaseStatement::checkColumnsAreValid(const std::vector &columns) const { for (int column : columns) { if (column < 0 || column >= m_columnCount) @@ -315,19 +304,19 @@ void Statement::checkColumnsAreValid(const std::vector &columns) const } } -void Statement::checkColumnIsValid(int column) const +void BaseStatement::checkColumnIsValid(int column) const { if (column < 0 || column >= m_columnCount) throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!"); } -void Statement::checkBindingName(int index) const +void BaseStatement::checkBindingName(int index) const { if (index <= 0 || index > m_bindingParameterCount) throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!"); } -void Statement::setBindingParameterCount() +void BaseStatement::setBindingParameterCount() { m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get()); } @@ -340,65 +329,57 @@ Utils::SmallStringView chopFirstLetter(const char *rawBindingName) return Utils::SmallStringView(""); } -void Statement::setBindingColumnNamesFromStatement() -{ - for (int index = 1; index <= m_bindingParameterCount; index++) { - Utils::SmallStringView bindingName = chopFirstLetter(sqlite3_bind_parameter_name(m_compiledStatement.get(), index)); - m_bindingColumnNames.push_back(Utils::SmallString(bindingName)); - } -} - -void Statement::setColumnCount() +void BaseStatement::setColumnCount() { m_columnCount = sqlite3_column_count(m_compiledStatement.get()); } -bool Statement::isReadOnlyStatement() const +bool BaseStatement::isReadOnlyStatement() const { return sqlite3_stmt_readonly(m_compiledStatement.get()); } -void Statement::throwStatementIsBusy(const char *whatHasHappened) const +void BaseStatement::throwStatementIsBusy(const char *whatHasHappened) const { throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -void Statement::throwStatementHasError(const char *whatHasHappened) const +void BaseStatement::throwStatementHasError(const char *whatHasHappened) const { throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -void Statement::throwStatementIsMisused(const char *whatHasHappened) const +void BaseStatement::throwStatementIsMisused(const char *whatHasHappened) const { throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const +void BaseStatement::throwConstraintPreventsModification(const char *whatHasHappened) const { throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -void Statement::throwNoValuesToFetch(const char *whatHasHappened) const +void BaseStatement::throwNoValuesToFetch(const char *whatHasHappened) const { throw NoValuesToFetch(whatHasHappened); } -void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const +void BaseStatement::throwInvalidColumnFetched(const char *whatHasHappened) const { throw InvalidColumnFetched(whatHasHappened); } -void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const +void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const { throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -void Statement::throwWrongBingingName(const char *whatHasHappened) const +void BaseStatement::throwWrongBingingName(const char *whatHasHappened) const { - throw WrongBingingName(whatHasHappened); + throw WrongBindingName(whatHasHappened); } -void Statement::throwUnknowError(const char *whatHasHappened) const +void BaseStatement::throwUnknowError(const char *whatHasHappened) const { if (sqliteDatabaseHandle()) throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); @@ -406,17 +387,17 @@ void Statement::throwUnknowError(const char *whatHasHappened) const throw UnknowError(whatHasHappened); } -void Statement::throwBingingTooBig(const char *whatHasHappened) const +void BaseStatement::throwBingingTooBig(const char *whatHasHappened) const { throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -QString Statement::columnName(int column) const +QString BaseStatement::columnName(int column) const { return QString::fromUtf8(sqlite3_column_name(m_compiledStatement.get(), column)); } -Database &Statement::database() const +Database &BaseStatement::database() const { return m_database; } @@ -445,7 +426,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column) Q_UNREACHABLE(); } -int Statement::fetchIntValue(int column) const +int BaseStatement::fetchIntValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); @@ -453,23 +434,23 @@ int Statement::fetchIntValue(int column) const } template<> -int Statement::fetchValue(int column) const +int BaseStatement::fetchValue(int column) const { return fetchIntValue(column); } -long Statement::fetchLongValue(int column) const +long BaseStatement::fetchLongValue(int column) const { return long(fetchValue(column)); } template<> -long Statement::fetchValue(int column) const +long BaseStatement::fetchValue(int column) const { return fetchLongValue(column); } -long long Statement::fetchLongLongValue(int column) const +long long BaseStatement::fetchLongLongValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); @@ -477,12 +458,12 @@ long long Statement::fetchLongLongValue(int column) const } template<> -long long Statement::fetchValue(int column) const +long long BaseStatement::fetchValue(int column) const { return fetchLongLongValue(column); } -double Statement::fetchDoubleValue(int column) const +double BaseStatement::fetchDoubleValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); @@ -490,62 +471,30 @@ double Statement::fetchDoubleValue(int column) const } template<> -double Statement::fetchValue(int column) const +double BaseStatement::fetchValue(int column) const { return fetchDoubleValue(column); } template -StringType Statement::fetchValue(int column) const +StringType BaseStatement::fetchValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); return convertToTextForColumn(m_compiledStatement.get(), column); } -Utils::SmallString Statement::fetchSmallStringValue(int column) const +Utils::SmallString BaseStatement::fetchSmallStringValue(int column) const { return fetchValue(column); } -Utils::PathString Statement::fetchPathStringValue(int column) const +Utils::PathString BaseStatement::fetchPathStringValue(int column) const { return fetchValue(column); } -template SQLITE_EXPORT Utils::SmallString Statement::fetchValue(int column) const; -template SQLITE_EXPORT Utils::PathString Statement::fetchValue(int column) const; - -Utils::SmallString Statement::text(int column) const -{ - return fetchValue(column); -} - -template -ContainerType Statement::columnValues(const std::vector &columnIndices) const -{ - using ElementType = typename ContainerType::value_type; - ContainerType valueContainer; - valueContainer.reserve(columnIndices.size()); - for (int columnIndex : columnIndices) - valueContainer.push_back(fetchValue(columnIndex)); - - return valueContainer; -} - -template -Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database) -{ - Statement statement(sqlStatement, database); - - statement.next(); - - return statement.fetchValue(0); -} - -template SQLITE_EXPORT int Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -template SQLITE_EXPORT long long Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -template SQLITE_EXPORT double Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -template SQLITE_EXPORT Utils::SmallString Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); +template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue(int column) const; +template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue(int column) const; } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitebasestatement.h similarity index 77% rename from src/libs/sqlite/sqlitestatement.h rename to src/libs/sqlite/sqlitebasestatement.h index 3e93b7ba8d6..bf6dfd4e5e6 100644 --- a/src/libs/sqlite/sqlitestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -48,10 +48,10 @@ namespace Sqlite { class Database; class DatabaseBackend; -class SQLITE_EXPORT Statement +class SQLITE_EXPORT BaseStatement { -protected: - explicit Statement(Utils::SmallStringView sqlStatement, Database &database); +public: + explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database); static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement); @@ -68,7 +68,6 @@ protected: Utils::PathString fetchPathStringValue(int column) const; template Type fetchValue(int column) const; - Utils::SmallString text(int column) const; int columnCount() const; Utils::SmallStringVector columnNames() const; @@ -87,140 +86,11 @@ protected: bind(index, static_cast(value)); } - void bindValues() - { - } - - template - void bindValues(const ValueType&... values) - { - bindValuesByIndex(1, values...); - } - - template - void write(const ValueType&... values) - { - bindValuesByIndex(1, values...); - execute(); - } - - template - void bindNameValues(const ValueType&... values) - { - bindValuesByName(values...); - } - - template - void writeNamed(const ValueType&... values) - { - bindValuesByName(values...); - execute(); - } - template void bind(Utils::SmallStringView name, Type fetchValue); int bindingIndexForName(Utils::SmallStringView name) const; - void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames); - const Utils::SmallStringVector &bindingColumnNames() const; - - template - std::vector values(std::size_t reserveSize) - { - std::vector resultValues; - resultValues.reserve(reserveSize); - - while (next()) - emplaceBackValues(resultValues); - - reset(); - - return resultValues; - } - - template - std::vector values(std::size_t reserveSize, const QueryTypes&... queryValues) - { - std::vector resultValues; - resultValues.reserve(reserveSize); - - bindValues(queryValues...); - - while (next()) - emplaceBackValues(resultValues); - - reset(); - - return resultValues; - } - - template - std::vector values(std::size_t reserveSize, - const std::vector &queryValues) - { - std::vector resultValues; - resultValues.reserve(reserveSize); - - for (const QueryElementType &queryValue : queryValues) { - bindValues(queryValue); - - while (next()) - emplaceBackValues(resultValues); - - reset(); - } - - return resultValues; - } - - template - std::vector values(std::size_t reserveSize, - const std::vector> &queryTuples) - { - using Container = std::vector; - Container resultValues; - resultValues.reserve(reserveSize); - - for (const auto &queryTuple : queryTuples) { - bindTupleValues(queryTuple); - - while (next()) - emplaceBackValues(resultValues); - - reset(); - } - - return resultValues; - } - - template - Utils::optional value( const QueryTypes&... queryValues) - { - Utils::optional resultValue; - - bindValues(queryValues...); - - if (next()) - resultValue = assignValue, ResultTypeCount>(); - - reset(); - - return resultValue; - } - - template - static Type toValue(Utils::SmallStringView sqlStatement, Database &database); - void prepare(Utils::SmallStringView sqlStatement); void waitForUnlockNotify() const; @@ -236,7 +106,6 @@ protected: void checkColumnIsValid(int column) const; void checkBindingName(int index) const; void setBindingParameterCount(); - void setBindingColumnNamesFromStatement(); void setColumnCount(); bool isReadOnlyStatement() const; [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const; @@ -250,22 +119,185 @@ protected: [[noreturn]] void throwUnknowError(const char *whatHasHappened) const; [[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const; - template - ContainerType columnValues(const std::vector &columnIndices) const; - QString columnName(int column) const; Database &database() const; -protected: - explicit Statement(Utils::SmallStringView sqlStatement, - DatabaseBackend &databaseBackend); +private: + std::unique_ptr m_compiledStatement; + Database &m_database; + int m_bindingParameterCount; + int m_columnCount; + mutable bool m_isReadyToFetchValues; +}; + +extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, int value); +extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value); +extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value); +extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value); +extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text); + +template <> SQLITE_EXPORT int BaseStatement::fetchValue(int column) const; +template <> SQLITE_EXPORT long BaseStatement::fetchValue(int column) const; +template <> SQLITE_EXPORT long long BaseStatement::fetchValue(int column) const; +template <> SQLITE_EXPORT double BaseStatement::fetchValue(int column) const; +extern template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue(int column) const; +extern template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue(int column) const; + +template +class SQLITE_EXPORT StatementImplementation : public BaseStatement +{ + +public: + using BaseStatement::BaseStatement; + + void bindValues() + { + } + + template + void bindValues(const ValueType&... values) + { + bindValuesByIndex(1, values...); + } + + template + void write(const ValueType&... values) + { + bindValuesByIndex(1, values...); + BaseStatement::execute(); + } + + template + void bindNameValues(const ValueType&... values) + { + bindValuesByName(values...); + } + + template + void writeNamed(const ValueType&... values) + { + bindValuesByName(values...); + BaseStatement::execute(); + } + + template + std::vector values(std::size_t reserveSize) + { + Resetter resetter{*this}; + std::vector resultValues; + resultValues.reserve(reserveSize); + + while (BaseStatement::next()) + emplaceBackValues(resultValues); + + return resultValues; + } + + template + std::vector values(std::size_t reserveSize, const QueryTypes&... queryValues) + { + Resetter resetter{*this}; + std::vector resultValues; + resultValues.reserve(reserveSize); + + bindValues(queryValues...); + + while (BaseStatement::next()) + emplaceBackValues(resultValues); + + return resultValues; + } + + template + std::vector values(std::size_t reserveSize, + const std::vector &queryValues) + { + std::vector resultValues; + resultValues.reserve(reserveSize); + + for (const QueryElementType &queryValue : queryValues) { + Resetter resetter{*this}; + bindValues(queryValue); + + while (BaseStatement::next()) + emplaceBackValues(resultValues); + } + + return resultValues; + } + + template + std::vector values(std::size_t reserveSize, + const std::vector> &queryTuples) + { + using Container = std::vector; + Container resultValues; + resultValues.reserve(reserveSize); + + for (const auto &queryTuple : queryTuples) { + Resetter resetter{*this}; + bindTupleValues(queryTuple); + + while (BaseStatement::next()) + emplaceBackValues(resultValues); + } + + return resultValues; + } + + template + Utils::optional value(const QueryTypes&... queryValues) + { + Resetter resetter{*this}; + Utils::optional resultValue; + + bindValues(queryValues...); + + if (BaseStatement::next()) + resultValue = assignValue, ResultTypeCount>(); + + return resultValue; + } + + template + static Type toValue(Utils::SmallStringView sqlStatement, Database &database) + { + StatementImplementation statement(sqlStatement, database); + + statement.next(); + + return statement.template fetchValue(0); + } + private: - class ValueGetter + struct Resetter { - public: - ValueGetter(Statement &statement, int column) + Resetter(StatementImplementation &statement) + : statement(statement) + {} + + ~Resetter() + { + statement.reset(); + } + + StatementImplementation &statement; + }; + + struct ValueGetter + { + ValueGetter(StatementImplementation &statement, int column) : statement(statement), column(column) {} @@ -300,7 +332,7 @@ private: return statement.fetchPathStringValue(column); } - Statement &statement; + StatementImplementation &statement; int column; }; @@ -335,26 +367,26 @@ private: template void bindValuesByIndex(int index, const ValueType &value) { - bind(index, value); + BaseStatement::bind(index, value); } template void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values) { - bind(index, value); + BaseStatement::bind(index, value); bindValuesByIndex(index + 1, values...); } template void bindValuesByName(Utils::SmallStringView name, const ValueType &value) { - bind(bindingIndexForName(name), value); + BaseStatement::bind(BaseStatement::bindingIndexForName(name), value); } template void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values) { - bind(bindingIndexForName(name), value); + BaseStatement::bind(BaseStatement::bindingIndexForName(name), value); bindValuesByName(values...); } @@ -371,30 +403,6 @@ private: bindTupleValuesElement(element, ColumnIndices()); } -private: - std::unique_ptr m_compiledStatement; - Utils::SmallStringVector m_bindingColumnNames; - Database &m_database; - int m_bindingParameterCount; - int m_columnCount; - mutable bool m_isReadyToFetchValues; }; -extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value); -extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value); -extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value); -extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value); -extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text); - -extern template SQLITE_EXPORT int Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -extern template SQLITE_EXPORT long long Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -extern template SQLITE_EXPORT double Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -extern template SQLITE_EXPORT Utils::SmallString Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); - -template <> SQLITE_EXPORT int Statement::fetchValue(int column) const; -template <> SQLITE_EXPORT long Statement::fetchValue(int column) const; -template <> SQLITE_EXPORT long long Statement::fetchValue(int column) const; -template <> SQLITE_EXPORT double Statement::fetchValue(int column) const; -extern template SQLITE_EXPORT Utils::SmallString Statement::fetchValue(int column) const; -extern template SQLITE_EXPORT Utils::PathString Statement::fetchValue(int column) const; } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp index 5c4fc95e732..928eb2b1d1e 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.cpp +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -28,7 +28,7 @@ #include "sqliteexception.h" #include "sqlitereadstatement.h" #include "sqlitereadwritestatement.h" -#include "sqlitestatement.h" +#include "sqlitebasestatement.h" #include "sqlitewritestatement.h" #include diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h index 319141d2573..3d6dfb5129e 100644 --- a/src/libs/sqlite/sqliteexception.h +++ b/src/libs/sqlite/sqliteexception.h @@ -125,10 +125,10 @@ public: } }; -class WrongBingingName : public Exception +class WrongBindingName : public Exception { public: - WrongBingingName(const char *whatErrorHasHappen) + WrongBindingName(const char *whatErrorHasHappen) : Exception(whatErrorHasHappen) { } diff --git a/src/libs/sqlite/sqlitereadstatement.cpp b/src/libs/sqlite/sqlitereadstatement.cpp index 9af95f1cffa..91e672985bd 100644 --- a/src/libs/sqlite/sqlitereadstatement.cpp +++ b/src/libs/sqlite/sqlitereadstatement.cpp @@ -31,7 +31,7 @@ namespace Sqlite { ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement, Database &database) - : Statement(sqlStatement, database) + : StatementImplementation(sqlStatement, database) { checkIsReadOnlyStatement(); } diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h index 828d1f7c377..310f91fbc93 100644 --- a/src/libs/sqlite/sqlitereadstatement.h +++ b/src/libs/sqlite/sqlitereadstatement.h @@ -25,19 +25,18 @@ #pragma once -#include "sqlitestatement.h" +#include "sqlitebasestatement.h" namespace Sqlite { -class SQLITE_EXPORT ReadStatement final : private Statement +class SQLITE_EXPORT ReadStatement final : protected StatementImplementation { public: explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database); - using Statement::value; - using Statement::values; - using Statement::toValue; - using Statement::database; + using StatementImplementation::value; + using StatementImplementation::values; + using StatementImplementation::toValue; protected: void checkIsReadOnlyStatement(); diff --git a/src/libs/sqlite/sqlitereadwritestatement.cpp b/src/libs/sqlite/sqlitereadwritestatement.cpp index 74190deae1b..8910ffd7f06 100644 --- a/src/libs/sqlite/sqlitereadwritestatement.cpp +++ b/src/libs/sqlite/sqlitereadwritestatement.cpp @@ -29,7 +29,7 @@ namespace Sqlite { ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database) - : Statement(sqlStatement, database) + : StatementImplementation(sqlStatement, database) { } diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h index 8645a6eae8a..c81ed628b29 100644 --- a/src/libs/sqlite/sqlitereadwritestatement.h +++ b/src/libs/sqlite/sqlitereadwritestatement.h @@ -25,24 +25,23 @@ #pragma once -#include "sqlitestatement.h" +#include "sqlitebasestatement.h" namespace Sqlite { -class SQLITE_EXPORT ReadWriteStatement final : private Statement +class SQLITE_EXPORT ReadWriteStatement final : protected StatementImplementation { friend class DatabaseBackend; public: ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database); - using Statement::execute; - using Statement::value; - using Statement::values; - using Statement::toValue; - using Statement::database; - using Statement::write; - using Statement::writeNamed; + using StatementImplementation::execute; + using StatementImplementation::value; + using StatementImplementation::values; + using StatementImplementation::toValue; + using StatementImplementation::write; + using StatementImplementation::writeNamed; }; } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitewritestatement.cpp b/src/libs/sqlite/sqlitewritestatement.cpp index 26c8522b8a5..89fce7abf3d 100644 --- a/src/libs/sqlite/sqlitewritestatement.cpp +++ b/src/libs/sqlite/sqlitewritestatement.cpp @@ -29,7 +29,7 @@ namespace Sqlite { WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement, Database &database) - : Statement(sqlStatement, database) + : StatementImplementation(sqlStatement, database) { checkIsWritableStatement(); } diff --git a/src/libs/sqlite/sqlitewritestatement.h b/src/libs/sqlite/sqlitewritestatement.h index ec00ae4e8f1..24cf5a87426 100644 --- a/src/libs/sqlite/sqlitewritestatement.h +++ b/src/libs/sqlite/sqlitewritestatement.h @@ -25,19 +25,19 @@ #pragma once -#include "sqlitestatement.h" +#include "sqlitebasestatement.h" namespace Sqlite { -class SQLITE_EXPORT WriteStatement : private Statement +class SQLITE_EXPORT WriteStatement : protected StatementImplementation { public: explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database); - using Statement::execute; - using Statement::database; - using Statement::write; - using Statement::writeNamed; + using StatementImplementation::execute; + using StatementImplementation::database; + using StatementImplementation::write; + using StatementImplementation::writeNamed; protected: void checkIsWritableStatement(); diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h index 5b30662592c..f3586092582 100644 --- a/src/libs/utils/smallstring.h +++ b/src/libs/utils/smallstring.h @@ -145,25 +145,7 @@ public: BasicSmallString(std::initializer_list list) : m_data(Internal::StringDataLayout()) { - std::size_t size = std::accumulate(list.begin(), - list.end(), - std::size_t(0), - [] (std::size_t size, Utils::SmallStringView string) { - return size + string.size(); - }); - - reserve(size); - setSize(size); - - char *currentData = data(); - - for (Utils::SmallStringView string : list) { - std::memcpy(currentData, string.data(), string.size()); - - currentData += string.size(); - } - - at(size) = 0; + appendInitializerList(list, 0); } ~BasicSmallString() noexcept @@ -478,6 +460,13 @@ public: return *this; } + BasicSmallString &operator+=(std::initializer_list list) + { + appendInitializerList(list, size()); + + return *this; + } + void replace(SmallStringView fromText, SmallStringView toText) { if (toText.size() == fromText.size()) @@ -690,6 +679,27 @@ private: { } + void appendInitializerList(std::initializer_list list, std::size_t initialSize) + { + auto addSize = [] (std::size_t size, Utils::SmallStringView string) { + return size + string.size(); + }; + + std::size_t size = std::accumulate(list.begin(), list.end(), initialSize, addSize); + + reserve(size); + setSize(size); + + char *currentData = data() + initialSize; + + for (Utils::SmallStringView string : list) { + std::memcpy(currentData, string.data(), string.size()); + currentData += string.size(); + } + + at(size) = 0; + } + void initializeLongString(size_type size, size_type capacity) { m_data.allocated.data.pointer[size] = 0; diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 3d479195f17..39cb86b193c 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -193,15 +193,16 @@ inline int reverse_memcmp(const char *first, const char *second, size_t n) { - const char *currentFirst = first + n; - const char *currentSecond = second + n; + const char *currentFirst = first + n - 1; + const char *currentSecond = second + n - 1; while (n > 0) { // If the current characters differ, return an appropriately signed // value; otherwise, keep searching backwards - if (*currentFirst != *currentSecond) - return *currentFirst - *currentSecond; + int difference = *currentFirst - *currentSecond; + if (difference != 0) + return difference; --currentFirst; --currentSecond; diff --git a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp index a2638212d65..ac5a96ee889 100644 --- a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp +++ b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp @@ -33,8 +33,15 @@ #include #include +#include +#include + +#include + #include +#include + namespace ClangRefactoring { namespace { @@ -54,9 +61,12 @@ class ClangRefactoringPluginData { using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater; public: + Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; RefactoringClient refactoringClient; ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient}; - RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient}; + RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient, filePathCache}; QtCreatorSearch qtCreatorSearch{*Core::SearchResultWindow::instance()}; QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(), qtCreatorSearch, diff --git a/src/plugins/clangrefactoring/querysqlitestatementfactory.h b/src/plugins/clangrefactoring/querysqlitestatementfactory.h index dec404f89b0..b2a7f97cb84 100644 --- a/src/plugins/clangrefactoring/querysqlitestatementfactory.h +++ b/src/plugins/clangrefactoring/querysqlitestatementfactory.h @@ -40,14 +40,9 @@ public: {} Database &database; ReadStatement selectLocationsForSymbolLocation{ - "SELECT sourceId, line, column FROM locations WHERE symbolId = " - " (SELECT symbolId FROM locations WHERE sourceId=" - " (SELECT sourceId FROM sources WHERE sourcePath =?)" - " AND line=? AND column=?) " + "SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = " + " (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) " "ORDER BY sourceId, line, column", - database}; // alternatively SELECT l2.symbolid, l2.sourceId, l2.line, l2.column FROM locations AS l2, sources, locations AS l1 ON sources.sourceId = l1.sourceId AND l2.symbolId=l1.symbolId WHERE sourcePath = ? AND l1.line=? AND l1.column=? ORDER BY l2.sourceId, l2.line, l2.column - ReadStatement selectSourcePathForId{ - "SELECT sourceId, sourcePath FROM sources WHERE sourceId = ?", database}; }; diff --git a/src/plugins/clangrefactoring/refactoringclient.cpp b/src/plugins/clangrefactoring/refactoringclient.cpp index 189e2bd4806..5c544e5a220 100644 --- a/src/plugins/clangrefactoring/refactoringclient.cpp +++ b/src/plugins/clangrefactoring/refactoringclient.cpp @@ -28,8 +28,9 @@ #include "clangqueryhighlighter.h" #include "clangqueryexamplehighlighter.h" -#include #include +#include +#include namespace ClangRefactoring { @@ -43,8 +44,8 @@ void RefactoringClient::sourceLocationsForRenamingMessage( ClangBackEnd::SourceLocationsForRenamingMessage &&message) { m_localRenamingCallback(message.symbolName().toQString(), - message.sourceLocations(), - message.textDocumentRevision()); + message.sourceLocations(), + message.textDocumentRevision()); m_refactoringEngine->setUsable(true); } @@ -122,45 +123,24 @@ void RefactoringClient::setRefactoringConnectionClient( m_connectionClient = connectionClient; } -std::unordered_map RefactoringClient::convertFilePaths( - const ClangBackEnd::FilePathDict &filePaths) -{ - using Dict = std::unordered_map; - Dict qstringFilePaths; - qstringFilePaths.reserve(filePaths.size()); - - auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) { - return std::make_pair(dictonaryEntry.first, - dictonaryEntry.second.path().toQString()); - }; - - std::transform(filePaths.begin(), - filePaths.end(), - std::inserter(qstringFilePaths, qstringFilePaths.begin()), - convertFilePath); - - return qstringFilePaths; -} - void RefactoringClient::addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges) { - auto filePaths = convertFilePaths(sourceRanges.filePaths()); - for (const auto &sourceRangeWithText : sourceRanges.sourceRangeWithTextContainers()) - addSearchResult(sourceRangeWithText, filePaths); + addSearchResult(sourceRangeWithText); } -void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText, - std::unordered_map &filePaths) +void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText) { - m_searchHandle->addResult(filePaths[sourceRangeWithText.fileHash()], - QString(sourceRangeWithText.text()), - {{int(sourceRangeWithText.start().line()), - int(sourceRangeWithText.start().column() - 1), - int(sourceRangeWithText.start().offset())}, - {int(sourceRangeWithText.end().line()), - int(sourceRangeWithText.end().column() - 1), - int(sourceRangeWithText.end().offset())}}); + auto &filePathCache = m_refactoringEngine->filePathCache(); + + m_searchHandle->addResult(QString(filePathCache.filePath(sourceRangeWithText.filePathId()).path()), + QString(sourceRangeWithText.text()), + {{int(sourceRangeWithText.start().line()), + int(sourceRangeWithText.start().column() - 1), + int(sourceRangeWithText.start().offset())}, + {int(sourceRangeWithText.end().line()), + int(sourceRangeWithText.end().column() - 1), + int(sourceRangeWithText.end().offset())}}); } void RefactoringClient::setResultCounterAndSendSearchIsFinishedIfFinished() diff --git a/src/plugins/clangrefactoring/refactoringclient.h b/src/plugins/clangrefactoring/refactoringclient.h index 09524f314f8..d504538b3ee 100644 --- a/src/plugins/clangrefactoring/refactoringclient.h +++ b/src/plugins/clangrefactoring/refactoringclient.h @@ -66,9 +66,6 @@ public: bool hasValidLocalRenamingCallback() const; - static std::unordered_map convertFilePaths( - const std::unordered_map &filePaths); - void setExpectedResultCount(uint count); uint expectedResultCount() const; uint resultCounter() const; @@ -76,8 +73,7 @@ public: void setRefactoringConnectionClient(ClangBackEnd::RefactoringConnectionClient *connectionClient); unittest_public: - void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange, - std::unordered_map &filePaths); + void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange); private: void addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges); diff --git a/src/plugins/clangrefactoring/refactoringengine.cpp b/src/plugins/clangrefactoring/refactoringengine.cpp index 696e38c468c..bc9ec9ab687 100644 --- a/src/plugins/clangrefactoring/refactoringengine.cpp +++ b/src/plugins/clangrefactoring/refactoringengine.cpp @@ -46,9 +46,11 @@ namespace ClangRefactoring { using ClangBackEnd::RequestSourceLocationsForRenamingMessage; RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server, - ClangBackEnd::RefactoringClientInterface &client) - : server(server), - client(client) + ClangBackEnd::RefactoringClientInterface &client, + ClangBackEnd::FilePathCachingInterface &filePathCache) + : m_server(server), + m_client(client), + m_filePathCache(filePathCache) { } @@ -60,7 +62,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data, setUsable(false); - client.setLocalRenamingCallback(std::move(renameSymbolsCallback)); + m_client.setLocalRenamingCallback(std::move(renameSymbolsCallback)); QString filePath = data.filePath().toString(); QTextCursor textCursor = data.cursor(); @@ -79,7 +81,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data, textCursor.document()->revision()); - server.requestSourceLocationsForRenamingMessage(std::move(message)); + m_server.requestSourceLocationsForRenamingMessage(std::move(message)); } void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &) @@ -89,12 +91,12 @@ void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &) bool RefactoringEngine::isUsable() const { - return server.isUsable(); + return m_server.isUsable(); } void RefactoringEngine::setUsable(bool isUsable) { - server.setUsable(isUsable); + m_server.setUsable(isUsable); } } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/refactoringengine.h b/src/plugins/clangrefactoring/refactoringengine.h index 83e67bfe27a..b64a2c8eebb 100644 --- a/src/plugins/clangrefactoring/refactoringengine.h +++ b/src/plugins/clangrefactoring/refactoringengine.h @@ -25,6 +25,8 @@ #pragma once +#include + #include namespace ClangBackEnd { @@ -37,8 +39,10 @@ namespace ClangRefactoring { class RefactoringEngine : public CppTools::RefactoringEngineInterface { public: - RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server, - ClangBackEnd::RefactoringClientInterface &client); + RefactoringEngine(ClangBackEnd::RefactoringServerInterface &m_server, + ClangBackEnd::RefactoringClientInterface &m_client, + ClangBackEnd::FilePathCachingInterface &filePathCache); + void startLocalRenaming(const CppTools::CursorInEditor &data, CppTools::ProjectPart *projectPart, RenameCallback &&renameSymbolsCallback) override; @@ -47,9 +51,15 @@ public: bool isUsable() const override; void setUsable(bool isUsable); + ClangBackEnd::FilePathCachingInterface &filePathCache() + { + return m_filePathCache; + } + private: - ClangBackEnd::RefactoringServerInterface &server; - ClangBackEnd::RefactoringClientInterface &client; + ClangBackEnd::RefactoringServerInterface &m_server; + ClangBackEnd::RefactoringClientInterface &m_client; + ClangBackEnd::FilePathCachingInterface &m_filePathCache; }; } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/sourcelocations.h b/src/plugins/clangrefactoring/sourcelocations.h index 9ae4241c01a..1eaf3fe3af8 100644 --- a/src/plugins/clangrefactoring/sourcelocations.h +++ b/src/plugins/clangrefactoring/sourcelocations.h @@ -27,39 +27,26 @@ #include -#include +#include + #include -#include -#include namespace ClangRefactoring { -class SourceLocations +struct SourceLocation { -public: - struct Location - { - Location(qint64 sourceId, qint64 line, qint64 column) - : sourceId(sourceId), line(line), column(column) - {} + SourceLocation(ClangBackEnd::FilePathId filePathId, int line, int column) + : filePathId(filePathId), line(line), column(column) + {} + SourceLocation(int directoryId, int sourceId, int line, int column) + : filePathId{directoryId, sourceId}, line(line), column(column) + {} - qint64 sourceId; - qint64 line; - qint64 column; - }; - - struct Source - { - Source(qint64 sourceId, Utils::PathString &&sourcePath) - : sourceId(sourceId), sourcePath(std::move(sourcePath)) - {} - - qint64 sourceId; - Utils::PathString sourcePath; - }; - - std::vector locations; - std::unordered_map sources; + ClangBackEnd::FilePathId filePathId; + int line; + int column; }; +using SourceLocations = std::vector; + } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/symbolquery.h b/src/plugins/clangrefactoring/symbolquery.h index 19faf972294..75c110eb765 100644 --- a/src/plugins/clangrefactoring/symbolquery.h +++ b/src/plugins/clangrefactoring/symbolquery.h @@ -27,6 +27,7 @@ #include +#include #include #include @@ -39,68 +40,20 @@ class SymbolQuery using ReadStatement = typename StatementFactory::ReadStatementType; public: - using Location = SourceLocations::Location; - using Source = SourceLocations::Source; - SymbolQuery(StatementFactory &statementFactory) : m_statementFactory(statementFactory) {} - SourceLocations locationsAt(const Utils::PathString &filePath, uint line, uint utf8Column) + SourceLocations locationsAt(ClangBackEnd::FilePathId filePathId, int line, int utf8Column) { ReadStatement &locationsStatement = m_statementFactory.selectLocationsForSymbolLocation; const std::size_t reserveSize = 128; - auto locations = locationsStatement.template values( - reserveSize, - filePath, - line, - utf8Column); - - const std::vector sourceIds = uniqueSourceIds(locations); - - ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId; - - auto sources = sourcesStatement.template values( - reserveSize, - sourceIds); - - return {locations, sourcesToHashMap(sources)}; - } - - static - qint64 sourceId(const Location &location) - { - return location.sourceId; - } - - static - std::vector uniqueSourceIds(const std::vector &locations) - { - std::vector ids; - ids.reserve(locations.size()); - - std::transform(locations.begin(), - locations.end(), - std::back_inserter(ids), - sourceId); - - auto newEnd = std::unique(ids.begin(), ids.end()); - ids.erase(newEnd, ids.end()); - - return ids; - } - - static - std::unordered_map sourcesToHashMap(const std::vector &sources) - { - std::unordered_map dictonary; - - for (const Source &source : sources) - dictonary.emplace(source.sourceId, std::move(source.sourcePath)); - - return dictonary; + return locationsStatement.template values(reserveSize, + filePathId.fileNameId, + line, + utf8Column); } private: diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index 5622179272b..d17fbd2bd97 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -31,7 +31,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -103,15 +105,16 @@ int main(int argc, char *argv[]) const QString connection = processArguments(application); - FilePathCache<> filePathCache; + Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; ClangPathWatcher includeWatcher(filePathCache); ApplicationEnvironment environment; PchGenerator pchGenerator(environment); PchCreator pchCreator(environment, filePathCache); pchCreator.setGenerator(&pchGenerator); ProjectParts projectParts; - PchManagerServer clangPchManagerServer(filePathCache, - includeWatcher, + PchManagerServer clangPchManagerServer(includeWatcher, pchCreator, projectParts); includeWatcher.setNotifier(&clangPchManagerServer); diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h index 85ad8bbd63e..e37668d7a78 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h +++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h @@ -28,7 +28,9 @@ #include "clangpathwatcherinterface.h" #include "clangpathwatchernotifier.h" #include "changedfilepathcompressor.h" -#include "stringcache.h" + +#include +#include #include @@ -37,34 +39,34 @@ namespace ClangBackEnd { class WatcherEntry { public: - FilePathIndex id; - FilePathIndex path; + int id; + FilePathId pathId; friend bool operator==(const WatcherEntry &first, const WatcherEntry &second) { - return first.id == second.id && first.path == second.path; + return first.id == second.id && first.pathId == second.pathId; } friend bool operator<(const WatcherEntry &first, const WatcherEntry &second) { - return std::tie(first.path, first.id) < std::tie(second.path, second.id); + return std::tie(first.pathId, first.id) < std::tie(second.pathId, second.id); } - friend bool operator<(const WatcherEntry &entry, FilePathIndex path) + friend bool operator<(const WatcherEntry &entry, FilePathId pathId) { - return entry.path < path; + return entry.pathId < pathId; } - friend bool operator<(FilePathIndex path, const WatcherEntry &entry) + friend bool operator<(FilePathId pathId, const WatcherEntry &entry) { - return path < entry.path; + return pathId < entry.pathId; } }; using WatcherEntries = std::vector; using IdCache = StringCache; @@ -74,7 +76,7 @@ template &pathCache, + ClangPathWatcher(FilePathCachingInterface &pathCache, ClangPathWatcherNotifier *notifier=nullptr) : m_pathCache(pathCache), m_notifier(notifier) @@ -136,9 +138,9 @@ unittest_public: return ids; } - std::vector convertToIdNumbers(const Utils::SmallStringVector &ids) + std::vector convertToIdNumbers(const Utils::SmallStringVector &ids) { - std::vector idNumbers = m_idCache.stringIds(ids); + std::vector idNumbers = m_idCache.stringIds(ids); std::sort(idNumbers.begin(), idNumbers.end()); @@ -148,33 +150,33 @@ unittest_public: std::size_t sizeOfIdPaths(const std::vector &idPaths) { auto sumSize = [] (std::size_t size, const IdPaths &idPath) { - return size + idPath.paths.size(); + return size + idPath.filePathIds.size(); }; return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize); } - std::pair> + std::pair> convertIdPathsToWatcherEntriesAndIds(const std::vector &idPaths) { WatcherEntries entries; entries.reserve(sizeOfIdPaths(idPaths)); - std::vector ids; + std::vector ids; ids.reserve(ids.size()); auto outputIterator = std::back_inserter(entries); for (const IdPaths &idPath : idPaths) { - FilePathIndex id = m_idCache.stringId(idPath.id); + int id = m_idCache.stringId(idPath.id); ids.push_back(id); - outputIterator = std::transform(idPath.paths.begin(), - idPath.paths.end(), + outputIterator = std::transform(idPath.filePathIds.begin(), + idPath.filePathIds.end(), outputIterator, - [&] (uint path) { return WatcherEntry{id, path}; }); + [&] (FilePathId pathId) { return WatcherEntry{id, pathId}; }); } std::sort(entries.begin(), entries.end()); @@ -196,7 +198,7 @@ unittest_public: } void removeUnusedEntries(const WatcherEntries &entries, - const std::vector &ids) + const std::vector &ids) { auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); @@ -222,7 +224,9 @@ unittest_public: std::transform(watcherEntries.begin(), watcherEntries.end(), std::back_inserter(paths), - [&] (const WatcherEntry &entry) { return QString(m_pathCache.string(entry.path)); }); + [&] (const WatcherEntry &entry) { + return QString(m_pathCache.filePath(entry.pathId).path()); + }); return paths; } @@ -252,7 +256,7 @@ unittest_public: WatcherEntries notWatchedPaths(const WatcherEntries &entries) const { auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) { - return first.path < second.path; + return first.pathId < second.pathId; }; return notWatchedEntries(entries, compare); @@ -278,7 +282,7 @@ unittest_public: WatcherEntries notAnymoreWatchedEntriesWithIds( const WatcherEntries &newEntries, - const std::vector &ids) const + const std::vector &ids) const { auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less()); @@ -313,7 +317,7 @@ unittest_public: WatcherEntries uniqueEntries; auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) { - return first.path == second.path; + return first.pathId == second.pathId; }; std::unique_copy(pathEntries.begin(), @@ -334,7 +338,7 @@ unittest_public: return m_watchedEntries; } - WatcherEntries removeIdsFromWatchedEntries(const std::vector &ids) + WatcherEntries removeIdsFromWatchedEntries(const std::vector &ids) { auto keep = [&] (const WatcherEntry &entry) { @@ -374,11 +378,11 @@ unittest_public: WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths) { - std::vector pathIds = m_pathCache.stringIds(filePaths); + FilePathIds pathIds = m_pathCache.filePathIds(filePaths); WatcherEntries foundEntries; - for (uint pathId : pathIds) { + for (FilePathId pathId : pathIds) { auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId); foundEntries.insert(foundEntries.end(), range.first, range.second); } @@ -420,7 +424,7 @@ unittest_public: } } - FilePathCache<> &pathCache() + FilePathCachingInterface &pathCache() { return m_pathCache; } @@ -435,10 +439,8 @@ private: WatcherEntries m_watchedEntries; ChangedFilePathCompressor m_changedFilePathCompressor; FileSystemWatcher m_fileSystemWatcher; - FilePathCache<> &m_pathCache; + FilePathCachingInterface &m_pathCache; ClangPathWatcherNotifier *m_notifier; }; -std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry); - } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri index 926280a5fa8..686d9a5d18a 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri +++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri @@ -2,9 +2,7 @@ INCLUDEPATH += $$PWD SOURCES += \ $$PWD/pchmanagerserver.cpp \ - $$PWD/clangpathwatcher.cpp \ $$PWD/projectparts.cpp \ - $$PWD/idpaths.cpp \ $$PWD/pchcreatorinterface.cpp \ $$PWD/clangpathwatcherinterface.cpp \ $$PWD/projectpartsinterface.cpp \ diff --git a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h index 339d491848d..c61dfecb612 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h @@ -25,10 +25,11 @@ #pragma once -#include "stringcache.h" - #include +#include +#include + #include #include #include @@ -38,10 +39,10 @@ namespace ClangBackEnd { class CollectIncludesAction final : public clang::PreprocessOnlyAction { public: - CollectIncludesAction(FilePathIndices &includeIds, - FilePathCache<> &filePathCache, - FilePathIndices &excludedIncludeUID, - FilePathIndices &alreadyIncludedFileUIDs) + CollectIncludesAction(FilePathIds &includeIds, + FilePathCachingInterface &filePathCache, + std::vector &excludedIncludeUID, + std::vector &alreadyIncludedFileUIDs) : m_includeIds(includeIds), m_filePathCache(filePathCache), m_excludedIncludeUID(excludedIncludeUID), @@ -78,10 +79,10 @@ public: } private: - FilePathIndices &m_includeIds; - FilePathCache<> &m_filePathCache; - FilePathIndices &m_excludedIncludeUID; - FilePathIndices &m_alreadyIncludedFileUIDs; + FilePathIds &m_includeIds; + FilePathCachingInterface &m_filePathCache; + std::vector &m_excludedIncludeUID; + std::vector &m_alreadyIncludedFileUIDs; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h index a57d72adfcb..dff1dc39cee 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h @@ -25,7 +25,10 @@ #pragma once -#include "stringcache.h" +#include +#include + +#include #include #include @@ -33,8 +36,6 @@ #include #include -#include - #include #include #include @@ -47,10 +48,10 @@ class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks { public: CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch, - std::vector &includeIds, - FilePathCache<> &filePathCache, - const std::vector &excludedIncludeUID, - std::vector &alreadyIncludedFileUIDs) + FilePathIds &includeIds, + FilePathCachingInterface &filePathCache, + const std::vector &excludedIncludeUID, + std::vector &alreadyIncludedFileUIDs) : m_headerSearch(headerSearch), m_includeIds(includeIds), m_filePathCache(filePathCache), @@ -78,7 +79,7 @@ public: m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID); Utils::PathString filePath = filePathFromFile(file); if (!filePath.isEmpty()) { - FilePathIndex includeId = m_filePathCache.stringId(filePath); + FilePathId includeId = m_filePathCache.filePathId(filePath); m_includeIds.emplace_back(includeId); } } @@ -132,7 +133,7 @@ public: uid); } - std::pair::iterator> isNotAlreadyIncluded(FilePathIndex uid) const + std::pair::iterator> isNotAlreadyIncluded(uint uid) const { auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(), m_alreadyIncludedFileUIDs.end(), @@ -174,10 +175,10 @@ public: private: clang::HeaderSearch &m_headerSearch; - std::vector &m_includeIds; - FilePathCache<> &m_filePathCache; - const std::vector &m_excludedIncludeUID; - std::vector &m_alreadyIncludedFileUIDs; + FilePathIds &m_includeIds; + FilePathCachingInterface &m_filePathCache; + const std::vector &m_excludedIncludeUID; + std::vector &m_alreadyIncludedFileUIDs; bool m_skipInclude = false; }; diff --git a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h index 42b8a62cea7..969a8ddb8bb 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h @@ -25,10 +25,11 @@ #pragma once -#include "stringcache.h" - #include "collectincludesaction.h" +#include +#include + #include namespace ClangBackEnd { @@ -36,8 +37,8 @@ namespace ClangBackEnd { class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory { public: - CollectIncludesToolAction(std::vector &includeIds, - FilePathCache<> &filePathCache, + CollectIncludesToolAction(FilePathIds &includeIds, + FilePathCachingInterface &filePathCache, const Utils::PathStringVector &excludedIncludes) : m_includeIds(includeIds), m_filePathCache(filePathCache), @@ -72,9 +73,9 @@ public: m_alreadyIncludedFileUIDs); } - std::vector generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const + std::vector generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const { - std::vector fileUIDs; + std::vector fileUIDs; fileUIDs.reserve(m_excludedIncludes.size()); for (const Utils::PathString &filePath : m_excludedIncludes) { @@ -90,10 +91,10 @@ public: } private: - std::vector m_alreadyIncludedFileUIDs; - std::vector m_excludedIncludeUIDs; - std::vector &m_includeIds; - FilePathCache<> &m_filePathCache; + std::vector m_alreadyIncludedFileUIDs; + std::vector m_excludedIncludeUIDs; + FilePathIds &m_includeIds; + FilePathCachingInterface &m_filePathCache; const Utils::PathStringVector &m_excludedIncludes; }; diff --git a/src/tools/clangpchmanagerbackend/source/idpaths.h b/src/tools/clangpchmanagerbackend/source/idpaths.h index a407e24530f..3b24ba7538e 100644 --- a/src/tools/clangpchmanagerbackend/source/idpaths.h +++ b/src/tools/clangpchmanagerbackend/source/idpaths.h @@ -27,9 +27,7 @@ #include -#include - -#include +#include namespace ClangBackEnd { @@ -37,14 +35,12 @@ class IdPaths { public: Utils::SmallString id; - std::vector paths; + FilePathIds filePathIds; friend bool operator==(const IdPaths &first, const IdPaths &second) { - return first.id == second.id && first.paths == second.paths; + return first.id == second.id && first.filePathIds == second.filePathIds; } }; -std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); - } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.cpp b/src/tools/clangpchmanagerbackend/source/includecollector.cpp index 421123b3a7c..6ac142e22b3 100644 --- a/src/tools/clangpchmanagerbackend/source/includecollector.cpp +++ b/src/tools/clangpchmanagerbackend/source/includecollector.cpp @@ -33,7 +33,7 @@ namespace ClangBackEnd { -IncludeCollector::IncludeCollector(FilePathCache<> &filePathCache) +IncludeCollector::IncludeCollector(FilePathCachingInterface &filePathCache) : m_filePathCache(filePathCache) { } @@ -69,7 +69,7 @@ void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedInc #endif } -std::vector IncludeCollector::takeIncludeIds() +FilePathIds 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 73f9b948afa..52e6e560dba 100644 --- a/src/tools/clangpchmanagerbackend/source/includecollector.h +++ b/src/tools/clangpchmanagerbackend/source/includecollector.h @@ -25,28 +25,28 @@ #pragma once -#include "stringcache.h" - #include +#include + namespace ClangBackEnd { class IncludeCollector : public ClangTool { public: - IncludeCollector(FilePathCache<> &filePathCache); + IncludeCollector(FilePathCachingInterface &filePathCache); void collectIncludes(); void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes); - std::vector takeIncludeIds(); + FilePathIds takeIncludeIds(); private: Utils::PathStringVector m_excludedIncludes; - std::vector m_includeIds; + FilePathIds m_includeIds; Utils::SmallStringVector m_directories; - FilePathCache<> &m_filePathCache; + FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp index fd6da580129..645e266db0b 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp @@ -29,6 +29,7 @@ #include "includecollector.h" #include "pchnotcreatederror.h" +#include #include #include @@ -37,7 +38,7 @@ namespace ClangBackEnd { -PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache) +PchCreator::PchCreator(Environment &environment, FilePathCachingInterface &filePathCache) : m_environment(environment), m_filePathCache(filePathCache) { @@ -45,7 +46,7 @@ PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache) PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts, Environment &environment, - FilePathCache<> &filePathCache, + FilePathCachingInterface &filePathCache, PchGeneratorInterface *pchGenerator, V2::FileContainers &&generatedFiles) : m_projectParts(std::move(projectsParts)), @@ -239,7 +240,7 @@ Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() cons return compilerArguments; } -std::vector PchCreator::generateGlobalPchIncludeIds() const +FilePathIds PchCreator::generateGlobalPchIncludeIds() const { IncludeCollector collector(m_filePathCache); @@ -256,7 +257,7 @@ std::vector PchCreator::generateGlobalPchIncludeIds() const namespace { -std::size_t contentSize(const std::vector &includes) +std::size_t contentSize(const FilePaths &includes) { auto countIncludeSize = [] (std::size_t size, const Utils::PathString &include) { return size + include.size(); @@ -266,20 +267,16 @@ std::size_t contentSize(const std::vector &includes) } } -Utils::SmallString PchCreator::generatePchIncludeFileContent( - const std::vector &includeIds) const +Utils::SmallString PchCreator::generatePchIncludeFileContent(const FilePathIds &includeIds) const { Utils::SmallString fileContent; const std::size_t lineTemplateSize = 12; - auto includes = m_filePathCache.strings(includeIds); + auto includes = m_filePathCache.filePaths(includeIds); fileContent.reserve(includes.size() * lineTemplateSize + contentSize(includes)); - for (const Utils::PathString &include : includes) { - fileContent += "#include \""; - fileContent += include; - fileContent += "\"\n"; - } + for (const Utils::PathString &include : includes) + fileContent += {"#include \"", include, "\"\n"}; return fileContent; } @@ -461,7 +458,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaderAndSourcePaths( return includeAndSources; } -std::vector PchCreator::generateProjectPartPchIncludes( +FilePathIds 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 5548ec7acd2..26e591302f4 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.h +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h @@ -28,9 +28,9 @@ #include "pchcreatorinterface.h" #include "pchgeneratorinterface.h" -#include "stringcache.h" #include "idpaths.h" +#include #include #include @@ -48,10 +48,10 @@ class PchCreator final : public PchCreatorInterface { public: PchCreator(Environment &environment, - FilePathCache<> &filePathCache); + FilePathCachingInterface &filePathCache); PchCreator(V2::ProjectPartContainers &&projectsParts, Environment &environment, - FilePathCache<> &filePathCache, + FilePathCachingInterface &filePathCache, PchGeneratorInterface *pchGenerator, V2::FileContainers &&generatedFiles); @@ -70,9 +70,9 @@ unittest_public: Utils::SmallStringVector generateGlobalPchCompilerArguments() const; Utils::SmallStringVector generateGlobalClangCompilerArguments() const; - std::vector generateGlobalPchIncludeIds() const; + FilePathIds generateGlobalPchIncludeIds() const; - Utils::SmallString generatePchIncludeFileContent(const std::vector &includeIds) const; + Utils::SmallString generatePchIncludeFileContent(const FilePathIds &includeIds) const; Utils::SmallString generateGlobalPchHeaderFileContent() const; std::unique_ptr 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 generateProjectPartPchIncludes( + FilePathIds generateProjectPartPchIncludes( const V2::ProjectPartContainer &projectPart) const; Utils::SmallString generateProjectPathPchHeaderFilePath( const V2::ProjectPartContainer &projectPart) const; @@ -127,7 +127,7 @@ private: std::vector m_projectPartPchs; std::vector m_projectsIncludeIds; Environment &m_environment; - FilePathCache<> &m_filePathCache; + FilePathCachingInterface &m_filePathCache; PchGeneratorInterface *m_pchGenerator = nullptr; }; diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index 03261ae164c..8abcda8d659 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -36,12 +36,10 @@ namespace ClangBackEnd { -PchManagerServer::PchManagerServer(FilePathCache<> &filePathCache, - ClangPathWatcherInterface &fileSystemWatcher, +PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchCreatorInterface &pchCreator, ProjectPartsInterface &projectParts) - : m_filePathCache(filePathCache), - m_fileSystemWatcher(fileSystemWatcher), + : m_fileSystemWatcher(fileSystemWatcher), m_pchCreator(pchCreator), m_projectParts(projectParts) { diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index 7be9c759669..bac2dcd00f6 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -31,7 +31,6 @@ #include "pchgeneratornotifierinterface.h" #include "pchmanagerserverinterface.h" #include "projectpartsinterface.h" -#include "stringcache.h" #include @@ -46,8 +45,7 @@ class PchManagerServer : public PchManagerServerInterface, { public: - PchManagerServer(FilePathCache<> &filePathCache, - ClangPathWatcherInterface &fileSystemWatcher, + PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchCreatorInterface &pchCreator, ProjectPartsInterface &projectParts); @@ -60,7 +58,6 @@ public: void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override; private: - FilePathCache<> &m_filePathCache; ClangPathWatcherInterface &m_fileSystemWatcher; PchCreatorInterface &m_pchCreator; ProjectPartsInterface &m_projectParts; diff --git a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp index 8c5fe3f751f..7c628fa3765 100644 --- a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp +++ b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp @@ -29,14 +29,15 @@ #include #include -#include +#include #include #include #include -using ClangBackEnd::FilePathCache; +using ClangBackEnd::FilePathCaching; using ClangBackEnd::RefactoringClientProxy; using ClangBackEnd::RefactoringServer; +using ClangBackEnd::RefactoringDatabaseInitializer; using ClangBackEnd::ConnectionServer; using ClangBackEnd::SymbolIndexing; @@ -69,8 +70,10 @@ try { const QString connection = processArguments(application); - FilePathCache filePathCache; - SymbolIndexing symbolIndexing{filePathCache, Utils::PathString{QDir::tempPath() + "/symbol.db"}}; + Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}}; + RefactoringDatabaseInitializer databaseInitializer{database}; + FilePathCaching filePathCache{database}; + SymbolIndexing symbolIndexing{database, filePathCache}; RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache}; ConnectionServer connectionServer(connection); connectionServer.start(); diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp index 620a7ebaab0..fc9dd868c03 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp @@ -54,16 +54,16 @@ struct CollectBoundNodes : MatchFinder::MatchCallback { } }; -ClangQuery::ClangQuery(FilePathCache &filePathCache, +ClangQuery::ClangQuery(FilePathCachingInterface &filePathCache, Utils::SmallString &&query) - : query(std::move(query)), - filePathCache(filePathCache) + : m_query(std::move(query)), + m_filePathCache(filePathCache) { } void ClangQuery::setQuery(Utils::SmallString &&query) { - this->query = std::move(query); + this->m_query = std::move(query); } void ClangQuery::findLocations() @@ -78,7 +78,7 @@ void ClangQuery::findLocations() std::make_move_iterator(asts.end()), [&] (std::unique_ptr &&ast) { Diagnostics diagnostics; - auto optionalMatcher = Parser::parseMatcherExpression({query.data(), query.size()}, + auto optionalMatcher = Parser::parseMatcherExpression({m_query.data(), m_query.size()}, nullptr, &diagnostics); parseDiagnostics(diagnostics); @@ -89,19 +89,19 @@ void ClangQuery::findLocations() SourceRangesContainer ClangQuery::takeSourceRanges() { - return std::move(sourceRangesContainer); + return std::move(m_sourceRangesContainer); } DynamicASTMatcherDiagnosticContainers ClangQuery::takeDiagnosticContainers() { - return std::move(diagnosticContainers_); + return std::move(m_diagnosticContainers_); } namespace { V2::SourceRangeContainer convertToContainer(const clang::ast_matchers::dynamic::SourceRange sourceRange) { - return V2::SourceRangeContainer(0, + return V2::SourceRangeContainer({1, 0}, sourceRange.Start.Line, sourceRange.Start.Column, 0, @@ -159,8 +159,8 @@ void ClangQuery::parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostic auto errors = diagnostics.errors(); for (const auto &errorContent : errors) { - diagnosticContainers_.emplace_back(); - DynamicASTMatcherDiagnosticContainer &diagnosticContainer = diagnosticContainers_.back(); + m_diagnosticContainers_.emplace_back(); + DynamicASTMatcherDiagnosticContainer &diagnosticContainer = m_diagnosticContainers_.back(); for (const auto &message : errorContent.Messages) { diagnosticContainer.insertMessage(convertToContainer(message.Range), @@ -216,8 +216,8 @@ void ClangQuery::matchLocation( SourceRangeExtractor extractor(ast->getSourceManager(), ast->getLangOpts(), - filePathCache, - sourceRangesContainer); + m_filePathCache, + m_sourceRangesContainer); extractor.addSourceRanges(sourceRanges); } diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h index 7d99766008d..daccd8335e4 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.h +++ b/src/tools/clangrefactoringbackend/source/clangquery.h @@ -30,7 +30,7 @@ #include #include -#include +#include namespace clang { namespace ast_matchers { @@ -51,9 +51,9 @@ namespace ClangBackEnd { class ClangQuery : public ClangTool { public: - ClangQuery(FilePathCache &filePathCache, Utils::SmallString &&query={}); + ClangQuery(FilePathCachingInterface &m_filePathCache, Utils::SmallString &&m_query={}); - void setQuery(Utils::SmallString &&query); + void setQuery(Utils::SmallString &&m_query); void findLocations(); @@ -66,10 +66,10 @@ private: std::unique_ptr ast); private: - SourceRangesContainer sourceRangesContainer; - Utils::SmallString query; - std::vector diagnosticContainers_; - FilePathCache &filePathCache; + SourceRangesContainer m_sourceRangesContainer; + Utils::SmallString m_query; + std::vector m_diagnosticContainers_; + ClangBackEnd::FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp index 692065a9e79..0ac42d6ef13 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp @@ -29,7 +29,7 @@ namespace ClangBackEnd { -ClangQueryGatherer::ClangQueryGatherer(FilePathCache *filePathCache, +ClangQueryGatherer::ClangQueryGatherer(FilePathCachingInterface *filePathCache, std::vector &&sources, std::vector &&unsaved, Utils::SmallString &&query) @@ -43,7 +43,7 @@ ClangQueryGatherer::ClangQueryGatherer(FilePathCache *filePathCache, SourceRangesForQueryMessage ClangQueryGatherer::createSourceRangesForSource( - FilePathCache *filePathCache, + FilePathCachingInterface *filePathCache, V2::FileContainer &&source, const std::vector &unsaved, Utils::SmallString &&query) diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h index c1fd6341fab..f0e0e181f25 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include @@ -41,13 +41,13 @@ public: using Future = std::future; ClangQueryGatherer() = default; - ClangQueryGatherer(FilePathCache *filePathCache, + ClangQueryGatherer(FilePathCachingInterface *filePathCache, std::vector &&sources, std::vector &&unsaved, Utils::SmallString &&query); static SourceRangesForQueryMessage createSourceRangesForSource( - FilePathCache *filePathCache, + FilePathCachingInterface *filePathCache, V2::FileContainer &&source, const std::vector &unsaved, Utils::SmallString &&query); @@ -69,7 +69,7 @@ protected: std::vector finishedFutures(); private: - FilePathCache *m_filePathCache = nullptr; + FilePathCachingInterface *m_filePathCache = nullptr; SourceRangeFilter m_sourceRangeFilter; std::vector m_sources; std::vector m_unsaved; diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index 50041e596a2..e95981a4a3b 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -57,5 +57,4 @@ HEADERS += \ SOURCES += \ $$PWD/sourcerangefilter.cpp \ $$PWD/symbolindexer.cpp \ - $$PWD/symbolentry.cpp \ - $$PWD/sourcelocationentry.cpp + $$PWD/symbolentry.cpp diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h index 1ddd34b595f..2c8a93e9400 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h @@ -31,7 +31,7 @@ #include -#include +#include #include @@ -42,7 +42,7 @@ namespace ClangBackEnd { class CollectSymbolsAction { public: - CollectSymbolsAction(FilePathCache &filePathCache) + CollectSymbolsAction(FilePathCachingInterface &filePathCache) : m_filePathCache(filePathCache) {} @@ -66,7 +66,7 @@ public: private: SymbolEntries m_symbolEntries; SourceLocationEntries m_sourceLocationEntries; - FilePathCache &m_filePathCache; + FilePathCachingInterface &m_filePathCache; }; diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h index fcedd6a6d04..f93f44a1cbf 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h @@ -28,7 +28,7 @@ #include "symbolentry.h" #include "sourcelocationentry.h" -#include +#include #include #include @@ -50,7 +50,7 @@ class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor &filePathCache, + FilePathCachingInterface &filePathCache, const clang::SourceManager &sourceManager) : m_symbolEntries(symbolEntries), m_sourceLocationEntries(sourceLocationEntries), @@ -100,7 +100,7 @@ public: return true; } - FilePathIndex filePathId(clang::SourceLocation sourceLocation) + FilePathId filePathId(clang::SourceLocation sourceLocation) { uint clangFileId = m_sourceManager.getFileID(sourceLocation).getHashValue(); @@ -111,11 +111,11 @@ public: auto filePath = m_sourceManager.getFilename(sourceLocation); - FilePathIndex index = m_filePathCache.stringId(toStringView(filePath)); + FilePathId filePathId = m_filePathCache.filePathId(toStringView(filePath)); - m_filePathIndices.emplace(clangFileId, index); + m_filePathIndices.emplace(clangFileId, filePathId); - return index; + return filePathId; } LineColumn lineColum(clang::SourceLocation sourceLocation) @@ -147,9 +147,9 @@ public: private: SymbolEntries &m_symbolEntries; - std::unordered_map m_filePathIndices; + std::unordered_map m_filePathIndices; SourceLocationEntries &m_sourceLocationEntries; - FilePathCache &m_filePathCache; + FilePathCachingInterface &m_filePathCache; const clang::SourceManager &m_sourceManager; }; diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h b/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h index 0eeb7a73f24..55822ab0919 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h @@ -31,7 +31,7 @@ #include #include -#include +#include namespace ClangBackEnd { @@ -40,7 +40,7 @@ class CollectSymbolsConsumer : public clang::ASTConsumer public: CollectSymbolsConsumer(SymbolEntries &symbolEntries, SourceLocationEntries &sourceLocationEntries, - FilePathCache &filePathCache) + FilePathCachingInterface &filePathCache) : m_symbolEntries(symbolEntries), m_sourceLocationEntries(sourceLocationEntries), m_filePathCache(filePathCache) @@ -69,6 +69,6 @@ public: private: SymbolEntries &m_symbolEntries; SourceLocationEntries &m_sourceLocationEntries; - FilePathCache &m_filePathCache; + FilePathCachingInterface &m_filePathCache; }; } diff --git a/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.cpp b/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.cpp index cc6e8e609ab..3dd43976a02 100644 --- a/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.cpp +++ b/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.cpp @@ -48,9 +48,12 @@ namespace ClangBackEnd { -LocationSourceFileCallbacks::LocationSourceFileCallbacks(uint line, uint column) - : line(line), - column(column) +LocationSourceFileCallbacks::LocationSourceFileCallbacks(uint line, + uint column, + FilePathCachingInterface &filePathCache) + : m_filePathCache(filePathCache), + m_line(line), + m_column(column) { } @@ -58,30 +61,31 @@ bool LocationSourceFileCallbacks::handleBeginSource(clang::CompilerInstance &com { auto &preprocessor = compilerInstance.getPreprocessor(); - macroPreprocessorCallbacks = new MacroPreprocessorCallbacks(sourceLocationsContainer, - symbolName, - preprocessor, - line, - column); + m_macroPreprocessorCallbacks = new MacroPreprocessorCallbacks(m_sourceLocationsContainer, + m_symbolName, + preprocessor, + m_filePathCache, + m_line, + m_column); - preprocessor.addPPCallbacks(std::unique_ptr(macroPreprocessorCallbacks)); + preprocessor.addPPCallbacks(std::unique_ptr(m_macroPreprocessorCallbacks)); return true; } SourceLocationsContainer LocationSourceFileCallbacks::takeSourceLocations() { - return std::move(sourceLocationsContainer); + return std::move(m_sourceLocationsContainer); } Utils::SmallString LocationSourceFileCallbacks::takeSymbolName() { - return std::move(symbolName); + return std::move(m_symbolName); } bool LocationSourceFileCallbacks::hasSourceLocations() const { - return sourceLocationsContainer.hasContent(); + return m_sourceLocationsContainer.hasContent(); } diff --git a/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h b/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h index cb9560ae7d8..5b7fe2af4a5 100644 --- a/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h +++ b/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h @@ -25,6 +25,7 @@ #pragma once +#include #include #include @@ -45,7 +46,7 @@ class SourceLocationsContainer; class LocationSourceFileCallbacks : public clang::tooling::SourceFileCallbacks { public: - LocationSourceFileCallbacks(uint line, uint column); + LocationSourceFileCallbacks(uint line, uint column, FilePathCachingInterface &filePathCache); bool handleBeginSource(clang::CompilerInstance &compilerInstance, llvm::StringRef fileName) override; @@ -56,11 +57,12 @@ public: bool hasSourceLocations() const; private: - SourceLocationsContainer sourceLocationsContainer; - Utils::SmallString symbolName; - MacroPreprocessorCallbacks *macroPreprocessorCallbacks; - uint line; - uint column; + SourceLocationsContainer m_sourceLocationsContainer; + Utils::SmallString m_symbolName; + MacroPreprocessorCallbacks *m_macroPreprocessorCallbacks; + FilePathCachingInterface &m_filePathCache; + uint m_line; + uint m_column; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.cpp b/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.cpp index c0015f867d8..2d46efed287 100644 --- a/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.cpp +++ b/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.cpp @@ -30,13 +30,15 @@ namespace ClangBackEnd { MacroPreprocessorCallbacks::MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer, Utils::SmallString &symbolName, clang::Preprocessor &preprocessor, + FilePathCachingInterface &filePathCache, uint line, uint column) - : sourceLocationsContainer(sourceLocationsContainer), - symbolName(symbolName), - preprocessor(preprocessor), - line(line), - column(column) + : m_sourceLocationsContainer(sourceLocationsContainer), + m_symbolName(symbolName), + m_preprocessor(preprocessor), + m_filePathCache(filePathCache), + m_line(line), + m_column(column) { } diff --git a/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.h b/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.h index 6c6010b2bb8..f94d993ef2d 100644 --- a/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.h +++ b/src/tools/clangrefactoringbackend/source/macropreprocessorcallbacks.h @@ -27,27 +27,14 @@ #include "sourcelocationsutils.h" +#include #include -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif - #include #include #include #include -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - #include namespace ClangBackEnd { @@ -67,18 +54,19 @@ struct MacroDirectiveToken class MacroPreprocessorCallbacks : public clang::PPCallbacks { public: - MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer, - Utils::SmallString &symbolName, - clang::Preprocessor &preprocessor, - uint line, - uint column); + MacroPreprocessorCallbacks(SourceLocationsContainer &m_sourceLocationsContainer, + Utils::SmallString &m_symbolName, + clang::Preprocessor &m_preprocessor, + FilePathCachingInterface &filePathCache, + uint m_line, + uint m_column); void FileChanged(clang::SourceLocation location, FileChangeReason reason, clang::SrcMgr::CharacteristicKind /*fileType*/, clang::FileID /*previousFileIdentifier*/) final { - if (!isMainFileEntered) { + if (!m_isMainFileEntered) { updateLocations(); updateIsMainFileEntered(location, reason); } @@ -88,9 +76,9 @@ public: { if (isInMainFile(token)) { if (includesCursorPosition(token)) { - sourceLocations.push_back(token.getLocation()); - cursorMacroDirective = macroDirective; - symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(), + m_sourceLocations.push_back(token.getLocation()); + m_cursorMacroDirective = macroDirective; + m_symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(), token.getIdentifierInfo()->getLength()); } } @@ -103,59 +91,60 @@ public: { if (includesCursorPosition(token)) { appendSourceLocations(token, macroDefinition); - cursorMacroDirective = macroDefinition.getLocalDirective(); - symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(), + m_cursorMacroDirective = macroDefinition.getLocalDirective(); + m_symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(), token.getIdentifierInfo()->getLength()); } else if (isCurrentTokenExpansion(macroDefinition)) { - sourceLocations.push_back(token.getLocation()); + m_sourceLocations.push_back(token.getLocation()); } else if (isBeforeCursorSourceLocation()) { - preCursorMacroDirectiveTokens.emplace_back(macroDefinition.getLocalDirective(), token); + m_preCursorMacroDirectiveTokens.emplace_back(macroDefinition.getLocalDirective(), token); } } void EndOfMainFile() final { - appendSourceLocationsToSourceLocationsContainer(sourceLocationsContainer, - sourceLocations, - sourceManager()); + appendSourceLocationsToSourceLocationsContainer(m_sourceLocationsContainer, + m_sourceLocations, + sourceManager(), + m_filePathCache); } private: void appendSourceLocations(const clang::Token &token, const clang::MacroDefinition ¯oDefinition) { - sourceLocations.push_back(macroDefinition.getLocalDirective()->getLocation()); - for (const auto ¯oDirectiveToken : preCursorMacroDirectiveTokens) { + m_sourceLocations.push_back(macroDefinition.getLocalDirective()->getLocation()); + for (const auto ¯oDirectiveToken : m_preCursorMacroDirectiveTokens) { if (macroDirectiveToken.macroDirective == macroDefinition.getLocalDirective()) - sourceLocations.push_back(macroDirectiveToken.token.getLocation()); + m_sourceLocations.push_back(macroDirectiveToken.token.getLocation()); } - sourceLocations.push_back(token.getLocation()); + m_sourceLocations.push_back(token.getLocation()); } void updateLocations() { - if (mainFileSourceLocation.isInvalid()) { - mainFileSourceLocation = sourceManager().getLocForStartOfFile(sourceManager().getMainFileID()); - cursorSourceLocation = sourceManager().translateLineCol(sourceManager().getMainFileID(), - line, - column); + if (m_mainFileSourceLocation.isInvalid()) { + m_mainFileSourceLocation = sourceManager().getLocForStartOfFile(sourceManager().getMainFileID()); + m_cursorSourceLocation = sourceManager().translateLineCol(sourceManager().getMainFileID(), + m_line, + m_column); } } void updateIsMainFileEntered(clang::SourceLocation location, FileChangeReason reason) { - if (location == mainFileSourceLocation && reason == PPCallbacks::EnterFile) - isMainFileEntered = true; + if (location == m_mainFileSourceLocation && reason == PPCallbacks::EnterFile) + m_isMainFileEntered = true; } const clang::SourceManager &sourceManager() const { - return preprocessor.getSourceManager(); + return m_preprocessor.getSourceManager(); } bool isInMainFile(const clang::Token &token) { - return isMainFileEntered && sourceManager().isWrittenInMainFile(token.getLocation()); + return m_isMainFileEntered && sourceManager().isWrittenInMainFile(token.getLocation()); } bool includesCursorPosition(const clang::Token &token) @@ -163,35 +152,36 @@ private: auto start = token.getLocation(); auto end = token.getEndLoc(); - return cursorSourceLocation == start - || cursorSourceLocation == end - || (sourceManager().isBeforeInTranslationUnit(start, cursorSourceLocation) && - sourceManager().isBeforeInTranslationUnit(cursorSourceLocation, end)); + return m_cursorSourceLocation == start + || m_cursorSourceLocation == end + || (sourceManager().isBeforeInTranslationUnit(start, m_cursorSourceLocation) && + sourceManager().isBeforeInTranslationUnit(m_cursorSourceLocation, end)); } bool isCurrentTokenExpansion(const clang::MacroDefinition ¯oDefinition) { - return cursorMacroDirective - && cursorMacroDirective == macroDefinition.getLocalDirective(); + return m_cursorMacroDirective + && m_cursorMacroDirective == macroDefinition.getLocalDirective(); } bool isBeforeCursorSourceLocation() const { - return !cursorMacroDirective; + return !m_cursorMacroDirective; } private: - std::vector sourceLocations; - std::vector preCursorMacroDirectiveTokens; - SourceLocationsContainer &sourceLocationsContainer; - Utils::SmallString &symbolName; - clang::Preprocessor &preprocessor; - const clang::MacroDirective *cursorMacroDirective = nullptr; - clang::SourceLocation mainFileSourceLocation; - clang::SourceLocation cursorSourceLocation; - uint line; - uint column; - bool isMainFileEntered = false; + std::vector m_sourceLocations; + std::vector m_preCursorMacroDirectiveTokens; + SourceLocationsContainer &m_sourceLocationsContainer; + Utils::SmallString &m_symbolName; + clang::Preprocessor &m_preprocessor; + const clang::MacroDirective *m_cursorMacroDirective = nullptr; + clang::SourceLocation m_mainFileSourceLocation; + clang::SourceLocation m_cursorSourceLocation; + FilePathCachingInterface &m_filePathCache; + uint m_line; + uint m_column; + bool m_isMainFileEntered = false; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index 84b588118e6..da16f5bdc4f 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -40,7 +40,7 @@ namespace ClangBackEnd { RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing, - FilePathCache &filePathCache) + FilePathCachingInterface &filePathCache) : m_symbolIndexing(symbolIndexing), m_filePathCache(filePathCache) { @@ -58,7 +58,7 @@ void RefactoringServer::end() void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) { - SymbolFinder symbolFinder(message.line(), message.column()); + SymbolFinder symbolFinder(message.line(), message.column(), m_filePathCache); symbolFinder.addFile(std::string(message.filePath().directory()), std::string(message.filePath().name()), diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h index b11cf3fc215..e0a1f23ce95 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.h +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h @@ -29,12 +29,13 @@ #include -#include #include -#include +#include #include +#include + #include #include #include @@ -54,7 +55,7 @@ class RefactoringServer : public RefactoringServerInterface, using Future = std::future; public: RefactoringServer(SymbolIndexingInterface &symbolIndexing, - FilePathCache &filePathCache); + FilePathCachingInterface &filePathCache); void end() override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; @@ -82,7 +83,7 @@ private: ClangQueryGatherer m_gatherer; QTimer m_pollTimer; SymbolIndexingInterface &m_symbolIndexing; - FilePathCache &m_filePathCache; + FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationentry.h b/src/tools/clangrefactoringbackend/source/sourcelocationentry.h index dbe70123883..1a7d89efcf9 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationentry.h +++ b/src/tools/clangrefactoringbackend/source/sourcelocationentry.h @@ -25,11 +25,10 @@ #pragma once -#include +#include #include #include -#include using uint = unsigned int; @@ -59,18 +58,18 @@ class SourceLocationEntry { public: SourceLocationEntry(SymbolIndex symbolId, - FilePathIndex fileId, + FilePathId filePathId, LineColumn lineColumn, SymbolType symbolType) : symbolId(symbolId), - fileId(fileId), + filePathId(filePathId), line(lineColumn.line), column(lineColumn.column), symbolType(symbolType) {} SymbolIndex symbolId = 0; - FilePathIndex fileId = std::numeric_limits::max(); + FilePathId filePathId; uint line = 0; uint column = 0; SymbolType symbolType; @@ -78,7 +77,7 @@ public: friend bool operator==(const SourceLocationEntry &first, const SourceLocationEntry &second) { return first.symbolId == second.symbolId - && first.fileId == second.fileId + && first.filePathId == second.filePathId && first.line == second.line && first.column == second.column && first.symbolType == second.symbolType; @@ -87,6 +86,4 @@ public: using SourceLocationEntries = std::vector; -std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); - } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h index 82dfcf2b40b..c7d11da5171 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h +++ b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h @@ -25,28 +25,15 @@ #pragma once +#include #include #include -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif - #include #include #include #include -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - #include #include @@ -79,7 +66,8 @@ inline void appendSourceLocationsToSourceLocationsContainer( ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer, const std::vector &sourceLocations, - const clang::SourceManager &sourceManager) + const clang::SourceManager &sourceManager, + FilePathCachingInterface &filePathCache) { sourceLocationsContainer.reserve(sourceLocations.size()); @@ -89,10 +77,9 @@ void appendSourceLocationsToSourceLocationsContainer( const auto fileId = decomposedLoction.first; const auto offset = decomposedLoction.second; const auto fileEntry = sourceManager.getFileEntryForID(fileId); + auto filePath = fromNativePath(absolutePath(fileEntry->getName())); - sourceLocationsContainer.insertFilePath(fileId.getHashValue(), - fromNativePath(absolutePath(fileEntry->getName()))); - sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(), + sourceLocationsContainer.insertSourceLocation(filePathCache.filePathId(filePath), fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingColumnNumber(), offset); diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp index 399a7353f3e..d275cfe4e2f 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp @@ -28,14 +28,7 @@ #include "sourcelocationsutils.h" #include - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif +#include #include #include @@ -43,18 +36,12 @@ #include #include -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - namespace ClangBackEnd { SourceRangeExtractor::SourceRangeExtractor( const clang::SourceManager &sourceManager, const clang::LangOptions &languageOptions, - ClangBackEnd::FilePathCache &filePathCache, + FilePathCachingInterface &filePathCache, SourceRangesContainer &sourceRangesContainer) : sourceManager(sourceManager), languageOptions(languageOptions), @@ -127,16 +114,14 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c return {sourceRange.getBegin(), endLocation}; } -void SourceRangeExtractor::insertSourceRange(uint fileId, - Utils::PathString &&filePath, +void SourceRangeExtractor::insertSourceRange(FilePathId filePathId, const clang::FullSourceLoc &startLocation, uint startOffset, const clang::FullSourceLoc &endLocation, uint endOffset, Utils::SmallString &&lineSnippet) { - sourceRangesContainer.insertFilePath(fileId, std::move(filePath)); - sourceRangesContainer.insertSourceRange(fileId, + sourceRangesContainer.insertSourceRange(filePathId, startLocation.getSpellingLineNumber(), startLocation.getSpellingColumnNumber(), startOffset, @@ -146,7 +131,7 @@ void SourceRangeExtractor::insertSourceRange(uint fileId, std::move(lineSnippet)); } -FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const +FilePathId SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const { auto found = m_fileIdMapping.find(fileId.getHashValue()); if (found != m_fileIdMapping.end()) { @@ -154,7 +139,7 @@ FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang } auto filePath = absolutePath(fileEntry->getName()); - return filePathCache.stringId(fromNativePath(filePath)); + return filePathCache.filePathId(fromNativePath(filePath)); } void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) @@ -176,13 +161,11 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) endOffset); insertSourceRange(findFileId(fileId, fileEntry), - fromNativePath(absolutePath(fileEntry->getName())), startSourceLocation, startOffset, endSourceLocation, endOffset, std::move(lineSnippet)); - } } diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h index 30646429747..85c277265d5 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h @@ -25,9 +25,10 @@ #pragma once -#include +#include #include +#include #include @@ -59,7 +60,7 @@ class SourceRangeExtractor public: SourceRangeExtractor(const clang::SourceManager &sourceManager, const clang::LangOptions &languageOptions, - ClangBackEnd::FilePathCache &filePathCache, + FilePathCachingInterface &filePathCache, SourceRangesContainer &sourceRangesContainer); void addSourceRange(const clang::SourceRange &sourceRange); @@ -74,21 +75,20 @@ public: const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange); private: - void insertSourceRange(uint fileId, - Utils::PathString &&filePath, + void insertSourceRange(FilePathId filePathId, const clang::FullSourceLoc &startLocation, uint startOffset, const clang::FullSourceLoc &endLocation, uint endOffset, Utils::SmallString &&lineSnippet); - FilePathIndex findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; + FilePathId findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; private: - mutable std::unordered_map m_fileIdMapping; + mutable std::unordered_map m_fileIdMapping; const clang::SourceManager &sourceManager; const clang::LangOptions &languageOptions; - ClangBackEnd::FilePathCache &filePathCache; + FilePathCachingInterface &filePathCache; SourceRangesContainer &sourceRangesContainer; }; diff --git a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h index c144c7a9c51..5a103fd233e 100644 --- a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h +++ b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h @@ -25,8 +25,6 @@ #pragma once -#include - #include #include @@ -96,9 +94,6 @@ public: "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 @@ -109,10 +104,6 @@ public: "(SELECT usr FROM symbols WHERE symbols.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 diff --git a/src/tools/clangrefactoringbackend/source/symbolfinder.cpp b/src/tools/clangrefactoringbackend/source/symbolfinder.cpp index 02f727b614c..8f002f10a14 100644 --- a/src/tools/clangrefactoringbackend/source/symbolfinder.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolfinder.cpp @@ -30,9 +30,10 @@ namespace ClangBackEnd { -SymbolFinder::SymbolFinder(uint line, uint column) - : usrFindingAction(line, column), - sourceFileCallbacks(line, column) +SymbolFinder::SymbolFinder(uint line, uint column, FilePathCachingInterface &filePathCache) + : m_usrFindingAction(line, column), + m_symbolLocationFinderAction(filePathCache), + m_sourceFileCallbacks(line, column, filePathCache) { } @@ -40,39 +41,39 @@ void SymbolFinder::findSymbol() { clang::tooling::ClangTool tool = createTool(); - tool.run(clang::tooling::newFrontendActionFactory(&usrFindingAction, &sourceFileCallbacks).get()); + tool.run(clang::tooling::newFrontendActionFactory(&m_usrFindingAction, &m_sourceFileCallbacks).get()); - if (sourceFileCallbacks.hasSourceLocations()) { - sourceLocations_ = sourceFileCallbacks.takeSourceLocations(); - symbolName = sourceFileCallbacks.takeSymbolName(); + if (m_sourceFileCallbacks.hasSourceLocations()) { + m_sourceLocations_ = m_sourceFileCallbacks.takeSourceLocations(); + m_symbolName = m_sourceFileCallbacks.takeSymbolName(); } else { - symbolLocationFinderAction.setUnifiedSymbolResolutions(usrFindingAction.takeUnifiedSymbolResolutions()); + m_symbolLocationFinderAction.setUnifiedSymbolResolutions(m_usrFindingAction.takeUnifiedSymbolResolutions()); - tool.run(clang::tooling::newFrontendActionFactory(&symbolLocationFinderAction).get()); + tool.run(clang::tooling::newFrontendActionFactory(&m_symbolLocationFinderAction).get()); - sourceLocations_ = symbolLocationFinderAction.takeSourceLocations(); - symbolName = usrFindingAction.takeSymbolName(); + m_sourceLocations_ = m_symbolLocationFinderAction.takeSourceLocations(); + m_symbolName = m_usrFindingAction.takeSymbolName(); } } Utils::SmallString SymbolFinder::takeSymbolName() { - return std::move(symbolName); + return std::move(m_symbolName); } const std::vector &SymbolFinder::unifiedSymbolResolutions() { - return symbolLocationFinderAction.unifiedSymbolResolutions(); + return m_symbolLocationFinderAction.unifiedSymbolResolutions(); } const SourceLocationsContainer &SymbolFinder::sourceLocations() const { - return sourceLocations_; + return m_sourceLocations_; } SourceLocationsContainer SymbolFinder::takeSourceLocations() { - return std::move(sourceLocations_); + return std::move(m_sourceLocations_); } } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolfinder.h b/src/tools/clangrefactoringbackend/source/symbolfinder.h index a76639aa26a..a3c96590320 100644 --- a/src/tools/clangrefactoringbackend/source/symbolfinder.h +++ b/src/tools/clangrefactoringbackend/source/symbolfinder.h @@ -30,6 +30,7 @@ #include "symbollocationfinderaction.h" #include "locationsourcefilecallbacks.h" +#include #include namespace ClangBackEnd { @@ -37,7 +38,7 @@ namespace ClangBackEnd { class SymbolFinder : public ClangTool { public: - SymbolFinder(uint line, uint column); + SymbolFinder(uint line, uint column, FilePathCachingInterface &filePathCache); void findSymbol(); @@ -47,12 +48,11 @@ public: SourceLocationsContainer takeSourceLocations(); private: - Utils::SmallString symbolName; - USRFindingAction usrFindingAction; - SymbolLocationFinderAction symbolLocationFinderAction; - LocationSourceFileCallbacks sourceFileCallbacks; - - ClangBackEnd::SourceLocationsContainer sourceLocations_; + Utils::SmallString m_symbolName; + USRFindingAction m_usrFindingAction; + SymbolLocationFinderAction m_symbolLocationFinderAction; + LocationSourceFileCallbacks m_sourceFileCallbacks; + ClangBackEnd::SourceLocationsContainer m_sourceLocations_; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h index 4dd173e1bfb..24957eb7bf8 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexing.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h @@ -33,7 +33,7 @@ #include "symbolstorage.h" #include -#include +#include #include #include @@ -48,13 +48,11 @@ public: Sqlite::ReadStatement, Sqlite::WriteStatement>; using Storage = ClangBackEnd::SymbolStorage; - using DatabaseInitializer = RefactoringDatabaseInitializer; - SymbolIndexing(FilePathCache &filePathCache, - Utils::PathString &&databaseFilePath) + SymbolIndexing(Sqlite::Database &database, + FilePathCachingInterface &filePathCache) : m_filePathCache(filePathCache), - m_database(std::move(databaseFilePath)), - m_databaseInitializer(m_database) + m_statementFactory(database) { } @@ -63,11 +61,6 @@ public: return m_indexer; } - Sqlite::Database &database() - { - return m_database; - } - void updateProjectParts(V2::ProjectPartContainers &&projectParts, V2::FileContainers &&generatedFiles) { @@ -75,11 +68,9 @@ public: } private: - FilePathCache &m_filePathCache; - Sqlite::Database m_database; - DatabaseInitializer m_databaseInitializer; + FilePathCachingInterface &m_filePathCache; SymbolsCollector m_collector{m_filePathCache}; - StatementFactory m_statementFactory{m_database}; + StatementFactory m_statementFactory; Storage m_symbolStorage{m_statementFactory, m_filePathCache}; SymbolIndexer m_indexer{m_collector, m_symbolStorage}; }; diff --git a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp index 2b07e893f58..f8782b405b6 100644 --- a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp +++ b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp @@ -28,6 +28,8 @@ #include "sourcelocationsutils.h" #include "findlocationsofusrs.h" +#include + #include #include @@ -38,8 +40,10 @@ namespace ClangBackEnd { class FindingSymbolsASTConsumer : public clang::ASTConsumer { public: - FindingSymbolsASTConsumer(std::vector &unifiedSymbolResolutions) - : m_unifiedSymbolResolutions(unifiedSymbolResolutions) + FindingSymbolsASTConsumer(std::vector &unifiedSymbolResolutions, + FilePathCachingInterface &filePathCache) + : m_unifiedSymbolResolutions(unifiedSymbolResolutions), + m_filePathCache(filePathCache) { } @@ -65,7 +69,10 @@ public: void updateSourceLocations(const std::vector &sourceLocations, const clang::SourceManager &sourceManager) { - appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer, sourceLocations, sourceManager); + appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer, + sourceLocations, + sourceManager, + m_filePathCache); } void setSourceLocations(ClangBackEnd::SourceLocationsContainer *sourceLocations) @@ -76,11 +83,13 @@ public: private: ClangBackEnd::SourceLocationsContainer *m_sourceLocationsContainer = nullptr; std::vector &m_unifiedSymbolResolutions; + FilePathCachingInterface &m_filePathCache; }; std::unique_ptr SymbolLocationFinderAction::newASTConsumer() { - auto consumer = std::unique_ptr(new FindingSymbolsASTConsumer(m_unifiedSymbolResolutions_)); + auto consumer = std::make_unique(m_unifiedSymbolResolutions_, + m_filePathCache); consumer->setSourceLocations(&m_sourceLocations); diff --git a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h index ae601d8219e..e3f4c4a2f39 100644 --- a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h +++ b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h @@ -27,6 +27,7 @@ #include "clangrefactoringbackend_global.h" +#include #include #include @@ -40,27 +41,31 @@ namespace ClangBackEnd { class SymbolLocationFinderAction { public: + SymbolLocationFinderAction(FilePathCachingInterface &filePathCache) + : m_filePathCache(filePathCache) + {} - std::unique_ptr newASTConsumer(); + std::unique_ptr newASTConsumer(); - SourceLocationsContainer takeSourceLocations() - { - return std::move(m_sourceLocations); - } + SourceLocationsContainer takeSourceLocations() + { + return std::move(m_sourceLocations); + } - void setUnifiedSymbolResolutions(std::vector &&unifiedSymbolResolutions) - { - m_unifiedSymbolResolutions_ = std::move(unifiedSymbolResolutions); - } + void setUnifiedSymbolResolutions(std::vector &&unifiedSymbolResolutions) + { + m_unifiedSymbolResolutions_ = std::move(unifiedSymbolResolutions); + } - const std::vector &unifiedSymbolResolutions() const - { - return m_unifiedSymbolResolutions_; - } + const std::vector &unifiedSymbolResolutions() const + { + return m_unifiedSymbolResolutions_; + } private: - ClangBackEnd::SourceLocationsContainer m_sourceLocations; - std::vector m_unifiedSymbolResolutions_; + ClangBackEnd::SourceLocationsContainer m_sourceLocations; + std::vector m_unifiedSymbolResolutions_; + FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp index c759232a04b..a6e8b217275 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp @@ -27,7 +27,7 @@ namespace ClangBackEnd { -SymbolsCollector::SymbolsCollector(FilePathCache &filePathCache) +SymbolsCollector::SymbolsCollector(FilePathCachingInterface &filePathCache) : m_collectSymbolsAction(filePathCache) { } diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.h b/src/tools/clangrefactoringbackend/source/symbolscollector.h index 6bbdfbcf9e5..279de0dadbe 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.h @@ -30,14 +30,15 @@ #include "collectsymbolsaction.h" #include "symbolscollectorinterface.h" #include "symbolentry.h" -#include "stringcache.h" + +#include namespace ClangBackEnd { class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface { public: - SymbolsCollector(FilePathCache &filePathCache); + SymbolsCollector(FilePathCachingInterface &filePathCache); void addFiles(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments) override; diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h index 835f7dec923..b1fdb75d11a 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorage.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h @@ -29,9 +29,7 @@ #include #include -#include - -#include +#include namespace ClangBackEnd { @@ -45,7 +43,7 @@ class SymbolStorage : public SymbolStorageInterface public: SymbolStorage(StatementFactory &statementFactory, - FilePathCache &filePathCache) + FilePathCachingInterface &filePathCache) : m_statementFactory(statementFactory), m_filePathCache(filePathCache) { @@ -61,7 +59,6 @@ public: addNewSymbolsToSymbols(); syncNewSymbolsFromSymbols(); syncSymbolsIntoNewLocations(); - insertNewSources(); deleteAllLocationsFromUpdatedFiles(); insertNewLocationsInLocations(); deleteNewSymbolsTable(); @@ -89,7 +86,7 @@ public: statement.write(locationsEntry.symbolId, locationsEntry.line, locationsEntry.column, - locationsEntry.fileId); + locationsEntry.filePathId.fileNameId); } } @@ -118,23 +115,6 @@ public: m_statementFactory.insertNewLocationsInLocationsStatement.execute(); } - FilePathIndices selectNewSourceIds() const - { - ReadStatement &statement = m_statementFactory.selectNewSourceIdsStatement; - - return statement.template values(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(); @@ -152,7 +132,7 @@ public: private: StatementFactory &m_statementFactory; - FilePathCache &m_filePathCache; + FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/tests/unit/unittest/clangdocumentprocessor-test.cpp b/tests/unit/unittest/clangdocumentprocessor-test.cpp index 2e3dd99e2f0..7b9b73891d7 100644 --- a/tests/unit/unittest/clangdocumentprocessor-test.cpp +++ b/tests/unit/unittest/clangdocumentprocessor-test.cpp @@ -23,6 +23,8 @@ ** ****************************************************************************/ +#include "googletest.h" + #include "clangiasyncjob.h" #include "dummyclangipcclient.h" #include "processevents-utilities.h" @@ -35,11 +37,6 @@ #include #include -#include -#include -#include -#include "gtest-qt-printing.h" - using namespace ClangBackEnd; namespace { diff --git a/tests/unit/unittest/clangdocumentprocessors-test.cpp b/tests/unit/unittest/clangdocumentprocessors-test.cpp index 10eba470c6b..87990bca114 100644 --- a/tests/unit/unittest/clangdocumentprocessors-test.cpp +++ b/tests/unit/unittest/clangdocumentprocessors-test.cpp @@ -23,6 +23,8 @@ ** ****************************************************************************/ +#include "googletest.h" + #include "clangiasyncjob.h" #include "dummyclangipcclient.h" #include "processevents-utilities.h" @@ -37,11 +39,6 @@ #include #include -#include -#include -#include -#include "gtest-qt-printing.h" - using testing::Eq; using namespace ClangBackEnd; diff --git a/tests/unit/unittest/clangpathwatcher-test.cpp b/tests/unit/unittest/clangpathwatcher-test.cpp index 4bbadca3a3c..960030ca99c 100644 --- a/tests/unit/unittest/clangpathwatcher-test.cpp +++ b/tests/unit/unittest/clangpathwatcher-test.cpp @@ -26,11 +26,13 @@ #include "googletest.h" #include "faketimer.h" +#include "mockfilepathcaching.h" #include "mockqfilesystemwatcher.h" #include "mockclangpathwatchernotifier.h" #include -#include + +#include namespace { @@ -42,34 +44,41 @@ using testing::NiceMock; using Watcher = ClangBackEnd::ClangPathWatcher, FakeTimer>; using ClangBackEnd::WatcherEntry; -using ClangBackEnd::FilePathIndices; +using ClangBackEnd::FilePath; +using ClangBackEnd::FilePathId; +using ClangBackEnd::FilePathIds; class ClangPathWatcher : public testing::Test { protected: - ClangBackEnd::FilePathCache<> pathCache; + void SetUp(); + +protected: + NiceMock filePathCache; NiceMock notifier; - Watcher watcher{pathCache, ¬ifier}; + Watcher watcher{filePathCache, ¬ifier}; NiceMock &mockQFileSytemWatcher = watcher.fileSystemWatcher(); Utils::SmallString id1{"id4"}; Utils::SmallString id2{"id2"}; Utils::SmallString id3{"id3"}; - Utils::PathString path1{"/path/path1"}; - Utils::PathString path2{"/path/path2"}; - 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]}; - WatcherEntry watcherEntry4{ids[1], paths[1]}; - WatcherEntry watcherEntry5{ids[2], paths[1]}; + FilePath path1{Utils::PathString{"/path/path1"}}; + FilePath path2{Utils::PathString{"/path/path2"}}; + QString path1QString = QString(path1.path()); + QString path2QString = QString(path2.path()); + FilePathIds pathIds = {{1, 1}, {1, 2}}; + std::vector ids{watcher.idCache().stringIds({id1, id2, id3})}; + WatcherEntry watcherEntry1{ids[0], pathIds[0]}; + WatcherEntry watcherEntry2{ids[1], pathIds[0]}; + WatcherEntry watcherEntry3{ids[0], pathIds[1]}; + WatcherEntry watcherEntry4{ids[1], pathIds[1]}; + WatcherEntry watcherEntry5{ids[2], pathIds[1]}; }; TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList) { auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3}); - ASSERT_THAT(convertedList, ElementsAre(QString(path1), QString(path2))); + ASSERT_THAT(convertedList, ElementsAre(path1QString, path2QString)); } TEST_F(ClangPathWatcher, UniquePaths) @@ -90,51 +99,51 @@ TEST_F(ClangPathWatcher, NotWatchedEntries) TEST_F(ClangPathWatcher, AddIdPaths) { - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)})); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString})); - watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher) { - watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[0]}}}); - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path2)})); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path2QString})); - watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileWatcher) { - watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString})); - watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[0]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathInFileWatcher) { - watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)})) + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString})) .Times(0); - watcher.updateIdPaths({{id1, {paths[1]}}, {id2, {paths[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[1]}}, {id2, {pathIds[0]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPaths) { - watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[1]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}}); - watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[1]}}}); + watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[1]}}}); ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5)); } TEST_F(ClangPathWatcher, ExtractSortedEntriesFromConvertIdPaths) { - auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {paths[0], paths[1]}}, {id1, {paths[0], paths[1]}}}); + auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {pathIds[0], pathIds[1]}}, {id1, {pathIds[0], pathIds[1]}}}); ASSERT_THAT(entriesAndIds.first, ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4)); } @@ -190,14 +199,14 @@ TEST_F(ClangPathWatcher, AddEmptyEntries) TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths) { - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)})); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString})); watcher.addEntries({watcherEntry1, watcherEntry3}); } TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths) { - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)})); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString})); watcher.addEntries({watcherEntry1, watcherEntry2}); } @@ -206,7 +215,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths) { watcher.addEntries({watcherEntry1}); - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)})) + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString})) .Times(0); watcher.addEntries({watcherEntry1}); @@ -216,7 +225,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths) { watcher.addEntries({watcherEntry1}); - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)})) + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString})) .Times(0); watcher.addEntries({watcherEntry2}); @@ -253,7 +262,7 @@ TEST_F(ClangPathWatcher, RemovePathForOneId) { watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString})); watcher.removeIds({id1}); } @@ -262,7 +271,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId) { watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1), QString(path2)})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString, path2QString})); watcher.removeIds({id1, id2, id3}); } @@ -271,7 +280,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId) { watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1)})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString})); watcher.removeIds({id1, id2}); } @@ -298,9 +307,9 @@ TEST_F(ClangPathWatcher, EmptyVectorNotifyFileChange) { watcher.addEntries({watcherEntry3}); - EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty())).Times(1); + EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty())); - mockQFileSytemWatcher.fileChanged(path1.toQString()); + mockQFileSytemWatcher.fileChanged(path1QString); } TEST_F(ClangPathWatcher, NotifyFileChange) @@ -309,7 +318,7 @@ TEST_F(ClangPathWatcher, NotifyFileChange) EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1))); - mockQFileSytemWatcher.fileChanged(path1.toQString()); + mockQFileSytemWatcher.fileChanged(path1QString); } TEST_F(ClangPathWatcher, TwoNotifyFileChanges) @@ -318,8 +327,19 @@ TEST_F(ClangPathWatcher, TwoNotifyFileChanges) EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id3, id1))); - mockQFileSytemWatcher.fileChanged(path2.toQString()); - mockQFileSytemWatcher.fileChanged(path1.toQString()); + mockQFileSytemWatcher.fileChanged(path2QString); + mockQFileSytemWatcher.fileChanged(path1QString); } +void ClangPathWatcher::SetUp() +{ + ON_CALL(filePathCache, filePathId(Eq(path1))) + .WillByDefault(Return(pathIds[0])); + ON_CALL(filePathCache, filePathId(Eq(path2))) + .WillByDefault(Return(pathIds[1])); + ON_CALL(filePathCache, filePath(pathIds[0])) + .WillByDefault(Return(path1)); + ON_CALL(filePathCache, filePath(Eq(pathIds[1]))) + .WillByDefault(Return(path2)); +} } diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp index 792c234570a..1723339809c 100644 --- a/tests/unit/unittest/clangquery-test.cpp +++ b/tests/unit/unittest/clangquery-test.cpp @@ -29,11 +29,19 @@ #include "filesystem-utilities.h" #include +#include + +#include + +#include + +#include #include using ClangBackEnd::ClangQuery; -using ClangBackEnd::FilePathCache; +using ClangBackEnd::FilePathCaching; +using ClangBackEnd::RefactoringDatabaseInitializer; using testing::AllOf; using testing::Contains; @@ -48,7 +56,9 @@ protected: void SetUp() override; protected: - FilePathCache filePathCache; + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + RefactoringDatabaseInitializer initializer{database}; + FilePathCaching filePathCache{database}; ::ClangQuery simpleFunctionQuery{filePathCache}; ::ClangQuery simpleClassQuery{filePathCache}; }; diff --git a/tests/unit/unittest/clangqueryexamplehighlightmarker-test.cpp b/tests/unit/unittest/clangqueryexamplehighlightmarker-test.cpp index 8af631774fe..7d65e40025a 100644 --- a/tests/unit/unittest/clangqueryexamplehighlightmarker-test.cpp +++ b/tests/unit/unittest/clangqueryexamplehighlightmarker-test.cpp @@ -66,7 +66,7 @@ TEST_F(ClangQueryExampleHighlightMarker, NoCallForNotSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, SingleLineSourceRange) { - SourceRanges sourceRanges{{1, 1, 3, 3, 1, 10, 10, "function"}}; + SourceRanges sourceRanges{{{1, 1}, 1, 3, 3, 1, 10, 10, "function"}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0])); @@ -76,7 +76,7 @@ TEST_F(ClangQueryExampleHighlightMarker, SingleLineSourceRange) TEST_F(ClangQueryExampleHighlightMarker, OtherSingleLineSourceRange) { - SourceRanges sourceRanges{{1, 2, 5, 5, 2, 11, 11, "function"}}; + SourceRanges sourceRanges{{{1, 1}, 2, 5, 5, 2, 11, 11, "function"}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); marker.highlightBlock(1, "foo"); @@ -88,9 +88,9 @@ TEST_F(ClangQueryExampleHighlightMarker, OtherSingleLineSourceRange) TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges) { InSequence sequence; - SourceRanges sourceRanges{{1, 1, 2, 2, 1, 15, 15, "void function"}, - {1, 1, 2, 2, 1, 6, 6, "void"}, - {1, 1, 7, 7, 1, 15, 15, "function"}}; + SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 1, 15, 15, "void function"}, + {{1, 1}, 1, 2, 2, 1, 6, 6, "void"}, + {{1, 1}, 1, 7, 7, 1, 15, 15, "function"}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); EXPECT_CALL(highlighter, setFormat(1, 13, textFormats[0])); @@ -103,7 +103,7 @@ TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges) { InSequence sequence; - SourceRanges sourceRanges{{1, 1, 2, 2, 2, 4, 20, "void f()\n {}"}}; + SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 2, 4, 20, "void f()\n {}"}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0])); @@ -116,7 +116,7 @@ TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges) { InSequence sequence; - SourceRanges sourceRanges{{1, 1, 2, 2, 3, 3, 20, "void f()\n {\n }"}}; + SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 3, 3, 20, "void f()\n {\n }"}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0])); @@ -131,9 +131,9 @@ TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges) { InSequence sequence; - SourceRanges sourceRanges{{1, 1, 1, 0, 4, 2, 0, ""}, - {1, 2, 2, 0, 2, 7, 0, ""}, - {1, 3, 2, 0, 3, 7, 0, ""}}; + SourceRanges sourceRanges{{{1, 1}, 1, 1, 0, 4, 2, 0, ""}, + {{1, 1}, 2, 2, 0, 2, 7, 0, ""}, + {{1, 1}, 3, 2, 0, 3, 7, 0, ""}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[0])); @@ -152,9 +152,9 @@ TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges) { InSequence sequence; - SourceRanges sourceRanges{{1, 1, 1, 0, 4, 2, 0, ""}, - {1, 2, 2, 0, 3, 4, 0, ""}, - {1, 2, 11, 0, 2, 16, 0, ""}}; + SourceRanges sourceRanges{{{1, 1}, 1, 1, 0, 4, 2, 0, ""}, + {{1, 1}, 2, 2, 0, 3, 4, 0, ""}, + {{1, 1}, 2, 11, 0, 2, 16, 0, ""}}; Marker marker(std::move(sourceRanges), highlighter, textFormats); EXPECT_CALL(highlighter, setFormat(0, 9, textFormats[0])); @@ -173,7 +173,7 @@ TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, FormatSingle) { - SourceRange sourceRange{1, 1, 3, 3, 1, 10, 10}; + SourceRange sourceRange{{1, 1}, 1, 3, 3, 1, 10, 10}; EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0])); @@ -182,7 +182,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatSingle) TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleStart) { - SourceRange sourceRange{1, 1, 3, 3, 2, 9, 20}; + SourceRange sourceRange{{1, 1}, 1, 3, 3, 2, 9, 20}; EXPECT_CALL(highlighter, setFormat(2, 8, textFormats[0])); @@ -191,7 +191,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleStart) TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleEnd) { - SourceRange sourceRange{1, 1, 3, 3, 2, 8, 20}; + SourceRange sourceRange{{1, 1}, 1, 3, 3, 2, 8, 20}; EXPECT_CALL(highlighter, setFormat(0, 7, textFormats[1])); @@ -200,7 +200,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleEnd) TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleMiddle) { - SourceRange sourceRange{1, 1, 3, 3, 3, 8, 20}; + SourceRange sourceRange{{1, 1}, 1, 3, 3, 3, 8, 20}; EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[2])); diff --git a/tests/unit/unittest/clangquerygatherer-test.cpp b/tests/unit/unittest/clangquerygatherer-test.cpp index a9a191383c1..9a2122f9500 100644 --- a/tests/unit/unittest/clangquerygatherer-test.cpp +++ b/tests/unit/unittest/clangquerygatherer-test.cpp @@ -30,9 +30,15 @@ #include "sourcerangecontainer-matcher.h" #include +#include +#include + +#include #include +#include + namespace { using testing::AllOf; @@ -75,7 +81,9 @@ protected: void SetUp() override; protected: - ClangBackEnd::FilePathCache filePathCache; + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), diff --git a/tests/unit/unittest/clangqueryhighlightmarker-test.cpp b/tests/unit/unittest/clangqueryhighlightmarker-test.cpp index 05e657b9eaa..11efd1d519f 100644 --- a/tests/unit/unittest/clangqueryhighlightmarker-test.cpp +++ b/tests/unit/unittest/clangqueryhighlightmarker-test.cpp @@ -74,10 +74,10 @@ TEST_F(ClangQueryHighlightMarker, NoCallForNoMessagesAndContexts) TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine) { InSequence sequence; - Messages messages{{{1, 1, 5, 0, 1, 10, 0}, ErrorType::RegistryMatcherNotFound, {}}, - {{1, 1, 30, 0, 1, 40, 0}, ErrorType::RegistryMatcherNotFound, {}}}; - Contexts contexts{{{1, 1, 2, 0, 1, 15, 0}, ContextType::MatcherArg, {}}, - {{1, 1, 20, 0, 1, 50, 0}, ContextType::MatcherArg, {}}}; + Messages messages{{{{0, 1}, 1, 5, 0, 1, 10, 0}, ErrorType::RegistryMatcherNotFound, {}}, + {{{0, 1}, 1, 30, 0, 1, 40, 0}, ErrorType::RegistryMatcherNotFound, {}}}; + Contexts contexts{{{{0, 1}, 1, 2, 0, 1, 15, 0}, ContextType::MatcherArg, {}}, + {{{0, 1}, 1, 20, 0, 1, 50, 0}, ContextType::MatcherArg, {}}}; marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); EXPECT_CALL(highlighter, setFormat(1, 13, contextTextFormat)); @@ -91,7 +91,7 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine) TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine) { InSequence sequence; - Messages messages{{{1, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}}; + Messages messages{{{{0, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}}; Contexts contexts; marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); @@ -107,8 +107,8 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine) TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextForAMultiLine) { InSequence sequence; - Messages messages{{{1, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}}; - Contexts contexts{{{1, 1, 2, 0, 3, 4, 0}, ContextType::MatcherArg, {}}}; + Messages messages{{{{1, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}}; + Contexts contexts{{{{1, 1}, 1, 2, 0, 3, 4, 0}, ContextType::MatcherArg, {}}}; marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); EXPECT_CALL(highlighter, setFormat(1, 11, contextTextFormat)); @@ -136,7 +136,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesIfEmpty) TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition) { - Messages messages{{{1, 1, 5, 0, 3, 3, 0}, + Messages messages{{{{0, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {"foo"}}}; Contexts contexts; @@ -149,7 +149,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition) TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition) { - Messages messages{{{1, 1, 5, 0, 3, 3, 0}, + Messages messages{{{{0, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {"foo"}}}; Contexts contexts; @@ -162,7 +162,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition) TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition) { - Message message{{1, 1, 5, 0, 3, 3, 0}, + Message message{{{0, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {"foo"}}; Messages messages{message.clone()}; @@ -176,7 +176,7 @@ TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition) TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition) { - Message message{{1, 1, 5, 0, 3, 3, 0}, + Message message{{{0, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {"foo"}}; Messages messages{message.clone()}; @@ -190,7 +190,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition) TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isAfterStartColumn = marker.isInsideRange(sourceRange, 1, 6); @@ -199,7 +199,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine) TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 4); @@ -208,7 +208,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn) TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 5); @@ -217,7 +217,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn) TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 6); @@ -226,7 +226,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 4, 1); @@ -235,7 +235,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 4); @@ -244,7 +244,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 3); @@ -253,7 +253,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 2); @@ -262,7 +262,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn) TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine) { - SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0}; bool isInBetween = marker.isInsideRange(sourceRange, 1, 6); @@ -271,7 +271,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine) TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine) { - SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 4, 3, 0}; bool isInBetween = marker.isInsideRange(sourceRange, 5, 1); @@ -280,7 +280,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine) TEST_F(ClangQueryHighlightMarker, InBetweenLine) { - SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 4, 3, 0}; bool isInBetween = marker.isInsideRange(sourceRange, 3, 1); @@ -289,7 +289,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLine) TEST_F(ClangQueryHighlightMarker, SingleLineBefore) { - SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 2, 10, 0}; bool isInRange = marker.isInsideRange(sourceRange, 2, 4); @@ -298,7 +298,7 @@ TEST_F(ClangQueryHighlightMarker, SingleLineBefore) TEST_F(ClangQueryHighlightMarker, SingleLineAfter) { - SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 2, 10, 0}; bool isInRange = marker.isInsideRange(sourceRange, 2, 11); @@ -307,7 +307,7 @@ TEST_F(ClangQueryHighlightMarker, SingleLineAfter) TEST_F(ClangQueryHighlightMarker, SingleLineInRange) { - SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; + SourceRange sourceRange{{0, 1}, 2, 5, 0, 2, 10, 0}; bool isInRange = marker.isInsideRange(sourceRange, 2, 6); @@ -328,7 +328,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsIfEmpty) TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition) { Messages messages; - Contexts contexts{{{1, 1, 5, 0, 3, 3, 0}, + Contexts contexts{{{{0, 1}, 1, 5, 0, 3, 3, 0}, ContextType::MatcherArg, {"foo"}}}; marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); @@ -341,7 +341,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition) TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition) { Messages messages; - Contexts contexts{{{1, 1, 5, 0, 3, 3, 0}, + Contexts contexts{{{{0, 1}, 1, 5, 0, 3, 3, 0}, ContextType::MatcherArg, {"foo"}}}; marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); @@ -353,7 +353,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition) TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition) { - Context context{{1, 1, 5, 0, 3, 3, 0}, + Context context{{{0, 1}, 1, 5, 0, 3, 3, 0}, ContextType::MatcherArg, {"foo"}}; Messages messages; @@ -367,7 +367,7 @@ TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition) TEST_F(ClangQueryHighlightMarker, NoContextsForOutsidePosition) { - Context context{{1, 1, 5, 0, 3, 3, 0}, + Context context{{{0, 1}, 1, 5, 0, 3, 3, 0}, ContextType::MatcherArg, {"foo"}}; Messages messages; diff --git a/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp b/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp index 7afb3fa54e5..cb6610921a2 100644 --- a/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp +++ b/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp @@ -23,6 +23,8 @@ ** ****************************************************************************/ +#include "googletest.h" + #include "dummyclangipcclient.h" #include "processevents-utilities.h" @@ -39,11 +41,6 @@ #include -#include -#include -#include -#include "gtest-qt-printing.h" - using namespace ClangBackEnd; using testing::Eq; diff --git a/tests/unit/unittest/clangtranslationunit-test.cpp b/tests/unit/unittest/clangtranslationunit-test.cpp index 3e10138c8b9..2cb936c9997 100644 --- a/tests/unit/unittest/clangtranslationunit-test.cpp +++ b/tests/unit/unittest/clangtranslationunit-test.cpp @@ -23,6 +23,8 @@ ** ****************************************************************************/ +#include "googletest.h" + #include #include #include @@ -30,11 +32,6 @@ #include -#include -#include -#include -#include "gtest-qt-printing.h" - using ClangBackEnd::DiagnosticContainer; using ClangBackEnd::TranslationUnit; using ClangBackEnd::TranslationUnitUpdateInput; diff --git a/tests/unit/unittest/clangtranslationunits-test.cpp b/tests/unit/unittest/clangtranslationunits-test.cpp index d89f3ba83e0..acdf5704819 100644 --- a/tests/unit/unittest/clangtranslationunits-test.cpp +++ b/tests/unit/unittest/clangtranslationunits-test.cpp @@ -23,6 +23,8 @@ ** ****************************************************************************/ +#include "googletest.h" + #include #include #include @@ -31,11 +33,6 @@ #include -#include -#include -#include -#include "gtest-qt-printing.h" - using ClangBackEnd::Clock; using ClangBackEnd::TranslationUnit; using ClangBackEnd::TranslationUnits; diff --git a/tests/unit/unittest/filepathcache-test.cpp b/tests/unit/unittest/filepathcache-test.cpp new file mode 100644 index 00000000000..9fe73faa639 --- /dev/null +++ b/tests/unit/unittest/filepathcache-test.cpp @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** 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 "mockfilepathstorage.h" + +#include + +namespace { + +using ClangBackEnd::FilePathId; +using FPCB = ClangBackEnd::FilePathCacheBase; +using Cache = ClangBackEnd::FilePathCache>; +using ClangBackEnd::FilePathId; + +class FilePathCache : public testing::Test +{ +protected: + void SetUp(); + +protected: + NiceMock mockStorage; + Cache cache{mockStorage}; +}; + +TEST_F(FilePathCache, FilePathSlashForEmptyPath) +{ + auto slashIndex = FPCB::lastSlashIndex(""); + + ASSERT_THAT(slashIndex, -1); +} + +TEST_F(FilePathCache, FilePathSlashForSingleSlash) +{ + auto slashIndex = FPCB::lastSlashIndex("/"); + + ASSERT_THAT(slashIndex, 0); +} + +TEST_F(FilePathCache, FilePathSlashForFileInRoot) +{ + auto slashIndex = FPCB::lastSlashIndex("/file.h"); + + ASSERT_THAT(slashIndex, 0); +} + +TEST_F(FilePathCache, FilePathSlashForSomeLongerPath) +{ + auto slashIndex = FPCB::lastSlashIndex("/path/to/some/file.h"); + + ASSERT_THAT(slashIndex, 13); +} + +TEST_F(FilePathCache, FilePathSlashForFileNameOnly) +{ + auto slashIndex = FPCB::lastSlashIndex("file.h"); + + ASSERT_THAT(slashIndex, -1); +} + +TEST_F(FilePathCache, DirectoryPathForEmptyPath) +{ + auto slashIndex = FPCB::lastSlashIndex(""); + + auto directoryPath = FPCB::directoryPath("", slashIndex); + + ASSERT_THAT(directoryPath, ""); +} + +TEST_F(FilePathCache, DirectoryPathForSingleSlashPath) +{ + Utils::SmallStringView singleSlashPath{"/"}; + auto slashIndex = FPCB::lastSlashIndex(singleSlashPath); + + auto directoryPath = FPCB::directoryPath(singleSlashPath, slashIndex); + + ASSERT_THAT(directoryPath, ""); +} + +TEST_F(FilePathCache, DirectoryPathForLongerPath) +{ + Utils::SmallStringView longerPath{"/path/to/some/file.h"}; + auto slashIndex = FPCB::lastSlashIndex(longerPath); + + auto directoryPath = FPCB::directoryPath(longerPath, slashIndex); + + ASSERT_THAT(directoryPath, "/path/to/some"); +} + +TEST_F(FilePathCache, DirectoryPathForFileNameOnly) +{ + Utils::SmallStringView longerPath{"file.h"}; + auto slashIndex = FPCB::lastSlashIndex(longerPath); + + auto directoryPath = FPCB::directoryPath(longerPath, slashIndex); + + ASSERT_THAT(directoryPath, IsEmpty()); +} + +TEST_F(FilePathCache, FileNameForEmptyPath) +{ + auto slashIndex = FPCB::lastSlashIndex(""); + + auto fileName = FPCB::fileName("", slashIndex); + + ASSERT_THAT(fileName, ""); +} + +TEST_F(FilePathCache, FileNameForSingleSlashPath) +{ + Utils::SmallStringView singleSlashPath{"/"}; + auto slashIndex = FPCB::lastSlashIndex(singleSlashPath); + + auto fileName = FPCB::fileName(singleSlashPath, slashIndex); + + ASSERT_THAT(fileName, ""); +} + +TEST_F(FilePathCache, FileNameForLongerPath) +{ + Utils::SmallStringView longerPath{"/path/to/some/file.h"}; + auto slashIndex = FPCB::lastSlashIndex(longerPath); + + auto fileName = FPCB::fileName(longerPath, slashIndex); + + ASSERT_THAT(fileName, "file.h"); +} + +TEST_F(FilePathCache, FileNameForFileNameOnly) +{ + Utils::SmallStringView longerPath{"file.h"}; + auto slashIndex = FPCB::lastSlashIndex(longerPath); + + auto fileName = FPCB::fileName(longerPath, slashIndex); + + ASSERT_THAT(fileName, "file.h"); +} + +TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId) +{ + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))); + + cache.filePathId("/path/to/file.cpp"); +} + +TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCalls) +{ + EXPECT_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp"))); + + cache.filePathId("/path/to/file.cpp"); +} + +TEST_F(FilePathCache, DirectoryIdOfFilePathIdWithOutAnyEntry) +{ + auto filePathId = cache.filePathId("/path/to/file.cpp"); + + ASSERT_THAT(filePathId.directoryId, 5); +} + +TEST_F(FilePathCache, FileNameIdOfFilePathIdWithOutAnyEntry) +{ + auto filePathId = cache.filePathId("/path/to/file.cpp"); + + ASSERT_THAT(filePathId.fileNameId, 42); +} + +TEST_F(FilePathCache, IfEntryExistsDontCallInStrorage) +{ + cache.filePathId("/path/to/file.cpp"); + + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))).Times(0); + EXPECT_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp"))).Times(0); + + cache.filePathId("/path/to/file.cpp"); +} + +TEST_F(FilePathCache, IfDirectoryEntryExistsDontCallFetchDirectoryIdButStillCallFetchSourceId) +{ + cache.filePathId("/path/to/file2.cpp"); + + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))).Times(0); + EXPECT_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp"))); + + cache.filePathId("/path/to/file.cpp"); +} + +TEST_F(FilePathCache, GetFileNameIdWithCachedValue) +{ + cache.filePathId("/path/to/file.cpp"); + + auto filePathId = cache.filePathId("/path/to/file.cpp"); + + ASSERT_THAT(filePathId.fileNameId, 42); +} + +TEST_F(FilePathCache, GetFileNameIdWithDirectoryIdCached) +{ + cache.filePathId("/path/to/file.cpp"); + + auto filePathId = cache.filePathId("/path/to/file2.cpp"); + + ASSERT_THAT(filePathId.fileNameId, 63); +} + +TEST_F(FilePathCache, GetDirectyIdWithCachedValue) +{ + cache.filePathId("/path/to/file.cpp"); + + auto filePathId = cache.filePathId("/path/to/file2.cpp"); + + ASSERT_THAT(filePathId.directoryId, 5); +} + +TEST_F(FilePathCache, GetDirectyIdWithDirectoryIdCached) +{ + cache.filePathId("/path/to/file.cpp"); + + auto filePathId = cache.filePathId("/path/to/file2.cpp"); + + ASSERT_THAT(filePathId.directoryId, 5); +} + +TEST_F(FilePathCache, ThrowForGettingAFilePathWithAnInvalidId) +{ + FilePathId filePathId; + + ASSERT_THROW(cache.filePath(filePathId), ClangBackEnd::NoFilePathForInvalidFilePathId); +} + +TEST_F(FilePathCache, GetAFilePath) +{ + FilePathId filePathId = cache.filePathId("/path/to/file.cpp"); + + auto filePath = cache.filePath(filePathId); + + ASSERT_THAT(filePath, Eq("/path/to/file.cpp")); +} + +TEST_F(FilePathCache, GetAFilePathWithCachedFilePathId) +{ + FilePathId filePathId{5, 42}; + + auto filePath = cache.filePath(filePathId); + + ASSERT_THAT(filePath, Eq("/path/to/file.cpp")); +} + +void FilePathCache::SetUp() +{ + ON_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))) + .WillByDefault(Return(5)); + ON_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp"))) + .WillByDefault(Return(42)); + ON_CALL(mockStorage, fetchSourceId(5, Eq("file2.cpp"))) + .WillByDefault(Return(63)); + ON_CALL(mockStorage, fetchDirectoryPath(5)) + .WillByDefault(Return(Utils::PathString("/path/to"))); + ON_CALL(mockStorage, fetchSourceName(42)) + .WillByDefault(Return(Utils::SmallString("file.cpp"))); +} + +} + diff --git a/tests/unit/unittest/filepathstorage-test.cpp b/tests/unit/unittest/filepathstorage-test.cpp new file mode 100644 index 00000000000..11711583ed2 --- /dev/null +++ b/tests/unit/unittest/filepathstorage-test.cpp @@ -0,0 +1,409 @@ +/**************************************************************************** +** +** 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 "mockmutex.h" +#include "mocksqlitedatabase.h" +#include "mocksqlitereadstatement.h" +#include "mocksqlitewritestatement.h" + +#include +#include + +namespace { + +using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory, + MockSqliteReadStatement, + MockSqliteWriteStatement>; +using Storage = ClangBackEnd::FilePathStorage; +using ClangBackEnd::Sources::Directory; +using ClangBackEnd::Sources::Source; + +class FilePathStorage : public testing::Test +{ +protected: + void SetUp(); + +protected: + NiceMock mockMutex; + NiceMock mockDatabase{mockMutex}; + StatementFactory factory{mockDatabase}; + MockSqliteReadStatement &selectDirectoryIdFromDirectoriesByDirectoryPath = factory.selectDirectoryIdFromDirectoriesByDirectoryPath; + MockSqliteReadStatement &selectSourceIdFromSourcesByDirectoryIdAndSourceName = factory.selectSourceIdFromSourcesByDirectoryIdAndSourceName; + MockSqliteReadStatement &selectDirectoryPathFromDirectoriesByDirectoryId = factory.selectDirectoryPathFromDirectoriesByDirectoryId; + MockSqliteReadStatement &selectSourceNameFromSourcesBySourceId = factory.selectSourceNameFromSourcesBySourceId; + MockSqliteReadStatement &selectAllDirectories = factory.selectAllDirectories; + MockSqliteWriteStatement &insertIntoDirectories = factory.insertIntoDirectories; + MockSqliteWriteStatement &insertIntoSources = factory.insertIntoSources; + MockSqliteReadStatement &selectAllSources = factory.selectAllSources; + Storage storage{factory}; +}; + +TEST_F(FilePathStorage, ReadDirectoryIdForNotContainedPath) +{ + auto directoryId = storage.readDirectoryId("/some/not/known/path"); + + ASSERT_FALSE(directoryId); +} + +TEST_F(FilePathStorage, ReadSourceIdForNotContainedPathAndDirectoryId) +{ + auto sourceId = storage.readSourceId(23, "/some/not/known/path"); + + ASSERT_FALSE(sourceId); +} + +TEST_F(FilePathStorage, ReadDirectoryIdForEmptyPath) +{ + auto directoryId = storage.readDirectoryId(""); + + ASSERT_THAT(directoryId.value(), 0); +} + +TEST_F(FilePathStorage, ReadSourceIdForEmptyNameAndZeroDirectoryId) +{ + auto sourceId = storage.readSourceId(0, ""); + + ASSERT_THAT(sourceId.value(), 0); +} + +TEST_F(FilePathStorage, ReadDirectoryIdForPath) +{ + auto directoryId = storage.readDirectoryId("/path/to"); + + ASSERT_THAT(directoryId.value(), 5); +} + +TEST_F(FilePathStorage, ReadSourceIdForPathAndDirectoryId) +{ + auto sourceId = storage.readSourceId(5, "file.h"); + + ASSERT_THAT(sourceId.value(), 42); +} + +TEST_F(FilePathStorage, FetchDirectoryIdForEmptyPath) +{ + auto directoryId = storage.fetchDirectoryId(""); + + ASSERT_THAT(directoryId, 0); +} + +TEST_F(FilePathStorage, FetchSourceIdForEmptyNameAndZeroDirectoryId) +{ + auto sourceId = storage.fetchSourceId(0, ""); + + ASSERT_THAT(sourceId, 0); +} + +TEST_F(FilePathStorage, FetchDirectoryIdForPath) +{ + auto directoryId = storage.fetchDirectoryId("/path/to"); + + ASSERT_THAT(directoryId, 5); +} + +TEST_F(FilePathStorage, FetchSourceIdForPathAndDirectoryId) +{ + auto sourceId = storage.fetchSourceId(5, "file.h"); + + ASSERT_THAT(sourceId, 42); +} + +TEST_F(FilePathStorage, CallWriteForWriteDirectory) +{ + EXPECT_CALL(insertIntoDirectories, write(Eq("/some/not/known/path"))); + + storage.writeDirectoryId("/some/not/known/path"); +} + +TEST_F(FilePathStorage, CallWriteForWriteSource) +{ + EXPECT_CALL(insertIntoSources, write(5, Eq("unknownfile.h"))); + + storage.writeSourceId(5, "unknownfile.h"); +} + +TEST_F(FilePathStorage, GetTheDirectoryIdBackAfterWritingANewEntryInDirectories) +{ + auto directoryId = storage.writeDirectoryId("/some/not/known/path"); + + ASSERT_THAT(directoryId, 12); +} + +TEST_F(FilePathStorage, GetTheSourceIdBackAfterWritingANewEntryInSources) +{ + auto sourceId = storage.writeSourceId(5, "unknownfile.h"); + + ASSERT_THAT(sourceId, 12); +} + +TEST_F(FilePathStorage, GetTheDirectoryIdBackAfterFetchingANewEntryFromDirectories) +{ + auto directoryId = storage.fetchDirectoryId("/some/not/known/path"); + + ASSERT_THAT(directoryId, 12); +} + +TEST_F(FilePathStorage, GetTheSourceIdBackAfterFetchingANewEntryFromSources) +{ + auto sourceId = storage.fetchSourceId(5, "unknownfile.h"); + + ASSERT_THAT(sourceId, 12); +} + +TEST_F(FilePathStorage, CallSelectForFetchingDirectoryIdForKnownPath) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(Eq("/path/to"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchDirectoryId("/path/to"); +} + +TEST_F(FilePathStorage, CallSelectForFetchingSourceIdForKnownPath) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(5, Eq("file.h"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchSourceId(5, "file.h"); +} + +TEST_F(FilePathStorage, CallNotWriteForFetchingDirectoryIdForKnownPath) +{ + EXPECT_CALL(insertIntoDirectories, write(_)).Times(0); + + storage.fetchDirectoryId("/path/to"); +} + +TEST_F(FilePathStorage, CallNotWriteForFetchingSoureIdForKnownEntry) +{ + EXPECT_CALL(insertIntoSources, write(_, _)).Times(0); + + storage.fetchSourceId(5, "file.h"); +} + +TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdForUnknownPath) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(Eq("/some/not/known/path"))); + EXPECT_CALL(insertIntoDirectories, write(Eq("/some/not/known/path"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchDirectoryId("/some/not/known/path"); +} + +TEST_F(FilePathStorage, CallSelectAndWriteForFetchingSourceIdForUnknownEntry) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(5, Eq("unknownfile.h"))); + EXPECT_CALL(insertIntoSources, write(5, Eq("unknownfile.h"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchSourceId(5, "unknownfile.h"); +} + +TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdTwoTimesIfTheDatabaseIsBusyBecauseTheTableAlreadyChanged) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(Eq("/other/unknow/path"))); + EXPECT_CALL(insertIntoDirectories, write(Eq("/other/unknow/path"))) + .WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); + EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK"))); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(Eq("/other/unknow/path"))); + EXPECT_CALL(insertIntoDirectories, write(Eq("/other/unknow/path"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchDirectoryId("/other/unknow/path"); +} + + +TEST_F(FilePathStorage, CallSelectAndWriteForFetchingSourceTwoTimesIfTheDatabaseIsBusyBecauseTheTableAlreadyChanged) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(5, Eq("otherunknownfile.h"))); + EXPECT_CALL(insertIntoSources, write(5, Eq("otherunknownfile.h"))) + .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));; + EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK"))); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(5, Eq("otherunknownfile.h"))); + EXPECT_CALL(insertIntoSources, write(5, Eq("otherunknownfile.h"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchSourceId(5, "otherunknownfile.h"); +} + +TEST_F(FilePathStorage, SelectAllDirectories) +{ + auto directories = storage.fetchAllDirectories(); + + ASSERT_THAT(directories, + ElementsAre(Directory{1, "/path/to"}, Directory{2, "/other/path"})); +} + +TEST_F(FilePathStorage, SelectAllSources) +{ + auto sources = storage.fetchAllSources(); + + ASSERT_THAT(sources, + ElementsAre(Source{1, "file.h"}, Source{4, "file.cpp"})); +} + +TEST_F(FilePathStorage, CallSelectAllDirectories) +{ + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectAllDirectories, valuesReturnStdVectorDirectory(256)); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchAllDirectories(); +} + +TEST_F(FilePathStorage, CallSelectAllSources) +{ + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectAllSources, valuesReturnStdVectorSource(8192)); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchAllSources(); +} + +TEST_F(FilePathStorage, CallValueForFetchDirectoryPathForId) +{ + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, valueReturnPathString(5)); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchDirectoryPath(5); +} + +TEST_F(FilePathStorage, FetchDirectoryPathForId) +{ + auto path = storage.fetchDirectoryPath(5); + + ASSERT_THAT(path, Eq("/path/to")); +} + +TEST_F(FilePathStorage, ThrowAsFetchingDirectoryPathForNonExistingId) +{ + ASSERT_THROW(storage.fetchDirectoryPath(12), ClangBackEnd::DirectoryPathIdDoesNotExists); +} + +TEST_F(FilePathStorage, CallValueForFetchSoureNameForId) +{ + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(selectSourceNameFromSourcesBySourceId, valueReturnSmallString(42)); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + + storage.fetchSourceName(42); +} + +TEST_F(FilePathStorage, FetchSoureNameForId) +{ + auto path = storage.fetchSourceName(42); + + ASSERT_THAT(path, Eq("file.cpp")); +} + +TEST_F(FilePathStorage, ThrowAsFetchingSourceNameForNonExistingId) +{ + ASSERT_THROW(storage.fetchSourceName(12), ClangBackEnd::SourceNameIdDoesNotExists); +} + +void FilePathStorage::SetUp() +{ + ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(_)) + .WillByDefault(Return(Utils::optional())); + ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(Utils::SmallStringView(""))) + .WillByDefault(Return(Utils::optional(0))); + ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(Utils::SmallStringView("/path/to"))) + .WillByDefault(Return(Utils::optional(5))); + ON_CALL(mockDatabase, lastInsertedRowId()) + .WillByDefault(Return(12)); + ON_CALL(selectAllDirectories, + valuesReturnStdVectorDirectory(_)) + .WillByDefault(Return(std::vector{{1, "/path/to"}, {2, "/other/path"}})); + ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(_, _)) + .WillByDefault(Return(Utils::optional())); + ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(0, Utils::SmallStringView(""))) + .WillByDefault(Return(Utils::optional(0))); + ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, + valueReturnInt32(5, Utils::SmallStringView("file.h"))) + .WillByDefault(Return(Utils::optional(42))); + ON_CALL(selectAllSources, + valuesReturnStdVectorSource(_)) + .WillByDefault(Return(std::vector{{1, "file.h"}, {4, "file.cpp"}})); + ON_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, + valueReturnPathString(5)) + .WillByDefault(Return(Utils::optional("/path/to"))); + ON_CALL(selectSourceNameFromSourcesBySourceId, + valueReturnSmallString(42)) + .WillByDefault(Return(Utils::optional("file.cpp"))); + + + EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, valueReturnInt32(_)) + .Times(AnyNumber()); + EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, valueReturnInt32(_, _)) + .Times(AnyNumber()); + EXPECT_CALL(insertIntoDirectories,write(_)) + .Times(AnyNumber()); + EXPECT_CALL(insertIntoSources,write(_, _)) + .Times(AnyNumber()); + EXPECT_CALL(selectAllDirectories, valuesReturnStdVectorDirectory(_)) + .Times(AnyNumber()); + EXPECT_CALL(selectAllSources, valuesReturnStdVectorSource(_)) + .Times(AnyNumber()); + EXPECT_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, valueReturnPathString(_)) + .Times(AnyNumber()); + EXPECT_CALL(selectSourceNameFromSourcesBySourceId, valueReturnSmallString(_)) + .Times(AnyNumber()); +} +} diff --git a/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp b/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp new file mode 100644 index 00000000000..79ee210a077 --- /dev/null +++ b/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 "mockmutex.h" +#include "mocksqlitedatabase.h" +#include "mocksqlitereadstatement.h" +#include "mocksqlitewritestatement.h" + +#include + +namespace { + +using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory, + MockSqliteReadStatement, + MockSqliteWriteStatement>; + +class FilePathStorageSqliteStatementFactory : public testing::Test +{ +protected: + NiceMock mockMutex; + NiceMock mockDatabase{mockMutex}; + StatementFactory factory{mockDatabase}; +}; + +TEST_F(FilePathStorageSqliteStatementFactory, SelectDirectoryIdFromDirectoriesByDirectoryPath) +{ + ASSERT_THAT(factory.selectDirectoryIdFromDirectoriesByDirectoryPath.sqlStatement, + Eq("SELECT directoryId FROM directories WHERE directoryPath = ?")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, SelectDirectoryPathFromDirectoriesByDirectoryId) +{ + ASSERT_THAT(factory.selectDirectoryPathFromDirectoriesByDirectoryId.sqlStatement, + Eq("SELECT directoryPath FROM directories WHERE directoryId = ?")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceIdFromSourcesByDirectoryIdAndSourceName) +{ + ASSERT_THAT(factory.selectSourceIdFromSourcesByDirectoryIdAndSourceName.sqlStatement, + Eq("SELECT sourceId FROM sources WHERE directoryId = ? AND sourceName = ?")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceNameFromSourcesByDirectoryIdAndSourceId) +{ + ASSERT_THAT(factory.selectSourceNameFromSourcesBySourceId.sqlStatement, + Eq("SELECT sourceName FROM sources WHERE sourceId = ?")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, SelectAllDirectories) +{ + ASSERT_THAT(factory.selectAllDirectories.sqlStatement, + Eq("SELECT directoryId, directoryPath FROM directories")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoDirectories) +{ + ASSERT_THAT(factory.insertIntoDirectories.sqlStatement, + Eq("INSERT INTO directories(directoryPath) VALUES (?)")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoSources) +{ + ASSERT_THAT(factory.insertIntoSources.sqlStatement, + Eq("INSERT INTO sources(directoryId, sourceName) VALUES (?,?)")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, SelectAllSources) +{ + ASSERT_THAT(factory.selectAllSources.sqlStatement, + Eq("SELECT sourceId, sourceName FROM sources")); +} + +} diff --git a/tests/unit/unittest/google-using-declarations.h b/tests/unit/unittest/google-using-declarations.h index 7a1fe3b30fe..c91c901efb2 100644 --- a/tests/unit/unittest/google-using-declarations.h +++ b/tests/unit/unittest/google-using-declarations.h @@ -29,6 +29,7 @@ using testing::_; using testing::AllOf; +using testing::AnyNumber; using testing::AnyOf; using testing::Contains; using testing::ElementsAre; @@ -36,12 +37,16 @@ using testing::Eq; using testing::Field; using testing::InSequence; using testing::IsEmpty; +using testing::Mock; using testing::NiceMock; +using testing::Not; using testing::Pair; using testing::PrintToString; using testing::Property; using testing::Return; using testing::ReturnRef; using testing::Sequence; +using testing::SizeIs; using testing::StrEq; +using testing::Throw; using testing::UnorderedElementsAre; diff --git a/tests/unit/unittest/gtest-clang-printing.cpp b/tests/unit/unittest/gtest-clang-printing.cpp index 4e488379d85..d6299f1057f 100644 --- a/tests/unit/unittest/gtest-clang-printing.cpp +++ b/tests/unit/unittest/gtest-clang-printing.cpp @@ -23,25 +23,11 @@ ** ****************************************************************************/ -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif - #ifdef CLANG_UNIT_TESTS #include #include #endif -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - #include namespace TestGlobal { diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index d7cb22b7ce4..6a2545067f1 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -27,10 +27,16 @@ #include -#include +#include + +#include +#include #include +#include + + namespace Core { namespace Search { @@ -54,8 +60,8 @@ void PrintTo(const TextRange &range, ::std::ostream *os) << PrintToString(range.end) << ")"; } -} -} +} // namespace Search +} // namespace Core namespace ProjectExplorer { @@ -87,4 +93,67 @@ std::ostream &operator<<(std::ostream &out, const Macro ¯o) return out; } +} // namespace ProjectExplorer + +namespace Utils { +void PrintTo(const Utils::SmallString &text, ::std::ostream *os) +{ + *os << text; } + +} // namespace Utils + +namespace ClangBackEnd { + +std::ostream &operator<<(std::ostream &out, const FilePathId &id) +{ + return out << "(" << id.directoryId << ", " << id.fileNameId << ")"; +} + +std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths) +{ + out << "(" + << idPaths.id << ", " + << idPaths.filePathIds << ")"; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry) +{ + out << "(" + << entry.filePathId << ", " + << entry.line << ", " + << entry.column << ")"; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry) +{ + out << "(" + << entry.id << ", " + << entry.pathId + << ")"; + + return out; +} + +void PrintTo(const FilePathId &id, ::std::ostream *os) +{ + *os << id; +} + +void PrintTo(const FilePath &filePath, ::std::ostream *os) +{ + *os << filePath; +} + +} // namespace ClangBackEnd + +namespace ClangRefactoring { +std::ostream &operator<<(std::ostream &out, const SourceLocation &location) +{ + return out << "(" << location.filePathId << ", " << location.line << ", " << location.column << ")"; +} +} // namespace ClangBackEnd diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index 92db70f6ed1..73afa782572 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -40,8 +40,8 @@ class TextRange; void PrintTo(const TextPosition &position, ::std::ostream *os); void PrintTo(const TextRange &range, ::std::ostream *os); -} -} +} // namespace TextPosition +} // namespace TextPosition namespace ProjectExplorer { @@ -51,4 +51,30 @@ class Macro; std::ostream &operator<<(std::ostream &out, const MacroType &type); std::ostream &operator<<(std::ostream &out, const Macro ¯o); -} +} // namespace ClangRefactoring + +namespace Utils { +void PrintTo(const Utils::SmallString &text, ::std::ostream *os); +} // namespace ProjectExplorer + +namespace ClangBackEnd { +class SourceLocationEntry; +class IdPaths; +class FilePathId; +class FilePath; +class WatcherEntry; + +std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); +std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); +std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry); +std::ostream &operator<<(std::ostream &out, const FilePath &filePath); + +void PrintTo(const FilePathId &id, ::std::ostream *os); +void PrintTo(const FilePath &filePath, ::std::ostream *os); +} // namespace ClangBackEnd + +namespace ClangRefactoring { +class SourceLocation; + +std::ostream &operator<<(std::ostream &out, const SourceLocation &location); +} // namespace ClangRefactoring diff --git a/tests/unit/unittest/gtest-qt-printing.cpp b/tests/unit/unittest/gtest-qt-printing.cpp index 0c1628184de..cd97883b164 100644 --- a/tests/unit/unittest/gtest-qt-printing.cpp +++ b/tests/unit/unittest/gtest-qt-printing.cpp @@ -83,4 +83,9 @@ std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format) return out; } +void PrintTo(const QString &text, std::ostream *os) +{ + *os << text; +} + QT_END_NAMESPACE diff --git a/tests/unit/unittest/gtest-qt-printing.h b/tests/unit/unittest/gtest-qt-printing.h index 2a1b37cbac1..424762273b3 100644 --- a/tests/unit/unittest/gtest-qt-printing.h +++ b/tests/unit/unittest/gtest-qt-printing.h @@ -39,4 +39,6 @@ std::ostream &operator<<(std::ostream &out, const QVariant &variant); std::ostream &operator<<(std::ostream &out, const QString &text); std::ostream &operator<<(std::ostream &out, const QByteArray &byteArray); std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format); + +void PrintTo(const QString &text, std::ostream *os); QT_END_NAMESPACE diff --git a/tests/unit/unittest/includecollector-test.cpp b/tests/unit/unittest/includecollector-test.cpp index ad405e55d7d..f887a712a21 100644 --- a/tests/unit/unittest/includecollector-test.cpp +++ b/tests/unit/unittest/includecollector-test.cpp @@ -25,8 +25,13 @@ #include "googletest.h" +#include +#include #include -#include + +#include + +#include using testing::AllOf; using testing::Contains; @@ -34,16 +39,20 @@ using testing::Not; using testing::ElementsAre; using testing::UnorderedElementsAre; +using ClangBackEnd::FilePathId; + namespace { class IncludeCollector : public ::testing::Test { protected: void SetUp(); - uint id(const Utils::SmallString &path); + FilePathId id(const Utils::SmallString &path); protected: - ClangBackEnd::FilePathCache<> filePathCache; + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::IncludeCollector collector{filePathCache}; ClangBackEnd::IncludeCollector emptyCollector{filePathCache}; Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector_main.h", @@ -76,7 +85,7 @@ TEST_F(IncludeCollector, NoDuplicate) ASSERT_THAT(collector.takeIncludeIds(), UnorderedElementsAre(id(TESTDATA_DIR "/includecollector_external1.h"), id(TESTDATA_DIR "/includecollector_external2.h"), - id(TESTDATA_DIR "/includecollector_external3.h"))) << filePathCache.string(3); + id(TESTDATA_DIR "/includecollector_external3.h"))); } TEST_F(IncludeCollector, IncludesAreSorted) @@ -84,7 +93,7 @@ TEST_F(IncludeCollector, IncludesAreSorted) collector.collectIncludes(); ASSERT_THAT(collector.takeIncludeIds(), - ElementsAre(0, 1, 2)); + SizeIs(3)); } TEST_F(IncludeCollector, If) @@ -130,9 +139,9 @@ void IncludeCollector::SetUp() emptyCollector.setExcludedIncludes(excludePaths.clone()); } -uint IncludeCollector::id(const Utils::SmallString &path) +FilePathId IncludeCollector::id(const Utils::SmallString &path) { - return filePathCache.stringId(path); + return filePathCache.filePathId(path); } } diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp b/tests/unit/unittest/mockfilepathcaching.h similarity index 72% rename from src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp rename to tests/unit/unittest/mockfilepathcaching.h index 1647fa79431..f77287b4bbb 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.cpp +++ b/tests/unit/unittest/mockfilepathcaching.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,20 +23,18 @@ ** ****************************************************************************/ -#include "clangpathwatcher.h" +#pragma once -#include +#include "googletest.h" -namespace ClangBackEnd { +#include -std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry) +class MockFilePathCaching : public ClangBackEnd::FilePathCachingInterface { - out << "(" - << entry.id << ", " - << entry.path - << ")"; +public: + MOCK_CONST_METHOD1(filePathId, + ClangBackEnd::FilePathId (Utils::SmallStringView filePath)); + MOCK_CONST_METHOD1(filePath, + ClangBackEnd::FilePath (ClangBackEnd::FilePathId filePathId)); +}; - return out; -} - -} // namespace ClangBackEnd diff --git a/tests/unit/unittest/mockfilepathstorage.h b/tests/unit/unittest/mockfilepathstorage.h new file mode 100644 index 00000000000..b1114747b1c --- /dev/null +++ b/tests/unit/unittest/mockfilepathstorage.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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" + +class MockFilePathStorage +{ +public: + MOCK_METHOD1(fetchDirectoryId, + int (Utils::SmallStringView directoryPath)); + MOCK_METHOD2(fetchSourceId, + int (int directoryId, Utils::SmallStringView sourceName)); + MOCK_METHOD1(fetchDirectoryPath, + Utils::PathString (int directoryId)); + MOCK_METHOD1(fetchSourceName, + Utils::SmallString (int sourceId)); +}; + diff --git a/tests/unit/unittest/mocksqlitedatabase.h b/tests/unit/unittest/mocksqlitedatabase.h index bad4eefda2e..ce903c5b626 100644 --- a/tests/unit/unittest/mocksqlitedatabase.h +++ b/tests/unit/unittest/mocksqlitedatabase.h @@ -50,5 +50,8 @@ public: MOCK_METHOD0(databaseMutex, MockMutex &()); + + MOCK_CONST_METHOD0(lastInsertedRowId, + int64_t ()); }; diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index 386424386f9..22ad51e7598 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -26,31 +26,51 @@ #include "mocksqlitereadstatement.h" template <> -std::vector MockSqliteReadStatement::values(std::size_t reserveSize) +SourceLocations +MockSqliteReadStatement::values(std::size_t reserveSize, + const int &sourceId, + const int &line, + const int &column) { - return valuesReturnStdVectorInt(reserveSize); + return valuesReturnSourceLocations(reserveSize, sourceId, line, column); } template <> -std::vector -MockSqliteReadStatement::values(std::size_t reserveSize, - const Utils::PathString &sourcePath, - const uint &line, - const uint &column) +std::vector MockSqliteReadStatement::values(std::size_t reserveSize) { - return valuesReturnStdVectorLocation(reserveSize, sourcePath, line, column); + return valuesReturnStdVectorDirectory(reserveSize); } template <> -std::vector -MockSqliteReadStatement::values(std::size_t reserveSize, const std::vector &sourceIds) +std::vector MockSqliteReadStatement::values(std::size_t reserveSize) { - return valuesReturnStdVectorSource(reserveSize, sourceIds); + return valuesReturnStdVectorSource(reserveSize); } template <> -Utils::optional -MockSqliteReadStatement::value(const Utils::SmallStringView &text) +Utils::optional +MockSqliteReadStatement::value(const Utils::SmallStringView &text) { - return valueReturnUInt32(text); + return valueReturnInt32(text); +} + +template <> +Utils::optional +MockSqliteReadStatement::value(const int &directoryId, const Utils::SmallStringView &text) +{ + return valueReturnInt32(directoryId, text); +} + +template <> +Utils::optional +MockSqliteReadStatement::value(const int &directoryId) +{ + return valueReturnPathString(directoryId); +} + +template <> +Utils::optional +MockSqliteReadStatement::value(const int &sourceId) +{ + return valueReturnSmallString(sourceId); } diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index b97ab1dc7d2..3b4c82b5193 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -25,11 +25,12 @@ #pragma once -#include +#include "mocksqlitedatabase.h" #include -#include "mocksqlitedatabase.h" +#include +#include #include #include @@ -39,9 +40,9 @@ #include using std::int64_t; -using ClangBackEnd::FilePathIndex; -using Location = ClangRefactoring::SourceLocations::Location; -using Source = ClangRefactoring::SourceLocations::Source; +using ClangRefactoring::SourceLocation; +using ClangRefactoring::SourceLocations; +namespace Sources = ClangBackEnd::Sources; class MockSqliteReadStatement { @@ -51,24 +52,37 @@ public: : sqlStatement(sqlStatement) {} - MOCK_CONST_METHOD1(valuesReturnStdVectorInt, - std::vector(std::size_t)); + MOCK_METHOD4(valuesReturnSourceLocations, + SourceLocations(std::size_t, int, int, int)); - MOCK_CONST_METHOD4(valuesReturnStdVectorLocation, - std::vector(std::size_t, Utils::SmallStringView, qint64, qint64)); + MOCK_METHOD1(valuesReturnStdVectorDirectory, + std::vector(std::size_t)); - MOCK_CONST_METHOD2(valuesReturnStdVectorSource, - std::vector(std::size_t, const std::vector &)); + MOCK_METHOD1(valuesReturnStdVectorSource, + std::vector(std::size_t)); - MOCK_CONST_METHOD1(valueReturnUInt32, - Utils::optional(Utils::SmallStringView)); + MOCK_METHOD1(valueReturnInt32, + Utils::optional(Utils::SmallStringView)); + MOCK_METHOD2(valueReturnInt32, + Utils::optional(int, Utils::SmallStringView)); + + MOCK_METHOD1(valueReturnPathString, + Utils::optional(int)); + + MOCK_METHOD1(valueReturnSmallString, + Utils::optional(int)); template std::vector values(std::size_t reserveSize, const QueryType&... queryValues); + template + std::vector values(std::size_t reserveSize); + template class QueryContainerType, @@ -85,23 +99,32 @@ public: }; template <> -std::vector MockSqliteReadStatement::values(std::size_t reserveSize); - -template <> -std::vector -MockSqliteReadStatement::values( +SourceLocations +MockSqliteReadStatement::values( std::size_t reserveSize, - const Utils::PathString &sourcePath, - const uint &line, - const uint &column); - -template <> -std::vector -MockSqliteReadStatement::values( - std::size_t reserveSize, - const std::vector &); + const int &sourceId, + const int &line, + const int &column); template <> -Utils::optional -MockSqliteReadStatement::value(const Utils::SmallStringView&); +std::vector MockSqliteReadStatement::values(std::size_t reserveSize); + +template <> +std::vector MockSqliteReadStatement::values(std::size_t reserveSize); + +template <> +Utils::optional +MockSqliteReadStatement::value(const Utils::SmallStringView&); + +template <> +Utils::optional +MockSqliteReadStatement::value(const int&, const Utils::SmallStringView&); + +template <> +Utils::optional +MockSqliteReadStatement::value(const int&); + +template <> +Utils::optional +MockSqliteReadStatement::value(const int&); diff --git a/tests/unit/unittest/mocksqlitestatement.h b/tests/unit/unittest/mocksqlitestatement.h new file mode 100644 index 00000000000..ab919b9f4e2 --- /dev/null +++ b/tests/unit/unittest/mocksqlitestatement.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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 + +#include + + +class BaseMockSqliteStatement +{ +public: + MOCK_METHOD0(next, bool ()); + MOCK_METHOD0(step, void ()); + MOCK_METHOD0(execute, void ()); + MOCK_METHOD0(reset, void ()); + + MOCK_CONST_METHOD1(fetchIntValue, int (int)); + MOCK_CONST_METHOD1(fetchLongValue, long (int)); + MOCK_CONST_METHOD1(fetchLongLongValue, long long (int)); + MOCK_CONST_METHOD1(fetchDoubleValue, double (int)); + MOCK_CONST_METHOD1(fetchSmallStringValue, Utils::SmallString (int)); + MOCK_CONST_METHOD1(fetchPathStringValue, Utils::PathString (int)); + + template + Type fetchValue(int column) const; + + MOCK_METHOD2(bind, void (int, int)); + MOCK_METHOD2(bind, void (int, long long)); + MOCK_METHOD2(bind, void (int, double)); + MOCK_METHOD2(bind, void (int, Utils::SmallStringView)); + MOCK_METHOD2(bind, void (int, long)); + + MOCK_METHOD1(prepare, void (Utils::SmallStringView sqlStatement)); +}; + +template<> +int BaseMockSqliteStatement::fetchValue(int column) const +{ + return fetchIntValue(column); +} + +template<> +long BaseMockSqliteStatement::fetchValue(int column) const +{ + return fetchLongValue(column); +} + +template<> +long long BaseMockSqliteStatement::fetchValue(int column) const +{ + return fetchLongLongValue(column); +} + +template<> +double BaseMockSqliteStatement::fetchValue(int column) const +{ + return fetchDoubleValue(column); +} + +template<> +Utils::SmallString BaseMockSqliteStatement::fetchValue(int column) const +{ + return fetchSmallStringValue(column); +} + +template<> +Utils::PathString BaseMockSqliteStatement::fetchValue(int column) const +{ + return fetchPathStringValue(column); +} + +class MockSqliteStatement : public Sqlite::StatementImplementation> +{ +public: + explicit MockSqliteStatement() + : Sqlite::StatementImplementation>() + {} + + +protected: + void checkIsWritableStatement(); +}; diff --git a/tests/unit/unittest/mocksqlitewritestatement.h b/tests/unit/unittest/mocksqlitewritestatement.h index 98ea4e7e249..159077c8060 100644 --- a/tests/unit/unittest/mocksqlitewritestatement.h +++ b/tests/unit/unittest/mocksqlitewritestatement.h @@ -55,5 +55,8 @@ public: MOCK_METHOD2(write, void (uint, Utils::SmallStringView)); + MOCK_METHOD1(write, + void (Utils::SmallStringView)); + Utils::SmallString sqlStatement; }; diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp index bb99b3a4aa9..9dccf204d15 100644 --- a/tests/unit/unittest/pchcreator-test.cpp +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -26,17 +26,18 @@ #include "googletest.h" #include "fakeprocess.h" +#include "mockfilepathcaching.h" #include "mockpchgeneratornotifier.h" #include "testenvironment.h" #include #include -#include #include namespace { +using ClangBackEnd::FilePathId; using ClangBackEnd::IdPaths; using ClangBackEnd::ProjectPartPch; using ClangBackEnd::V2::ProjectPartContainer; @@ -65,10 +66,11 @@ using UnitTests::EndsWith; class PchCreator: public ::testing::Test { protected: - ClangBackEnd::FilePathIndex id(const Utils::PathString &path); + void SetUp(); + ClangBackEnd::FilePathId id(const Utils::PathString &path); protected: - ClangBackEnd::FilePathCache<> filePathCache; + NiceMock filePathCache; PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp"; PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; @@ -292,7 +294,10 @@ TEST_F(PchCreatorVerySlowTest, DISABLED_CreatePartPchs) auto includePaths = creator.generateProjectPartPch(projectPart1); ASSERT_THAT(includePaths.id, projectPart1.projectPartId()); - ASSERT_THAT(includePaths.paths, AllOf(Contains(1), Contains(2), Contains(3))); + ASSERT_THAT(includePaths.filePathIds, + AllOf(Contains(FilePathId{1, 1}), + Contains(FilePathId{1, 2}), + Contains(FilePathId{1, 3}))); } TEST_F(PchCreatorVerySlowTest, IncludesForCreatePchsForProjectParts) @@ -322,11 +327,11 @@ TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts) ASSERT_THAT(creator.takeProjectsIncludes(), ElementsAre(AllOf(Field(&IdPaths::id, "project1"), - Field(&IdPaths::paths, AllOf(Contains(id(TESTDATA_DIR "/includecollector_header2.h")), + Field(&IdPaths::filePathIds, AllOf(Contains(id(TESTDATA_DIR "/includecollector_header2.h")), Contains(id(TESTDATA_DIR "/includecollector_external1.h")), Contains(id(TESTDATA_DIR "/includecollector_external2.h"))))), AllOf(Field(&IdPaths::id, "project2"), - Field(&IdPaths::paths, AllOf(Contains(id(TESTDATA_DIR "/includecollector_external1.h")), + Field(&IdPaths::filePathIds, AllOf(Contains(id(TESTDATA_DIR "/includecollector_external1.h")), Contains(id(TESTDATA_DIR "/includecollector_external3.h")), Contains(id(TESTDATA_DIR "/includecollector_header1.h")), Contains(id(TESTDATA_DIR "/includecollector_external2.h"))))))); @@ -340,8 +345,32 @@ TEST_F(PchCreator, CreateProjectPartHeaderAndSourcesContent) "#include \"" TESTDATA_DIR "/includecollector_main3.cpp\"\n")); } -ClangBackEnd::FilePathIndex PchCreator::id(const Utils::PathString &path) +void PchCreator::SetUp() { - return filePathCache.stringId(path); + ON_CALL(filePathCache, filePathId(Eq(TESTDATA_DIR "/includecollector_external1.h"))) + .WillByDefault(Return(FilePathId{1, 1})); + ON_CALL(filePathCache, filePathId(Eq(TESTDATA_DIR "/includecollector_external2.h"))) + .WillByDefault(Return(FilePathId{1, 2})); + ON_CALL(filePathCache, filePathId(Eq(TESTDATA_DIR "/includecollector_external3.h"))) + .WillByDefault(Return(FilePathId{1, 3})); + ON_CALL(filePathCache, filePathId(Eq(header1Path))) + .WillByDefault(Return(FilePathId{1, 4})); + ON_CALL(filePathCache, filePathId(Eq(header2Path))) + .WillByDefault(Return(FilePathId{1, 5})); + ON_CALL(filePathCache, filePath(Eq(FilePathId{1, 1}))) + .WillByDefault(Return(FilePath{PathString{TESTDATA_DIR "/includecollector_external1.h"}})); + ON_CALL(filePathCache, filePath(Eq(FilePathId{1, 2}))) + .WillByDefault(Return(FilePath{PathString{TESTDATA_DIR "/includecollector_external2.h"}})); + ON_CALL(filePathCache, filePath(Eq(FilePathId{1, 3}))) + .WillByDefault(Return(FilePath{PathString{TESTDATA_DIR "/includecollector_external3.h"}})); + ON_CALL(filePathCache, filePath(Eq(FilePathId{1, 4}))) + .WillByDefault(Return(FilePath{header1Path})); + ON_CALL(filePathCache, filePath(Eq(FilePathId{1, 5}))) + .WillByDefault(Return(FilePath{header2Path})); +} + +ClangBackEnd::FilePathId PchCreator::id(const Utils::PathString &path) +{ + return filePathCache.filePathId(path); } } diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp index b9b170e3dc8..a01facb02cb 100644 --- a/tests/unit/unittest/pchmanagerserver-test.cpp +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -59,8 +59,8 @@ protected: NiceMock mockPchCreator; NiceMock mockClangPathWatcher; NiceMock mockProjectParts; - ClangBackEnd::FilePathCache<> filePathCache; - ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts}; + + ClangBackEnd::PchManagerServer server{mockClangPathWatcher, mockPchCreator, mockProjectParts}; NiceMock mockPchManagerClient; SmallString projectPartId1 = "project1"; SmallString projectPartId2 = "project2"; @@ -68,7 +68,7 @@ protected: PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header2Path = TESTDATA_DIR "/includecollector_header2.h"; - std::vector idPaths = {{projectPartId1, {1, 2}}}; + std::vector idPaths = {{projectPartId1, {{1, 1}, {1, 2}}}}; ProjectPartContainer projectPart1{projectPartId1.clone(), {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {header1Path.clone()}, @@ -147,7 +147,7 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier) { EXPECT_CALL(mockClangPathWatcher, setNotifier(_)); - ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts}; + ClangBackEnd::PchManagerServer server{mockClangPathWatcher, mockPchCreator, mockProjectParts}; } TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange) diff --git a/tests/unit/unittest/querysqlitestatementfactory-test.cpp b/tests/unit/unittest/querysqlitestatementfactory-test.cpp index d751cea6dab..d93a4cf8b10 100644 --- a/tests/unit/unittest/querysqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/querysqlitestatementfactory-test.cpp @@ -46,17 +46,9 @@ protected: TEST_F(QuerySqliteStatementFactory, SelectLocationsForSymbolLocation) { ASSERT_THAT(factory.selectLocationsForSymbolLocation.sqlStatement, - "SELECT sourceId, line, column FROM locations WHERE symbolId = " - " (SELECT symbolId FROM locations WHERE sourceId=" - " (SELECT sourceId FROM sources WHERE sourcePath =?)" - " AND line=? AND column=?) " + "SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = " + " (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) " "ORDER BY sourceId, line, column"); } -TEST_F(QuerySqliteStatementFactory, SelectSourcePathForId) -{ - ASSERT_THAT(factory.selectSourcePathForId.sqlStatement, - "SELECT sourceId, sourcePath FROM sources WHERE sourceId = ?"); -} - } diff --git a/tests/unit/unittest/refactoringclient-test.cpp b/tests/unit/unittest/refactoringclient-test.cpp index 8935f0968a1..f159c424009 100644 --- a/tests/unit/unittest/refactoringclient-test.cpp +++ b/tests/unit/unittest/refactoringclient-test.cpp @@ -26,6 +26,7 @@ #include "googletest.h" #include "mockrefactoringclientcallback.h" #include "mocksearchhandle.h" +#include "mockfilepathcaching.h" #include #include @@ -48,6 +49,8 @@ using CppTools::ClangCompilerOptionsBuilder; using ClangRefactoring::RefactoringEngine; +using ClangBackEnd::FilePath; +using ClangBackEnd::FilePathId; using ClangBackEnd::SourceLocationsForRenamingMessage; using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage; using ClangBackEnd::SourceRangesForQueryMessage; @@ -57,6 +60,7 @@ using testing::Pair; using testing::Contains; using testing::NiceMock; +using Utils::PathString; using Utils::SmallString; using Utils::SmallStringVector; @@ -65,11 +69,12 @@ class RefactoringClient : public ::testing::Test void SetUp(); protected: + NiceMock mockFilePathCaching; NiceMock mockSearchHandle; MockRefactoringClientCallBack callbackMock; ClangRefactoring::RefactoringClient client; ClangBackEnd::RefactoringConnectionClient connectionClient{&client}; - RefactoringEngine engine{connectionClient.serverProxy(), client}; + RefactoringEngine engine{connectionClient.serverProxy(), client, mockFilePathCaching}; QString fileContent{QStringLiteral("int x;\nint y;")}; QTextDocument textDocument{fileContent}; QTextCursor cursor{&textDocument}; @@ -80,13 +85,11 @@ protected: CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; SourceLocationsForRenamingMessage renameMessage{"symbol", - {{{42u, clangBackEndFilePath.clone()}}, - {{42u, 1, 1, 0}, {42u, 2, 5, 10}}}, + {{{{1, 42}, 1, 1, 0}, {{1, 42}, 2, 5, 10}}}, 1}; - SourceRangesForQueryMessage queryResultMessage{{{{42u, clangBackEndFilePath.clone()}}, - {{42u, 1, 1, 0, 1, 5, 4, ""}, - {42u, 2, 1, 5, 2, 5, 10, ""}}}}; - SourceRangesForQueryMessage emptyQueryResultMessage{{{},{}}}; + SourceRangesForQueryMessage queryResultMessage{{{{{1, 42}, 1, 1, 0, 1, 5, 4, ""}, + {{1, 42}, 2, 1, 5, 2, 5, 10, ""}}}}; + SourceRangesForQueryMessage emptyQueryResultMessage; }; TEST_F(RefactoringClient, SourceLocationsForRenaming) @@ -219,25 +222,15 @@ TEST_F(RefactoringClient, ResultCounterIsZeroAfterSettingExpectedResultCount) ASSERT_THAT(client.resultCounter(), 0); } -TEST_F(RefactoringClient, ConvertFilePaths) -{ - std::unordered_map filePaths{{42u, clangBackEndFilePath.clone()}}; - - auto qstringFilePaths = ClangRefactoring::RefactoringClient::convertFilePaths(filePaths); - - ASSERT_THAT(qstringFilePaths, Contains(Pair(42u, qStringFilePath))); -} - TEST_F(RefactoringClient, XXX) { const Core::Search::TextRange textRange{{1,0,1},{1,0,1}}; - const ClangBackEnd::SourceRangeWithTextContainer sourceRange{1, 1, 1, 1, 1, 1, 1, "function"}; - std::unordered_map filePaths = {{1, "/path/to/file"}}; + const ClangBackEnd::SourceRangeWithTextContainer sourceRange{{1, 1}, 1, 1, 1, 1, 1, 1, "function"}; EXPECT_CALL(mockSearchHandle, addResult(QString("/path/to/file"), QString("function"), textRange)) .Times(1); - client.addSearchResult(sourceRange, filePaths); + client.addSearchResult(sourceRange); } void RefactoringClient::SetUp() @@ -253,6 +246,11 @@ void RefactoringClient::SetUp() client.setSearchHandle(&mockSearchHandle); client.setExpectedResultCount(1); + + ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{1, 1}))) + .WillByDefault(Return(FilePath(PathString("/path/to/file")))); + ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{1, 42}))) + .WillByDefault(Return(clangBackEndFilePath)); } } diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp index 3f1c52a0212..4687140dab4 100644 --- a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp +++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp @@ -58,7 +58,7 @@ TEST_F(RefactoringDatabaseInitializer, AddLocationsTable) InSequence s; 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 INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_line_column ON locations(sourceId, line, column)"))); initializer.createLocationsTable(); } @@ -67,11 +67,21 @@ TEST_F(RefactoringDatabaseInitializer, AddSourcesTable) { InSequence s; - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, directoryId INTEGER, sourceName TEXT, sourceType INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sources_sourceName ON sources(sourceName)"))); initializer.createSourcesTable(); } +TEST_F(RefactoringDatabaseInitializer, AddDirectoriesTable) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY KEY, directoryPath TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_directories_directoryPath ON directories(directoryPath)"))); + initializer.createDirectoriesTable(); +} + TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor) { @@ -82,8 +92,11 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor) 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 INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); 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 INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_line_column ON locations(sourceId, line, column)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, directoryId INTEGER, sourceName TEXT, sourceType INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sources_sourceName ON sources(sourceName)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY KEY, directoryPath TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_directories_directoryPath ON directories(directoryPath)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); EXPECT_CALL(mockMutex, unlock()); diff --git a/tests/unit/unittest/refactoringengine-test.cpp b/tests/unit/unittest/refactoringengine-test.cpp index a4f7d32d04a..c1363bf7d88 100644 --- a/tests/unit/unittest/refactoringengine-test.cpp +++ b/tests/unit/unittest/refactoringengine-test.cpp @@ -25,6 +25,7 @@ #include "googletest.h" +#include "mockfilepathcaching.h" #include "mockrefactoringserver.h" #include "mockrefactoringclient.h" @@ -54,14 +55,15 @@ using Utils::SmallStringVector; class RefactoringEngine : public ::testing::Test { protected: - RefactoringEngine(); - void SetUp(); protected: + NiceMock mockFilePathCaching; MockRefactoringServer mockRefactoringServer; MockRefactoringClient mockRefactoringClient; - ClangRefactoring::RefactoringEngine engine; + ClangRefactoring::RefactoringEngine engine{mockRefactoringServer, + mockRefactoringClient, + mockFilePathCaching}; QString fileContent{QStringLiteral("int x;\nint y;")}; QTextDocument textDocument{fileContent}; QTextCursor cursor{&textDocument}; @@ -119,11 +121,6 @@ TEST_F(RefactoringEngine, ServerIsUsableForUsableEngine) ASSERT_TRUE(mockRefactoringServer.isUsable()); } -RefactoringEngine::RefactoringEngine() - : engine(mockRefactoringServer, mockRefactoringClient) -{ -} - void RefactoringEngine::SetUp() { projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp index 8b2586ba0bf..11a9e6be95c 100644 --- a/tests/unit/unittest/refactoringserver-test.cpp +++ b/tests/unit/unittest/refactoringserver-test.cpp @@ -30,8 +30,11 @@ #include "mocksymbolindexing.h" #include "sourcerangecontainer-matcher.h" -#include #include +#include +#include +#include +#include #include #include @@ -82,7 +85,9 @@ protected: protected: NiceMock mockRefactoringClient; NiceMock mockSymbolIndexing; - ClangBackEnd::FilePathCache filePathCache; + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache}; Utils::SmallString sourceContent{"void f()\n {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, @@ -109,11 +114,9 @@ TEST_F(RefactoringServerSlowTest, RequestSourceLocationsForRenamingMessage) AllOf(Property(&SourceLocationsForRenamingMessage::textDocumentRevision, 1), Property(&SourceLocationsForRenamingMessage::symbolName, "v"), Property(&SourceLocationsForRenamingMessage::sourceLocations, - AllOf(Property(&SourceLocationsContainer::sourceLocationContainers, + Property(&SourceLocationsContainer::sourceLocationContainers, AllOf(Contains(IsSourceLocation(1, 5)), - Contains(IsSourceLocation(3, 9)))), - Property(&SourceLocationsContainer::filePaths, - Contains(Pair(_, FilePath(TESTDATA_DIR, "renamevariable.cpp"))))))))); + Contains(IsSourceLocation(3, 9)))))))); refactoringServer.requestSourceLocationsForRenamingMessage(std::move(message)); } diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp index 345480182bc..bee07f58ffa 100644 --- a/tests/unit/unittest/smallstring-test.cpp +++ b/tests/unit/unittest/smallstring-test.cpp @@ -813,7 +813,7 @@ TEST(SmallString, AppendNullSmallString) { SmallString text("text"); - text.append(SmallString()); + text += SmallString(); ASSERT_THAT(text, SmallString("text")); } @@ -822,17 +822,16 @@ TEST(SmallString, AppendEmptySmallString) { SmallString text("text"); - text.append(SmallString("")); + text += SmallString(""); ASSERT_THAT(text, SmallString("text")); } - TEST(SmallString, AppendShortSmallString) { SmallString text("some "); - text.append(SmallString("text")); + text += SmallString("text"); ASSERT_THAT(text, SmallString("some text")); } @@ -841,7 +840,7 @@ TEST(SmallString, AppendLongSmallStringToShortSmallString) { SmallString text("some "); - text.append(SmallString("very very very very very long string")); + text += SmallString("very very very very very long string"); ASSERT_THAT(text, SmallString("some very very very very very long string")); } @@ -849,11 +848,29 @@ TEST(SmallString, AppendLongSmallStringToShortSmallString) TEST(SmallString, AppendLongSmallString) { SmallString longText("some very very very very very very very very very very very long string"); - longText.append(SmallString(" text")); + longText+= SmallString(" text"); ASSERT_THAT(longText, SmallString("some very very very very very very very very very very very long string text")); } +TEST(SmallString, AppendInitializerList) +{ + SmallString text("some text"); + + text += {" and", " some", " other", " text"}; + + ASSERT_THAT(text, Eq("some text and some other text")); +} + +TEST(SmallString, AppendEmptyInitializerList) +{ + SmallString text("some text"); + + text += {}; + + ASSERT_THAT(text, Eq("some text")); +} + TEST(SmallString, ToByteArray) { SmallString text("some text"); @@ -1660,8 +1677,11 @@ TEST(SmallString, ToView) TEST(SmallString, Compare) { + const char longText[] = "textfoo"; + ASSERT_THAT(Utils::compare("", ""), Eq(0)); ASSERT_THAT(Utils::compare("text", "text"), Eq(0)); + ASSERT_THAT(Utils::compare("text", Utils::SmallStringView(longText, 4)), Eq(0)); ASSERT_THAT(Utils::compare("", "text"), Le(0)); ASSERT_THAT(Utils::compare("textx", "text"), Gt(0)); ASSERT_THAT(Utils::compare("text", "textx"), Le(0)); @@ -1671,8 +1691,11 @@ TEST(SmallString, Compare) TEST(SmallString, ReverseCompare) { + const char longText[] = "textfoo"; + ASSERT_THAT(Utils::reverseCompare("", ""), Eq(0)); ASSERT_THAT(Utils::reverseCompare("text", "text"), Eq(0)); + ASSERT_THAT(Utils::reverseCompare("text", Utils::SmallStringView(longText, 4)), Eq(0)); ASSERT_THAT(Utils::reverseCompare("", "text"), Le(0)); ASSERT_THAT(Utils::reverseCompare("textx", "text"), Gt(0)); ASSERT_THAT(Utils::reverseCompare("text", "textx"), Le(0)); diff --git a/tests/unit/unittest/sourcerangeextractor-test.cpp b/tests/unit/unittest/sourcerangeextractor-test.cpp index 8235f51858c..f5a877c5852 100644 --- a/tests/unit/unittest/sourcerangeextractor-test.cpp +++ b/tests/unit/unittest/sourcerangeextractor-test.cpp @@ -24,15 +24,21 @@ ****************************************************************************/ #include "googletest.h" +#include "sourcerangecontainer-matcher.h" #include "testclangtool.h" +#include #include #include -#include +#include + +#include #include #include +#include + #include using testing::Contains; @@ -54,7 +60,9 @@ protected: TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; ClangBackEnd::SourceRangesContainer sourceRangesContainer; const clang::SourceManager &sourceManager{clangTool.sourceManager()}; - ClangBackEnd::FilePathCache filePathCache; + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer}; clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); @@ -66,11 +74,12 @@ using SourceRangeExtractorSlowTest = SourceRangeExtractor; TEST_F(SourceRangeExtractorSlowTest, ExtractSourceRangeContainer) { - SourceRangeWithTextContainer sourceRangeContainer{0, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; + SourceRangeWithTextContainer sourceRangeContainer{{1, 1}, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; extractor.addSourceRange(sourceRange); - ASSERT_THAT(extractor.sourceRangeWithTextContainers(), Contains(sourceRangeContainer)); + ASSERT_THAT(extractor.sourceRangeWithTextContainers(), + Contains(IsSourceRangeWithText(1, 1, 1, 10, "int value;"))); } TEST_F(SourceRangeExtractorSlowTest, ExtendedSourceRange) diff --git a/tests/unit/unittest/sourcerangefilter-test.cpp b/tests/unit/unittest/sourcerangefilter-test.cpp index 8620458a54e..f5630af57cb 100644 --- a/tests/unit/unittest/sourcerangefilter-test.cpp +++ b/tests/unit/unittest/sourcerangefilter-test.cpp @@ -42,21 +42,21 @@ protected: protected: - SourceRangeWithTextContainers sourceRanges1{{1, 1, 1, 1, 2, 1, 4, "foo"}, - {1, 1, 1, 1, 2, 2, 5, "foo"}, - {2, 1, 1, 1, 2, 1, 4, "foo"}}; - SourceRangeWithTextContainers sourceRanges2{{3, 1, 1, 1, 2, 1, 4, "foo"}, - {1, 1, 1, 1, 2, 1, 4, "foo"}, - {1, 1, 1, 1, 2, 3, 6, "foo"}}; - SourceRangeWithTextContainers sourceRanges3{{1, 1, 1, 1, 2, 3, 6, "foo"}, - {3, 1, 1, 1, 2, 1, 4, "foo"}}; - SourceRangeWithTextContainers sourceRanges4{{1, 1, 1, 1, 2, 3, 6, "foo"}, - {3, 1, 1, 1, 2, 1, 4, "foo"}, - {3, 1, 1, 1, 2, 1, 4, "foo"}}; - SourceRangeWithTextContainers sourceRanges5{{3, 1, 1, 1, 2, 1, 4, "foo"}, - {1, 1, 1, 1, 2, 3, 6, "foo"}}; - SourceRangesForQueryMessage message1{{{}, Utils::clone(sourceRanges1)}}; - SourceRangesForQueryMessage message2{{{}, Utils::clone(sourceRanges2)}}; + SourceRangeWithTextContainers sourceRanges1{{{1, 1}, 1, 1, 1, 2, 1, 4, "foo"}, + {{1, 1}, 1, 1, 1, 2, 2, 5, "foo"}, + {{1, 2}, 1, 1, 1, 2, 1, 4, "foo"}}; + SourceRangeWithTextContainers sourceRanges2{{{1, 3}, 1, 1, 1, 2, 1, 4, "foo"}, + {{1, 1}, 1, 1, 1, 2, 1, 4, "foo"}, + {{1, 1}, 1, 1, 1, 2, 3, 6, "foo"}}; + SourceRangeWithTextContainers sourceRanges3{{{1, 1}, 1, 1, 1, 2, 3, 6, "foo"}, + {{1, 3}, 1, 1, 1, 2, 1, 4, "foo"}}; + SourceRangeWithTextContainers sourceRanges4{{{1, 1}, 1, 1, 1, 2, 3, 6, "foo"}, + {{1, 3}, 1, 1, 1, 2, 1, 4, "foo"}, + {{1, 3}, 1, 1, 1, 2, 1, 4, "foo"}}; + SourceRangeWithTextContainers sourceRanges5{{{1, 3}, 1, 1, 1, 2, 1, 4, "foo"}, + {{1, 1}, 1, 1, 1, 2, 3, 6, "foo"}}; + SourceRangesForQueryMessage message1{{Utils::clone(sourceRanges1)}}; + SourceRangesForQueryMessage message2{{Utils::clone(sourceRanges2)}}; ClangBackEnd::SourceRangeFilter filter{3}; }; diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index 30ea9cbca84..3f5236e7b65 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "googletest.h" +#include "mocksqlitestatement.h" #include "sqliteteststatement.h" #include @@ -60,7 +61,7 @@ MATCHER_P3(HasValues, value1, value2, rowid, statement.next(); - return statement.text(0) == value1 && statement.text(1) == value2; + return statement.fetchPathStringValue(0) == value1 && statement.fetchPathStringValue(1) == value2; } class SqliteStatement : public ::testing::Test @@ -131,11 +132,13 @@ TEST_F(SqliteStatement, Value) ASSERT_THAT(statement.fetchValue(0), 0); ASSERT_THAT(statement.fetchValue(0), 0); ASSERT_THAT(statement.fetchValue(0), 0.0); - ASSERT_THAT(statement.text(0), "foo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "foo"); + ASSERT_THAT(statement.fetchPathStringValue(0), "foo"); ASSERT_THAT(statement.fetchValue(1), 23); ASSERT_THAT(statement.fetchValue(1), 23); ASSERT_THAT(statement.fetchValue(1), 23.3); - ASSERT_THAT(statement.text(1), "23.3"); + ASSERT_THAT(statement.fetchSmallStringValue(1), "23.3"); + ASSERT_THAT(statement.fetchPathStringValue(1), "23.3"); } TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement) @@ -209,7 +212,7 @@ TEST_F(SqliteStatement, BindString) statement.next(); - ASSERT_THAT(statement.text(0), "foo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "foo"); ASSERT_THAT(statement.fetchValue(1), 23.3); } @@ -220,7 +223,7 @@ TEST_F(SqliteStatement, BindInteger) statement.bind(1, 40); statement.next(); - ASSERT_THAT(statement.text(0),"poo"); + ASSERT_THAT(statement.fetchSmallStringValue(0),"poo"); } TEST_F(SqliteStatement, BindLongInteger) @@ -230,7 +233,7 @@ TEST_F(SqliteStatement, BindLongInteger) statement.bind(1, int64_t(40)); statement.next(); - ASSERT_THAT(statement.text(0), "poo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "poo"); } TEST_F(SqliteStatement, BindDouble) @@ -240,7 +243,7 @@ TEST_F(SqliteStatement, BindDouble) statement.bind(1, 23.3); statement.next(); - ASSERT_THAT(statement.text(0), "foo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "foo"); } TEST_F(SqliteStatement, BindIntegerByParameter) @@ -250,7 +253,7 @@ TEST_F(SqliteStatement, BindIntegerByParameter) statement.bind("@number", 40); statement.next(); - ASSERT_THAT(statement.text(0), "poo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "poo"); } TEST_F(SqliteStatement, BindLongIntegerByParameter) @@ -260,7 +263,7 @@ TEST_F(SqliteStatement, BindLongIntegerByParameter) statement.bind("@number", int64_t(40)); statement.next(); - ASSERT_THAT(statement.text(0), "poo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "poo"); } TEST_F(SqliteStatement, BindDoubleByIndex) @@ -270,7 +273,7 @@ TEST_F(SqliteStatement, BindDoubleByIndex) statement.bind(statement.bindingIndexForName("@number"), 23.3); statement.next(); - ASSERT_THAT(statement.text(0), "foo"); + ASSERT_THAT(statement.fetchSmallStringValue(0), "foo"); } TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBound) @@ -291,14 +294,7 @@ TEST_F(SqliteStatement, WrongBindingNameThrowingBindingIndexIsOutOfBound) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@name", database); - ASSERT_THROW(statement.bind("@name2", 40), Sqlite::WrongBingingName); -} - -TEST_F(SqliteStatement, RequestBindingNamesFromStatement) -{ - SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); - - ASSERT_THAT(statement.bindingColumnNames(), ElementsAre("name", "number", "id")); + ASSERT_THROW(statement.bind("@name2", 40), Sqlite::WrongBindingName); } TEST_F(SqliteStatement, BindValues) @@ -524,6 +520,102 @@ TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue) ASSERT_THAT(value.value(), Eq(Tuple{"bar", "blah", 1})); } +TEST_F(SqliteStatement, GetOptionalValueCallsReset) +{ + MockSqliteStatement mockStatement; + + EXPECT_CALL(mockStatement, reset()); + + mockStatement.value("bar"); +} + +TEST_F(SqliteStatement, GetOptionalValueCallsResetIfExceptionIsThrown) +{ + MockSqliteStatement mockStatement; + ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); + + EXPECT_CALL(mockStatement, reset()); + + EXPECT_THROW(mockStatement.value("bar"), Sqlite::StatementHasError); +} + +TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsReset) +{ + MockSqliteStatement mockStatement; + + EXPECT_CALL(mockStatement, reset()); + + mockStatement.values(3); +} + +TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsResetIfExceptionIsThrown) +{ + MockSqliteStatement mockStatement; + ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); + + EXPECT_CALL(mockStatement, reset()); + + EXPECT_THROW(mockStatement.values(3), Sqlite::StatementHasError); +} + +TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsReset) +{ + MockSqliteStatement mockStatement; + + EXPECT_CALL(mockStatement, reset()); + + mockStatement.values(3, "foo", "bar"); +} + +TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsResetIfExceptionIsThrown) +{ + MockSqliteStatement mockStatement; + ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); + + EXPECT_CALL(mockStatement, reset()); + + EXPECT_THROW(mockStatement.values(3, "foo", "bar"), Sqlite::StatementHasError); +} + +TEST_F(SqliteStatement, GetValuesWithVectorArgumentsCallsReset) +{ + MockSqliteStatement mockStatement; + + EXPECT_CALL(mockStatement, reset()).Times(2); + + mockStatement.values(3, std::vector{"bar", "foo"}); +} + +TEST_F(SqliteStatement, GetValuesWithVectorArgumentCallsResetIfExceptionIsThrown) +{ + MockSqliteStatement mockStatement; + ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); + + EXPECT_CALL(mockStatement, reset()); + + EXPECT_THROW(mockStatement.values(3, std::vector{"bar", "foo"}), + Sqlite::StatementHasError); +} + +TEST_F(SqliteStatement, GetValuesWithTupleArgumentsCallsReset) +{ + MockSqliteStatement mockStatement; + + EXPECT_CALL(mockStatement, reset()).Times(2); + + mockStatement.values(3, std::vector>{{1}, {2}}); +} + +TEST_F(SqliteStatement, GetValuesWithTupleArgumentsCallsResetIfExceptionIsThrown) +{ + MockSqliteStatement mockStatement; + ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); + + EXPECT_CALL(mockStatement, reset()); + + EXPECT_THROW(mockStatement.values(3, std::vector>{{1}, {2}}), + Sqlite::StatementHasError); +} void SqliteStatement::SetUp() { diff --git a/tests/unit/unittest/sqliteteststatement.h b/tests/unit/unittest/sqliteteststatement.h index 870180b5d05..8705280ca62 100644 --- a/tests/unit/unittest/sqliteteststatement.h +++ b/tests/unit/unittest/sqliteteststatement.h @@ -25,30 +25,13 @@ #pragma once -#pragma once +#include -#include - -class SQLITE_EXPORT SqliteTestStatement : public Sqlite::Statement +class SqliteTestStatement : public Sqlite::StatementImplementation { public: explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database) - : Sqlite::Statement(sqlStatement, database) + : Sqlite::StatementImplementation(sqlStatement, database) {} - - using Statement::bind; - using Statement::bindingColumnNames; - using Statement::bindingIndexForName; - using Statement::bindNameValues; - using Statement::bindValues; - using Statement::columnNames; - using Statement::database; - using Statement::execute; - using Statement::next; - using Statement::text; - using Statement::fetchValue; - -protected: - void checkIsWritableStatement(); }; diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp index 0995663ad44..b8575c5fc2d 100644 --- a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp @@ -117,12 +117,6 @@ TEST_F(StorageSqliteStatementFactory, AddNewSymbolsToSymbolsStatement) Eq("INSERT INTO symbols(usr, symbolName) SELECT usr, symbolName FROM newSymbols WHERE NOT EXISTS (SELECT usr FROM symbols WHERE symbols.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, diff --git a/tests/unit/unittest/stringcache-test.cpp b/tests/unit/unittest/stringcache-test.cpp index e023ae7ff2b..1a20e473de6 100644 --- a/tests/unit/unittest/stringcache-test.cpp +++ b/tests/unit/unittest/stringcache-test.cpp @@ -25,6 +25,9 @@ #include "googletest.h" +#include "mockmutex.h" +#include "mockfilepathstorage.h" + #include #include @@ -38,8 +41,15 @@ using uint64 = unsigned long long; using Utils::compare; using Utils::reverseCompare; using ClangBackEnd::findInSorted; +using StorageIdFunction = std::function; +using StorageStringFunction = std::function; -using CacheEntries = ClangBackEnd::FileCacheCacheEntries; +using Cache = ClangBackEnd::StringCache, + decltype(&Utils::reverseCompare), + Utils::reverseCompare>; +using CacheEntries = Cache::CacheEntries; class StringCache : public testing::Test { @@ -47,7 +57,15 @@ protected: void SetUp(); protected: - ClangBackEnd::FilePathCache<> cache; + NiceMock mockStorage; + StorageIdFunction mockStorageFetchDirectyId = [&] (Utils::SmallStringView string) { + return mockStorage.fetchDirectoryId(string); + }; + StorageStringFunction mockStorageFetchDirectyPath = [&] (int id) { + return mockStorage.fetchDirectoryPath(id); + }; + Cache cache; + NiceMock &mockMutex = cache.mutex(); Utils::PathString filePath1{"/file/pathOne"}; Utils::PathString filePath2{"/file/pathTwo"}; Utils::PathString filePath3{"/file/pathThree"}; @@ -311,11 +329,123 @@ TEST_F(StringCache, FindInSortedFifeReverse) ASSERT_TRUE(found.wasFound); } +TEST_F(StringCache, StringIdIsLocked) +{ + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockMutex, unlock()); + + cache.stringId("foo"); +} + +TEST_F(StringCache, StringIdsIsLocked) +{ + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockMutex, unlock()); + + cache.stringIds({"foo"}); +} + +TEST_F(StringCache, StringIsLocked) +{ + cache.stringId("foo"); + + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockMutex, unlock()); + + cache.string(0); +} + +TEST_F(StringCache, StringsIsLocked) +{ + cache.stringId("foo"); + + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockMutex, unlock()); + + cache.strings({0}); +} + +TEST_F(StringCache, StringIdWithStorageFunctionIsLocked) +{ + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockMutex, unlock()); + + cache.stringId("foo", mockStorageFetchDirectyId); +} + +TEST_F(StringCache, StringIdWithStorageFunctionWhichHasNoEntryIsCallingStorageFunction) +{ + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("foo"))); + + cache.stringId("foo", mockStorageFetchDirectyId); +} + +TEST_F(StringCache, StringIdWithStorageFunctionWhichHasEntryIsNotCallingStorageFunction) +{ + cache.stringId("foo", mockStorageFetchDirectyId); + + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("foo"))).Times(0); + + cache.stringId("foo", mockStorageFetchDirectyId); +} + +TEST_F(StringCache, IndexOfStringIdWithStorageFunctionWhichHasEntry) +{ + cache.stringId("foo", mockStorageFetchDirectyId); + + auto index = cache.stringId("foo", mockStorageFetchDirectyId); + + ASSERT_THAT(index, 42); +} + +TEST_F(StringCache, IndexOfStringIdWithStorageFunctionWhichHasNoEntry) +{ + auto index = cache.stringId("foo", mockStorageFetchDirectyId); + + ASSERT_THAT(index, 42); +} + +TEST_F(StringCache, GetEntryByIndexAfterInsertingByCustomIndex) +{ + auto index = cache.stringId("foo", mockStorageFetchDirectyId); + + auto string = cache.string(index, mockStorageFetchDirectyPath); + + ASSERT_THAT(string, Eq("foo")); +} + +TEST_F(StringCache, CallFetchDirectoryPathForLowerIndex) +{ + auto index = cache.stringId("foo", mockStorageFetchDirectyId); + + EXPECT_CALL(mockStorage, fetchDirectoryPath(Eq(index - 1))); + + cache.string(index - 1, mockStorageFetchDirectyPath); +} + +TEST_F(StringCache, CallFetchDirectoryPathForUnknownIndex) +{ + EXPECT_CALL(mockStorage, fetchDirectoryPath(Eq(0))); + + cache.string(0, mockStorageFetchDirectyPath); +} + +TEST_F(StringCache, FetchDirectoryPathForUnknownIndex) +{ + auto string = cache.string(41, mockStorageFetchDirectyPath); + + ASSERT_THAT(string, Eq("bar")); +} void StringCache::SetUp() { std::sort(filePaths.begin(), filePaths.end(), [] (auto &f, auto &l) { return compare(f, l) < 0;}); std::sort(reverseFilePaths.begin(), reverseFilePaths.end(), [] (auto &f, auto &l) { return reverseCompare(f, l) < 0;}); + + ON_CALL(mockStorage, fetchDirectoryId(Eq("foo"))) + .WillByDefault(Return(42)); + ON_CALL(mockStorage, fetchDirectoryPath(41)) + .WillByDefault(Return(Utils::PathString("bar"))); } } diff --git a/tests/unit/unittest/symbolfinder-test.cpp b/tests/unit/unittest/symbolfinder-test.cpp index c32bed0baad..d036b5b227d 100644 --- a/tests/unit/unittest/symbolfinder-test.cpp +++ b/tests/unit/unittest/symbolfinder-test.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "googletest.h" +#include "mockfilepathcaching.h" #include #include @@ -33,11 +34,6 @@ using ClangBackEnd::SymbolFinder; using ClangBackEnd::FileContent; -using testing::PrintToString; -using testing::AllOf; -using testing::Contains; -using testing::Not; - namespace { MATCHER_P2(IsSourceLocation, line, column, @@ -61,16 +57,26 @@ MATCHER_P(StrEq, text, return std::string(arg.data(), arg.size()) == std::string(text); } -TEST(SymbolFinder, FileContentFilePath) +using Finder = SymbolFinder; + +class SymbolFinder : public testing::Test +{ +protected: + NiceMock filePathCaching; +}; + +using SymbolFinderSlowTest = SymbolFinder; + +TEST_F(SymbolFinder, FileContentFilePath) { FileContent fileContent(toNativePath("/tmp"), "data.cpp", "int variable;", {"cc", "data.cpp"}); ASSERT_THAT(fileContent.filePath, toNativePath("/tmp/data.cpp")); } -TEST(SymbolFinderSlowTest, FindName) +TEST_F(SymbolFinderSlowTest, FindName) { - SymbolFinder finder(1, 5); + Finder finder(1, 5, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "int variable;", {"cc", "renamevariable.cpp"}); finder.findSymbol(); @@ -78,9 +84,9 @@ TEST(SymbolFinderSlowTest, FindName) ASSERT_THAT(finder.takeSymbolName(), "variable"); } -TEST(SymbolFinderSlowTest, FindNameInUnsavedFile) +TEST_F(SymbolFinderSlowTest, FindNameInUnsavedFile) { - SymbolFinder finder(1, 5); + Finder finder(1, 5, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "int newVariable;", {"cc", "renamevariable.cpp"}); finder.findSymbol(); @@ -88,9 +94,9 @@ TEST(SymbolFinderSlowTest, FindNameInUnsavedFile) ASSERT_THAT(finder.takeSymbolName(), "newVariable"); } -TEST(SymbolFinderSlowTest, FindUsrs) +TEST_F(SymbolFinderSlowTest, FindUsrs) { - SymbolFinder finder(1, 5); + Finder finder(1, 5, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "int variable;", {"cc", "renamevariable.cpp", "-std=c++14"}); finder.findSymbol(); @@ -98,9 +104,9 @@ TEST(SymbolFinderSlowTest, FindUsrs) ASSERT_THAT(finder.unifiedSymbolResolutions().front(), StrEq("c:@variable")); } -TEST(SymbolFinderSlowTest, VariableDeclarationSourceLocations) +TEST_F(SymbolFinderSlowTest, VariableDeclarationSourceLocations) { - SymbolFinder finder(1, 5); + Finder finder(1, 5, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); finder.findSymbol(); @@ -110,9 +116,9 @@ TEST(SymbolFinderSlowTest, VariableDeclarationSourceLocations) Contains(IsSourceLocation(3, 9)))); } -TEST(SymbolFinderSlowTest, VariableUsageSourceLocations) +TEST_F(SymbolFinderSlowTest, VariableUsageSourceLocations) { - SymbolFinder finder(3, 9); + Finder finder(3, 9, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); finder.findSymbol(); @@ -122,9 +128,9 @@ TEST(SymbolFinderSlowTest, VariableUsageSourceLocations) Contains(IsSourceLocation(3, 9)))); } -TEST(SymbolFinderSlowTest, TemplateMemberVariableDeclarationSourceLocations) +TEST_F(SymbolFinderSlowTest, TemplateMemberVariableDeclarationSourceLocations) { - SymbolFinder finder(8, 18); + Finder finder(8, 18, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); finder.findSymbol(); @@ -135,9 +141,9 @@ TEST(SymbolFinderSlowTest, TemplateMemberVariableDeclarationSourceLocations) Contains(IsSourceLocation(18, 19)))); } -TEST(SymbolFinderSlowTest, TemplateMemberVariableUsageSourceLocations) +TEST_F(SymbolFinderSlowTest, TemplateMemberVariableUsageSourceLocations) { - SymbolFinder finder(15, 14); + Finder finder(15, 14, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); finder.findSymbol(); @@ -148,9 +154,9 @@ TEST(SymbolFinderSlowTest, TemplateMemberVariableUsageSourceLocations) Contains(IsSourceLocation(18, 19)))); } -TEST(SymbolFinderSlowTest, TemplateMemberVariableUsageInLambdaSourceLocations) +TEST_F(SymbolFinderSlowTest, TemplateMemberVariableUsageInLambdaSourceLocations) { - SymbolFinder finder(18, 19); + Finder finder(18, 19, filePathCaching); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); finder.findSymbol(); @@ -161,9 +167,9 @@ TEST(SymbolFinderSlowTest, TemplateMemberVariableUsageInLambdaSourceLocations) Contains(IsSourceLocation(18, 19)))); } -TEST(SymbolFinderSlowTest, CursorOverMacroDefintionSymbolName) +TEST_F(SymbolFinderSlowTest, CursorOverMacroDefintionSymbolName) { - SymbolFinder finder(1, 9); + Finder finder(1, 9, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -171,9 +177,9 @@ TEST(SymbolFinderSlowTest, CursorOverMacroDefintionSymbolName) ASSERT_THAT(finder.takeSymbolName(), "Macro"); } -TEST(SymbolFinderSlowTest, CursorOverMacroExpansionSymbolName) +TEST_F(SymbolFinderSlowTest, CursorOverMacroExpansionSymbolName) { - SymbolFinder finder(10, 10); + Finder finder(10, 10, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -181,9 +187,9 @@ TEST(SymbolFinderSlowTest, CursorOverMacroExpansionSymbolName) ASSERT_THAT(finder.takeSymbolName(), "Macro"); } -TEST(SymbolFinderSlowTest, FindMacroDefinition) +TEST_F(SymbolFinderSlowTest, FindMacroDefinition) { - SymbolFinder finder(1, 9); + Finder finder(1, 9, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -192,9 +198,9 @@ TEST(SymbolFinderSlowTest, FindMacroDefinition) Contains(IsSourceLocation(1, 9))); } -TEST(SymbolFinderSlowTest, FindMacroExpansion) +TEST_F(SymbolFinderSlowTest, FindMacroExpansion) { - SymbolFinder finder(1, 9); + Finder finder(1, 9, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -203,9 +209,9 @@ TEST(SymbolFinderSlowTest, FindMacroExpansion) Contains(IsSourceLocation(5, 17))); } -TEST(SymbolFinderSlowTest, DoNotFindUndedefinedMacroExpansion) +TEST_F(SymbolFinderSlowTest, DoNotFindUndedefinedMacroExpansion) { - SymbolFinder finder(1, 9); + Finder finder(1, 9, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -214,9 +220,9 @@ TEST(SymbolFinderSlowTest, DoNotFindUndedefinedMacroExpansion) Not(Contains(IsSourceLocation(10, 10)))); } -TEST(SymbolFinderSlowTest, FindMacroDefinitionFromMacroExpansion) +TEST_F(SymbolFinderSlowTest, FindMacroDefinitionFromMacroExpansion) { - SymbolFinder finder(10, 10); + Finder finder(10, 10, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -226,9 +232,9 @@ TEST(SymbolFinderSlowTest, FindMacroDefinitionFromMacroExpansion) } -TEST(SymbolFinderSlowTest, FindMacroExpansionBeforeMacroExpansionWithCursor) +TEST_F(SymbolFinderSlowTest, FindMacroExpansionBeforeMacroExpansionWithCursor) { - SymbolFinder finder(12, 10); + Finder finder(12, 10, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); @@ -237,9 +243,9 @@ TEST(SymbolFinderSlowTest, FindMacroExpansionBeforeMacroExpansionWithCursor) Contains(IsSourceLocation(10, 10))); } -TEST(SymbolFinderSlowTest, FindMacroExpansionAfterMacroExpansionWithCursor) +TEST_F(SymbolFinderSlowTest, FindMacroExpansionAfterMacroExpansionWithCursor) { - SymbolFinder finder(10, 10); + Finder finder(10, 10, filePathCaching); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); finder.findSymbol(); diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 6684b2cddb2..9b7c471312d 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -77,7 +77,7 @@ protected: "void f();", {}}}; SymbolEntries symbolEntries{{1, {"function", "function"}}}; - SourceLocationEntries sourceLocations{{1, 1, {42, 23}, SymbolType::Declaration}}; + SourceLocationEntries sourceLocations{{1, {1, 1}, {42, 23}, SymbolType::Declaration}}; NiceMock mockCollector; NiceMock mockStorage; ClangBackEnd::SymbolIndexer indexer{mockCollector, mockStorage}; diff --git a/tests/unit/unittest/symbolindexing-test.cpp b/tests/unit/unittest/symbolindexing-test.cpp index a80e4342547..116a4c30915 100644 --- a/tests/unit/unittest/symbolindexing-test.cpp +++ b/tests/unit/unittest/symbolindexing-test.cpp @@ -25,12 +25,14 @@ #include "googletest.h" -#include - #include #include #include +#include +#include +#include + #include namespace { @@ -40,8 +42,9 @@ using Sqlite::ReadStatement; using ClangBackEnd::SymbolIndexer; using ClangBackEnd::SymbolsCollector; using ClangBackEnd::SymbolStorage; -using ClangBackEnd::FilePathCache; -using ClangBackEnd::FilePathCache; +using ClangBackEnd::FilePathCaching; +using ClangBackEnd::FilePathId; +using ClangBackEnd::RefactoringDatabaseInitializer; using ClangBackEnd::V2::ProjectPartContainer; using ClangBackEnd::V2::ProjectPartContainer; using ClangRefactoring::SymbolQuery; @@ -52,16 +55,16 @@ using SL = ClangRefactoring::SourceLocations; using StatementFactory = QuerySqliteStatementFactory; using Query = SymbolQuery; -MATCHER_P3(IsLocation, sourceId, line, column, +MATCHER_P3(IsLocation, filePathId, line, column, std::string(negation ? "isn't" : "is") - + " source id " + PrintToString(sourceId) + + " file path id " + PrintToString(filePathId) + " line " + PrintToString(line) + " and column " + PrintToString(column) ) { - const SL::Location &location = arg; + const ClangRefactoring::SourceLocation &location = arg; - return location.sourceId == sourceId + return location.filePathId == filePathId && location.line == line && location.column == column; }; @@ -69,9 +72,14 @@ MATCHER_P3(IsLocation, sourceId, line, column, class SymbolIndexing : public testing::Test { protected: - FilePathCache filePathCache; - ClangBackEnd::SymbolIndexing indexing{filePathCache, QDir::tempPath() + "/symbol.db"}; - StatementFactory queryFactory{indexing.database()}; + FilePathId filePathId(Utils::SmallString filePath); + +protected: + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + RefactoringDatabaseInitializer initializer{database}; + FilePathCaching filePathCache{database}; + ClangBackEnd::SymbolIndexing indexing{database, filePathCache}; + StatementFactory queryFactory{database}; Query query{queryFactory}; PathString main1Path = TESTDATA_DIR "/symbolindexing_main1.cpp"; ProjectPartContainer projectPart1{"project1", @@ -84,29 +92,26 @@ TEST_F(SymbolIndexing, Locations) { indexing.indexer().updateProjectParts({projectPart1}, {}); - auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5); - ASSERT_THAT(locations.locations, + auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 6, 5); + ASSERT_THAT(locations, ElementsAre( - IsLocation(0, 5, 9), - IsLocation(0, 6, 5))); -} - -TEST_F(SymbolIndexing, Sources) -{ - indexing.indexer().updateProjectParts({projectPart1}, {}); - - auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5); - ASSERT_THAT(locations.sources, ElementsAre(Pair(0, Eq(TESTDATA_DIR "/symbolindexing_main1.cpp")))); + IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 5, 9), + IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 6, 5))); } TEST_F(SymbolIndexing, DISABLED_TemplateFunction) { indexing.indexer().updateProjectParts({projectPart1}, {}); - auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 21, 24); - ASSERT_THAT(locations.locations, + auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 21, 24); + ASSERT_THAT(locations, ElementsAre( - IsLocation(0, 5, 9), - IsLocation(0, 6, 5))); + IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 5, 9), + IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 6, 5))); +} + +ClangBackEnd::FilePathId SymbolIndexing::filePathId(Utils::SmallString filePath) +{ + return filePathCache.filePathId(filePath); } } diff --git a/tests/unit/unittest/symbolquery-test.cpp b/tests/unit/unittest/symbolquery-test.cpp index 50925bd7f3c..6b8988eace4 100644 --- a/tests/unit/unittest/symbolquery-test.cpp +++ b/tests/unit/unittest/symbolquery-test.cpp @@ -42,8 +42,6 @@ using StatementFactory = QuerySqliteStatementFactory; using Query = ClangRefactoring::SymbolQuery; -using Location = Query::Location; -using Source = Query::Source; class SymbolQuery : public testing::Test { @@ -51,43 +49,21 @@ protected: NiceMock mockDatabase; StatementFactory statementFactory{mockDatabase}; MockSqliteReadStatement &selectLocationsForSymbolLocation = statementFactory.selectLocationsForSymbolLocation; - MockSqliteReadStatement &selectSourcePathForId = statementFactory.selectSourcePathForId; - std::vector locations{{1, 1, 1}, - {1, 2, 3}, - {2, 1, 1}, - {2, 3, 1}, - {4, 1, 1}, - {4, 1, 3}}; + SourceLocations locations{{{1, 1}, 1, 1}, + {{1, 1}, 2, 3}, + {{1, 2}, 1, 1}, + {{1, 2}, 3, 1}, + {{1, 4}, 1, 1}, + {{1, 4}, 1, 3}}; Query query{statementFactory}; }; TEST_F(SymbolQuery, LocationsAt) { - EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnStdVectorLocation(_, Eq("/path/to/file.cpp"), 14, 7)) + EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnSourceLocations(_, 42, 14, 7)) .WillRepeatedly(Return(locations)); - EXPECT_CALL(selectSourcePathForId, valuesReturnStdVectorSource(_, ElementsAre(1, 2, 4))); - query.locationsAt("/path/to/file.cpp", 14, 7); -} - -TEST_F(SymbolQuery, UniqueSourceIds) -{ - auto uniqueSourceIds = query.uniqueSourceIds(locations); - - ASSERT_THAT(uniqueSourceIds, ElementsAre(1, 2, 4)); -} - -TEST_F(SymbolQuery, SourcesToHashMap) -{ - std::vector sources{{1, "/path/first"}, - {2, "/path/second"}, - {4, "/path/third"}}; - - auto hashMap = query.sourcesToHashMap(sources); - - ASSERT_THAT(hashMap, UnorderedElementsAre(Pair(1, Eq("/path/first")), - Pair(2, Eq("/path/second")), - Pair(4, Eq("/path/third")))); + query.locationsAt({1, 42}, 14, 7); } } diff --git a/tests/unit/unittest/symbolscollector-test.cpp b/tests/unit/unittest/symbolscollector-test.cpp index 9b1f046cbd7..b45406c6f9d 100644 --- a/tests/unit/unittest/symbolscollector-test.cpp +++ b/tests/unit/unittest/symbolscollector-test.cpp @@ -25,9 +25,13 @@ #include "googletest.h" +#include "filesystem-utilities.h" + #include -#include "filesystem-utilities.h" +#include + +#include using testing::PrintToString; using testing::AllOf; @@ -39,26 +43,31 @@ using testing::Pair; using testing::Value; using testing::_; +using ClangBackEnd::FilePathId; +using ClangBackEnd::FilePathCaching; using ClangBackEnd::V2::FileContainers; using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SymbolEntry; using ClangBackEnd::SymbolType; using ClangBackEnd::SymbolIndex; +using Sqlite::Database; + namespace { class SymbolsCollector : public testing::Test { protected: - uint stringId(Utils::SmallStringView string) + FilePathId filePathId(Utils::SmallStringView string) { - return filePathCache.stringId(string); + return filePathCache.filePathId(string); } SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName); protected: - ClangBackEnd::FilePathCache filePathCache; + Sqlite::Database database{QDir::tempPath() + "/symbol.db"}; + FilePathCaching filePathCache{database}; ClangBackEnd::SymbolsCollector collector{filePathCache}; }; @@ -107,8 +116,8 @@ TEST_F(SymbolsCollector, CollectFilePath) ASSERT_THAT(collector.sourceLocations(), Contains( - AllOf(Field(&SourceLocationEntry::fileId, - stringId(TESTDATA_DIR"/symbolscollector_simple.cpp")), + AllOf(Field(&SourceLocationEntry::filePathId, + filePathId(TESTDATA_DIR"/symbolscollector_simple.cpp")), Field(&SourceLocationEntry::symbolType, SymbolType::Declaration)))); } diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp index 2628157a330..0f93e210a70 100644 --- a/tests/unit/unittest/symbolstorage-test.cpp +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -25,6 +25,7 @@ #include "googletest.h" +#include "mockfilepathcaching.h" #include "mocksqlitereadstatement.h" #include "mocksqlitewritestatement.h" @@ -37,7 +38,7 @@ namespace { using Utils::PathString; -using ClangBackEnd::FilePathCache; +using ClangBackEnd::FilePathCachingInterface; using ClangBackEnd::SymbolEntries; using ClangBackEnd::SymbolEntry; using ClangBackEnd::SourceLocationEntries; @@ -58,13 +59,12 @@ protected: void SetUp(); protected: - FilePathCache filePathCache; + MockFilePathCaching filePathCache; NiceMock mockMutex; NiceMock mockDatabase{mockMutex}; 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; @@ -75,8 +75,8 @@ protected: 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}}; + SourceLocationEntries sourceLocations{{1, {1, 3}, {42, 23}, SymbolType::Declaration}, + {2, {1, 4}, {7, 11}, SymbolType::Declaration}}; Storage storage{statementFactory, filePathCache}; }; @@ -125,35 +125,6 @@ TEST_F(SymbolStorage, InsertNewLocationsInLocations) 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()); @@ -180,10 +151,6 @@ TEST_F(SymbolStorage, AddSymbolsAndSourceLocationsCallsWrite) 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()); @@ -196,10 +163,6 @@ TEST_F(SymbolStorage, AddSymbolsAndSourceLocationsCallsWrite) void SymbolStorage::SetUp() { - ON_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_)) - .WillByDefault(Return(std::vector{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 25ba21f42f8..e43f59758c8 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -76,7 +76,10 @@ SOURCES += \ querysqlitestatementfactory-test.cpp \ sqliteindex-test.cpp \ sqlitetransaction-test.cpp \ - refactoringdatabaseinitializer-test.cpp + refactoringdatabaseinitializer-test.cpp \ + filepathcache-test.cpp \ + filepathstorage-test.cpp \ + filepathstoragesqlitestatementfactory-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -204,7 +207,10 @@ HEADERS += \ google-using-declarations.h \ mocksymbolindexing.h \ sqliteteststatement.h \ - mockmutex.h + mockmutex.h \ + mockfilepathstorage.h \ + mockfilepathcaching.h \ + mocksqlitestatement.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \