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 \