From 53454b0f79fcfebab909d071e931557114ace558 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 20 Feb 2018 12:43:05 +0100 Subject: [PATCH] Clang: Use PCHs for indexing As generating the AST is quite expensive it would be very useful to cache the not changed include. So we generate PCHs for include outside of a project part. With this change this PCHs are used by the indexer. For that they are save to the symbol database by the PCH manager and when fetched by the symbol indexer. Change-Id: I7a5b07cfb32d72d50dc52d2b108cd41727a7bfc7 Reviewed-by: Ivan Donchevskii --- .../clangrefactoringservermessages.h | 4 +- src/libs/clangsupport/clangsupport-lib.pri | 14 ++- src/libs/clangsupport/clangsupport_global.h | 4 +- src/libs/clangsupport/filepathcaching.h | 4 +- src/libs/clangsupport/filepathstorage.h | 6 +- .../filepathstoragesqlitestatementfactory.h | 10 +- .../pchmanagerserverinterface.cpp | 12 +- .../clangsupport/pchmanagerserverinterface.h | 4 +- .../clangsupport/pchmanagerserverproxy.cpp | 8 +- src/libs/clangsupport/pchmanagerserverproxy.h | 4 +- .../precompiledheadersupdatedmessage.h | 7 +- .../projectmanagementserverinterface.h | 8 +- src/libs/clangsupport/projectpartpch.h | 7 ++ .../projectpartpchproviderinterface.cpp | 34 ++++++ .../projectpartpchproviderinterface.h | 44 ++++++++ .../refactoringdatabaseinitializer.h | 14 +++ .../refactoringserverinterface.cpp | 8 +- .../clangsupport/refactoringserverinterface.h | 4 +- .../clangsupport/refactoringserverproxy.cpp | 4 +- .../clangsupport/refactoringserverproxy.h | 4 +- ...sage.cpp => removeprojectpartsmessage.cpp} | 4 +- ...smessage.h => removeprojectpartsmessage.h} | 22 ++-- ...sage.cpp => updateprojectpartsmessage.cpp} | 6 +- ...smessage.h => updateprojectpartsmessage.h} | 24 ++-- src/libs/sqlite/sqlitedatabase.h | 5 + .../clangpchmanager-source.pri | 7 +- .../clangpchmanager/clangpchmanagerplugin.cpp | 4 +- .../clangpchmanager/clangpchmanagerplugin.h | 4 +- .../clangpchmanager/pchmanagerclient.cpp | 78 ++++++++++++- .../clangpchmanager/pchmanagerclient.h | 24 +++- .../pchmanagernotifierinterface.h | 9 +- .../precompiledheaderstorage.h | 80 +++++++++++++ .../precompiledheaderstorageinterface.cpp | 32 ++++++ .../precompiledheaderstorageinterface.h | 48 ++++++++ .../clangpchmanager/projectupdater.cpp | 12 +- .../clangrefactoring-source.pri | 6 +- .../projectpartproviderinterface.cpp | 32 ++++++ .../projectpartproviderinterface.h | 54 +++++++++ .../source/pchmanagerserver.cpp | 8 +- .../source/pchmanagerserver.h | 4 +- .../source/refactoringserver.cpp | 4 +- .../source/refactoringserver.h | 4 +- .../source/storagesqlitestatementfactory.h | 14 ++- .../source/symbolindexer.cpp | 52 +++++++-- .../source/symbolindexer.h | 11 +- .../source/symbolindexing.h | 4 +- .../source/symbolstorage.h | 15 ++- .../source/symbolstorageinterface.h | 2 + tests/unit/unittest/filepathstorage-test.cpp | 4 +- ...pathstoragesqlitestatementfactory-test.cpp | 4 +- .../unit/unittest/gtest-creator-printing.cpp | 7 +- tests/unit/unittest/gtest-creator-printing.h | 8 +- tests/unit/unittest/mockpchmanagernotifier.h | 4 +- tests/unit/unittest/mockpchmanagerserver.h | 16 +-- .../unittest/mockprecompiledheaderstorage.h | 41 +++++++ tests/unit/unittest/mockprojectpartprovider.h | 39 +++++++ tests/unit/unittest/mockrefactoringserver.h | 16 +-- tests/unit/unittest/mocksqlitedatabase.h | 5 + .../unit/unittest/mocksqlitereadstatement.cpp | 7 ++ tests/unit/unittest/mocksqlitereadstatement.h | 12 +- .../unit/unittest/mocksqlitewritestatement.h | 7 +- tests/unit/unittest/mocksymbolstorage.h | 2 + tests/unit/unittest/pchmanagerclient-test.cpp | 86 +++++++++++++- .../pchmanagerclientserverinprocess-test.cpp | 24 ++-- tests/unit/unittest/pchmanagerserver-test.cpp | 32 +++--- .../precompiledheaderstorage-test.cpp | 106 ++++++++++++++++++ tests/unit/unittest/projectupdater-test.cpp | 26 +++-- .../refactoringclientserverinprocess-test.cpp | 20 ++-- .../refactoringdatabaseinitializer-test.cpp | 10 ++ .../unit/unittest/refactoringserver-test.cpp | 4 +- .../storagesqlitestatementfactory-test.cpp | 11 +- tests/unit/unittest/symbolindexer-test.cpp | 86 ++++++++++++-- tests/unit/unittest/symbolindexing-test.cpp | 2 - tests/unit/unittest/symbolstorage-test.cpp | 31 +++-- tests/unit/unittest/unittest.pro | 7 +- 75 files changed, 1139 insertions(+), 251 deletions(-) create mode 100644 src/libs/clangsupport/projectpartpchproviderinterface.cpp create mode 100644 src/libs/clangsupport/projectpartpchproviderinterface.h rename src/libs/clangsupport/{removepchprojectpartsmessage.cpp => removeprojectpartsmessage.cpp} (95%) rename src/libs/clangsupport/{removepchprojectpartsmessage.h => removeprojectpartsmessage.h} (76%) rename src/libs/clangsupport/{updatepchprojectpartsmessage.cpp => updateprojectpartsmessage.cpp} (88%) rename src/libs/clangsupport/{updatepchprojectpartsmessage.h => updateprojectpartsmessage.h} (78%) create mode 100644 src/plugins/clangpchmanager/precompiledheaderstorage.h create mode 100644 src/plugins/clangpchmanager/precompiledheaderstorageinterface.cpp create mode 100644 src/plugins/clangpchmanager/precompiledheaderstorageinterface.h create mode 100644 src/plugins/clangrefactoring/projectpartproviderinterface.cpp create mode 100644 src/plugins/clangrefactoring/projectpartproviderinterface.h create mode 100644 tests/unit/unittest/mockprecompiledheaderstorage.h create mode 100644 tests/unit/unittest/mockprojectpartprovider.h create mode 100644 tests/unit/unittest/precompiledheaderstorage-test.cpp diff --git a/src/libs/clangsupport/clangrefactoringservermessages.h b/src/libs/clangsupport/clangrefactoringservermessages.h index 2be6f0d54d0..1f7866444b1 100644 --- a/src/libs/clangsupport/clangrefactoringservermessages.h +++ b/src/libs/clangsupport/clangrefactoringservermessages.h @@ -30,5 +30,5 @@ #include "requestsourcelocationforrenamingmessage.h" #include "requestsourcerangesanddiagnosticsforquerymessage.h" #include "requestsourcerangesforquerymessage.h" -#include "updatepchprojectpartsmessage.h" -#include "removepchprojectpartsmessage.h" +#include "updateprojectpartsmessage.h" +#include "removeprojectpartsmessage.h" diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index 16aa926a51c..9b0a59adbf3 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -61,7 +61,7 @@ SOURCES += \ $$PWD/refactoringserverproxy.cpp \ $$PWD/referencesmessage.cpp \ $$PWD/registerunsavedfilesforeditormessage.cpp \ - $$PWD/removepchprojectpartsmessage.cpp \ + $$PWD/removeprojectpartsmessage.cpp \ $$PWD/requestdocumentannotations.cpp \ $$PWD/requestfollowsymbolmessage.cpp \ $$PWD/requestreferencesmessage.cpp \ @@ -86,13 +86,14 @@ SOURCES += \ $$PWD/tooltipmessage.cpp \ $$PWD/tooltipinfo.cpp \ $$PWD/unregisterunsavedfilesforeditormessage.cpp \ - $$PWD/updatepchprojectpartsmessage.cpp \ + $$PWD/updateprojectpartsmessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \ $$PWD/updatevisibletranslationunitsmessage.cpp \ $$PWD/writemessageblock.cpp \ $$PWD/filepathcaching.cpp \ $$PWD/filepathid.cpp \ - $$PWD/baseserverproxy.cpp + $$PWD/baseserverproxy.cpp \ + $$PWD/projectpartpchproviderinterface.cpp HEADERS += \ $$PWD/cancelmessage.h \ @@ -155,7 +156,7 @@ HEADERS += \ $$PWD/refactoringserverproxy.h \ $$PWD/referencesmessage.h \ $$PWD/registerunsavedfilesforeditormessage.h \ - $$PWD/removepchprojectpartsmessage.h \ + $$PWD/removeprojectpartsmessage.h \ $$PWD/requestdocumentannotations.h \ $$PWD/requestfollowsymbolmessage.h \ $$PWD/requestreferencesmessage.h \ @@ -183,7 +184,7 @@ HEADERS += \ $$PWD/tooltipmessage.h \ $$PWD/tooltipinfo.h \ $$PWD/unregisterunsavedfilesforeditormessage.h \ - $$PWD/updatepchprojectpartsmessage.h \ + $$PWD/updateprojectpartsmessage.h \ $$PWD/updatetranslationunitsforeditormessage.h \ $$PWD/updatevisibletranslationunitsmessage.h \ $$PWD/writemessageblock.h \ @@ -206,6 +207,7 @@ HEADERS += \ $$PWD/filepath.h \ $$PWD/nativefilepath.h \ $$PWD/filepathview.h \ - $$PWD/compilermacro.h + $$PWD/compilermacro.h \ + $$PWD/projectpartpchproviderinterface.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangsupport/clangsupport_global.h b/src/libs/clangsupport/clangsupport_global.h index 22b14aa6024..202ca45b93f 100644 --- a/src/libs/clangsupport/clangsupport_global.h +++ b/src/libs/clangsupport/clangsupport_global.h @@ -173,8 +173,8 @@ enum class MessageType : quint8 { SourceRangesForQueryMessage, CancelMessage, - UpdatePchProjectPartsMessage, - RemovePchProjectPartsMessage, + UpdateProjectPartsMessage, + RemoveProjectPartsMessage, PrecompiledHeadersUpdatedMessage }; diff --git a/src/libs/clangsupport/filepathcaching.h b/src/libs/clangsupport/filepathcaching.h index d5e89fd7aa2..a3337755fd2 100644 --- a/src/libs/clangsupport/filepathcaching.h +++ b/src/libs/clangsupport/filepathcaching.h @@ -40,9 +40,7 @@ namespace ClangBackEnd { class CLANGSUPPORT_EXPORT FilePathCaching final : public FilePathCachingInterface { - using Factory = FilePathStorageSqliteStatementFactory; + using Factory = FilePathStorageSqliteStatementFactory; using Storage = FilePathStorage; using Cache = FilePathCache; public: diff --git a/src/libs/clangsupport/filepathstorage.h b/src/libs/clangsupport/filepathstorage.h index 874374dfa5c..b33789105e1 100644 --- a/src/libs/clangsupport/filepathstorage.h +++ b/src/libs/clangsupport/filepathstorage.h @@ -39,9 +39,9 @@ namespace ClangBackEnd { template class FilePathStorage { - using ReadStatement = typename StatementFactory::ReadStatementType; - using WriteStatement = typename StatementFactory::WriteStatementType; - using Database = typename StatementFactory::DatabaseType; + using ReadStatement = typename StatementFactory::ReadStatement; + using WriteStatement = typename StatementFactory::WriteStatement; + using Database = typename StatementFactory::Database; public: FilePathStorage(StatementFactory &statementFactory) diff --git a/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h b/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h index 6c4c48302ad..71e2c3e7734 100644 --- a/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h +++ b/src/libs/clangsupport/filepathstoragesqlitestatementfactory.h @@ -30,15 +30,13 @@ namespace ClangBackEnd { -template +template class FilePathStorageSqliteStatementFactory { public: - using DatabaseType = Database; - using ReadStatementType = ReadStatement; - using WriteStatementType = WriteStatement; + using Database = DatabaseType; + using ReadStatement = typename DatabaseType::ReadStatement; + using WriteStatement = typename DatabaseType::WriteStatement; FilePathStorageSqliteStatementFactory(Database &database) : database(database) diff --git a/src/libs/clangsupport/pchmanagerserverinterface.cpp b/src/libs/clangsupport/pchmanagerserverinterface.cpp index 1a6d9d4a25d..549e8354504 100644 --- a/src/libs/clangsupport/pchmanagerserverinterface.cpp +++ b/src/libs/clangsupport/pchmanagerserverinterface.cpp @@ -26,8 +26,8 @@ #include "pchmanagerserverinterface.h" #include "messageenvelop.h" -#include "removepchprojectpartsmessage.h" -#include "updatepchprojectpartsmessage.h" +#include "removeprojectpartsmessage.h" +#include "updateprojectpartsmessage.h" #include @@ -39,11 +39,11 @@ void PchManagerServerInterface::dispatch(const MessageEnvelop &messageEnvelop) case MessageType::EndMessage: end(); break; - case MessageType::UpdatePchProjectPartsMessage: - updatePchProjectParts(messageEnvelop.message()); + case MessageType::UpdateProjectPartsMessage: + updateProjectParts(messageEnvelop.message()); break; - case MessageType::RemovePchProjectPartsMessage: - removePchProjectParts(messageEnvelop.message()); + case MessageType::RemoveProjectPartsMessage: + removeProjectParts(messageEnvelop.message()); break; default: qWarning() << "Unknown IpcClientMessage"; diff --git a/src/libs/clangsupport/pchmanagerserverinterface.h b/src/libs/clangsupport/pchmanagerserverinterface.h index 2f406f365a1..8f61c0ebce7 100644 --- a/src/libs/clangsupport/pchmanagerserverinterface.h +++ b/src/libs/clangsupport/pchmanagerserverinterface.h @@ -32,8 +32,8 @@ namespace ClangBackEnd { class PchManagerClientInterface; -class RemovePchProjectPartsMessage; -class UpdatePchProjectPartsMessage; +class RemoveProjectPartsMessage; +class UpdateProjectPartsMessage; class CLANGSUPPORT_EXPORT PchManagerServerInterface : public ProjectManagementServerInterface { diff --git a/src/libs/clangsupport/pchmanagerserverproxy.cpp b/src/libs/clangsupport/pchmanagerserverproxy.cpp index 3a181fd3dc3..079c8890d94 100644 --- a/src/libs/clangsupport/pchmanagerserverproxy.cpp +++ b/src/libs/clangsupport/pchmanagerserverproxy.cpp @@ -28,8 +28,8 @@ #include "cmbendmessage.h" #include "messageenvelop.h" #include "pchmanagerclientinterface.h" -#include "removepchprojectpartsmessage.h" -#include "updatepchprojectpartsmessage.h" +#include "removeprojectpartsmessage.h" +#include "updateprojectpartsmessage.h" #include #include @@ -46,12 +46,12 @@ void PchManagerServerProxy::end() m_writeMessageBlock.write(EndMessage()); } -void PchManagerServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) +void PchManagerServerProxy::updateProjectParts(UpdateProjectPartsMessage &&message) { m_writeMessageBlock.write(message); } -void PchManagerServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message) +void PchManagerServerProxy::removeProjectParts(RemoveProjectPartsMessage &&message) { m_writeMessageBlock.write(message); } diff --git a/src/libs/clangsupport/pchmanagerserverproxy.h b/src/libs/clangsupport/pchmanagerserverproxy.h index 8f9164f9d5a..30ae12782c4 100644 --- a/src/libs/clangsupport/pchmanagerserverproxy.h +++ b/src/libs/clangsupport/pchmanagerserverproxy.h @@ -50,8 +50,8 @@ public: explicit PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice); void end() override; - void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; - void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; + void updateProjectParts(UpdateProjectPartsMessage &&message) override; + void removeProjectParts(RemoveProjectPartsMessage &&message) override; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/precompiledheadersupdatedmessage.h b/src/libs/clangsupport/precompiledheadersupdatedmessage.h index 2119693e6f2..b909e304e21 100644 --- a/src/libs/clangsupport/precompiledheadersupdatedmessage.h +++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.h @@ -37,11 +37,16 @@ public: : m_projectPartPchs(std::move(projectPartPchs)) {} - const std::vector &projectPartPchs() const + const ProjectPartPchs &projectPartPchs() const { return m_projectPartPchs; } + ProjectPartPchs takeProjectPartPchs() const + { + return std::move(m_projectPartPchs); + } + friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message) { out << message.m_projectPartPchs; diff --git a/src/libs/clangsupport/projectmanagementserverinterface.h b/src/libs/clangsupport/projectmanagementserverinterface.h index 5ccef00451c..c8c57c45f69 100644 --- a/src/libs/clangsupport/projectmanagementserverinterface.h +++ b/src/libs/clangsupport/projectmanagementserverinterface.h @@ -29,14 +29,14 @@ namespace ClangBackEnd { -class RemovePchProjectPartsMessage; -class UpdatePchProjectPartsMessage; +class RemoveProjectPartsMessage; +class UpdateProjectPartsMessage; class CLANGSUPPORT_EXPORT ProjectManagementServerInterface : public IpcInterface { public: - virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0; - virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0; + virtual void updateProjectParts(UpdateProjectPartsMessage &&message) = 0; + virtual void removeProjectParts(RemoveProjectPartsMessage &&message) = 0; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartpch.h b/src/libs/clangsupport/projectpartpch.h index 1a9e73666b6..6048a0b2f0c 100644 --- a/src/libs/clangsupport/projectpartpch.h +++ b/src/libs/clangsupport/projectpartpch.h @@ -42,6 +42,11 @@ public: pchPath(std::move(pchPath)), lastModified(lastModified) {} + ProjectPartPch(Utils::SmallStringView pchPath, + long long lastModified) + : pchPath(pchPath), + lastModified(lastModified) + {} friend QDataStream &operator<<(QDataStream &out, const ProjectPartPch &container) { @@ -77,5 +82,7 @@ public: long long lastModified = -1; }; +using ProjectPartPchs = std::vector; + CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch); } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartpchproviderinterface.cpp b/src/libs/clangsupport/projectpartpchproviderinterface.cpp new file mode 100644 index 00000000000..7d93450ab78 --- /dev/null +++ b/src/libs/clangsupport/projectpartpchproviderinterface.cpp @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "projectpartpchproviderinterface.h" + +namespace ClangBackEnd { + +ProjectPartPchProviderInterface::~ProjectPartPchProviderInterface() +{ +} + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartpchproviderinterface.h b/src/libs/clangsupport/projectpartpchproviderinterface.h new file mode 100644 index 00000000000..f0a6741cad2 --- /dev/null +++ b/src/libs/clangsupport/projectpartpchproviderinterface.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 "projectpartpch.h" + +#include + +namespace ClangBackEnd { + +class CLANGSUPPORT_EXPORT ProjectPartPchProviderInterface +{ +public: + virtual ~ProjectPartPchProviderInterface(); + virtual Utils::optional projectPartPch( + Utils::SmallStringView projectPartId) const = 0; + virtual const ClangBackEnd::ProjectPartPchs &projectPartPchs() const = 0; + +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h index fabd231395c..4a5ebda798c 100644 --- a/src/libs/clangsupport/refactoringdatabaseinitializer.h +++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h @@ -50,6 +50,7 @@ public: createUsedMacrosTable(); createFileStatusesTable(); createSourceDependenciesTable(); + createPrecompiledHeadersTable(); transaction.commit(); } @@ -172,6 +173,19 @@ public: table.initialize(database); } + + void createPrecompiledHeadersTable() + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("precompiledHeaders"); + table.addColumn("projectPartId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); + table.addColumn("pchPath", Sqlite::ColumnType::Text); + table.addColumn("pchBuildTime", Sqlite::ColumnType::Integer); + + table.initialize(database); + } + public: DatabaseType &database; }; diff --git a/src/libs/clangsupport/refactoringserverinterface.cpp b/src/libs/clangsupport/refactoringserverinterface.cpp index 52ab7834b06..e9a2456d746 100644 --- a/src/libs/clangsupport/refactoringserverinterface.cpp +++ b/src/libs/clangsupport/refactoringserverinterface.cpp @@ -47,11 +47,11 @@ void RefactoringServerInterface::dispatch(const MessageEnvelop &messageEnvelop) case MessageType::RequestSourceRangesForQueryMessage: requestSourceRangesForQueryMessage(messageEnvelop.message()); break; - case MessageType::UpdatePchProjectPartsMessage: - updatePchProjectParts(messageEnvelop.message()); + case MessageType::UpdateProjectPartsMessage: + updateProjectParts(messageEnvelop.message()); break; - case MessageType::RemovePchProjectPartsMessage: - removePchProjectParts(messageEnvelop.message()); + case MessageType::RemoveProjectPartsMessage: + removeProjectParts(messageEnvelop.message()); break; case MessageType::CancelMessage: cancel(); diff --git a/src/libs/clangsupport/refactoringserverinterface.h b/src/libs/clangsupport/refactoringserverinterface.h index 96ce57c86d8..4bea6ee9f36 100644 --- a/src/libs/clangsupport/refactoringserverinterface.h +++ b/src/libs/clangsupport/refactoringserverinterface.h @@ -36,8 +36,8 @@ class RequestSourceLocationsForRenamingMessage; class RequestSourceRangesAndDiagnosticsForQueryMessage; class RequestSourceRangesForQueryMessage; class CancelMessage; -class UpdatePchProjectPartsMessage; -class RemovePchProjectPartsMessage; +class UpdateProjectPartsMessage; +class RemoveProjectPartsMessage; class CLANGSUPPORT_EXPORT RefactoringServerInterface : public ProjectManagementServerInterface diff --git a/src/libs/clangsupport/refactoringserverproxy.cpp b/src/libs/clangsupport/refactoringserverproxy.cpp index 47a61fbb315..809a66fe579 100644 --- a/src/libs/clangsupport/refactoringserverproxy.cpp +++ b/src/libs/clangsupport/refactoringserverproxy.cpp @@ -59,12 +59,12 @@ void RefactoringServerProxy::requestSourceRangesForQueryMessage(RequestSourceRan m_writeMessageBlock.write(message); } -void RefactoringServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) +void RefactoringServerProxy::updateProjectParts(UpdateProjectPartsMessage &&message) { m_writeMessageBlock.write(message); } -void RefactoringServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message) +void RefactoringServerProxy::removeProjectParts(RemoveProjectPartsMessage &&message) { m_writeMessageBlock.write(message); } diff --git a/src/libs/clangsupport/refactoringserverproxy.h b/src/libs/clangsupport/refactoringserverproxy.h index 8af6e426168..e5006e66e96 100644 --- a/src/libs/clangsupport/refactoringserverproxy.h +++ b/src/libs/clangsupport/refactoringserverproxy.h @@ -53,8 +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 updateProjectParts(UpdateProjectPartsMessage &&message) override; + void removeProjectParts(RemoveProjectPartsMessage &&message) override; void cancel() override; }; diff --git a/src/libs/clangsupport/removepchprojectpartsmessage.cpp b/src/libs/clangsupport/removeprojectpartsmessage.cpp similarity index 95% rename from src/libs/clangsupport/removepchprojectpartsmessage.cpp rename to src/libs/clangsupport/removeprojectpartsmessage.cpp index 5aae5513fe0..edc8e4999c7 100644 --- a/src/libs/clangsupport/removepchprojectpartsmessage.cpp +++ b/src/libs/clangsupport/removeprojectpartsmessage.cpp @@ -23,11 +23,11 @@ ** ****************************************************************************/ -#include "removepchprojectpartsmessage.h" +#include "removeprojectpartsmessage.h" namespace ClangBackEnd { -CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemovePchProjectPartsMessage &message) +CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemoveProjectPartsMessage &message) { debug.nospace() << "RemoveProjectPartsMessage(" << message.projectsPartIds() << ")"; diff --git a/src/libs/clangsupport/removepchprojectpartsmessage.h b/src/libs/clangsupport/removeprojectpartsmessage.h similarity index 76% rename from src/libs/clangsupport/removepchprojectpartsmessage.h rename to src/libs/clangsupport/removeprojectpartsmessage.h index 8589a7df490..4223d1f303c 100644 --- a/src/libs/clangsupport/removepchprojectpartsmessage.h +++ b/src/libs/clangsupport/removeprojectpartsmessage.h @@ -29,11 +29,11 @@ namespace ClangBackEnd { -class RemovePchProjectPartsMessage +class RemoveProjectPartsMessage { public: - RemovePchProjectPartsMessage() = default; - RemovePchProjectPartsMessage(Utils::SmallStringVector &&projectsPartIds) + RemoveProjectPartsMessage() = default; + RemoveProjectPartsMessage(Utils::SmallStringVector &&projectsPartIds) : m_projectsPartIds(std::move(projectsPartIds)) {} @@ -47,37 +47,37 @@ public: return std::move(m_projectsPartIds); } - friend QDataStream &operator<<(QDataStream &out, const RemovePchProjectPartsMessage &message) + friend QDataStream &operator<<(QDataStream &out, const RemoveProjectPartsMessage &message) { out << message.m_projectsPartIds; return out; } - friend QDataStream &operator>>(QDataStream &in, RemovePchProjectPartsMessage &message) + friend QDataStream &operator>>(QDataStream &in, RemoveProjectPartsMessage &message) { in >> message.m_projectsPartIds; return in; } - friend bool operator==(const RemovePchProjectPartsMessage &first, - const RemovePchProjectPartsMessage &second) + friend bool operator==(const RemoveProjectPartsMessage &first, + const RemoveProjectPartsMessage &second) { return first.m_projectsPartIds == second.m_projectsPartIds; } - RemovePchProjectPartsMessage clone() const + RemoveProjectPartsMessage clone() const { - return RemovePchProjectPartsMessage(m_projectsPartIds.clone()); + return RemoveProjectPartsMessage(m_projectsPartIds.clone()); } private: Utils::SmallStringVector m_projectsPartIds; }; -CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemovePchProjectPartsMessage &message); +CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemoveProjectPartsMessage &message); -DECLARE_MESSAGE(RemovePchProjectPartsMessage) +DECLARE_MESSAGE(RemoveProjectPartsMessage) } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/updatepchprojectpartsmessage.cpp b/src/libs/clangsupport/updateprojectpartsmessage.cpp similarity index 88% rename from src/libs/clangsupport/updatepchprojectpartsmessage.cpp rename to src/libs/clangsupport/updateprojectpartsmessage.cpp index 5b93b78a02e..76fc6ea6221 100644 --- a/src/libs/clangsupport/updatepchprojectpartsmessage.cpp +++ b/src/libs/clangsupport/updateprojectpartsmessage.cpp @@ -23,13 +23,13 @@ ** ****************************************************************************/ -#include "updatepchprojectpartsmessage.h" +#include "updateprojectpartsmessage.h" namespace ClangBackEnd { -QDebug operator<<(QDebug debug, const UpdatePchProjectPartsMessage &message) +QDebug operator<<(QDebug debug, const UpdateProjectPartsMessage &message) { - debug.nospace() << "UpdatePchProjectPartsMessage(" + debug.nospace() << "UpdateProjectPartsMessage(" << message.projectsParts() << ")"; return debug; diff --git a/src/libs/clangsupport/updatepchprojectpartsmessage.h b/src/libs/clangsupport/updateprojectpartsmessage.h similarity index 78% rename from src/libs/clangsupport/updatepchprojectpartsmessage.h rename to src/libs/clangsupport/updateprojectpartsmessage.h index 0cd925571cb..5807d89bc60 100644 --- a/src/libs/clangsupport/updatepchprojectpartsmessage.h +++ b/src/libs/clangsupport/updateprojectpartsmessage.h @@ -30,12 +30,12 @@ namespace ClangBackEnd { -class UpdatePchProjectPartsMessage +class UpdateProjectPartsMessage { public: - UpdatePchProjectPartsMessage() = default; - UpdatePchProjectPartsMessage(V2::ProjectPartContainers &&projectsParts, - V2::FileContainers &&generatedFiles) + UpdateProjectPartsMessage() = default; + UpdateProjectPartsMessage(V2::ProjectPartContainers &&projectsParts, + V2::FileContainers &&generatedFiles) : m_projectsParts(std::move(projectsParts)), m_generatedFiles(std::move(generatedFiles)) {} @@ -60,7 +60,7 @@ public: return std::move(m_generatedFiles); } - friend QDataStream &operator<<(QDataStream &out, const UpdatePchProjectPartsMessage &message) + friend QDataStream &operator<<(QDataStream &out, const UpdateProjectPartsMessage &message) { out << message.m_projectsParts; out << message.m_generatedFiles; @@ -68,7 +68,7 @@ public: return out; } - friend QDataStream &operator>>(QDataStream &in, UpdatePchProjectPartsMessage &message) + friend QDataStream &operator>>(QDataStream &in, UpdateProjectPartsMessage &message) { in >> message.m_projectsParts; in >> message.m_generatedFiles; @@ -76,16 +76,16 @@ public: return in; } - friend bool operator==(const UpdatePchProjectPartsMessage &first, - const UpdatePchProjectPartsMessage &second) + friend bool operator==(const UpdateProjectPartsMessage &first, + const UpdateProjectPartsMessage &second) { return first.m_projectsParts == second.m_projectsParts && first.m_generatedFiles == second.m_generatedFiles; } - UpdatePchProjectPartsMessage clone() const + UpdateProjectPartsMessage clone() const { - return UpdatePchProjectPartsMessage(Utils::clone(m_projectsParts), + return UpdateProjectPartsMessage(Utils::clone(m_projectsParts), Utils::clone(m_generatedFiles)); } @@ -94,8 +94,8 @@ private: V2::FileContainers m_generatedFiles; }; -CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const UpdatePchProjectPartsMessage &message); +CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const UpdateProjectPartsMessage &message); -DECLARE_MESSAGE(UpdatePchProjectPartsMessage) +DECLARE_MESSAGE(UpdateProjectPartsMessage) } // namespace ClangBackEnd diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index b45e99849c4..3b79a782aca 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -37,6 +37,9 @@ namespace Sqlite { +class ReadStatement; +class WriteStatement; + class SQLITE_EXPORT Database final : public TransactionInterface { template @@ -45,6 +48,8 @@ class SQLITE_EXPORT Database final : public TransactionInterface public: using MutexType = std::mutex; + using ReadStatement = Sqlite::ReadStatement; + using WriteStatement = Sqlite::WriteStatement; Database(); Database(Utils::PathString &&databaseFilePath, JournalMode journalMode=JournalMode::Wal); diff --git a/src/plugins/clangpchmanager/clangpchmanager-source.pri b/src/plugins/clangpchmanager/clangpchmanager-source.pri index 25d8d637305..08664854dde 100644 --- a/src/plugins/clangpchmanager/clangpchmanager-source.pri +++ b/src/plugins/clangpchmanager/clangpchmanager-source.pri @@ -12,7 +12,9 @@ HEADERS += \ $$PWD/pchmanagerconnectionclient.h \ $$PWD/clangpchmanager_global.h \ $$PWD/projectupdater.h \ - $$PWD/pchmanagerprojectupdater.h + $$PWD/pchmanagerprojectupdater.h \ + $$PWD/precompiledheaderstorage.h \ + $$PWD/precompiledheaderstorageinterface.h SOURCES += \ @@ -20,5 +22,6 @@ SOURCES += \ $$PWD/pchmanagernotifierinterface.cpp \ $$PWD/pchmanagerconnectionclient.cpp \ $$PWD/projectupdater.cpp \ - $$PWD/pchmanagerprojectupdater.cpp + $$PWD/pchmanagerprojectupdater.cpp \ + $$PWD/precompiledheaderstorageinterface.cpp diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp index c76342a0cd0..fa85c4133bc 100644 --- a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp +++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp @@ -27,6 +27,7 @@ #include "pchmanagerconnectionclient.h" #include "pchmanagerclient.h" +#include "precompiledheaderstorage.h" #include "qtcreatorprojectupdater.h" #include @@ -57,7 +58,8 @@ public: Sqlite::Database database{Utils::PathString{Core::ICore::userResourcePath() + "/symbol-experimental-v1.db"}}; ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; - PchManagerClient pchManagerClient; + PrecompiledHeaderStorage<> preCompiledHeaderStorage{database}; + PchManagerClient pchManagerClient{preCompiledHeaderStorage}; PchManagerConnectionClient connectionClient{&pchManagerClient}; QtCreatorProjectUpdater projectUpdate{connectionClient.serverProxy(), pchManagerClient, diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.h b/src/plugins/clangpchmanager/clangpchmanagerplugin.h index 666e3df5c9a..60c7d2b2661 100644 --- a/src/plugins/clangpchmanager/clangpchmanagerplugin.h +++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.h @@ -25,6 +25,8 @@ #pragma once +#include "clangpchmanager_global.h" + #include #include @@ -34,7 +36,7 @@ namespace ClangPchManager { class ClangPchManagerPluginData; class PchManagerClient; -class ClangPchManagerPlugin : public ExtensionSystem::IPlugin +class CLANGPCHMANAGER_EXPORT ClangPchManagerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangPchManager.json") diff --git a/src/plugins/clangpchmanager/pchmanagerclient.cpp b/src/plugins/clangpchmanager/pchmanagerclient.cpp index e930a5748e2..e5321865cee 100644 --- a/src/plugins/clangpchmanager/pchmanagerclient.cpp +++ b/src/plugins/clangpchmanager/pchmanagerclient.cpp @@ -34,6 +34,11 @@ namespace ClangPchManager { +PchManagerClient::PchManagerClient(PrecompiledHeaderStorageInterface &precompiledHeaderStorage) + : m_precompiledHeaderStorage(precompiledHeaderStorage) +{ +} + void PchManagerClient::alive() { if (m_connectionClient) @@ -42,17 +47,23 @@ void PchManagerClient::alive() void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) { - for (const ClangBackEnd::ProjectPartPch &projectPartPch : message.projectPartPchs()) { - precompiledHeaderUpdated(QString(projectPartPch.projectPartId), - QString(projectPartPch.pchPath), - projectPartPch.lastModified); + for (ClangBackEnd::ProjectPartPch &projectPartPch : message.takeProjectPartPchs()) { + const QString projectPartId{projectPartPch.projectPartId}; + const QString pchPath{projectPartPch.pchPath}; + addPchToDatabase(projectPartPch); + addProjectPartPch(std::move(projectPartPch)); + precompiledHeaderUpdated(projectPartId, pchPath, projectPartPch.lastModified); } } void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId) { - for (auto notifier : m_notifiers) + for (auto notifier : m_notifiers) { + Utils::SmallString id(projectPartId); + removePchFromDatabase(id); + removeProjectPartPch(id); notifier->precompiledHeaderRemoved(projectPartId); + } } void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectionClient) @@ -60,6 +71,21 @@ void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectio m_connectionClient = connectionClient; } +Utils::optional PchManagerClient::projectPartPch(Utils::SmallStringView projectPartId) const +{ + auto found = std::lower_bound(m_projectPartPchs.cbegin(), + m_projectPartPchs.cend(), + projectPartId, + [] (const auto &projectPartPch, auto projectPartId) { + return projectPartId < projectPartPch.projectPartId; + }); + + if (found != m_projectPartPchs.end() && found->projectPartId == projectPartId) + return *found; + + return Utils::nullopt; +} + void PchManagerClient::attach(PchManagerNotifierInterface *notifier) { m_notifiers.push_back(notifier); @@ -76,6 +102,48 @@ void PchManagerClient::detach(PchManagerNotifierInterface *notifierToBeDeleted) m_notifiers.erase(newEnd, m_notifiers.end()); } +void PchManagerClient::removeProjectPartPch(Utils::SmallStringView projectPartId) +{ + auto found = std::lower_bound(m_projectPartPchs.begin(), + m_projectPartPchs.end(), + projectPartId, + [] (const auto &projectPartPch, auto projectPartId) { + return projectPartId < projectPartPch.projectPartId; + }); + + if (found != m_projectPartPchs.end() && found->projectPartId == projectPartId) { + *found = std::move(m_projectPartPchs.back()); + m_projectPartPchs.pop_back(); + } +} + +void PchManagerClient::addPchToDatabase(const ClangBackEnd::ProjectPartPch &projectPartPch) +{ + m_precompiledHeaderStorage.insertPrecompiledHeader(projectPartPch.projectPartId, + projectPartPch.pchPath, + projectPartPch.lastModified); +} + +void PchManagerClient::removePchFromDatabase(const Utils::SmallStringView &projectPartId) +{ + m_precompiledHeaderStorage.deletePrecompiledHeader(projectPartId); +} + +void PchManagerClient::addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch) +{ + auto found = std::lower_bound(m_projectPartPchs.begin(), + m_projectPartPchs.end(), + projectPartPch.projectPartId, + [] (const auto &projectPartPch, auto projectPartId) { + return projectPartId < projectPartPch.projectPartId; + }); + + if (found != m_projectPartPchs.end() && found->projectPartId == projectPartPch.projectPartId) + *found = std::move(projectPartPch); + else + m_projectPartPchs.insert(found, std::move(projectPartPch)); +} + const std::vector &PchManagerClient::notifiers() const { return m_notifiers; diff --git a/src/plugins/clangpchmanager/pchmanagerclient.h b/src/plugins/clangpchmanager/pchmanagerclient.h index 2da600fa54b..e9b80ebe513 100644 --- a/src/plugins/clangpchmanager/pchmanagerclient.h +++ b/src/plugins/clangpchmanager/pchmanagerclient.h @@ -25,7 +25,11 @@ #pragma once +#include "clangpchmanager_global.h" +#include "precompiledheaderstorageinterface.h" + #include +#include #include @@ -34,10 +38,12 @@ class PchManagerConnectionClient; class PchManagerNotifierInterface; -class PchManagerClient final : public ClangBackEnd::PchManagerClientInterface +class CLANGPCHMANAGER_EXPORT PchManagerClient final : public ClangBackEnd::PchManagerClientInterface, + public ClangBackEnd::ProjectPartPchProviderInterface { friend class PchManagerNotifierInterface; public: + PchManagerClient(PrecompiledHeaderStorageInterface &precompiledHeaderStorage); void alive() override; void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override; @@ -45,6 +51,14 @@ public: void setConnectionClient(PchManagerConnectionClient *connectionClient); + Utils::optional projectPartPch( + Utils::SmallStringView projectPartId) const override; + + const ClangBackEnd::ProjectPartPchs &projectPartPchs() const override + { + return m_projectPartPchs; + } + unittest_public: const std::vector ¬ifiers() const; void precompiledHeaderUpdated(const QString &projectPartId, @@ -54,9 +68,17 @@ unittest_public: void attach(PchManagerNotifierInterface *notifier); void detach(PchManagerNotifierInterface *notifier); + void addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch); + void removeProjectPartPch(Utils::SmallStringView projectPartId); + + void addPchToDatabase(const ClangBackEnd::ProjectPartPch &projectPartPch); + void removePchFromDatabase(const Utils::SmallStringView &projectPartId); + private: + ClangBackEnd::ProjectPartPchs m_projectPartPchs; std::vector m_notifiers; PchManagerConnectionClient *m_connectionClient=nullptr; + PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage; }; } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/pchmanagernotifierinterface.h b/src/plugins/clangpchmanager/pchmanagernotifierinterface.h index fde500feac3..eef722f6493 100644 --- a/src/plugins/clangpchmanager/pchmanagernotifierinterface.h +++ b/src/plugins/clangpchmanager/pchmanagernotifierinterface.h @@ -25,7 +25,7 @@ #pragma once -#include +#include "clangpchmanager_global.h" QT_FORWARD_DECLARE_CLASS(QString) @@ -33,10 +33,10 @@ namespace ClangPchManager { class PchManagerClient; -class PchManagerNotifierInterface +class CLANGPCHMANAGER_EXPORT PchManagerNotifierInterface { public: - PchManagerNotifierInterface(PchManagerClient &pchManagerClientso); + PchManagerNotifierInterface(PchManagerClient &pchManagerClient); virtual ~PchManagerNotifierInterface(); virtual void precompiledHeaderUpdated(const QString &projectPartId, @@ -44,6 +44,9 @@ public: long long lastModified) = 0; virtual void precompiledHeaderRemoved(const QString &projectPartId) = 0; + PchManagerNotifierInterface(const PchManagerNotifierInterface &) = delete; + void operator=(const PchManagerNotifierInterface &) const = delete; + PchManagerClient &m_pchManagerClient; }; diff --git a/src/plugins/clangpchmanager/precompiledheaderstorage.h b/src/plugins/clangpchmanager/precompiledheaderstorage.h new file mode 100644 index 00000000000..682e9c3492e --- /dev/null +++ b/src/plugins/clangpchmanager/precompiledheaderstorage.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 "precompiledheaderstorageinterface.h" + +#include + +#include + +namespace ClangPchManager { + +template +class PrecompiledHeaderStorage final : public PrecompiledHeaderStorageInterface +{ + using ReadStatement = typename Database::ReadStatement; + using WriteStatement = typename Database::WriteStatement; +public: + PrecompiledHeaderStorage(Database &database) + : m_transaction(database), + m_database(database) + { + m_transaction.commit(); + } + + void insertPrecompiledHeader(Utils::SmallStringView projectPartName, + Utils::SmallStringView pchPath, + long long pchBuildTime) override + { + m_insertProjectPartStatement.write(projectPartName); + m_insertPrecompiledHeaderStatement .write(projectPartName, pchPath, pchBuildTime); + } + + void deletePrecompiledHeader(Utils::SmallStringView projectPartName) override + { + m_deletePrecompiledHeaderStatement.write(projectPartName); + } + + +public: + Sqlite::ImmediateNonThrowingDestructorTransaction m_transaction; + Database &m_database; + WriteStatement m_insertPrecompiledHeaderStatement { + "INSERT OR REPLACE INTO precompiledHeaders(projectPartId, pchPath, pchBuildTime) VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?),?,?)", + m_database + }; + WriteStatement m_insertProjectPartStatement{ + "INSERT OR IGNORE INTO projectParts(projectPartName) VALUES (?)", + m_database + }; + WriteStatement m_deletePrecompiledHeaderStatement{ + "DELETE FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId FROM projectParts WHERE projectPartName = ?)", + m_database + }; +}; + +} diff --git a/src/plugins/clangpchmanager/precompiledheaderstorageinterface.cpp b/src/plugins/clangpchmanager/precompiledheaderstorageinterface.cpp new file mode 100644 index 00000000000..8cc27abe112 --- /dev/null +++ b/src/plugins/clangpchmanager/precompiledheaderstorageinterface.cpp @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** 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 "precompiledheaderstorageinterface.h" + +namespace ClangPchManager { + +PrecompiledHeaderStorageInterface::~PrecompiledHeaderStorageInterface() = default; + +} // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/precompiledheaderstorageinterface.h b/src/plugins/clangpchmanager/precompiledheaderstorageinterface.h new file mode 100644 index 00000000000..2db132dbce0 --- /dev/null +++ b/src/plugins/clangpchmanager/precompiledheaderstorageinterface.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace ClangPchManager { + +class PrecompiledHeaderStorageInterface +{ +public: + PrecompiledHeaderStorageInterface() = default; + virtual ~PrecompiledHeaderStorageInterface(); + + PrecompiledHeaderStorageInterface(const PrecompiledHeaderStorageInterface&) = delete; + PrecompiledHeaderStorageInterface &operator=(const PrecompiledHeaderStorageInterface&) = delete; + + virtual void insertPrecompiledHeader(Utils::SmallStringView projectPartName, + Utils::SmallStringView pchPath, + long long pchBuildTime) = 0; + + virtual void deletePrecompiledHeader(Utils::SmallStringView projectPartName) = 0; +}; + +} // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp index 5bd170897b3..c43c10dc464 100644 --- a/src/plugins/clangpchmanager/projectupdater.cpp +++ b/src/plugins/clangpchmanager/projectupdater.cpp @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -67,17 +67,17 @@ void ProjectUpdater::updateProjectParts(const std::vector + +namespace CppTools { +class ProjectPart; +} + +namespace ClangRefactoring { + +class ProjectPartProviderInterface +{ +public: + ProjectPartProviderInterface() = default; + virtual ~ProjectPartProviderInterface(); + + ProjectPartProviderInterface(const ProjectPartProviderInterface&) = delete; + ProjectPartProviderInterface& operator=(const ProjectPartProviderInterface&) = delete; + + ProjectPartProviderInterface(ProjectPartProviderInterface&&) = default; + ProjectPartProviderInterface& operator=(ProjectPartProviderInterface&&) = default; + + virtual CppTools::ProjectPart *projectPart(const QString &projectPartId) const = 0; + virtual ClangBackEnd::V2::FileContainers generatedFiles() const = 0; +}; + +} // namespace ClangRefactoring diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index 5bd40b18277..4a3960b8cbc 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -27,8 +27,8 @@ #include #include -#include -#include +#include +#include #include @@ -52,7 +52,7 @@ void PchManagerServer::end() } -void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) +void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message) { m_pchCreator.setGeneratedFiles(message.takeGeneratedFiles()); @@ -61,7 +61,7 @@ void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&mess m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes()); } -void PchManagerServer::removePchProjectParts(RemovePchProjectPartsMessage &&message) +void PchManagerServer::removeProjectParts(RemoveProjectPartsMessage &&message) { m_fileSystemWatcher.removeIds(message.projectsPartIds()); diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index 5e736b18873..0921ce772cd 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -51,8 +51,8 @@ public: void end() override; - void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; - void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; + void updateProjectParts(UpdateProjectPartsMessage &&message) override; + void removeProjectParts(RemoveProjectPartsMessage &&message) override; void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override; void pathsChanged(const FilePathIds &filePathIds) override; diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index da16f5bdc4f..d45098f3999 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -95,12 +95,12 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo message.takeQuery()); } -void RefactoringServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) +void RefactoringServer::updateProjectParts(UpdateProjectPartsMessage &&message) { m_symbolIndexing.updateProjectParts(message.takeProjectsParts(), message.takeGeneratedFiles()); } -void RefactoringServer::removePchProjectParts(RemovePchProjectPartsMessage &&) +void RefactoringServer::removeProjectParts(RemoveProjectPartsMessage &&) { } diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h index e0a1f23ce95..1823174335d 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.h +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h @@ -61,8 +61,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 updateProjectParts(UpdateProjectPartsMessage &&message) override; + void removeProjectParts(RemoveProjectPartsMessage &&message) override; void cancel() override; bool isCancelingJobs() const; diff --git a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h index d74c55a3e02..7c63b0478f1 100644 --- a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h +++ b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h @@ -30,15 +30,13 @@ namespace ClangBackEnd { -template +template class StorageSqliteStatementFactory { public: - using DatabaseType = Database; - using ReadStatementType = ReadStatement; - using WriteStatementType = WriteStatement; + using Database = DatabaseType; + using ReadStatement = typename Database::ReadStatement; + using WriteStatement = typename Database::WriteStatement; StorageSqliteStatementFactory(Database &database) : transaction(database), @@ -229,5 +227,9 @@ public: "WITH RECURSIVE sourceIds(sourceId) AS (VALUES(?) UNION SELECT dependencySourceId FROM sourceDependencies, sourceIds WHERE sourceDependencies.sourceId = sourceIds.sourceId) SELECT min(lastModified) FROM fileStatuses, sourceIds WHERE fileStatuses.sourceId = sourceIds.sourceId", database }; + ReadStatement getPrecompiledHeader{ + "SELECT pchPath, pchBuildTime FROM precompiledHeaders WHERE projectPartId = ?", + database + }; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp index e38009ed878..0cc7dbc53d2 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp @@ -54,10 +54,14 @@ void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart, { m_symbolsCollector.clear(); - FilePathIds sourcePathIds = updatableFilePathIds(projectPart); + const Utils::optional optionalArtefact = m_symbolStorage.fetchProjectPartArtefact( + projectPart.projectPartId()); + + FilePathIds sourcePathIds = updatableFilePathIds(projectPart, optionalArtefact); if (!sourcePathIds.empty()) { - m_symbolsCollector.addFiles(projectPart.sourcePathIds(), projectPart.arguments()); + m_symbolsCollector.addFiles(projectPart.sourcePathIds(), + compilerArguments(projectPart, optionalArtefact)); m_symbolsCollector.addUnsavedFiles(generatedFiles); @@ -102,10 +106,11 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId) const Utils::optional optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(filePathId); - if (optionalArtefact) { + if (optionalArtefact && !optionalArtefact.value().compilerArguments.empty()) { const ProjectPartArtefact &artefact = optionalArtefact.value(); - m_symbolsCollector.addFiles({filePathId}, artefact.compilerArguments); + m_symbolsCollector.addFiles({filePathId}, + compilerArguments(artefact.compilerArguments, artefact.projectPartId)); m_symbolsCollector.collectSymbols(); @@ -127,11 +132,10 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId) } } -bool SymbolIndexer::compilerMacrosOrIncludeSearchPathsAreDifferent(const V2::ProjectPartContainer &projectPart) const +bool SymbolIndexer::compilerMacrosOrIncludeSearchPathsAreDifferent( + const V2::ProjectPartContainer &projectPart, + const Utils::optional &optionalArtefact) const { - const Utils::optional optionalArtefact = m_symbolStorage.fetchProjectPartArtefact( - projectPart.projectPartId()); - if (optionalArtefact) { const ProjectPartArtefact &artefact = optionalArtefact.value(); return projectPart.compilerMacros() != artefact.compilerMacros @@ -156,12 +160,40 @@ FilePathIds SymbolIndexer::filterChangedFiles(const V2::ProjectPartContainer &pr return ids; } -FilePathIds SymbolIndexer::updatableFilePathIds(const V2::ProjectPartContainer &projectPart) const +FilePathIds SymbolIndexer::updatableFilePathIds(const V2::ProjectPartContainer &projectPart, + const Utils::optional &optionalArtefact) const { - if (compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart)) + if (compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart, optionalArtefact)) return projectPart.sourcePathIds(); return filterChangedFiles(projectPart); } +Utils::SmallStringVector SymbolIndexer::compilerArguments( + Utils::SmallStringVector arguments, + int projectPartId) const +{ + Utils::optional optionalProjectPartPch = m_symbolStorage.fetchPrecompiledHeader(projectPartId); + + if (optionalProjectPartPch) { + arguments.emplace_back("-Xclang"); + arguments.emplace_back("-include-pch"); + arguments.emplace_back("-Xclang"); + arguments.emplace_back(std::move(optionalProjectPartPch.value().pchPath)); + } + + return arguments; +} + +Utils::SmallStringVector SymbolIndexer::compilerArguments( + const V2::ProjectPartContainer &projectPart, + const Utils::optional &optionalProjectPartArtefact) const +{ + if (optionalProjectPartArtefact) + return compilerArguments(projectPart.arguments(), + optionalProjectPartArtefact.value().projectPartId); + + return projectPart.arguments(); +} + } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.h b/src/tools/clangrefactoringbackend/source/symbolindexer.h index 6460d307e7c..42ab3876620 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.h @@ -55,12 +55,19 @@ public: void updateChangedPath(FilePathId filePath); bool compilerMacrosOrIncludeSearchPathsAreDifferent( - const V2::ProjectPartContainer &projectPart) const; + const V2::ProjectPartContainer &projectPart, + const Utils::optional &optionalArtefact) const; FilePathIds filterChangedFiles( const V2::ProjectPartContainer &projectPart) const; - FilePathIds updatableFilePathIds(const V2::ProjectPartContainer &projectPart) const; + FilePathIds updatableFilePathIds(const V2::ProjectPartContainer &projectPart, + const Utils::optional &optionalArtefact) const; + + Utils::SmallStringVector compilerArguments(const V2::ProjectPartContainer &projectPart, + const Utils::optional &optionalArtefact) const; + Utils::SmallStringVector compilerArguments(Utils::SmallStringVector arguments, + int projectPartId) const; private: SymbolsCollectorInterface &m_symbolsCollector; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h index 5726b6aa19a..042b2368a5f 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexing.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h @@ -46,9 +46,7 @@ namespace ClangBackEnd { class SymbolIndexing final : public SymbolIndexingInterface { public: - using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory; + using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory; using Storage = ClangBackEnd::SymbolStorage; SymbolIndexing(Sqlite::Database &database, diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h index 592df6bd8ba..efb45b04d49 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorage.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h @@ -40,9 +40,9 @@ namespace ClangBackEnd { template class SymbolStorage final : public SymbolStorageInterface { - using ReadStatement = typename StatementFactory::ReadStatementType; - using WriteStatement = typename StatementFactory::WriteStatementType; - using Database = typename StatementFactory::DatabaseType; + using ReadStatement = typename StatementFactory::ReadStatement; + using WriteStatement = typename StatementFactory::WriteStatement; + using Database = typename StatementFactory::Database; public: SymbolStorage(StatementFactory &statementFactory, @@ -87,8 +87,8 @@ public: WriteStatement &updateStatement = m_statementFactory.updateProjectPartStatement; updateStatement.write(compilerArguementsAsJson, compilerMacrosAsJson, - projectPartName, - includeSearchPathsAsJason); + includeSearchPathsAsJason, + projectPartName); } } @@ -252,6 +252,11 @@ public: m_statementFactory.deleteNewLocationsTableStatement.execute(); } + Utils::optional fetchPrecompiledHeader(int projectPartId) const + { + return m_statementFactory.getPrecompiledHeader.template value(projectPartId); + } + SourceLocationEntries sourceLocations() const { return SourceLocationEntries(); diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h index fcbaaff7e31..71db663c4e4 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h @@ -27,6 +27,7 @@ #include "filestatus.h" #include "projectpartentry.h" +#include "projectpartpch.h" #include "projectpartartefact.h" #include "sourcelocationentry.h" #include "sourcedependency.h" @@ -63,6 +64,7 @@ public: virtual Utils::optional fetchProjectPartArtefact(FilePathId sourceId) const = 0; virtual Utils::optional fetchProjectPartArtefact(Utils::SmallStringView projectPartName) const = 0; virtual long long fetchLowestLastModifiedTime(FilePathId sourceId) const = 0; + virtual Utils::optional fetchPrecompiledHeader(int projectPartId) const = 0; }; } // namespace ClangBackEnd diff --git a/tests/unit/unittest/filepathstorage-test.cpp b/tests/unit/unittest/filepathstorage-test.cpp index c9249a89b73..0e1cf6caf12 100644 --- a/tests/unit/unittest/filepathstorage-test.cpp +++ b/tests/unit/unittest/filepathstorage-test.cpp @@ -35,9 +35,7 @@ namespace { -using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory, - MockSqliteReadStatement, - MockSqliteWriteStatement>; +using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory>; using Storage = ClangBackEnd::FilePathStorage; using ClangBackEnd::Sources::Directory; using ClangBackEnd::Sources::Source; diff --git a/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp b/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp index 51e3ae67199..92ddc10a4a8 100644 --- a/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp @@ -34,9 +34,7 @@ namespace { -using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory, - MockSqliteReadStatement, - MockSqliteWriteStatement>; +using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory>; class FilePathStorageSqliteStatementFactory : public testing::Test { diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 3f8b059e26e..a2cd4c3d41b 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -617,7 +617,7 @@ std::ostream &operator<<(std::ostream &os, const RequestDocumentAnnotationsMessa return os; } -std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &message) +std::ostream &operator<<(std::ostream &out, const RemoveProjectPartsMessage &message) { return out << "(" << message.projectsPartIds() << ")"; } @@ -792,7 +792,7 @@ std::ostream &operator<<(std::ostream &os, const UnregisterUnsavedFilesForEditor return os; } -std::ostream &operator<<(std::ostream &out, const UpdatePchProjectPartsMessage &message) +std::ostream &operator<<(std::ostream &out, const UpdateProjectPartsMessage &message) { return out << "(" << message.projectsParts() @@ -945,7 +945,8 @@ std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &containe << container.projectPartId() << ", " << container.arguments() << ", " << container.headerPathIds() << ", " - << container.sourcePathIds()<< ")"; + << container.compilerMacros() << ", " + << container.includeSearchPaths() << ")"; return out; } diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index 52681807c68..4f03d76d077 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -122,7 +122,7 @@ class PrecompiledHeadersUpdatedMessage; class ProjectPartContainer; class ProjectPartPch; class RegisterUnsavedFilesForEditorMessage; -class RemovePchProjectPartsMessage; +class RemoveProjectPartsMessage; class RequestDocumentAnnotationsMessage; class RequestFollowSymbolMessage; class RequestReferencesMessage; @@ -141,7 +141,7 @@ class TokenInfo; template class TokenProcessor; class UnregisterUnsavedFilesForEditorMessage; -class UpdatePchProjectPartsMessage; +class UpdateProjectPartsMessage; class UpdateTranslationUnitsForEditorMessage; class UpdateVisibleTranslationUnitsMessage; class FilePath; @@ -191,7 +191,7 @@ std::ostream &operator<<(std::ostream &out, const PrecompiledHeadersUpdatedMessa std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container); std::ostream &operator<<(std::ostream &out, const ProjectPartPch &projectPartPch); std::ostream &operator<<(std::ostream &out, const RegisterUnsavedFilesForEditorMessage &message); -std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &message); +std::ostream &operator<<(std::ostream &out, const RemoveProjectPartsMessage &message); std::ostream &operator<<(std::ostream &out, const RequestDocumentAnnotationsMessage &message); std::ostream &operator<<(std::ostream &out, const RequestFollowSymbolMessage &message); std::ostream &operator<<(std::ostream &out, const RequestReferencesMessage &message); @@ -208,7 +208,7 @@ std::ostream &operator<<(std::ostream &out, const SourceRangesContainer &contain std::ostream &operator<<(std::ostream &out, const SourceRangesForQueryMessage &message); std::ostream &operator<<(std::ostream &out, const SourceRangeWithTextContainer &container); std::ostream &operator<<(std::ostream &out, const UnregisterUnsavedFilesForEditorMessage &message); -std::ostream &operator<<(std::ostream &out, const UpdatePchProjectPartsMessage &message); +std::ostream &operator<<(std::ostream &out, const UpdateProjectPartsMessage &message); std::ostream &operator<<(std::ostream &out, const UpdateTranslationUnitsForEditorMessage &message); std::ostream &operator<<(std::ostream &out, const UpdateVisibleTranslationUnitsMessage &message); std::ostream &operator<<(std::ostream &out, const FilePath &filePath); diff --git a/tests/unit/unittest/mockpchmanagernotifier.h b/tests/unit/unittest/mockpchmanagernotifier.h index 64f446e3949..985dc3c1449 100644 --- a/tests/unit/unittest/mockpchmanagernotifier.h +++ b/tests/unit/unittest/mockpchmanagernotifier.h @@ -32,8 +32,8 @@ class MockPchManagerNotifier : public ClangPchManager::PchManagerNotifierInterface { public: - MockPchManagerNotifier(ClangPchManager::PchManagerClient &pchManagerClient) - : ClangPchManager::PchManagerNotifierInterface(pchManagerClient) + MockPchManagerNotifier(const ClangPchManager::PchManagerClient &pchManagerClient) + : ClangPchManager::PchManagerNotifierInterface(const_cast(pchManagerClient)) {} MOCK_METHOD3(precompiledHeaderUpdated, diff --git a/tests/unit/unittest/mockpchmanagerserver.h b/tests/unit/unittest/mockpchmanagerserver.h index f5c703afd1a..766abd95ab6 100644 --- a/tests/unit/unittest/mockpchmanagerserver.h +++ b/tests/unit/unittest/mockpchmanagerserver.h @@ -34,18 +34,18 @@ class MockPchManagerServer : public ClangBackEnd::PchManagerServerInterface public: MOCK_METHOD0(end, void()); - MOCK_METHOD1(updatePchProjectParts, - void (const ClangBackEnd::UpdatePchProjectPartsMessage&)); - MOCK_METHOD1(removePchProjectParts, - void (const ClangBackEnd::RemovePchProjectPartsMessage&)); + MOCK_METHOD1(updateProjectParts, + void (const ClangBackEnd::UpdateProjectPartsMessage&)); + MOCK_METHOD1(removeProjectParts, + void (const ClangBackEnd::RemoveProjectPartsMessage&)); - void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override + void updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage &&message) override { - updatePchProjectParts(message); + updateProjectParts(message); } - void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override + void removeProjectParts(ClangBackEnd::RemoveProjectPartsMessage &&message) override { - removePchProjectParts(message); + removeProjectParts(message); } }; diff --git a/tests/unit/unittest/mockprecompiledheaderstorage.h b/tests/unit/unittest/mockprecompiledheaderstorage.h new file mode 100644 index 00000000000..60ba3525842 --- /dev/null +++ b/tests/unit/unittest/mockprecompiledheaderstorage.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include + +class MockPrecompiledHeaderStorage : public ClangPchManager::PrecompiledHeaderStorageInterface +{ +public: + MOCK_METHOD3(insertPrecompiledHeader, + void (Utils::SmallStringView projectPartName, + Utils::SmallStringView pchPath, + long long pchBuildTime)); + + MOCK_METHOD1(deletePrecompiledHeader, void (Utils::SmallStringView projectPartName)); +}; diff --git a/tests/unit/unittest/mockprojectpartprovider.h b/tests/unit/unittest/mockprojectpartprovider.h new file mode 100644 index 00000000000..1bde9e082fd --- /dev/null +++ b/tests/unit/unittest/mockprojectpartprovider.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** 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 + +class MockProjectPartProvider : public ClangRefactoring::ProjectPartProviderInterface +{ +public: + MOCK_CONST_METHOD0(generatedFiles, + ClangBackEnd::V2::FileContainers()); + MOCK_CONST_METHOD1(projectPart, + CppTools::ProjectPart*(const QString &projectPartId)); +}; diff --git a/tests/unit/unittest/mockrefactoringserver.h b/tests/unit/unittest/mockrefactoringserver.h index c265f88cbcf..091807e2031 100644 --- a/tests/unit/unittest/mockrefactoringserver.h +++ b/tests/unit/unittest/mockrefactoringserver.h @@ -44,11 +44,11 @@ public: MOCK_METHOD1(requestSourceRangesForQueryMessage, void (const ClangBackEnd::RequestSourceRangesForQueryMessage&)); - MOCK_METHOD1(updatePchProjectParts, - void (const ClangBackEnd::UpdatePchProjectPartsMessage&)); + MOCK_METHOD1(updateProjectParts, + void (const ClangBackEnd::UpdateProjectPartsMessage&)); - MOCK_METHOD1(removePchProjectParts, - void (const ClangBackEnd::RemovePchProjectPartsMessage&)); + MOCK_METHOD1(removeProjectParts, + void (const ClangBackEnd::RemoveProjectPartsMessage&)); MOCK_METHOD0(cancel, void()); @@ -68,13 +68,13 @@ public: requestSourceRangesForQueryMessage(message); } - void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override + void updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage &&message) override { - updatePchProjectParts(message); + updateProjectParts(message); } - void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override + void removeProjectParts(ClangBackEnd::RemoveProjectPartsMessage &&message) override { - removePchProjectParts(message); + removeProjectParts(message); } }; diff --git a/tests/unit/unittest/mocksqlitedatabase.h b/tests/unit/unittest/mocksqlitedatabase.h index 271fd77ae0a..36fb370e707 100644 --- a/tests/unit/unittest/mocksqlitedatabase.h +++ b/tests/unit/unittest/mocksqlitedatabase.h @@ -27,7 +27,9 @@ #include "googletest.h" +#include "mocksqlitereadstatement.h" #include "mocksqlitetransactionbackend.h" +#include "mocksqlitewritestatement.h" #include #include @@ -37,6 +39,9 @@ class MockSqliteDatabase : public MockSqliteTransactionBackend { public: + using ReadStatement = MockSqliteReadStatement; + using WriteStatement = MockSqliteWriteStatement; + MOCK_METHOD1(execute, void (Utils::SmallStringView sqlStatement)); diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index d415e785a7f..bb604b34e12 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -107,6 +107,13 @@ MockSqliteReadStatement::value(const Utils return valueReturnProjectPartArtefact(projectPartName); } +template <> +Utils::optional +MockSqliteReadStatement::value(const int &projectPartId) +{ + return valueReturnProjectPartPch(projectPartId); +} + template <> Utils::optional MockSqliteReadStatement::value(const int &sourceId) diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index 9e1f4cb25c2..5ab53705cf0 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -25,13 +25,14 @@ #pragma once -#include "mocksqlitedatabase.h" +#include "googletest.h" #include #include #include #include +#include #include @@ -47,6 +48,8 @@ using ClangRefactoring::SourceLocation; using ClangRefactoring::SourceLocations; namespace Sources = ClangBackEnd::Sources; +class MockSqliteDatabase; + class MockSqliteReadStatement { public: @@ -88,6 +91,9 @@ public: MOCK_METHOD1(valueReturnProjectPartArtefact, Utils::optional(Utils::SmallStringView)); + MOCK_METHOD1(valueReturnProjectPartPch, + Utils::optional(int)); + template @@ -164,6 +170,10 @@ template <> Utils::optional MockSqliteReadStatement::value(const int&); +template <> +Utils::optional +MockSqliteReadStatement::value(const int&); + template <> Utils::optional MockSqliteReadStatement::value(const int&); diff --git a/tests/unit/unittest/mocksqlitewritestatement.h b/tests/unit/unittest/mocksqlitewritestatement.h index 3a823e89677..132fd9728e7 100644 --- a/tests/unit/unittest/mocksqlitewritestatement.h +++ b/tests/unit/unittest/mocksqlitewritestatement.h @@ -25,10 +25,12 @@ #pragma once -#include "mocksqlitedatabase.h" +#include "googletest.h" #include +class MockSqliteDatabase; + class MockSqliteWriteStatement { public: @@ -61,6 +63,9 @@ public: MOCK_METHOD2(write, void (Utils::SmallStringView, Utils::SmallStringView)); + MOCK_METHOD3(write, + void (Utils::SmallStringView, Utils::SmallStringView, long long)); + MOCK_METHOD3(write, void (Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView)); diff --git a/tests/unit/unittest/mocksymbolstorage.h b/tests/unit/unittest/mocksymbolstorage.h index b12f62989dc..90142fe9ee1 100644 --- a/tests/unit/unittest/mocksymbolstorage.h +++ b/tests/unit/unittest/mocksymbolstorage.h @@ -60,4 +60,6 @@ public: Utils::optional (Utils::SmallStringView projectPartName)); MOCK_CONST_METHOD1(fetchLowestLastModifiedTime, long long (ClangBackEnd::FilePathId sourceId)); + MOCK_CONST_METHOD1(fetchPrecompiledHeader, + Utils::optional (int projectPartId)); }; diff --git a/tests/unit/unittest/pchmanagerclient-test.cpp b/tests/unit/unittest/pchmanagerclient-test.cpp index 60bdb39fdbd..9e40a21249d 100644 --- a/tests/unit/unittest/pchmanagerclient-test.cpp +++ b/tests/unit/unittest/pchmanagerclient-test.cpp @@ -27,6 +27,7 @@ #include "mockpchmanagernotifier.h" #include "mockpchmanagerserver.h" +#include "mockprecompiledheaderstorage.h" #include #include @@ -34,8 +35,8 @@ #include #include #include -#include -#include +#include +#include namespace { @@ -48,9 +49,10 @@ using testing::Not; class PchManagerClient : public ::testing::Test { protected: - MockPchManagerServer mockPchManagerServer; - ClangPchManager::PchManagerClient client; - MockPchManagerNotifier mockPchManagerNotifier{client}; + NiceMock mockPchManagerServer; + NiceMock mockPrecompiledHeaderStorage; + ClangPchManager::PchManagerClient client{mockPrecompiledHeaderStorage}; + NiceMock mockPchManagerNotifier{client}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; @@ -58,6 +60,9 @@ protected: Utils::SmallString projectPartId{"projectPartId"}; Utils::SmallString pchFilePath{"/path/to/pch"}; PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone(), 1}}}; + Utils::SmallString projectPartId2{"projectPartId2"}; + Utils::SmallString pchFilePath2{"/path/to/pch2"}; + PrecompiledHeadersUpdatedMessage message2{{{projectPartId2.clone(), pchFilePath2.clone(), 1}}}; }; TEST_F(PchManagerClient, NotifierAttached) @@ -95,4 +100,75 @@ TEST_F(PchManagerClient, Remove) QString(projectPartId.clone())}); } +TEST_F(PchManagerClient, GetNoProjectPartPchForWrongProjectPartId) +{ + auto optional = client.projectPartPch("foo"); + + ASSERT_FALSE(optional); +} + +TEST_F(PchManagerClient, GetProjectPartPchForProjectPartId) +{ + client.precompiledHeadersUpdated(std::move(message)); + + auto optional = client.projectPartPch(projectPartId); + + ASSERT_TRUE(optional); +} + +TEST_F(PchManagerClient, ProjectPartPchRemoved) +{ + client.precompiledHeadersUpdated(std::move(message)); + + client.precompiledHeaderRemoved(QString(projectPartId)); + + ASSERT_FALSE(client.projectPartPch(projectPartId)); +} + +TEST_F(PchManagerClient, ProjectPartPchHasNoDublicateEntries) +{ + client.precompiledHeadersUpdated(message.clone()); + client.precompiledHeadersUpdated(message2.clone()); + + client.precompiledHeadersUpdated(message.clone()); + + ASSERT_THAT(client.projectPartPchs(), SizeIs(2)); +} + +TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdLastModified) +{ + client.precompiledHeadersUpdated(std::move(message)); + + ASSERT_THAT(client.projectPartPch(projectPartId).value().lastModified, + 1); +} + +TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdIsUpdated) +{ + client.precompiledHeadersUpdated(message.clone()); + PrecompiledHeadersUpdatedMessage updateMessage{{{projectPartId.clone(), pchFilePath.clone(), 42}}}; + + client.precompiledHeadersUpdated(updateMessage.clone()); + + ASSERT_THAT(client.projectPartPch(projectPartId).value().lastModified, + 42); +} + +TEST_F(PchManagerClient, ProjectPartPchAddedToDatabase) +{ + EXPECT_CALL(mockPrecompiledHeaderStorage, insertPrecompiledHeader(TypedEq(projectPartId), + TypedEq(pchFilePath), + TypedEq(1))); + + client.precompiledHeadersUpdated(message.clone()); +} + +TEST_F(PchManagerClient, ProjectPartPchRemovedFromDatabase) +{ + EXPECT_CALL(mockPrecompiledHeaderStorage, deletePrecompiledHeader(TypedEq(projectPartId))); + + + projectUpdater.removeProjectParts({QString(projectPartId)}); +} + } diff --git a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp index c5469ee8e2b..f37fe2ae5e0 100644 --- a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp +++ b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp @@ -32,8 +32,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -41,10 +41,10 @@ #include -using ClangBackEnd::UpdatePchProjectPartsMessage; +using ClangBackEnd::UpdateProjectPartsMessage; using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::ProjectPartContainer; -using ClangBackEnd::RemovePchProjectPartsMessage; +using ClangBackEnd::RemoveProjectPartsMessage; using ClangBackEnd::PrecompiledHeadersUpdatedMessage; using ::testing::Args; @@ -90,7 +90,7 @@ TEST_F(PchManagerClientServerInProcess, SendAliveMessage) scheduleClientMessages(); } -TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage) +TEST_F(PchManagerClientServerInProcess, SendUpdateProjectPartsMessage) { ProjectPartContainer projectPart2{"projectPartId", {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, @@ -99,21 +99,21 @@ TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage) {{1, 1}}, {{1, 2}}}; FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; - UpdatePchProjectPartsMessage message{{projectPart2}, {fileContainer}}; + UpdateProjectPartsMessage message{{projectPart2}, {fileContainer}}; - EXPECT_CALL(mockPchManagerServer, updatePchProjectParts(message)); + EXPECT_CALL(mockPchManagerServer, updateProjectParts(message)); - serverProxy.updatePchProjectParts(message.clone()); + serverProxy.updateProjectParts(message.clone()); scheduleServerMessages(); } -TEST_F(PchManagerClientServerInProcess, SendRemovePchProjectPartsMessage) +TEST_F(PchManagerClientServerInProcess, SendRemoveProjectPartsMessage) { - RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}}; + RemoveProjectPartsMessage message{{"projectPartId1", "projectPartId2"}}; - EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message)); + EXPECT_CALL(mockPchManagerServer, removeProjectParts(message)); - serverProxy.removePchProjectParts(message.clone()); + serverProxy.removeProjectParts(message.clone()); scheduleServerMessages(); } diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp index 793e10345d0..0950a656ac5 100644 --- a/tests/unit/unittest/pchmanagerserver-test.cpp +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -34,8 +34,8 @@ #include #include #include -#include -#include +#include +#include namespace { using Utils::PathString; @@ -82,14 +82,14 @@ protected: {id(main2Path)}}; std::vector projectParts{projectPart1, projectPart2}; FileContainer generatedFile{{"/path/to/", "file"}, "content", {}}; - ClangBackEnd::UpdatePchProjectPartsMessage updatePchProjectPartsMessage{Utils::clone(projectParts), + ClangBackEnd::UpdateProjectPartsMessage UpdateProjectPartsMessage{Utils::clone(projectParts), {generatedFile}}; ClangBackEnd::ProjectPartPch projectPartPch1{projectPart1.projectPartId().clone(), "/path1/to/pch", 1}; ClangBackEnd::ProjectPartPch projectPartPch2{projectPart2.projectPartId().clone(), "/path2/to/pch", 1}; std::vector projectPartPchs{projectPartPch1, projectPartPch2}; ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage1{{projectPartPch1}}; ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage2{{projectPartPch2}}; - ClangBackEnd::RemovePchProjectPartsMessage removePchProjectPartsMessage{{projectPart1.projectPartId().clone(), + ClangBackEnd::RemoveProjectPartsMessage RemoveProjectPartsMessage{{projectPart1.projectPartId().clone(), projectPart2.projectPartId().clone()}}; }; @@ -111,39 +111,39 @@ TEST_F(PchManagerServer, DoNotCallPrecompiledHeadersForUnsuccessfullyFinishedTas TEST_F(PchManagerServer, CallBuildInPchCreator) { auto &&callSetGeneratedFiles = EXPECT_CALL(mockPchCreator, - setGeneratedFiles(updatePchProjectPartsMessage.generatedFiles())); - EXPECT_CALL(mockPchCreator, generatePchs(updatePchProjectPartsMessage.projectsParts())) + setGeneratedFiles(UpdateProjectPartsMessage.generatedFiles())); + EXPECT_CALL(mockPchCreator, generatePchs(UpdateProjectPartsMessage.projectsParts())) .After(callSetGeneratedFiles); - server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + server.updateProjectParts(UpdateProjectPartsMessage.clone()); } TEST_F(PchManagerServer, UpdateIncludesOfFileWatcher) { EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths)); - server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + server.updateProjectParts(UpdateProjectPartsMessage.clone()); } TEST_F(PchManagerServer, GetChangedProjectPartsFromProjectParts) { EXPECT_CALL(mockProjectParts, update(_)); - server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + server.updateProjectParts(UpdateProjectPartsMessage.clone()); } TEST_F(PchManagerServer, RemoveIncludesFromFileWatcher) { - EXPECT_CALL(mockClangPathWatcher, removeIds(removePchProjectPartsMessage.projectsPartIds())); + EXPECT_CALL(mockClangPathWatcher, removeIds(RemoveProjectPartsMessage.projectsPartIds())); - server.removePchProjectParts(removePchProjectPartsMessage.clone()); + server.removeProjectParts(RemoveProjectPartsMessage.clone()); } TEST_F(PchManagerServer, RemoveProjectPartsFromProjectParts) { - EXPECT_CALL(mockProjectParts, remove(removePchProjectPartsMessage.projectsPartIds())); + EXPECT_CALL(mockProjectParts, remove(RemoveProjectPartsMessage.projectsPartIds())); - server.removePchProjectParts(removePchProjectPartsMessage.clone()); + server.removeProjectParts(RemoveProjectPartsMessage.clone()); } TEST_F(PchManagerServer, SetPathWatcherNotifier) @@ -155,7 +155,7 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier) TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange) { - server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + server.updateProjectParts(UpdateProjectPartsMessage.clone()); EXPECT_CALL(mockProjectParts, projects(ElementsAre(projectPart1.projectPartId()))); @@ -164,7 +164,7 @@ TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange) TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange) { - server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + server.updateProjectParts(UpdateProjectPartsMessage.clone()); EXPECT_CALL(mockPchCreator, generatePchs(ElementsAre(projectPart1))); @@ -173,7 +173,7 @@ TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange) TEST_F(PchManagerServer, CallUpdateIdPathsInFileSystemWatcherForIncludeChange) { - server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + server.updateProjectParts(UpdateProjectPartsMessage.clone()); EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths)); diff --git a/tests/unit/unittest/precompiledheaderstorage-test.cpp b/tests/unit/unittest/precompiledheaderstorage-test.cpp new file mode 100644 index 00000000000..2871e3fd112 --- /dev/null +++ b/tests/unit/unittest/precompiledheaderstorage-test.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" +#include "mocksqlitedatabase.h" + +#include +#include +#include +#include + +namespace { + +using Storage = ClangPchManager::PrecompiledHeaderStorage>; + +class PrecompiledHeaderStorage : public testing::Test +{ +protected: + NiceMock database; + Storage storage{database}; + MockSqliteWriteStatement &insertPrecompiledHeaderStatement = storage.m_insertPrecompiledHeaderStatement; + MockSqliteWriteStatement &insertProjectPartStatement = storage.m_insertProjectPartStatement; + MockSqliteWriteStatement &deletePrecompiledHeaderStatement = storage.m_deletePrecompiledHeaderStatement; +}; + +TEST_F(PrecompiledHeaderStorage, UseTransaction) +{ + InSequence s; + + EXPECT_CALL(database, immediateBegin()); + EXPECT_CALL(database, commit()); + + Storage storage{database}; +} + +TEST_F(PrecompiledHeaderStorage, InsertPrecompiledHeader) +{ + InSequence s; + + EXPECT_CALL(insertProjectPartStatement, write(TypedEq("project1"))); + EXPECT_CALL(insertPrecompiledHeaderStatement, + write(TypedEq("project1"), + TypedEq("/path/to/pch"), + TypedEq(22))); + + storage.insertPrecompiledHeader("project1", "/path/to/pch", 22); +} + +TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeader) +{ + InSequence s; + + EXPECT_CALL(deletePrecompiledHeaderStatement, write(TypedEq("project1"))); + + storage.deletePrecompiledHeader("project1"); +} + +TEST_F(PrecompiledHeaderStorage, InsertPrecompiledHeaderStatement) +{ + ASSERT_THAT(insertPrecompiledHeaderStatement.sqlStatement, + Eq("INSERT OR REPLACE INTO precompiledHeaders(projectPartId, pchPath, pchBuildTime) VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?),?,?)")); +} + +TEST_F(PrecompiledHeaderStorage, InsertProjectPartStatement) +{ + ASSERT_THAT(insertProjectPartStatement.sqlStatement, + Eq("INSERT OR IGNORE INTO projectParts(projectPartName) VALUES (?)")); +} + +TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeaderStatement) +{ + ASSERT_THAT(deletePrecompiledHeaderStatement.sqlStatement, + Eq("DELETE FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId FROM projectParts WHERE projectPartName = ?)")); +} + +TEST_F(PrecompiledHeaderStorage, CompilePrecompiledHeaderStatements) +{ + Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; + ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; + + ASSERT_NO_THROW(ClangPchManager::PrecompiledHeaderStorage<>{database}); +} + +} diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp index 49a69aee306..a77dfc0b5b9 100644 --- a/tests/unit/unittest/projectupdater-test.cpp +++ b/tests/unit/unittest/projectupdater-test.cpp @@ -28,15 +28,17 @@ #include "mockpchmanagerclient.h" #include "mockpchmanagernotifier.h" #include "mockpchmanagerserver.h" +#include "mockprecompiledheaderstorage.h" #include #include #include +#include #include #include -#include -#include +#include +#include #include #include @@ -97,7 +99,8 @@ protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; - ClangPchManager::PchManagerClient pchManagerClient; + MockPrecompiledHeaderStorage mockPrecompiledHeaderStorage; + ClangPchManager::PchManagerClient pchManagerClient{mockPrecompiledHeaderStorage}; MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient}; NiceMock mockPchManagerServer; ClangPchManager::ProjectUpdater updater{mockPchManagerServer, filePathCache}; @@ -115,23 +118,22 @@ protected: FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}}; }; -TEST_F(ProjectUpdater, CallUpdatePchProjectParts) +TEST_F(ProjectUpdater, CallUpdateProjectParts) { std::vector projectParts = {&projectPart, &projectPart}; - ClangBackEnd::UpdatePchProjectPartsMessage message{{expectedContainer.clone(), expectedContainer.clone()}, - {generatedFile}}; + ClangBackEnd::UpdateProjectPartsMessage message{{expectedContainer.clone(), expectedContainer.clone()}, + {generatedFile}}; - EXPECT_CALL(mockPchManagerServer, updatePchProjectParts(message)); + EXPECT_CALL(mockPchManagerServer, updateProjectParts(message)); updater.updateProjectParts(projectParts, {generatedFile}); } -TEST_F(ProjectUpdater, CallRemovePchProjectParts) +TEST_F(ProjectUpdater, CallRemoveProjectParts) { + ClangBackEnd::RemoveProjectPartsMessage message{{projectPartId, projectPartId2}}; - ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; - - EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message)); + EXPECT_CALL(mockPchManagerServer, removeProjectParts(message)); updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); } @@ -139,7 +141,7 @@ TEST_F(ProjectUpdater, CallRemovePchProjectParts) TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater) { ClangPchManager::PchManagerProjectUpdater pchUpdater{mockPchManagerServer, pchManagerClient, filePathCache}; - ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; + ClangBackEnd::RemoveProjectPartsMessage message{{projectPartId, projectPartId2}}; EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString())); EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString())); diff --git a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp index ed539afc441..a5658ab1788 100644 --- a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp +++ b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp @@ -47,10 +47,10 @@ using ::testing::Args; using ::testing::Property; using ::testing::Eq; -using ClangBackEnd::UpdatePchProjectPartsMessage; +using ClangBackEnd::UpdateProjectPartsMessage; using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::ProjectPartContainer; -using ClangBackEnd::RemovePchProjectPartsMessage; +using ClangBackEnd::RemoveProjectPartsMessage; class RefactoringClientServerInProcess : public ::testing::Test { @@ -174,7 +174,7 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage) scheduleServerMessages(); } -TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage) +TEST_F(RefactoringClientServerInProcess, SendUpdateProjectPartsMessage) { ProjectPartContainer projectPart2{"projectPartId", {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, @@ -183,21 +183,21 @@ TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage) {{1, 1}}, {{1, 2}}}; FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; - UpdatePchProjectPartsMessage message{{projectPart2}, {fileContainer}}; + UpdateProjectPartsMessage message{{projectPart2}, {fileContainer}}; - EXPECT_CALL(mockRefactoringServer, updatePchProjectParts(message)); + EXPECT_CALL(mockRefactoringServer, updateProjectParts(message)); - serverProxy.updatePchProjectParts(message.clone()); + serverProxy.updateProjectParts(message.clone()); scheduleServerMessages(); } -TEST_F(RefactoringClientServerInProcess, SendRemovePchProjectPartsMessage) +TEST_F(RefactoringClientServerInProcess, SendRemoveProjectPartsMessage) { - RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}}; + RemoveProjectPartsMessage message{{"projectPartId1", "projectPartId2"}}; - EXPECT_CALL(mockRefactoringServer, removePchProjectParts(message)); + EXPECT_CALL(mockRefactoringServer, removeProjectParts(message)); - serverProxy.removePchProjectParts(message.clone()); + serverProxy.removeProjectParts(message.clone()); scheduleServerMessages(); } diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp index adc98c37fed..aa48e790946 100644 --- a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp +++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp @@ -133,6 +133,15 @@ TEST_F(RefactoringDatabaseInitializer, AddSourceDependenciesTable) initializer.createSourceDependenciesTable(); } +TEST_F(RefactoringDatabaseInitializer, AddPrecompiledHeaderTable) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, pchPath TEXT, pchBuildTime INTEGER)"))); + + initializer.createPrecompiledHeadersTable(); +} + TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor) { InSequence s; @@ -157,6 +166,7 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor) EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, lastModified INTEGER, isInPrecompiledHeader INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, pchPath TEXT, pchBuildTime INTEGER)"))); EXPECT_CALL(mockDatabase, commit()); Initializer initializer{mockDatabase}; diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp index 70441e1e3b1..f4161c6cb8f 100644 --- a/tests/unit/unittest/refactoringserver-test.cpp +++ b/tests/unit/unittest/refactoringserver-test.cpp @@ -297,7 +297,7 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); } -TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectParts) +TEST_F(RefactoringServer, UpdateProjectPartsCallsSymbolIndexingUpdateProjectParts) { ProjectPartContainers projectParts{{{"projectPartId", {"-I", TESTDATA_DIR}, @@ -313,7 +313,7 @@ TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectP EXPECT_CALL(mockSymbolIndexing, updateProjectParts(projectParts, unsaved)); - refactoringServer.updatePchProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)}); + refactoringServer.updateProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)}); } void RefactoringServer::SetUp() diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp index 4f994909d17..63876bbb368 100644 --- a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp @@ -33,9 +33,7 @@ namespace { -using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory, - MockSqliteReadStatement, - MockSqliteWriteStatement>; +using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory>; using Sqlite::Table; @@ -274,4 +272,11 @@ TEST_F(StorageSqliteStatementFactory, GetLowestLastModifiedTimeOfDependencies) ASSERT_THAT(factory.getLowestLastModifiedTimeOfDependencies.sqlStatement, Eq("WITH RECURSIVE sourceIds(sourceId) AS (VALUES(?) UNION SELECT dependencySourceId FROM sourceDependencies, sourceIds WHERE sourceDependencies.sourceId = sourceIds.sourceId) SELECT min(lastModified) FROM fileStatuses, sourceIds WHERE fileStatuses.sourceId = sourceIds.sourceId")); } + +TEST_F(StorageSqliteStatementFactory, GetPrecompiledHeaderForProjectPartName) +{ + ASSERT_THAT(factory.getPrecompiledHeader.sqlStatement, + Eq("SELECT pchPath, pchBuildTime FROM precompiledHeaders WHERE projectPartId = ?")); +} + } diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index b29e1ee1fa1..b2a471bf100 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include @@ -59,6 +59,7 @@ using ClangBackEnd::SourceLocationEntries; using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SymbolType; using ClangBackEnd::UsedMacros; +using OptionalProjectPartArtefact = Utils::optional; MATCHER_P2(IsFileId, directoryId, fileNameId, std::string(negation ? "isn't " : "is ") @@ -148,6 +149,8 @@ protected: FileStatuses fileStatus{{{1, 2}, 3, 4, false}}; SourceDependencies sourceDependencies{{{1, 1}, {1, 2}}, {{1, 1}, {1, 3}}}; ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\",\"BAR\":\"1\"}", "[\"/includes\"]", 74}; + ClangBackEnd::ProjectPartArtefact emptyArtefact{"", "", "", 74}; + ClangBackEnd::ProjectPartPch projectPartPch{"/path/to/pch", 4}; NiceMock mockSqliteTransactionBackend; NiceMock mockCollector; NiceMock mockStorage; @@ -170,6 +173,35 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector) indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); } +TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInCollector) +{ + ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq(projectPart1.projectPartId()))).WillByDefault(Return(emptyArtefact)); + ON_CALL(mockStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))).WillByDefault(Return(projectPartPch)); + + EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds(), + ElementsAre(Eq("-I"), + Eq(TESTDATA_DIR), + Eq("-Wno-pragma-once-outside-header"), + Eq("-Xclang"), + Eq("-include-pch"), + Eq("-Xclang"), + Eq("/path/to/pch")))); + + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); +} + +TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithoutPrecompiledHeaderInCollector) +{ + ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq(projectPart1.projectPartId()))).WillByDefault(Return(emptyArtefact)); + + EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds(), + ElementsAre(Eq("-I"), + Eq(TESTDATA_DIR), + Eq("-Wno-pragma-once-outside-header")))); + + indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); +} + TEST_F(SymbolIndexer, UpdateProjectPartsCallsClearInCollector) { EXPECT_CALL(mockCollector, clear()).Times(2); @@ -340,8 +372,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder) TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) { - ON_CALL(mockStorage, fetchProjectPartArtefact(A())) - .WillByDefault(Return(Utils::optional())); + ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) + .WillByDefault(Return(emptyArtefact)); EXPECT_CALL(mockCollector, clear()); EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0])); @@ -358,11 +390,41 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) indexer.updateChangedPath(sourceFileIds[0]); } +TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader) +{ + ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) + .WillByDefault(Return(artefact)); + ON_CALL(mockStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))) + .WillByDefault(Return(projectPartPch)); + + EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds(), + ElementsAre(Eq("-DFOO"), + Eq("-Xclang"), + Eq("-include-pch"), + Eq("-Xclang"), + Eq("/path/to/pch")))); + + indexer.updateChangedPath(sourceFileIds[0]); +} + +TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists) +{ + ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) + .WillByDefault(Return(artefact)); + + EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds(), + ElementsAre(Eq("-DFOO")))); + + indexer.updateChangedPath(sourceFileIds[0]); +} + + TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent) { ON_CALL(mockStorage, fetchProjectPartArtefact(An())).WillByDefault(Return(artefact)); - auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart1); + auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart1, + artefact); ASSERT_FALSE(areDifferent); } @@ -371,7 +433,8 @@ TEST_F(SymbolIndexer, CompilerMacrosAreDifferent) { ON_CALL(mockStorage, fetchProjectPartArtefact(An())).WillByDefault(Return(artefact)); - auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart2); + auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart2, + artefact); ASSERT_TRUE(areDifferent); } @@ -386,7 +449,8 @@ TEST_F(SymbolIndexer, IncludeSearchPathsAreDifferent) {main1PathId}}; ON_CALL(mockStorage, fetchProjectPartArtefact(An())).WillByDefault(Return(artefact)); - auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart3); + auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart3, + artefact); ASSERT_TRUE(areDifferent); } @@ -425,7 +489,7 @@ TEST_F(SymbolIndexer, GetUpdatableFilePathIdsIfCompilerMacrosAreDifferent) { ON_CALL(mockStorage, fetchProjectPartArtefact(An())).WillByDefault(Return(artefact)); - auto filePathIds = indexer.updatableFilePathIds(projectPart2); + auto filePathIds = indexer.updatableFilePathIds(projectPart2, artefact); ASSERT_THAT(filePathIds, projectPart2.sourcePathIds()); } @@ -434,7 +498,7 @@ TEST_F(SymbolIndexer, GetUpdatableFilePathIdsIfIncludeSearchPathsAreDifferent) { ON_CALL(mockStorage, fetchProjectPartArtefact(An())).WillByDefault(Return(artefact)); - auto filePathIds = indexer.updatableFilePathIds(projectPart3); + auto filePathIds = indexer.updatableFilePathIds(projectPart3, artefact); ASSERT_THAT(filePathIds, projectPart3.sourcePathIds()); } @@ -443,7 +507,7 @@ TEST_F(SymbolIndexer, GetNoUpdatableFilePathIdsIfArtefactsAreTheSame) { ON_CALL(mockStorage, fetchProjectPartArtefact(An())).WillByDefault(Return(artefact)); - auto filePathIds = indexer.updatableFilePathIds(projectPart1); + auto filePathIds = indexer.updatableFilePathIds(projectPart1, artefact); ASSERT_THAT(filePathIds, IsEmpty()); } @@ -455,7 +519,7 @@ TEST_F(SymbolIndexer, OutdatedFilesPassUpdatableFilePathIds) ON_CALL(mockStorage, fetchLowestLastModifiedTime(A())) .WillByDefault(Return(0)); - auto filePathIds = indexer.updatableFilePathIds(projectPart1); + auto filePathIds = indexer.updatableFilePathIds(projectPart1, artefact); ASSERT_THAT(filePathIds, ElementsAre(main1PathId)); } @@ -467,7 +531,7 @@ TEST_F(SymbolIndexer, UpToDateFilesDontPassFilteredUpdatableFilePathIds) ON_CALL(mockStorage, fetchLowestLastModifiedTime(A())) .WillByDefault(Return(QDateTime::currentSecsSinceEpoch())); - auto filePathIds = indexer.updatableFilePathIds(projectPart1); + auto filePathIds = indexer.updatableFilePathIds(projectPart1, artefact); ASSERT_THAT(filePathIds, IsEmpty()); } diff --git a/tests/unit/unittest/symbolindexing-test.cpp b/tests/unit/unittest/symbolindexing-test.cpp index 47b09ca0081..aa8452ecfb2 100644 --- a/tests/unit/unittest/symbolindexing-test.cpp +++ b/tests/unit/unittest/symbolindexing-test.cpp @@ -115,6 +115,4 @@ TEST_F(SymbolIndexing, DISABLED_TemplateFunction) IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 6, 5))); } - - } diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp index 1b84f9a668b..f69d49c9ae9 100644 --- a/tests/unit/unittest/symbolstorage-test.cpp +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -26,8 +26,7 @@ #include "googletest.h" #include "mockfilepathcaching.h" -#include "mocksqlitereadstatement.h" -#include "mocksqlitewritestatement.h" +#include "mocksqlitedatabase.h" #include #include @@ -52,9 +51,7 @@ using ClangBackEnd::SymbolType; using Sqlite::Database; using Sqlite::Table; -using StatementFactory = StorageSqliteStatementFactory; +using StatementFactory = StorageSqliteStatementFactory; using Storage = ClangBackEnd::SymbolStorage; class SymbolStorage : public testing::Test @@ -90,6 +87,8 @@ protected: MockSqliteReadStatement &getProjectPartArtefactsBySourceId = statementFactory.getProjectPartArtefactsBySourceId; MockSqliteReadStatement &getProjectPartArtefactsByProjectPartName = statementFactory.getProjectPartArtefactsByProjectPartName; MockSqliteReadStatement &getLowestLastModifiedTimeOfDependencies = statementFactory.getLowestLastModifiedTimeOfDependencies; + MockSqliteReadStatement &getPrecompiledHeader = statementFactory.getPrecompiledHeader; + SymbolEntries symbolEntries{{1, {"functionUSR", "function"}}, {2, {"function2USR", "function2"}}}; SourceLocationEntries sourceLocations{{1, {1, 3}, {42, 23}, SymbolType::Declaration}, @@ -215,8 +214,8 @@ TEST_F(SymbolStorage, UpdateProjectPart) EXPECT_CALL(updateProjectPartStatement, write(TypedEq("[\"foo\"]"), TypedEq("{\"FOO\":\"1\"}"), - TypedEq("project"), - TypedEq("[\"/includes\"]"))); + TypedEq("[\"/includes\"]"), + TypedEq("project"))); storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"}); } @@ -321,6 +320,24 @@ TEST_F(SymbolStorage, FetchLowestLastModifiedTime) ASSERT_THAT(lowestLastModified, Eq(12)); } +TEST_F(SymbolStorage, FetchPrecompiledHeaderCallsValueInStatement) +{ + EXPECT_CALL(getPrecompiledHeader, valueReturnProjectPartPch(Eq(25))); + + storage.fetchPrecompiledHeader(25); +} + +TEST_F(SymbolStorage, FetchPrecompiledHeader) +{ + ClangBackEnd::ProjectPartPch pch{"", "/path/to/pch", 131}; + EXPECT_CALL(getPrecompiledHeader, valueReturnProjectPartPch(Eq(25))) + .WillRepeatedly(Return(pch)); + + auto precompiledHeader = storage.fetchPrecompiledHeader(25); + + ASSERT_THAT(precompiledHeader.value(), Eq(pch)); +} + } diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 66d675c5c67..25b29ddea45 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -94,7 +94,8 @@ SOURCES += \ tokenprocessor-test.cpp \ projectpartartefact-test.cpp \ filestatuscache-test.cpp \ - highlightingresultreporter-test.cpp + highlightingresultreporter-test.cpp \ + precompiledheaderstorage-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -229,7 +230,9 @@ HEADERS += \ runprojectcreateorupdate-utility.h \ rundocumentparse-utility.h \ mocktimer.h \ - mocksqlitetransactionbackend.h + mocksqlitetransactionbackend.h \ + mockprojectpartprovider.h \ + mockprecompiledheaderstorage.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ chunksreportedmonitor.h \