diff options
author | Marco Bubke <marco.bubke@qt.io> | 2017-08-17 12:44:52 +0200 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2017-09-14 13:39:55 +0000 |
commit | 3adb71d45ebebd8c8fc2ec6beeb7a5ee67d64e4e (patch) | |
tree | 7bbe767ce3f6c39f4e19428dc67e5ddb6f6c233e | |
parent | 8488ce627b82238c7737c24909d7f6164b2061dd (diff) | |
download | qt-creator-3adb71d45ebebd8c8fc2ec6beeb7a5ee67d64e4e.tar.gz |
Clang: Add Symbol Indexing
It is a first step and now a database is generated if you start QtCreator.
Some code is now shared with the PchManager which can be improved in the
future.
Change-Id: Ic267fe7960f6c455d91832859a673ce98f269aa2
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
65 files changed, 1194 insertions, 174 deletions
diff --git a/src/libs/clangsupport/clangrefactoringservermessages.h b/src/libs/clangsupport/clangrefactoringservermessages.h index 797b3d58ef..2be6f0d54d 100644 --- a/src/libs/clangsupport/clangrefactoringservermessages.h +++ b/src/libs/clangsupport/clangrefactoringservermessages.h @@ -30,3 +30,5 @@ #include "requestsourcelocationforrenamingmessage.h" #include "requestsourcerangesanddiagnosticsforquerymessage.h" #include "requestsourcerangesforquerymessage.h" +#include "updatepchprojectpartsmessage.h" +#include "removepchprojectpartsmessage.h" diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index c6584b24b0..f7bd2674ae 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -174,6 +174,7 @@ HEADERS += \ $$PWD/ipcclientprovider.h \ $$PWD/requestsourcerangesforquerymessage.h \ $$PWD/stringcachefwd.h \ - $$PWD/stringcachealgorithms.h + $$PWD/stringcachealgorithms.h \ + $$PWD/projectmanagementserverinterface.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangsupport/pchmanagerserverinterface.h b/src/libs/clangsupport/pchmanagerserverinterface.h index 58ce649997..6af04c91fe 100644 --- a/src/libs/clangsupport/pchmanagerserverinterface.h +++ b/src/libs/clangsupport/pchmanagerserverinterface.h @@ -25,7 +25,7 @@ #pragma once -#include "ipcserverinterface.h" +#include "projectmanagementserverinterface.h" #include <memory> @@ -35,15 +35,12 @@ class PchManagerClientInterface; class RemovePchProjectPartsMessage; class UpdatePchProjectPartsMessage; - -class CMBIPC_EXPORT PchManagerServerInterface : public IpcServerInterface +class CMBIPC_EXPORT PchManagerServerInterface : public ProjectManagementServerInterface { public: void dispatch(const MessageEnvelop &messageEnvelop) override; virtual void end() = 0; - virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0; - virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectmanagementserverinterface.h b/src/libs/clangsupport/projectmanagementserverinterface.h new file mode 100644 index 0000000000..5704db417c --- /dev/null +++ b/src/libs/clangsupport/projectmanagementserverinterface.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 "ipcserverinterface.h" + +namespace ClangBackEnd { + +class RemovePchProjectPartsMessage; +class UpdatePchProjectPartsMessage; + +class CMBIPC_EXPORT ProjectManagementServerInterface : public IpcInterface +{ +public: + virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0; + virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/refactoringserverinterface.cpp b/src/libs/clangsupport/refactoringserverinterface.cpp index d6b0f6815b..52ab7834b0 100644 --- a/src/libs/clangsupport/refactoringserverinterface.cpp +++ b/src/libs/clangsupport/refactoringserverinterface.cpp @@ -47,6 +47,12 @@ void RefactoringServerInterface::dispatch(const MessageEnvelop &messageEnvelop) case MessageType::RequestSourceRangesForQueryMessage: requestSourceRangesForQueryMessage(messageEnvelop.message<RequestSourceRangesForQueryMessage>()); break; + case MessageType::UpdatePchProjectPartsMessage: + updatePchProjectParts(messageEnvelop.message<UpdatePchProjectPartsMessage>()); + break; + case MessageType::RemovePchProjectPartsMessage: + removePchProjectParts(messageEnvelop.message<RemovePchProjectPartsMessage>()); + break; case MessageType::CancelMessage: cancel(); break; diff --git a/src/libs/clangsupport/refactoringserverinterface.h b/src/libs/clangsupport/refactoringserverinterface.h index 8c36a7351e..a4a3b1e6f4 100644 --- a/src/libs/clangsupport/refactoringserverinterface.h +++ b/src/libs/clangsupport/refactoringserverinterface.h @@ -25,7 +25,7 @@ #pragma once -#include "ipcserverinterface.h" +#include "projectmanagementserverinterface.h" #include <memory> @@ -36,8 +36,10 @@ class RequestSourceLocationsForRenamingMessage; class RequestSourceRangesAndDiagnosticsForQueryMessage; class RequestSourceRangesForQueryMessage; class CancelMessage; +class UpdatePchProjectPartsMessage; +class RemovePchProjectPartsMessage; -class CMBIPC_EXPORT RefactoringServerInterface : public IpcServerInterface +class CMBIPC_EXPORT RefactoringServerInterface : public ProjectManagementServerInterface { public: diff --git a/src/libs/clangsupport/refactoringserverproxy.cpp b/src/libs/clangsupport/refactoringserverproxy.cpp index 0cf4473f07..cc6741b118 100644 --- a/src/libs/clangsupport/refactoringserverproxy.cpp +++ b/src/libs/clangsupport/refactoringserverproxy.cpp @@ -62,6 +62,16 @@ void RefactoringServerProxy::requestSourceRangesForQueryMessage(RequestSourceRan writeMessageBlock.write(message); } +void RefactoringServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) +{ + writeMessageBlock.write(message); +} + +void RefactoringServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message) +{ + writeMessageBlock.write(message); +} + void RefactoringServerProxy::cancel() { writeMessageBlock.write(CancelMessage()); diff --git a/src/libs/clangsupport/refactoringserverproxy.h b/src/libs/clangsupport/refactoringserverproxy.h index 9b10e37529..611155b511 100644 --- a/src/libs/clangsupport/refactoringserverproxy.h +++ b/src/libs/clangsupport/refactoringserverproxy.h @@ -53,6 +53,8 @@ public: void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override; void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override; + void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; + void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; void cancel() override; void readMessages(); diff --git a/src/libs/clangsupport/stringcache.h b/src/libs/clangsupport/stringcache.h index e38649488c..6d5f4e986b 100644 --- a/src/libs/clangsupport/stringcache.h +++ b/src/libs/clangsupport/stringcache.h @@ -125,12 +125,7 @@ public: { std::lock_guard<Mutex> lock(m_mutex); - Found found = find(stringView); - - if (!found.wasFound) - return insertString(found.iterator, stringView); - - return found.iterator->id; + return ungardedStringId(stringView); } template <typename Container> @@ -144,7 +139,7 @@ public: std::transform(strings.begin(), strings.end(), std::back_inserter(ids), - [&] (const auto &string) { return this->stringId(string); }); + [&] (const auto &string) { return this->ungardedStringId(string); }); return ids; } @@ -182,6 +177,16 @@ public: } private: + IndexType ungardedStringId(Utils::SmallStringView stringView) + { + Found found = find(stringView); + + if (!found.wasFound) + return insertString(found.iterator, stringView); + + return found.iterator->id; + } + Found find(Utils::SmallStringView stringView) { return findInSorted(m_strings.cbegin(), m_strings.cend(), stringView, compare); diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri index a953a70e0a..67c8c6b937 100644 --- a/src/libs/sqlite/sqlite-lib.pri +++ b/src/libs/sqlite/sqlite-lib.pri @@ -43,7 +43,8 @@ HEADERS += \ $$PWD/utf8stringvector.h \ $$PWD/sqlitedatabase.h \ $$PWD/sqlitetable.h \ - $$PWD/sqlitecolumn.h + $$PWD/sqlitecolumn.h \ + $$PWD/sqliteindex.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/sqlitecolumn.h b/src/libs/sqlite/sqlitecolumn.h index e25ee68b2d..a253aee488 100644 --- a/src/libs/sqlite/sqlitecolumn.h +++ b/src/libs/sqlite/sqlitecolumn.h @@ -29,6 +29,8 @@ #include <utils/smallstring.h> +#include <functional> + namespace Sqlite { class SqliteColumn @@ -108,5 +110,7 @@ private: }; using SqliteColumns = std::vector<SqliteColumn>; +using SqliteColumnConstReference = std::reference_wrapper<const SqliteColumn>; +using SqliteColumnConstReferences = std::vector<SqliteColumnConstReference>; } // namespace Sqlite diff --git a/src/libs/sqlite/sqliteindex.h b/src/libs/sqlite/sqliteindex.h new file mode 100644 index 0000000000..a6d92432d3 --- /dev/null +++ b/src/libs/sqlite/sqliteindex.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 "sqliteglobal.h" + +#include "sqliteexception.h" + +#include <utils/smallstringvector.h> + +namespace Sqlite { + +class SqliteIndex +{ +public: + SqliteIndex(Utils::SmallString &&tableName, Utils::SmallStringVector &&columnNames) + : m_tableName(std::move(tableName)), + m_columnNames(std::move(columnNames)) + { + } + + Utils::SmallString sqlStatement() const + { + checkTableName(); + checkColumns(); + + return {"CREATE INDEX IF NOT EXISTS index_", + m_tableName, + "_", + m_columnNames.join("_"), + " ON ", + m_tableName, + "(", + m_columnNames.join(", "), + ")" + }; + } + + void checkTableName() const + { + if (m_tableName.isEmpty()) + throw SqliteException("SqliteIndex has not table name!"); + } + + void checkColumns() const + { + if (m_columnNames.empty()) + throw SqliteException("SqliteIndex has no columns!"); + } + +private: + Utils::SmallString m_tableName; + Utils::SmallStringVector m_columnNames; +}; + +using SqliteIndices = std::vector<SqliteIndex>; + +} // diff --git a/src/libs/sqlite/sqlitetable.h b/src/libs/sqlite/sqlitetable.h index d9e7d5cd16..be63e5ae5e 100644 --- a/src/libs/sqlite/sqlitetable.h +++ b/src/libs/sqlite/sqlitetable.h @@ -28,6 +28,7 @@ #include "createtablesqlstatementbuilder.h" #include "sqliteglobal.h" #include "sqlitecolumn.h" +#include "sqliteindex.h" #include "sqliteexception.h" namespace Sqlite { @@ -37,6 +38,12 @@ class SqliteDatabase; class SqliteTable { public: + SqliteTable(std::size_t reserve = 10) + { + m_sqliteColumns.reserve(reserve); + m_sqliteIndices.reserve(reserve); + } + void setName(Utils::SmallString &&name) { m_tableName = std::move(name); @@ -76,6 +83,13 @@ public: return m_sqliteColumns.back(); } + SqliteIndex &addIndex(const SqliteColumnConstReferences &columns) + { + m_sqliteIndices.emplace_back(m_tableName.clone(), sqliteColumnNames(columns)); + + return m_sqliteIndices.back(); + } + const SqliteColumns &columns() const { return m_sqliteColumns; @@ -89,22 +103,25 @@ public: template <typename Database> void initialize(Database &database) { - try { - CreateTableSqlStatementBuilder builder; + CreateTableSqlStatementBuilder builder; - builder.setTableName(m_tableName.clone()); - builder.setUseWithoutRowId(m_withoutRowId); - builder.setUseIfNotExists(m_useIfNotExists); - builder.setUseTemporaryTable(m_useTemporaryTable); - builder.setColumns(m_sqliteColumns); + builder.setTableName(m_tableName.clone()); + builder.setUseWithoutRowId(m_withoutRowId); + builder.setUseIfNotExists(m_useIfNotExists); + builder.setUseTemporaryTable(m_useTemporaryTable); + builder.setColumns(m_sqliteColumns); - database.execute(builder.sqlStatement()); + database.execute(builder.sqlStatement()); - m_isReady = true; + initializeIndices(database); - } catch (const SqliteException &exception) { - exception.printWarning(); - } + m_isReady = true; + } + template <typename Database> + void initializeIndices(Database &database) + { + for (const SqliteIndex &index : m_sqliteIndices) + database.execute(index.sqlStatement()); } friend bool operator==(const SqliteTable &first, const SqliteTable &second) @@ -117,8 +134,20 @@ public: } private: + Utils::SmallStringVector sqliteColumnNames(const SqliteColumnConstReferences &columns) + { + Utils::SmallStringVector columnNames; + + for (const SqliteColumn &column : columns) + columnNames.push_back(column.name()); + + return columnNames; + } + +private: Utils::SmallString m_tableName; SqliteColumns m_sqliteColumns; + SqliteIndices m_sqliteIndices; bool m_withoutRowId = false; bool m_useIfNotExists = false; bool m_useTemporaryTable = false; diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h index 373b33fd8a..2b817123f1 100644 --- a/src/libs/sqlite/sqlitetransaction.h +++ b/src/libs/sqlite/sqlitetransaction.h @@ -36,7 +36,7 @@ template <typename Database> class SqliteAbstractTransaction { public: - virtual ~SqliteAbstractTransaction() + ~SqliteAbstractTransaction() { if (!m_isAlreadyCommited) m_database.execute("ROLLBACK"); @@ -68,7 +68,6 @@ public: { database.execute("BEGIN"); } - }; template <typename Database> @@ -80,7 +79,6 @@ public: { database.execute("BEGIN IMMEDIATE"); } - }; template <typename Database> @@ -92,7 +90,6 @@ public: { database.execute("BEGIN EXCLUSIVE"); } - }; } // namespace Sqlite diff --git a/src/plugins/clangpchmanager/clangpchmanager-source.pri b/src/plugins/clangpchmanager/clangpchmanager-source.pri index fd5b61a24d..25d8d63730 100644 --- a/src/plugins/clangpchmanager/clangpchmanager-source.pri +++ b/src/plugins/clangpchmanager/clangpchmanager-source.pri @@ -11,12 +11,14 @@ HEADERS += \ $$PWD/pchmanagernotifierinterface.h \ $$PWD/pchmanagerconnectionclient.h \ $$PWD/clangpchmanager_global.h \ - $$PWD/projectupdater.h + $$PWD/projectupdater.h \ + $$PWD/pchmanagerprojectupdater.h SOURCES += \ $$PWD/pchmanagerclient.cpp \ $$PWD/pchmanagernotifierinterface.cpp \ $$PWD/pchmanagerconnectionclient.cpp \ - $$PWD/projectupdater.cpp + $$PWD/projectupdater.cpp \ + $$PWD/pchmanagerprojectupdater.cpp diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp index 4c53696807..086b2fce8e 100644 --- a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp +++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp @@ -52,7 +52,7 @@ class ClangPchManagerPluginData public: PchManagerClient pchManagerClient; PchManagerConnectionClient connectionClient{&pchManagerClient}; - QtCreatorProjectUpdater projectUpdate{connectionClient.serverProxy(), pchManagerClient}; + QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(), pchManagerClient}; }; std::unique_ptr<ClangPchManagerPluginData> ClangPchManagerPlugin::d; diff --git a/src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp b/src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp new file mode 100644 index 0000000000..d74ea2a7b0 --- /dev/null +++ b/src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** 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 "pchmanagerprojectupdater.h" + +#include "pchmanagerclient.h" + +namespace ClangPchManager { + +PchManagerProjectUpdater::PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server, + PchManagerClient &client) + : ProjectUpdater(server), + m_client(client) +{ +} + +void PchManagerProjectUpdater::removeProjectParts(const QStringList &projectPartIds) +{ + ProjectUpdater::removeProjectParts(projectPartIds); + + for (const QString &projectPartiId : projectPartIds) + m_client.precompiledHeaderRemoved(projectPartiId); +} + +} // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/pchmanagerprojectupdater.h b/src/plugins/clangpchmanager/pchmanagerprojectupdater.h new file mode 100644 index 0000000000..0849554751 --- /dev/null +++ b/src/plugins/clangpchmanager/pchmanagerprojectupdater.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** 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 "projectupdater.h" + +namespace ClangPchManager { + +class PchManagerProjectUpdater : public ProjectUpdater +{ +public: + PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server, + PchManagerClient &client); + + void removeProjectParts(const QStringList &projectPartIds); + +private: + PchManagerClient &m_client; +}; + +} // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp index 9d5d7c7577..046c5f769f 100644 --- a/src/plugins/clangpchmanager/projectupdater.cpp +++ b/src/plugins/clangpchmanager/projectupdater.cpp @@ -52,10 +52,8 @@ public: Utils::PathStringVector sources; }; -ProjectUpdater::ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, - PchManagerClient &client) - : m_server(server), - m_client(client) +ProjectUpdater::ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server) + : m_server(server) { } @@ -75,9 +73,6 @@ void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds) ClangBackEnd::RemovePchProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)}; m_server.removePchProjectParts(std::move(message)); - - for (const QString &projectPartiId : projectPartIds) - m_client.precompiledHeaderRemoved(projectPartiId); } void ProjectUpdater::setExcludedPaths(Utils::PathStringVector &&excludedPaths) diff --git a/src/plugins/clangpchmanager/projectupdater.h b/src/plugins/clangpchmanager/projectupdater.h index 60fd636408..e207a88971 100644 --- a/src/plugins/clangpchmanager/projectupdater.h +++ b/src/plugins/clangpchmanager/projectupdater.h @@ -35,7 +35,7 @@ class ProjectFile; } namespace ClangBackEnd { -class PchManagerServerInterface; +class ProjectManagementServerInterface; namespace V2 { class ProjectPartContainer; @@ -51,11 +51,10 @@ namespace ClangPchManager { class HeaderAndSources; class PchManagerClient; -class ProjectUpdater +class CLANGPCHMANAGER_EXPORT ProjectUpdater { public: - ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, - PchManagerClient &client); + ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server); void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts, ClangBackEnd::V2::FileContainers &&generatedFiles); @@ -77,8 +76,7 @@ unittest_public: private: Utils::PathStringVector m_excludedPaths; - ClangBackEnd::PchManagerServerInterface &m_server; - PchManagerClient &m_client; + ClangBackEnd::ProjectManagementServerInterface &m_server; }; } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp b/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp index 6ac93c747a..53b37ee2b5 100644 --- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp +++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp @@ -26,26 +26,18 @@ #include "qtcreatorprojectupdater.h" #include <cpptools/abstracteditorsupport.h> -#include <cpptools/cppmodelmanager.h> #include <projectexplorer/project.h> namespace ClangPchManager { -static CppTools::CppModelManager *cppModelManager() -{ - return CppTools::CppModelManager::instance(); -} +namespace Internal { -QtCreatorProjectUpdater::QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, - PchManagerClient &client) - : ProjectUpdater(server, client) +CppTools::CppModelManager *cppModelManager() { - connectToCppModelManager(); + return CppTools::CppModelManager::instance(); } -namespace { - std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles() { auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); @@ -85,30 +77,7 @@ std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project convertToRawPointer); return projectParts; -} - -} -void QtCreatorProjectUpdater::projectPartsUpdated(ProjectExplorer::Project *project) -{ - updateProjectParts(createProjectParts(project), createGeneratedFiles()); -} - -void QtCreatorProjectUpdater::projectPartsRemoved(const QStringList &projectPartIds) -{ - removeProjectParts(projectPartIds); } - -void QtCreatorProjectUpdater::connectToCppModelManager() -{ - connect(cppModelManager(), - &CppTools::CppModelManager::projectPartsUpdated, - this, - &QtCreatorProjectUpdater::projectPartsUpdated); - connect(cppModelManager(), - &CppTools::CppModelManager::projectPartsRemoved, - this, - &QtCreatorProjectUpdater::projectPartsRemoved); -} - +} // namespace Internal } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h index ec99eab50e..44858ef936 100644 --- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h +++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h @@ -25,7 +25,11 @@ #pragma once -#include "projectupdater.h" +#include "pchmanagerprojectupdater.h" + +#include <cpptools/cppmodelmanager.h> + +#include <filecontainerv2.h> #include <QObject> @@ -33,19 +37,57 @@ namespace ProjectExplorer { class Project; } +namespace CppTools { +class CppModelManager; +} + namespace ClangPchManager { -class QtCreatorProjectUpdater : public QObject, public ProjectUpdater +namespace Internal { +CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager(); +CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(); +CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project *project); +} + +template <typename ProjectUpdaterType> +class QtCreatorProjectUpdater : public ProjectUpdaterType { public: - QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, - PchManagerClient &client); + template <typename ClientType> + QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server, + ClientType &client) + : ProjectUpdaterType(server, client) + { + connectToCppModelManager(); + } + + QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server) + : ProjectUpdaterType(server) + { + connectToCppModelManager(); + } + + void projectPartsUpdated(ProjectExplorer::Project *project) + { + ProjectUpdaterType::updateProjectParts(Internal::createProjectParts(project), + Internal::createGeneratedFiles()); + } - void projectPartsUpdated(ProjectExplorer::Project *project); - void projectPartsRemoved(const QStringList &projectPartIds); + void projectPartsRemoved(const QStringList &projectPartIds) + { + ProjectUpdaterType::removeProjectParts(projectPartIds); + } private: - void connectToCppModelManager(); + void connectToCppModelManager() + { + QObject::connect(Internal::cppModelManager(), + &CppTools::CppModelManager::projectPartsUpdated, + [&] (ProjectExplorer::Project *project) { projectPartsUpdated(project); }); + QObject::connect(Internal::cppModelManager(), + &CppTools::CppModelManager::projectPartsRemoved, + [&] (const QStringList &projectPartIds) { projectPartsRemoved(projectPartIds); }); + } }; } // namespace ClangPchManager diff --git a/src/plugins/clangrefactoring/clangrefactoring-source.pri b/src/plugins/clangrefactoring/clangrefactoring-source.pri index 24102dfd99..b08d292190 100644 --- a/src/plugins/clangrefactoring/clangrefactoring-source.pri +++ b/src/plugins/clangrefactoring/clangrefactoring-source.pri @@ -11,7 +11,8 @@ HEADERS += \ $$PWD/clangqueryexamplehighlightmarker.h \ $$PWD/clangqueryhighlightmarker.h \ $$PWD/clangqueryexamplehighlighter.h \ - $$PWD/clangqueryhighlighter.h + $$PWD/clangqueryhighlighter.h \ + $$PWD/refactoringprojectupdater.h SOURCES += \ $$PWD/refactoringengine.cpp \ @@ -22,4 +23,5 @@ SOURCES += \ $$PWD/projectpartutilities.cpp \ $$PWD/clangqueryprojectsfindfilter.cpp \ $$PWD/clangqueryexamplehighlighter.cpp \ - $$PWD/clangqueryhighlighter.cpp + $$PWD/clangqueryhighlighter.cpp \ + $$PWD/refactoringprojectupdater.cpp diff --git a/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri b/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri index ed775ae4fc..8a08236177 100644 --- a/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri +++ b/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri @@ -5,4 +5,5 @@ QTC_LIB_DEPENDS += \ QTC_PLUGIN_DEPENDS += \ coreplugin \ cpptools \ - texteditor + texteditor \ + clangpchmanager diff --git a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp index 921cc24005..ea17409fac 100644 --- a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp +++ b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp @@ -25,6 +25,8 @@ #include "clangrefactoringplugin.h" +#include <clangpchmanager/qtcreatorprojectupdater.h> + #include <cpptools/cppmodelmanager.h> #include <coreplugin/icore.h> @@ -50,6 +52,7 @@ std::unique_ptr<ClangRefactoringPluginData> ClangRefactoringPlugin::d; class ClangRefactoringPluginData { + using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>; public: RefactoringClient refactoringClient; ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient}; @@ -58,6 +61,9 @@ public: QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(), qtCreatorSearch, refactoringClient}; + ProjectUpdater projectUpdate{connectionClient.serverProxy()}; + + }; ClangRefactoringPlugin::ClangRefactoringPlugin() diff --git a/src/plugins/clangrefactoring/refactoringprojectupdater.cpp b/src/plugins/clangrefactoring/refactoringprojectupdater.cpp new file mode 100644 index 0000000000..07a9e97163 --- /dev/null +++ b/src/plugins/clangrefactoring/refactoringprojectupdater.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** 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 "refactoringprojectupdater.h" + +namespace ClangRefactoring { + +RefactoringProjectUpdater::RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server, + RefactoringClient &) + : ClangPchManager::ProjectUpdater(server) +{ + +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/refactoringprojectupdater.h b/src/plugins/clangrefactoring/refactoringprojectupdater.h new file mode 100644 index 0000000000..3debed0c4d --- /dev/null +++ b/src/plugins/clangrefactoring/refactoringprojectupdater.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <clangpchmanager/projectupdater.h> + +namespace ClangRefactoring { + +class RefactoringClient; + +class RefactoringProjectUpdater : public ClangPchManager::ProjectUpdater +{ +public: + RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server, + RefactoringClient &client); +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/sourcelocations.h b/src/plugins/clangrefactoring/sourcelocations.h index e4cb1df450..fe2d3dace9 100644 --- a/src/plugins/clangrefactoring/sourcelocations.h +++ b/src/plugins/clangrefactoring/sourcelocations.h @@ -50,6 +50,13 @@ public: Utils::PathString sourcePath; }; + enum LocationGetter + { + SourceId = 0, + Line, + Column + }; + std::vector<Location> locations; std::unordered_map<qint64, Utils::PathString> sources; }; diff --git a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp index fca9a0c9fc..fcf6f12f1f 100644 --- a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp +++ b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp @@ -26,14 +26,19 @@ #include <QCommandLineParser> #include <QCoreApplication> #include <QLoggingCategory> +#include <QDir> #include <connectionserver.h> +#include <stringcache.h> #include <refactoringserver.h> #include <refactoringclientproxy.h> +#include <symbolindexing.h> +using ClangBackEnd::FilePathCache; using ClangBackEnd::RefactoringClientProxy; using ClangBackEnd::RefactoringServer; using ClangBackEnd::ConnectionServer; +using ClangBackEnd::SymbolIndexing; QString processArguments(QCoreApplication &application) { @@ -52,7 +57,7 @@ QString processArguments(QCoreApplication &application) } int main(int argc, char *argv[]) -{ +try { //QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false")); QCoreApplication::setOrganizationName(QStringLiteral("QtProject")); @@ -64,13 +69,17 @@ int main(int argc, char *argv[]) const QString connection = processArguments(application); - RefactoringServer clangCodeModelServer; + FilePathCache<std::mutex> filePathCache; + SymbolIndexing symbolIndexing{filePathCache, Utils::PathString{QDir::tempPath() + "/symbol.db"}}; + RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache}; ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection); connectionServer.start(); connectionServer.setServer(&clangCodeModelServer); return application.exec(); +} catch (const Sqlite::SqliteException &exception) { + exception.printWarning(); } diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index 21748bb071..8ed0c6803c 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -9,7 +9,9 @@ HEADERS += \ $$PWD/symbolscollectorinterface.h \ $$PWD/symbolstorageinterface.h \ $$PWD/symbolstorage.h \ - $$PWD/storagesqlitestatementfactory.h + $$PWD/storagesqlitestatementfactory.h \ + $$PWD/symbolindexing.h \ + $$PWD/symbolindexinginterface.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -55,4 +57,5 @@ SOURCES += \ $$PWD/symbolindexer.cpp \ $$PWD/symbolentry.cpp \ $$PWD/sourcelocationentry.cpp \ - $$PWD/symbolstorage.cpp + $$PWD/symbolstorage.cpp \ + $$PWD/symbolindexing.cpp diff --git a/src/tools/clangrefactoringbackend/source/clangtool.h b/src/tools/clangrefactoringbackend/source/clangtool.h index 7957bb7044..0f436a0e37 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.h +++ b/src/tools/clangrefactoringbackend/source/clangtool.h @@ -110,4 +110,11 @@ private: std::vector<UnsavedFileContent> m_unsavedFileContents; }; +extern template +void ClangTool::addFiles<Utils::SmallStringVector>(const Utils::SmallStringVector &filePaths, + const Utils::SmallStringVector &arguments); +extern template +void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths, + const Utils::SmallStringVector &arguments); + } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h index ceaf0ee85b..1ddd34b595 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h @@ -35,12 +35,14 @@ #include <clang/Frontend/FrontendAction.h> +#include <mutex> + namespace ClangBackEnd { class CollectSymbolsAction { public: - CollectSymbolsAction(FilePathCache<> &filePathCache) + CollectSymbolsAction(FilePathCache<std::mutex> &filePathCache) : m_filePathCache(filePathCache) {} @@ -64,7 +66,7 @@ public: private: SymbolEntries m_symbolEntries; SourceLocationEntries m_sourceLocationEntries; - FilePathCache<> &m_filePathCache; + FilePathCache<std::mutex> &m_filePathCache; }; diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h index 837ede57da..fcedd6a6d0 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h @@ -50,7 +50,7 @@ class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbol public: CollectSymbolsASTVisitor(SymbolEntries &symbolEntries, SourceLocationEntries &sourceLocationEntries, - FilePathCache<> &filePathCache, + FilePathCache<std::mutex> &filePathCache, const clang::SourceManager &sourceManager) : m_symbolEntries(symbolEntries), m_sourceLocationEntries(sourceLocationEntries), @@ -58,8 +58,16 @@ public: m_sourceManager(sourceManager) {} + bool shouldVisitTemplateInstantiations() const + { + return true; + } + bool VisitNamedDecl(const clang::NamedDecl *declaration) { + if (!declaration->getIdentifier()) + return true; + SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl()); auto sourceLocation = declaration->getLocation(); @@ -141,7 +149,7 @@ private: SymbolEntries &m_symbolEntries; std::unordered_map<uint, FilePathIndex> m_filePathIndices; SourceLocationEntries &m_sourceLocationEntries; - FilePathCache<> &m_filePathCache; + FilePathCache<std::mutex> &m_filePathCache; const clang::SourceManager &m_sourceManager; }; diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h b/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h index 035db37ebc..0eeb7a73f2 100644 --- a/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h +++ b/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h @@ -40,13 +40,14 @@ class CollectSymbolsConsumer : public clang::ASTConsumer public: CollectSymbolsConsumer(SymbolEntries &symbolEntries, SourceLocationEntries &sourceLocationEntries, - FilePathCache<> &filePathCache) + FilePathCache<std::mutex> &filePathCache) : m_symbolEntries(symbolEntries), m_sourceLocationEntries(sourceLocationEntries), m_filePathCache(filePathCache) {} - void HandleTranslationUnit(clang::ASTContext &astContext) override { + void HandleTranslationUnit(clang::ASTContext &astContext) override + { CollectSymbolsASTVisitor visitor{m_symbolEntries, m_sourceLocationEntries, m_filePathCache, @@ -54,9 +55,20 @@ public: visitor.TraverseDecl(astContext.getTranslationUnitDecl()); } + bool shouldSkipFunctionBody(clang::Decl *declation) override + { + const clang::SourceManager &sourceManager = declation->getASTContext().getSourceManager(); + const clang::SourceLocation location = declation->getLocation(); + + if (sourceManager.isInSystemHeader(location)) + return true; + + return false; + } + private: SymbolEntries &m_symbolEntries; SourceLocationEntries &m_sourceLocationEntries; - FilePathCache<> &m_filePathCache; + FilePathCache<std::mutex> &m_filePathCache; }; } diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index 043fa87711..84b588118e 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -27,6 +27,7 @@ #include "symbolfinder.h" #include "clangquery.h" +#include "symbolindexing.h" #include <refactoringclientinterface.h> #include <clangrefactoringmessages.h> @@ -38,7 +39,10 @@ namespace ClangBackEnd { -RefactoringServer::RefactoringServer() +RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing, + FilePathCache<std::mutex> &filePathCache) + : m_symbolIndexing(symbolIndexing), + m_filePathCache(filePathCache) { m_pollTimer.setInterval(100); @@ -88,7 +92,17 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo { gatherSourceRangesForQueryMessages(message.takeSources(), message.takeUnsavedContent(), - message.takeQuery()); + message.takeQuery()); +} + +void RefactoringServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) +{ + m_symbolIndexing.updateProjectParts(message.takeProjectsParts(), message.takeGeneratedFiles()); +} + +void RefactoringServer::removePchProjectParts(RemovePchProjectPartsMessage &&) +{ + } void RefactoringServer::cancel() diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h index 33eaee2a0a..b11cf3fc21 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.h +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h @@ -42,6 +42,7 @@ namespace ClangBackEnd { class SourceRangesForQueryMessage; +class SymbolIndexingInterface; namespace V2 { class FileContainer; @@ -52,12 +53,15 @@ class RefactoringServer : public RefactoringServerInterface, { using Future = std::future<SourceRangesForQueryMessage>; public: - RefactoringServer(); + RefactoringServer(SymbolIndexingInterface &symbolIndexing, + FilePathCache<std::mutex> &filePathCache); void end() override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override; void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override; + void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; + void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; void cancel() override; bool isCancelingJobs() const; @@ -75,9 +79,10 @@ private: Utils::SmallString &&query); private: - FilePathCache<std::mutex> m_filePathCache; ClangQueryGatherer m_gatherer; QTimer m_pollTimer; + SymbolIndexingInterface &m_symbolIndexing; + FilePathCache<std::mutex> &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h index 22bd7cf5f5..8e1149ca3f 100644 --- a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h +++ b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h @@ -53,8 +53,9 @@ public: table.setUseIfNotExists(true); table.setName("symbols"); table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); - table.addColumn("usr", Sqlite::ColumnType::Text); + const Sqlite::SqliteColumn &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text); table.addColumn("symbolName", Sqlite::ColumnType::Text); + table.addIndex({usrColumn}); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); table.initialize(database); @@ -71,7 +72,8 @@ public: table.addColumn("symbolId", Sqlite::ColumnType::Integer); table.addColumn("line", Sqlite::ColumnType::Integer); table.addColumn("column", Sqlite::ColumnType::Integer); - table.addColumn("sourceId", Sqlite::ColumnType::Integer); + const Sqlite::SqliteColumn &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); + table.addIndex({sourceIdColumn}); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); table.initialize(database); @@ -101,9 +103,11 @@ public: table.setName("newSymbols"); table.setUseTemporaryTable(true); table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); - table.addColumn("symbolId", Sqlite::ColumnType::Integer); - table.addColumn("usr", Sqlite::ColumnType::Text); - table.addColumn("symbolName", Sqlite::ColumnType::Text); + const Sqlite::SqliteColumn &symbolIdColumn = table.addColumn("symbolId", Sqlite::ColumnType::Integer); + const Sqlite::SqliteColumn &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text); + const Sqlite::SqliteColumn &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text); + table.addIndex({usrColumn, symbolNameColumn}); + table.addIndex({symbolIdColumn}); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); table.initialize(database); @@ -121,7 +125,8 @@ public: table.addColumn("symbolId", Sqlite::ColumnType::Integer); table.addColumn("line", Sqlite::ColumnType::Integer); table.addColumn("column", Sqlite::ColumnType::Integer); - table.addColumn("sourceId", Sqlite::ColumnType::Integer); + const Sqlite::SqliteColumn &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); + table.addIndex({sourceIdColumn}); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); table.initialize(database); @@ -142,39 +147,49 @@ public: database}; WriteStatement insertLocationsToNewLocationsStatement{ "INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)", - database}; + 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}; + database + }; WriteStatement addNewSymbolsToSymbolsStatement{ - "INSERT INTO symbols(usr, symbolname) " - "SELECT usr, symbolname FROM newsymbols WHERE NOT EXISTS " - "(SELECT usr FROM symbols WHERE usr == newsymbols.usr)", - database}; + "INSERT INTO symbols(usr, symbolName) " + "SELECT usr, symbolName FROM newSymbols WHERE NOT EXISTS " + "(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)", + database + }; WriteStatement insertSourcesStatement{ "INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)", - database}; + database + }; WriteStatement syncNewSymbolsFromSymbolsStatement{ "UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)", - database}; + database + }; WriteStatement syncSymbolsIntoNewLocationsStatement{ "UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)", - database}; + database + }; WriteStatement deleteAllLocationsFromUpdatedFilesStatement{ "DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)", - database}; + database + }; WriteStatement insertNewLocationsInLocationsStatement{ "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations", - database}; + database + }; WriteStatement deleteNewSymbolsTableStatement{ "DELETE FROM newSymbols", - database}; + database + }; WriteStatement deleteNewLocationsTableStatement{ "DELETE FROM newLocations", - database}; + database + }; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp index 477c7c72f4..ed48d920a6 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp @@ -33,11 +33,14 @@ SymbolIndexer::SymbolIndexer(SymbolsCollectorInterface &symbolsCollector, Symbol { } -void SymbolIndexer::updateProjectParts(V2::ProjectPartContainers &&projectParts) +void SymbolIndexer::updateProjectParts(V2::ProjectPartContainers &&projectParts, + V2::FileContainers &&generatedFiles) { for (const V2::ProjectPartContainer &projectPart : projectParts) m_symbolsCollector.addFiles(projectPart.sourcePaths(), projectPart.arguments()); + m_symbolsCollector.addUnsavedFiles(generatedFiles); + m_symbolsCollector.collectSymbols(); m_symbolStorage.addSymbolsAndSourceLocations(m_symbolsCollector.symbols(), diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.h b/src/tools/clangrefactoringbackend/source/symbolindexer.h index 625fc21c98..283e761da5 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.h @@ -29,6 +29,7 @@ #include "symbolstorageinterface.h" #include <projectpartcontainerv2.h> +#include <filecontainerv2.h> namespace ClangBackEnd { @@ -38,7 +39,8 @@ public: SymbolIndexer(SymbolsCollectorInterface &symbolsCollector, SymbolStorageInterface &symbolStorage); - void updateProjectParts(V2::ProjectPartContainers &&projectParts); + void updateProjectParts(V2::ProjectPartContainers &&projectParts, + V2::FileContainers &&generatedFiles); private: SymbolsCollectorInterface &m_symbolsCollector; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.cpp b/src/tools/clangrefactoringbackend/source/symbolindexing.cpp new file mode 100644 index 0000000000..11e34e449f --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolindexing.cpp @@ -0,0 +1,30 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "symbolindexing.h" + +namespace ClangBackEnd { + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h new file mode 100644 index 0000000000..2986f6e4ce --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 "symbolindexinginterface.h" + +#include "storagesqlitestatementfactory.h" +#include "symbolindexer.h" +#include "symbolscollector.h" +#include "symbolstorage.h" + +#include <stringcache.h> + +#include <sqlitedatabase.h> +#include <sqlitereadstatement.h> +#include <sqlitewritestatement.h> + +namespace ClangBackEnd { + +class SymbolIndexing final : public SymbolIndexingInterface +{ +public: + using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<Sqlite::SqliteDatabase, + Sqlite::SqliteReadStatement, + Sqlite::SqliteWriteStatement>; + using Storage = ClangBackEnd::SymbolStorage<StatementFactory>; + + SymbolIndexing(FilePathCache<std::mutex> &filePathCache, + Utils::PathString &&databaseFilePath) + : m_filePathCache(filePathCache), + m_database(std::move(databaseFilePath)) + + { + } + + SymbolIndexer &indexer() + { + return m_indexer; + } + + Sqlite::SqliteDatabase &database() + { + return m_database; + } + + void updateProjectParts(V2::ProjectPartContainers &&projectParts, + V2::FileContainers &&generatedFiles) + { + m_indexer.updateProjectParts(std::move(projectParts), std::move(generatedFiles)); + } + +private: + FilePathCache<std::mutex> &m_filePathCache; + Sqlite::SqliteDatabase m_database; + SymbolsCollector m_collector{m_filePathCache}; + StatementFactory m_statementFactory{m_database}; + Storage m_symbolStorage{m_statementFactory, m_filePathCache}; + SymbolIndexer m_indexer{m_collector, m_symbolStorage}; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexinginterface.h b/src/tools/clangrefactoringbackend/source/symbolindexinginterface.h new file mode 100644 index 0000000000..8c331aadce --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolindexinginterface.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** 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 <projectpartcontainerv2.h> +#include <filecontainerv2.h> + +namespace ClangBackEnd { + +class SymbolIndexingInterface +{ +public: + virtual void updateProjectParts(V2::ProjectPartContainers &&projectParts, + V2::FileContainers &&generatedFiles) = 0; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp index f83d71e1c1..c759232a04 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(FilePathCache<std::mutex> &filePathCache) : m_collectSymbolsAction(filePathCache) { } @@ -37,6 +37,11 @@ void SymbolsCollector::addFiles(const Utils::PathStringVector &filePaths, const ClangTool::addFiles(filePaths, arguments); } +void SymbolsCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles) +{ + ClangTool::addUnsavedFiles(unsavedFiles); +} + void SymbolsCollector::collectSymbols() { auto tool = createTool(); diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.h b/src/tools/clangrefactoringbackend/source/symbolscollector.h index d0eb020158..6bbdfbcf9e 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.h @@ -37,11 +37,13 @@ namespace ClangBackEnd { class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface { public: - SymbolsCollector(FilePathCache<> &filePathCache); + SymbolsCollector(FilePathCache<std::mutex> &filePathCache); void addFiles(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments) override; + void addUnsavedFiles(const V2::FileContainers &unsavedFiles) override; + void collectSymbols() override; const SymbolEntries &symbols() const override; diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h index a34705382e..fcb909bdc8 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h @@ -28,6 +28,8 @@ #include "symbolentry.h" #include "sourcelocationentry.h" +#include <filecontainerv2.h> + #include <utils/smallstringvector.h> #include <string> @@ -41,6 +43,8 @@ public: virtual void addFiles(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments) = 0; + virtual void addUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0; + virtual void collectSymbols() = 0; virtual const SymbolEntries &symbols() const = 0; diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h index 12163b0f25..cbe2e570da 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorage.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h @@ -27,9 +27,12 @@ #include "symbolstorageinterface.h" +#include <sqliteexception.h> #include <sqlitetransaction.h> #include <stringcache.h> +#include <mutex> + namespace ClangBackEnd { template <typename StatementFactory> @@ -42,7 +45,7 @@ class SymbolStorage : public SymbolStorageInterface public: SymbolStorage(StatementFactory &statementFactory, - FilePathCache<> &filePathCache) + FilePathCache<std::mutex> &filePathCache) : m_statementFactory(statementFactory), m_filePathCache(filePathCache) { @@ -149,7 +152,7 @@ public: private: StatementFactory &m_statementFactory; - FilePathCache<> &m_filePathCache; + FilePathCache<std::mutex> &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/tests/unit/unittest/data/symbolindexing_main1.cpp b/tests/unit/unittest/data/symbolindexing_main1.cpp new file mode 100644 index 0000000000..58df77916a --- /dev/null +++ b/tests/unit/unittest/data/symbolindexing_main1.cpp @@ -0,0 +1,36 @@ +void function(); + +void function() +{ + int x; + x = 20; +} + +template <typename T> +T templateFunction(T t) +{ + return t; +} + +template <> +int templateFunction(int t) +{ + return t; +} + +extern template double templateFunction<double>(double); +template double templateFunction<double>(double); + +template<typename T> +using TemplateFunctionType = T(&)(T); + + +TemplateFunctionType<int> aliasToTemplateFunction = templateFunction<int>; + +void f() +{ + aliasToTemplateFunction(1); +} + +void f(int); +void f(double); diff --git a/tests/unit/unittest/data/symbolscollector_unsaved.cpp b/tests/unit/unittest/data/symbolscollector_unsaved.cpp new file mode 100644 index 0000000000..a57a4e69f7 --- /dev/null +++ b/tests/unit/unittest/data/symbolscollector_unsaved.cpp @@ -0,0 +1 @@ +#include "symbolscollector_generated_file.h" diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index 7792475d8f..814130f227 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -25,6 +25,8 @@ #pragma once +#include <utils/smallstringio.h> + #include <QtGlobal> #include <iosfwd> diff --git a/tests/unit/unittest/mockrefactoringserver.h b/tests/unit/unittest/mockrefactoringserver.h index abafc15244..c265f88cbc 100644 --- a/tests/unit/unittest/mockrefactoringserver.h +++ b/tests/unit/unittest/mockrefactoringserver.h @@ -44,6 +44,12 @@ public: MOCK_METHOD1(requestSourceRangesForQueryMessage, void (const ClangBackEnd::RequestSourceRangesForQueryMessage&)); + MOCK_METHOD1(updatePchProjectParts, + void (const ClangBackEnd::UpdatePchProjectPartsMessage&)); + + MOCK_METHOD1(removePchProjectParts, + void (const ClangBackEnd::RemovePchProjectPartsMessage&)); + MOCK_METHOD0(cancel, void()); @@ -61,4 +67,14 @@ public: { requestSourceRangesForQueryMessage(message); } + + void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override + { + updatePchProjectParts(message); + } + + void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override + { + removePchProjectParts(message); + } }; diff --git a/tests/unit/unittest/mocksymbolindexing.h b/tests/unit/unittest/mocksymbolindexing.h new file mode 100644 index 0000000000..8a42ebfbc9 --- /dev/null +++ b/tests/unit/unittest/mocksymbolindexing.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <symbolindexinginterface.h> + +class MockSymbolIndexing : public ClangBackEnd::SymbolIndexingInterface +{ +public: + MOCK_METHOD2(updateProjectParts, + void(const ClangBackEnd::V2::ProjectPartContainers &projectParts, + const ClangBackEnd::V2::FileContainers &generatedFiles)); + + void updateProjectParts(ClangBackEnd::V2::ProjectPartContainers &&projectParts, + ClangBackEnd::V2::FileContainers &&generatedFiles) override + { + updateProjectParts(projectParts, generatedFiles); + } +}; + diff --git a/tests/unit/unittest/mocksymbolscollector.h b/tests/unit/unittest/mocksymbolscollector.h index 75e7b74423..14f8f6cdf5 100644 --- a/tests/unit/unittest/mocksymbolscollector.h +++ b/tests/unit/unittest/mocksymbolscollector.h @@ -39,6 +39,9 @@ public: void(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments)); + MOCK_METHOD1(addUnsavedFiles, + void(const ClangBackEnd::V2::FileContainers &unsavedFiles)); + MOCK_CONST_METHOD0(symbols, const ClangBackEnd::SymbolEntries &()); diff --git a/tests/unit/unittest/pchmanagerclient-test.cpp b/tests/unit/unittest/pchmanagerclient-test.cpp index 3f26243cc5..53a544841d 100644 --- a/tests/unit/unittest/pchmanagerclient-test.cpp +++ b/tests/unit/unittest/pchmanagerclient-test.cpp @@ -29,7 +29,7 @@ #include "mockpchmanagerserver.h" #include <pchmanagerclient.h> -#include <projectupdater.h> +#include <pchmanagerprojectupdater.h> #include <precompiledheadersupdatedmessage.h> #include <removepchprojectpartsmessage.h> @@ -49,7 +49,7 @@ protected: MockPchManagerServer mockPchManagerServer; ClangPchManager::PchManagerClient client; MockPchManagerNotifier mockPchManagerNotifier{client}; - ClangPchManager::ProjectUpdater projectUpdater{mockPchManagerServer, client}; + ClangPchManager::PchManagerProjectUpdater projectUpdater{mockPchManagerServer, client}; Utils::SmallString projectPartId{"projectPartId"}; Utils::SmallString pchFilePath{"/path/to/pch"}; PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone()}}}; diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp index 98cb1b05d8..071f9ea5db 100644 --- a/tests/unit/unittest/projectupdater-test.cpp +++ b/tests/unit/unittest/projectupdater-test.cpp @@ -29,7 +29,7 @@ #include "mockpchmanagernotifier.h" #include "mockpchmanagerserver.h" -#include <projectupdater.h> +#include <pchmanagerprojectupdater.h> #include <pchmanagerclient.h> #include <precompiledheadersupdatedmessage.h> @@ -60,7 +60,7 @@ protected: ClangPchManager::PchManagerClient pchManagerClient; MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient}; NiceMock<MockPchManagerServer> mockPchManagerServer; - ClangPchManager::ProjectUpdater updater{mockPchManagerServer, pchManagerClient}; + ClangPchManager::ProjectUpdater updater{mockPchManagerServer}; Utils::SmallString projectPartId{"project1"}; Utils::SmallString projectPartId2{"project2"}; Utils::PathStringVector headerPaths = {"/path/to/header1.h", "/path/to/header2.h"}; @@ -87,7 +87,7 @@ TEST_F(ProjectUpdater, CallUpdatePchProjectParts) TEST_F(ProjectUpdater, CallRemovePchProjectParts) { - EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(_)).Times(AnyNumber()); + ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message)); @@ -95,14 +95,15 @@ TEST_F(ProjectUpdater, CallRemovePchProjectParts) updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); } -TEST_F(ProjectUpdater, CallPrecompiledHeaderRemoved) +TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater) { + ClangPchManager::PchManagerProjectUpdater pchUpdater{mockPchManagerServer, pchManagerClient}; ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString())); EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString())); - updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); + pchUpdater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); } TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer) diff --git a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp index aaac7c1433..f1ce7a9f5f 100644 --- a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp +++ b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp @@ -47,6 +47,11 @@ using ::testing::Args; using ::testing::Property; using ::testing::Eq; +using ClangBackEnd::UpdatePchProjectPartsMessage; +using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangBackEnd::RemovePchProjectPartsMessage; + class RefactoringClientServerInProcess : public ::testing::Test { protected: @@ -169,6 +174,31 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage) scheduleServerMessages(); } +TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage) +{ + ProjectPartContainer projectPart2{"projectPartId", + {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, + {TESTDATA_DIR "/includecollector_header.h"}, + {TESTDATA_DIR "/includecollector_main.cpp"}}; + FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; + UpdatePchProjectPartsMessage message{{projectPart2}, {fileContainer}}; + + EXPECT_CALL(mockRefactoringServer, updatePchProjectParts(message)); + + serverProxy.updatePchProjectParts(message.clone()); + scheduleServerMessages(); +} + +TEST_F(RefactoringClientServerInProcess, SendRemovePchProjectPartsMessage) +{ + RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}}; + + EXPECT_CALL(mockRefactoringServer, removePchProjectParts(message)); + + serverProxy.removePchProjectParts(message.clone()); + scheduleServerMessages(); +} + TEST_F(RefactoringClientServerInProcess, CancelMessage) { EXPECT_CALL(mockRefactoringServer, cancel()); diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp index b07d490a12..8b2586ba0b 100644 --- a/tests/unit/unittest/refactoringserver-test.cpp +++ b/tests/unit/unittest/refactoringserver-test.cpp @@ -27,6 +27,7 @@ #include "filesystem-utilities.h" #include "mockrefactoringclient.h" +#include "mocksymbolindexing.h" #include "sourcerangecontainer-matcher.h" #include <refactoringserver.h> @@ -57,6 +58,9 @@ using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage; using ClangBackEnd::SourceRangesForQueryMessage; using ClangBackEnd::SourceRangesContainer; using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::V2::FileContainers; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangBackEnd::V2::ProjectPartContainers; MATCHER_P2(IsSourceLocation, line, column, std::string(negation ? "isn't " : "is ") @@ -76,8 +80,10 @@ protected: void TearDown() override; protected: - ClangBackEnd::RefactoringServer refactoringServer; NiceMock<MockRefactoringClient> mockRefactoringClient; + NiceMock<MockSymbolIndexing> mockSymbolIndexing; + ClangBackEnd::FilePathCache<std::mutex> filePathCache; + ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache}; Utils::SmallString sourceContent{"void f()\n {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), @@ -283,6 +289,23 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); } +TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectParts) +{ + ProjectPartContainers projectParts{{{"projectPartId", + {"-I", TESTDATA_DIR}, + {"header1.h"}, + {"main.cpp"}}}}; + FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, + "void f();", + {}}}; + + + EXPECT_CALL(mockSymbolIndexing, + updateProjectParts(projectParts, unsaved)); + + refactoringServer.updatePchProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)}); +} + void RefactoringServer::SetUp() { temporaryFile.open(); diff --git a/tests/unit/unittest/sqlitedatabase-test.cpp b/tests/unit/unittest/sqlitedatabase-test.cpp index 85b8a68e80..7c9cd9cf0e 100644 --- a/tests/unit/unittest/sqlitedatabase-test.cpp +++ b/tests/unit/unittest/sqlitedatabase-test.cpp @@ -96,6 +96,18 @@ TEST_F(SqliteDatabase, AddTable) ASSERT_THAT(database.tables(), Contains(sqliteTable)); } +TEST_F(SqliteDatabase, TableIsReadyAfterOpenDatabase) +{ + database.close(); + auto &table = database.addTable(); + table.setName("foo"); + table.addColumn("name"); + + database.open(); + + ASSERT_TRUE(table.isReady()); +} + void SqliteDatabase::SetUp() { database.setJournalMode(JournalMode::Memory); diff --git a/tests/unit/unittest/sqliteindex-test.cpp b/tests/unit/unittest/sqliteindex-test.cpp new file mode 100644 index 0000000000..dcf02fa02c --- /dev/null +++ b/tests/unit/unittest/sqliteindex-test.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 <sqliteindex.h> + +namespace { + +using Sqlite::SqliteException; +using Sqlite::SqliteIndex; + +TEST(SqliteIndex, OneColumn) +{ + SqliteIndex index{"tableName", {"column1"}}; + + auto sqlStatement = index.sqlStatement(); + + ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1 ON tableName(column1)")); +} + +TEST(SqliteIndex, TwoColumn) +{ + SqliteIndex index{"tableName", {"column1", "column2"}}; + + auto sqlStatement = index.sqlStatement(); + + ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1_column2 ON tableName(column1, column2)")); +} + +TEST(SqliteIndex, EmptyTableName) +{ + SqliteIndex index{"", {"column1", "column2"}}; + + ASSERT_THROW(index.sqlStatement(), SqliteException); +} + +TEST(SqliteIndex, EmptyColumns) +{ + SqliteIndex index{"tableName", {}}; + + ASSERT_THROW(index.sqlStatement(), SqliteException); +} +} diff --git a/tests/unit/unittest/sqlitetable-test.cpp b/tests/unit/unittest/sqlitetable-test.cpp index 7873181580..fc5917d296 100644 --- a/tests/unit/unittest/sqlitetable-test.cpp +++ b/tests/unit/unittest/sqlitetable-test.cpp @@ -27,7 +27,7 @@ #include "spydummy.h" #include <sqlitecolumn.h> -#include <sqlitedatabase.h> +#include <mocksqlitedatabase.h> #include <sqlitetable.h> namespace { @@ -41,13 +41,8 @@ using Sqlite::SqliteDatabase; class SqliteTable : public ::testing::Test { protected: - void SetUp() override; - void TearDown() override; - -protected: - SpyDummy spyDummy; - SqliteDatabase database; - Sqlite::SqliteTable &table = database.addTable(); + NiceMock<MockSqliteDatabase> mockDatabase; + Sqlite::SqliteTable table; Utils::SmallString tableName = "testTable"; }; @@ -73,26 +68,46 @@ TEST_F(SqliteTable, SetUseWithoutRowid) ASSERT_TRUE(table.useWithoutRowId()); } -TEST_F(SqliteTable, TableIsReadyAfterOpenDatabase) +TEST_F(SqliteTable, AddIndex) { table.setName(tableName.clone()); - table.addColumn("name"); + auto &column = table.addColumn("name"); + auto &column2 = table.addColumn("value"); - database.open(); + auto index = table.addIndex({column, column2}); - ASSERT_TRUE(table.isReady()); + ASSERT_THAT(Utils::SmallStringView(index.sqlStatement()), + Eq("CREATE INDEX IF NOT EXISTS index_testTable_name_value ON testTable(name, value)")); } -void SqliteTable::SetUp() +TEST_F(SqliteTable, InitializeTable) { - database.setJournalMode(JournalMode::Memory); - database.setDatabaseFilePath( QStringLiteral(":memory:")); + table.setName(tableName.clone()); + table.setUseIfNotExists(true); + table.setUseTemporaryTable(true); + table.setUseWithoutRowId(true); + table.addColumn("name"); + table.addColumn("value"); + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name NUMERIC, value NUMERIC) WITHOUT ROWID"))); + + table.initialize(mockDatabase); } -void SqliteTable::TearDown() +TEST_F(SqliteTable, InitializeTableWithIndex) { - if (database.isOpen()) - database.close(); + InSequence sequence; + table.setName(tableName.clone()); + auto &column = table.addColumn("name"); + auto &column2 = table.addColumn("value"); + table.addIndex({column}); + table.addIndex({column2}); + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE testTable(name NUMERIC, value NUMERIC)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_value ON testTable(value)"))); + + table.initialize(mockDatabase); } } diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp index 98c99d908e..1553ad76f9 100644 --- a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp @@ -52,6 +52,7 @@ TEST_F(StorageSqliteStatementFactory, AddSymbolsTable) EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); factory.createSymbolsTable(); @@ -63,6 +64,7 @@ TEST_F(StorageSqliteStatementFactory, AddLocationsTable) EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); factory.createLocationsTable(); @@ -85,6 +87,8 @@ TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable) EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); factory.createNewSymbolsTable(); @@ -97,6 +101,7 @@ TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable) EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); factory.createNewLocationsTable(); @@ -108,10 +113,15 @@ TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor) EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE 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 TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)"))); StatementFactory factory{mockDatabase}; } @@ -137,7 +147,7 @@ TEST_F(StorageSqliteStatementFactory, SelectNewSourceIdsStatement) TEST_F(StorageSqliteStatementFactory, AddNewSymbolsToSymbolsStatement) { ASSERT_THAT(factory.addNewSymbolsToSymbolsStatement.sqlStatement, - Eq("INSERT INTO symbols(usr, symbolname) SELECT usr, symbolname FROM newsymbols WHERE NOT EXISTS (SELECT usr FROM symbols WHERE usr == newsymbols.usr)")); + 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) diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 35a09fbef0..6684b2cddb 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -46,6 +46,7 @@ using testing::Sequence; using Utils::PathString; using ClangBackEnd::V2::ProjectPartContainer; using ClangBackEnd::V2::ProjectPartContainers; +using ClangBackEnd::V2::FileContainers; using ClangBackEnd::SymbolEntries; using ClangBackEnd::SymbolEntry; using ClangBackEnd::SourceLocationEntries; @@ -72,6 +73,9 @@ protected: {"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"}, {header2Path.clone()}, {main2Path.clone()}}; + FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, + "void f();", + {}}}; SymbolEntries symbolEntries{{1, {"function", "function"}}}; SourceLocationEntries sourceLocations{{1, 1, {42, 23}, SymbolType::Declaration}}; NiceMock<MockSymbolsCollector> mockCollector; @@ -83,7 +87,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector) { EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePaths(), projectPart1.arguments())); - indexer.updateProjectParts({projectPart1}); + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectPart) @@ -91,7 +95,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectP EXPECT_CALL(mockCollector, addFiles(_, _)) .Times(2); - indexer.updateProjectParts({projectPart1, projectPart2}); + indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved)); } TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEveryProjectParts) @@ -99,48 +103,54 @@ TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEv EXPECT_CALL(mockCollector, addFiles(_, _)) .Times(0); - indexer.updateProjectParts({}); + indexer.updateProjectParts({}, {}); } TEST_F(SymbolIndexer, UpdateProjectPartsCallscollectSymbolsInCollector) { EXPECT_CALL(mockCollector, collectSymbols()); - indexer.updateProjectParts({projectPart1}); + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } TEST_F(SymbolIndexer, UpdateProjectPartsCallsSymbolsInCollector) { EXPECT_CALL(mockCollector, symbols()); - indexer.updateProjectParts({projectPart1}); + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } TEST_F(SymbolIndexer, UpdateProjectPartsCallsSourceLocationsInCollector) { EXPECT_CALL(mockCollector, sourceLocations()); - indexer.updateProjectParts({projectPart1}); + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); +} + +TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddUnsavedFilesInCollector) +{ + EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved)); + + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddSymbolsAndSourceLocationsInStorage) { EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - indexer.updateProjectParts({projectPart1}); + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder) { - Sequence sequence; - EXPECT_CALL(mockCollector, addFiles(_, _)); + EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved)); EXPECT_CALL(mockCollector, collectSymbols()); EXPECT_CALL(mockCollector, symbols()); EXPECT_CALL(mockCollector, sourceLocations()); EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - indexer.updateProjectParts({projectPart1}); + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } void SymbolIndexer::SetUp() diff --git a/tests/unit/unittest/symbolindexing-test.cpp b/tests/unit/unittest/symbolindexing-test.cpp new file mode 100644 index 0000000000..1ed64e6deb --- /dev/null +++ b/tests/unit/unittest/symbolindexing-test.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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 <projectpartcontainerv2.h> + +#include <symbolindexing.h> +#include <symbolquery.h> +#include <querysqlitestatementfactory.h> + +#include <QDir> + +namespace { + +using Sqlite::SqliteDatabase; +using Sqlite::SqliteReadStatement; +using ClangBackEnd::SymbolIndexer; +using ClangBackEnd::SymbolsCollector; +using ClangBackEnd::SymbolStorage; +using ClangBackEnd::FilePathCache; +using ClangBackEnd::FilePathCache; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangRefactoring::SymbolQuery; +using ClangRefactoring::QuerySqliteStatementFactory; +using Utils::PathString; +using SL = ClangRefactoring::SourceLocations; + +using StatementFactory = QuerySqliteStatementFactory<SqliteDatabase, SqliteReadStatement>; +using Query = SymbolQuery<StatementFactory>; + +MATCHER_P3(IsLocation, sourceId, line, column, + std::string(negation ? "isn't" : "is") + + " source id " + PrintToString(sourceId) + + " line " + PrintToString(line) + + " and column " + PrintToString(column) + ) +{ + const SL::Location &location = arg; + + return location.sourceId == sourceId + && location.line == line + && location.column == column; +}; + +class SymbolIndexing : public testing::Test +{ +protected: + FilePathCache<std::mutex> filePathCache; + ClangBackEnd::SymbolIndexing indexing{filePathCache, QDir::tempPath() + "/symbol.db"}; + StatementFactory queryFactory{indexing.database()}; + Query query{queryFactory}; + PathString main1Path = TESTDATA_DIR "/symbolindexing_main1.cpp"; + ProjectPartContainer projectPart1{"project1", + {"cc", "-I", TESTDATA_DIR, "-std=c++1z"}, + {}, + {main1Path.clone()}}; +}; + +TEST_F(SymbolIndexing, Locations) +{ + indexing.indexer().updateProjectParts({projectPart1}, {}); + + auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5); + ASSERT_THAT(locations.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")))); +} + +TEST_F(SymbolIndexing, DISABLED_TemplateFunction) +{ + indexing.indexer().updateProjectParts({projectPart1}, {}); + + auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 21, 24); + ASSERT_THAT(locations.locations, + ElementsAre( + IsLocation(0, 5, 9), + IsLocation(0, 6, 5))); +} +} diff --git a/tests/unit/unittest/symbolscollector-test.cpp b/tests/unit/unittest/symbolscollector-test.cpp index 4543c61e44..9b1f046cbd 100644 --- a/tests/unit/unittest/symbolscollector-test.cpp +++ b/tests/unit/unittest/symbolscollector-test.cpp @@ -39,6 +39,7 @@ using testing::Pair; using testing::Value; using testing::_; +using ClangBackEnd::V2::FileContainers; using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SymbolEntry; using ClangBackEnd::SymbolType; @@ -57,7 +58,7 @@ protected: SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName); protected: - ClangBackEnd::FilePathCache<> filePathCache; + ClangBackEnd::FilePathCache<std::mutex> filePathCache; ClangBackEnd::SymbolsCollector collector{filePathCache}; }; @@ -150,6 +151,21 @@ TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation) Field(&SourceLocationEntry::column, 5)))); } +TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile)) +{ + FileContainers unsaved{{{TESTDATA_DIR, "symbolscollector_generated_file.h"}, + "void function();", + {}}}; + collector.addFile(TESTDATA_DIR, "symbolscollector_unsaved.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_unsaved.cpp"}); + collector.addUnsavedFiles(std::move(unsaved)); + + collector.collectSymbols(); + + ASSERT_THAT(collector.symbols(), + Contains( + Pair(_, Field(&SymbolEntry::symbolName, "function")))); +} + SymbolIndex SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName) { for (const auto &entry : collector.symbols()) { diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp index ec30b9289d..fbe9ab9cc4 100644 --- a/tests/unit/unittest/symbolstorage-test.cpp +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -58,7 +58,7 @@ protected: void SetUp(); protected: - FilePathCache<> filePathCache; + FilePathCache<std::mutex> filePathCache; NiceMock<MockSqliteDatabase> mockDatabase; StatementFactory statementFactory{mockDatabase}; diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index db1b818c8a..1f1b490536 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -74,7 +74,9 @@ SOURCES += \ mocksqlitereadstatement.cpp \ symbolquery-test.cpp \ storagesqlitestatementfactory-test.cpp \ - querysqlitestatementfactory-test.cpp + querysqlitestatementfactory-test.cpp \ + symbolindexing-test.cpp \ + sqliteindex-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -197,7 +199,8 @@ HEADERS += \ mocksqlitewritestatement.h \ mocksqlitedatabase.h \ mocksqlitereadstatement.h \ - google-using-declarations.h + google-using-declarations.h \ + mocksymbolindexing.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ |