Clang: Use PCHs for indexing

As generating the AST is quite expensive it would be very useful to cache
the not changed include. So we generate PCHs for include outside of a
project part. With this change this PCHs are used by the indexer.

For that they are save to the symbol database by the PCH manager and when
fetched by the symbol indexer.

Change-Id: I7a5b07cfb32d72d50dc52d2b108cd41727a7bfc7
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2018-02-20 12:43:05 +01:00
parent 70f5e0e264
commit 53454b0f79
75 changed files with 1139 additions and 251 deletions

View File

@@ -30,5 +30,5 @@
#include "requestsourcelocationforrenamingmessage.h" #include "requestsourcelocationforrenamingmessage.h"
#include "requestsourcerangesanddiagnosticsforquerymessage.h" #include "requestsourcerangesanddiagnosticsforquerymessage.h"
#include "requestsourcerangesforquerymessage.h" #include "requestsourcerangesforquerymessage.h"
#include "updatepchprojectpartsmessage.h" #include "updateprojectpartsmessage.h"
#include "removepchprojectpartsmessage.h" #include "removeprojectpartsmessage.h"

View File

@@ -61,7 +61,7 @@ SOURCES += \
$$PWD/refactoringserverproxy.cpp \ $$PWD/refactoringserverproxy.cpp \
$$PWD/referencesmessage.cpp \ $$PWD/referencesmessage.cpp \
$$PWD/registerunsavedfilesforeditormessage.cpp \ $$PWD/registerunsavedfilesforeditormessage.cpp \
$$PWD/removepchprojectpartsmessage.cpp \ $$PWD/removeprojectpartsmessage.cpp \
$$PWD/requestdocumentannotations.cpp \ $$PWD/requestdocumentannotations.cpp \
$$PWD/requestfollowsymbolmessage.cpp \ $$PWD/requestfollowsymbolmessage.cpp \
$$PWD/requestreferencesmessage.cpp \ $$PWD/requestreferencesmessage.cpp \
@@ -86,13 +86,14 @@ SOURCES += \
$$PWD/tooltipmessage.cpp \ $$PWD/tooltipmessage.cpp \
$$PWD/tooltipinfo.cpp \ $$PWD/tooltipinfo.cpp \
$$PWD/unregisterunsavedfilesforeditormessage.cpp \ $$PWD/unregisterunsavedfilesforeditormessage.cpp \
$$PWD/updatepchprojectpartsmessage.cpp \ $$PWD/updateprojectpartsmessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \
$$PWD/updatevisibletranslationunitsmessage.cpp \ $$PWD/updatevisibletranslationunitsmessage.cpp \
$$PWD/writemessageblock.cpp \ $$PWD/writemessageblock.cpp \
$$PWD/filepathcaching.cpp \ $$PWD/filepathcaching.cpp \
$$PWD/filepathid.cpp \ $$PWD/filepathid.cpp \
$$PWD/baseserverproxy.cpp $$PWD/baseserverproxy.cpp \
$$PWD/projectpartpchproviderinterface.cpp
HEADERS += \ HEADERS += \
$$PWD/cancelmessage.h \ $$PWD/cancelmessage.h \
@@ -155,7 +156,7 @@ HEADERS += \
$$PWD/refactoringserverproxy.h \ $$PWD/refactoringserverproxy.h \
$$PWD/referencesmessage.h \ $$PWD/referencesmessage.h \
$$PWD/registerunsavedfilesforeditormessage.h \ $$PWD/registerunsavedfilesforeditormessage.h \
$$PWD/removepchprojectpartsmessage.h \ $$PWD/removeprojectpartsmessage.h \
$$PWD/requestdocumentannotations.h \ $$PWD/requestdocumentannotations.h \
$$PWD/requestfollowsymbolmessage.h \ $$PWD/requestfollowsymbolmessage.h \
$$PWD/requestreferencesmessage.h \ $$PWD/requestreferencesmessage.h \
@@ -183,7 +184,7 @@ HEADERS += \
$$PWD/tooltipmessage.h \ $$PWD/tooltipmessage.h \
$$PWD/tooltipinfo.h \ $$PWD/tooltipinfo.h \
$$PWD/unregisterunsavedfilesforeditormessage.h \ $$PWD/unregisterunsavedfilesforeditormessage.h \
$$PWD/updatepchprojectpartsmessage.h \ $$PWD/updateprojectpartsmessage.h \
$$PWD/updatetranslationunitsforeditormessage.h \ $$PWD/updatetranslationunitsforeditormessage.h \
$$PWD/updatevisibletranslationunitsmessage.h \ $$PWD/updatevisibletranslationunitsmessage.h \
$$PWD/writemessageblock.h \ $$PWD/writemessageblock.h \
@@ -206,6 +207,7 @@ HEADERS += \
$$PWD/filepath.h \ $$PWD/filepath.h \
$$PWD/nativefilepath.h \ $$PWD/nativefilepath.h \
$$PWD/filepathview.h \ $$PWD/filepathview.h \
$$PWD/compilermacro.h $$PWD/compilermacro.h \
$$PWD/projectpartpchproviderinterface.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -173,8 +173,8 @@ enum class MessageType : quint8 {
SourceRangesForQueryMessage, SourceRangesForQueryMessage,
CancelMessage, CancelMessage,
UpdatePchProjectPartsMessage, UpdateProjectPartsMessage,
RemovePchProjectPartsMessage, RemoveProjectPartsMessage,
PrecompiledHeadersUpdatedMessage PrecompiledHeadersUpdatedMessage
}; };

View File

@@ -40,9 +40,7 @@ namespace ClangBackEnd {
class CLANGSUPPORT_EXPORT FilePathCaching final : public FilePathCachingInterface class CLANGSUPPORT_EXPORT FilePathCaching final : public FilePathCachingInterface
{ {
using Factory = FilePathStorageSqliteStatementFactory<Sqlite::Database, using Factory = FilePathStorageSqliteStatementFactory<Sqlite::Database>;
Sqlite::ReadStatement,
Sqlite::WriteStatement>;
using Storage = FilePathStorage<Factory>; using Storage = FilePathStorage<Factory>;
using Cache = FilePathCache<Storage>; using Cache = FilePathCache<Storage>;
public: public:

View File

@@ -39,9 +39,9 @@ namespace ClangBackEnd {
template <typename StatementFactory> template <typename StatementFactory>
class FilePathStorage class FilePathStorage
{ {
using ReadStatement = typename StatementFactory::ReadStatementType; using ReadStatement = typename StatementFactory::ReadStatement;
using WriteStatement = typename StatementFactory::WriteStatementType; using WriteStatement = typename StatementFactory::WriteStatement;
using Database = typename StatementFactory::DatabaseType; using Database = typename StatementFactory::Database;
public: public:
FilePathStorage(StatementFactory &statementFactory) FilePathStorage(StatementFactory &statementFactory)

View File

@@ -30,15 +30,13 @@
namespace ClangBackEnd { namespace ClangBackEnd {
template<typename Database, template<typename DatabaseType>
typename ReadStatement,
typename WriteStatement>
class FilePathStorageSqliteStatementFactory class FilePathStorageSqliteStatementFactory
{ {
public: public:
using DatabaseType = Database; using Database = DatabaseType;
using ReadStatementType = ReadStatement; using ReadStatement = typename DatabaseType::ReadStatement;
using WriteStatementType = WriteStatement; using WriteStatement = typename DatabaseType::WriteStatement;
FilePathStorageSqliteStatementFactory(Database &database) FilePathStorageSqliteStatementFactory(Database &database)
: database(database) : database(database)

View File

@@ -26,8 +26,8 @@
#include "pchmanagerserverinterface.h" #include "pchmanagerserverinterface.h"
#include "messageenvelop.h" #include "messageenvelop.h"
#include "removepchprojectpartsmessage.h" #include "removeprojectpartsmessage.h"
#include "updatepchprojectpartsmessage.h" #include "updateprojectpartsmessage.h"
#include <QDebug> #include <QDebug>
@@ -39,11 +39,11 @@ void PchManagerServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
case MessageType::EndMessage: case MessageType::EndMessage:
end(); end();
break; break;
case MessageType::UpdatePchProjectPartsMessage: case MessageType::UpdateProjectPartsMessage:
updatePchProjectParts(messageEnvelop.message<UpdatePchProjectPartsMessage>()); updateProjectParts(messageEnvelop.message<UpdateProjectPartsMessage>());
break; break;
case MessageType::RemovePchProjectPartsMessage: case MessageType::RemoveProjectPartsMessage:
removePchProjectParts(messageEnvelop.message<RemovePchProjectPartsMessage>()); removeProjectParts(messageEnvelop.message<RemoveProjectPartsMessage>());
break; break;
default: default:
qWarning() << "Unknown IpcClientMessage"; qWarning() << "Unknown IpcClientMessage";

View File

@@ -32,8 +32,8 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class PchManagerClientInterface; class PchManagerClientInterface;
class RemovePchProjectPartsMessage; class RemoveProjectPartsMessage;
class UpdatePchProjectPartsMessage; class UpdateProjectPartsMessage;
class CLANGSUPPORT_EXPORT PchManagerServerInterface : public ProjectManagementServerInterface class CLANGSUPPORT_EXPORT PchManagerServerInterface : public ProjectManagementServerInterface
{ {

View File

@@ -28,8 +28,8 @@
#include "cmbendmessage.h" #include "cmbendmessage.h"
#include "messageenvelop.h" #include "messageenvelop.h"
#include "pchmanagerclientinterface.h" #include "pchmanagerclientinterface.h"
#include "removepchprojectpartsmessage.h" #include "removeprojectpartsmessage.h"
#include "updatepchprojectpartsmessage.h" #include "updateprojectpartsmessage.h"
#include <QIODevice> #include <QIODevice>
#include <QVector> #include <QVector>
@@ -46,12 +46,12 @@ void PchManagerServerProxy::end()
m_writeMessageBlock.write(EndMessage()); m_writeMessageBlock.write(EndMessage());
} }
void PchManagerServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) void PchManagerServerProxy::updateProjectParts(UpdateProjectPartsMessage &&message)
{ {
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }
void PchManagerServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message) void PchManagerServerProxy::removeProjectParts(RemoveProjectPartsMessage &&message)
{ {
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }

View File

@@ -50,8 +50,8 @@ public:
explicit PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice); explicit PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice);
void end() override; void end() override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; void updateProjectParts(UpdateProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; void removeProjectParts(RemoveProjectPartsMessage &&message) override;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -37,11 +37,16 @@ public:
: m_projectPartPchs(std::move(projectPartPchs)) : m_projectPartPchs(std::move(projectPartPchs))
{} {}
const std::vector<ProjectPartPch> &projectPartPchs() const const ProjectPartPchs &projectPartPchs() const
{ {
return m_projectPartPchs; return m_projectPartPchs;
} }
ProjectPartPchs takeProjectPartPchs() const
{
return std::move(m_projectPartPchs);
}
friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message) friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message)
{ {
out << message.m_projectPartPchs; out << message.m_projectPartPchs;

View File

@@ -29,14 +29,14 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class RemovePchProjectPartsMessage; class RemoveProjectPartsMessage;
class UpdatePchProjectPartsMessage; class UpdateProjectPartsMessage;
class CLANGSUPPORT_EXPORT ProjectManagementServerInterface : public IpcInterface class CLANGSUPPORT_EXPORT ProjectManagementServerInterface : public IpcInterface
{ {
public: public:
virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0; virtual void updateProjectParts(UpdateProjectPartsMessage &&message) = 0;
virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0; virtual void removeProjectParts(RemoveProjectPartsMessage &&message) = 0;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -42,6 +42,11 @@ public:
pchPath(std::move(pchPath)), pchPath(std::move(pchPath)),
lastModified(lastModified) lastModified(lastModified)
{} {}
ProjectPartPch(Utils::SmallStringView pchPath,
long long lastModified)
: pchPath(pchPath),
lastModified(lastModified)
{}
friend QDataStream &operator<<(QDataStream &out, const ProjectPartPch &container) friend QDataStream &operator<<(QDataStream &out, const ProjectPartPch &container)
{ {
@@ -77,5 +82,7 @@ public:
long long lastModified = -1; long long lastModified = -1;
}; };
using ProjectPartPchs = std::vector<ProjectPartPch>;
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch); CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -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

View File

@@ -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 <utils/optional.h>
namespace ClangBackEnd {
class CLANGSUPPORT_EXPORT ProjectPartPchProviderInterface
{
public:
virtual ~ProjectPartPchProviderInterface();
virtual Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch(
Utils::SmallStringView projectPartId) const = 0;
virtual const ClangBackEnd::ProjectPartPchs &projectPartPchs() const = 0;
};
} // namespace ClangBackEnd

View File

@@ -50,6 +50,7 @@ public:
createUsedMacrosTable(); createUsedMacrosTable();
createFileStatusesTable(); createFileStatusesTable();
createSourceDependenciesTable(); createSourceDependenciesTable();
createPrecompiledHeadersTable();
transaction.commit(); transaction.commit();
} }
@@ -172,6 +173,19 @@ public:
table.initialize(database); 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: public:
DatabaseType &database; DatabaseType &database;
}; };

View File

@@ -47,11 +47,11 @@ void RefactoringServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
case MessageType::RequestSourceRangesForQueryMessage: case MessageType::RequestSourceRangesForQueryMessage:
requestSourceRangesForQueryMessage(messageEnvelop.message<RequestSourceRangesForQueryMessage>()); requestSourceRangesForQueryMessage(messageEnvelop.message<RequestSourceRangesForQueryMessage>());
break; break;
case MessageType::UpdatePchProjectPartsMessage: case MessageType::UpdateProjectPartsMessage:
updatePchProjectParts(messageEnvelop.message<UpdatePchProjectPartsMessage>()); updateProjectParts(messageEnvelop.message<UpdateProjectPartsMessage>());
break; break;
case MessageType::RemovePchProjectPartsMessage: case MessageType::RemoveProjectPartsMessage:
removePchProjectParts(messageEnvelop.message<RemovePchProjectPartsMessage>()); removeProjectParts(messageEnvelop.message<RemoveProjectPartsMessage>());
break; break;
case MessageType::CancelMessage: case MessageType::CancelMessage:
cancel(); cancel();

View File

@@ -36,8 +36,8 @@ class RequestSourceLocationsForRenamingMessage;
class RequestSourceRangesAndDiagnosticsForQueryMessage; class RequestSourceRangesAndDiagnosticsForQueryMessage;
class RequestSourceRangesForQueryMessage; class RequestSourceRangesForQueryMessage;
class CancelMessage; class CancelMessage;
class UpdatePchProjectPartsMessage; class UpdateProjectPartsMessage;
class RemovePchProjectPartsMessage; class RemoveProjectPartsMessage;
class CLANGSUPPORT_EXPORT RefactoringServerInterface : public ProjectManagementServerInterface class CLANGSUPPORT_EXPORT RefactoringServerInterface : public ProjectManagementServerInterface

View File

@@ -59,12 +59,12 @@ void RefactoringServerProxy::requestSourceRangesForQueryMessage(RequestSourceRan
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }
void RefactoringServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) void RefactoringServerProxy::updateProjectParts(UpdateProjectPartsMessage &&message)
{ {
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }
void RefactoringServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message) void RefactoringServerProxy::removeProjectParts(RemoveProjectPartsMessage &&message)
{ {
m_writeMessageBlock.write(message); m_writeMessageBlock.write(message);
} }

View File

@@ -53,8 +53,8 @@ public:
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override; void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override; void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; void updateProjectParts(UpdateProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; void removeProjectParts(RemoveProjectPartsMessage &&message) override;
void cancel() override; void cancel() override;
}; };

View File

@@ -23,11 +23,11 @@
** **
****************************************************************************/ ****************************************************************************/
#include "removepchprojectpartsmessage.h" #include "removeprojectpartsmessage.h"
namespace ClangBackEnd { namespace ClangBackEnd {
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemovePchProjectPartsMessage &message) CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemoveProjectPartsMessage &message)
{ {
debug.nospace() << "RemoveProjectPartsMessage(" debug.nospace() << "RemoveProjectPartsMessage("
<< message.projectsPartIds() << ")"; << message.projectsPartIds() << ")";

View File

@@ -29,11 +29,11 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class RemovePchProjectPartsMessage class RemoveProjectPartsMessage
{ {
public: public:
RemovePchProjectPartsMessage() = default; RemoveProjectPartsMessage() = default;
RemovePchProjectPartsMessage(Utils::SmallStringVector &&projectsPartIds) RemoveProjectPartsMessage(Utils::SmallStringVector &&projectsPartIds)
: m_projectsPartIds(std::move(projectsPartIds)) : m_projectsPartIds(std::move(projectsPartIds))
{} {}
@@ -47,37 +47,37 @@ public:
return std::move(m_projectsPartIds); 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; out << message.m_projectsPartIds;
return out; return out;
} }
friend QDataStream &operator>>(QDataStream &in, RemovePchProjectPartsMessage &message) friend QDataStream &operator>>(QDataStream &in, RemoveProjectPartsMessage &message)
{ {
in >> message.m_projectsPartIds; in >> message.m_projectsPartIds;
return in; return in;
} }
friend bool operator==(const RemovePchProjectPartsMessage &first, friend bool operator==(const RemoveProjectPartsMessage &first,
const RemovePchProjectPartsMessage &second) const RemoveProjectPartsMessage &second)
{ {
return first.m_projectsPartIds == second.m_projectsPartIds; return first.m_projectsPartIds == second.m_projectsPartIds;
} }
RemovePchProjectPartsMessage clone() const RemoveProjectPartsMessage clone() const
{ {
return RemovePchProjectPartsMessage(m_projectsPartIds.clone()); return RemoveProjectPartsMessage(m_projectsPartIds.clone());
} }
private: private:
Utils::SmallStringVector m_projectsPartIds; 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 } // namespace ClangBackEnd

View File

@@ -23,13 +23,13 @@
** **
****************************************************************************/ ****************************************************************************/
#include "updatepchprojectpartsmessage.h" #include "updateprojectpartsmessage.h"
namespace ClangBackEnd { namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const UpdatePchProjectPartsMessage &message) QDebug operator<<(QDebug debug, const UpdateProjectPartsMessage &message)
{ {
debug.nospace() << "UpdatePchProjectPartsMessage(" debug.nospace() << "UpdateProjectPartsMessage("
<< message.projectsParts() << ")"; << message.projectsParts() << ")";
return debug; return debug;

View File

@@ -30,11 +30,11 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class UpdatePchProjectPartsMessage class UpdateProjectPartsMessage
{ {
public: public:
UpdatePchProjectPartsMessage() = default; UpdateProjectPartsMessage() = default;
UpdatePchProjectPartsMessage(V2::ProjectPartContainers &&projectsParts, UpdateProjectPartsMessage(V2::ProjectPartContainers &&projectsParts,
V2::FileContainers &&generatedFiles) V2::FileContainers &&generatedFiles)
: m_projectsParts(std::move(projectsParts)), : m_projectsParts(std::move(projectsParts)),
m_generatedFiles(std::move(generatedFiles)) m_generatedFiles(std::move(generatedFiles))
@@ -60,7 +60,7 @@ public:
return std::move(m_generatedFiles); 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_projectsParts;
out << message.m_generatedFiles; out << message.m_generatedFiles;
@@ -68,7 +68,7 @@ public:
return out; return out;
} }
friend QDataStream &operator>>(QDataStream &in, UpdatePchProjectPartsMessage &message) friend QDataStream &operator>>(QDataStream &in, UpdateProjectPartsMessage &message)
{ {
in >> message.m_projectsParts; in >> message.m_projectsParts;
in >> message.m_generatedFiles; in >> message.m_generatedFiles;
@@ -76,16 +76,16 @@ public:
return in; return in;
} }
friend bool operator==(const UpdatePchProjectPartsMessage &first, friend bool operator==(const UpdateProjectPartsMessage &first,
const UpdatePchProjectPartsMessage &second) const UpdateProjectPartsMessage &second)
{ {
return first.m_projectsParts == second.m_projectsParts return first.m_projectsParts == second.m_projectsParts
&& first.m_generatedFiles == second.m_generatedFiles; && 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)); Utils::clone(m_generatedFiles));
} }
@@ -94,8 +94,8 @@ private:
V2::FileContainers m_generatedFiles; 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 } // namespace ClangBackEnd

View File

@@ -37,6 +37,9 @@
namespace Sqlite { namespace Sqlite {
class ReadStatement;
class WriteStatement;
class SQLITE_EXPORT Database final : public TransactionInterface class SQLITE_EXPORT Database final : public TransactionInterface
{ {
template <typename Database> template <typename Database>
@@ -45,6 +48,8 @@ class SQLITE_EXPORT Database final : public TransactionInterface
public: public:
using MutexType = std::mutex; using MutexType = std::mutex;
using ReadStatement = Sqlite::ReadStatement;
using WriteStatement = Sqlite::WriteStatement;
Database(); Database();
Database(Utils::PathString &&databaseFilePath, JournalMode journalMode=JournalMode::Wal); Database(Utils::PathString &&databaseFilePath, JournalMode journalMode=JournalMode::Wal);

View File

@@ -12,7 +12,9 @@ HEADERS += \
$$PWD/pchmanagerconnectionclient.h \ $$PWD/pchmanagerconnectionclient.h \
$$PWD/clangpchmanager_global.h \ $$PWD/clangpchmanager_global.h \
$$PWD/projectupdater.h \ $$PWD/projectupdater.h \
$$PWD/pchmanagerprojectupdater.h $$PWD/pchmanagerprojectupdater.h \
$$PWD/precompiledheaderstorage.h \
$$PWD/precompiledheaderstorageinterface.h
SOURCES += \ SOURCES += \
@@ -20,5 +22,6 @@ SOURCES += \
$$PWD/pchmanagernotifierinterface.cpp \ $$PWD/pchmanagernotifierinterface.cpp \
$$PWD/pchmanagerconnectionclient.cpp \ $$PWD/pchmanagerconnectionclient.cpp \
$$PWD/projectupdater.cpp \ $$PWD/projectupdater.cpp \
$$PWD/pchmanagerprojectupdater.cpp $$PWD/pchmanagerprojectupdater.cpp \
$$PWD/precompiledheaderstorageinterface.cpp

View File

@@ -27,6 +27,7 @@
#include "pchmanagerconnectionclient.h" #include "pchmanagerconnectionclient.h"
#include "pchmanagerclient.h" #include "pchmanagerclient.h"
#include "precompiledheaderstorage.h"
#include "qtcreatorprojectupdater.h" #include "qtcreatorprojectupdater.h"
#include <filepathcaching.h> #include <filepathcaching.h>
@@ -57,7 +58,8 @@ public:
Sqlite::Database database{Utils::PathString{Core::ICore::userResourcePath() + "/symbol-experimental-v1.db"}}; Sqlite::Database database{Utils::PathString{Core::ICore::userResourcePath() + "/symbol-experimental-v1.db"}};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
PchManagerClient pchManagerClient; PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
PchManagerClient pchManagerClient{preCompiledHeaderStorage};
PchManagerConnectionClient connectionClient{&pchManagerClient}; PchManagerConnectionClient connectionClient{&pchManagerClient};
QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(), QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(),
pchManagerClient, pchManagerClient,

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "clangpchmanager_global.h"
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <memory> #include <memory>
@@ -34,7 +36,7 @@ namespace ClangPchManager {
class ClangPchManagerPluginData; class ClangPchManagerPluginData;
class PchManagerClient; class PchManagerClient;
class ClangPchManagerPlugin : public ExtensionSystem::IPlugin class CLANGPCHMANAGER_EXPORT ClangPchManagerPlugin : public ExtensionSystem::IPlugin
{ {
Q_OBJECT Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangPchManager.json") Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangPchManager.json")

View File

@@ -34,6 +34,11 @@
namespace ClangPchManager { namespace ClangPchManager {
PchManagerClient::PchManagerClient(PrecompiledHeaderStorageInterface &precompiledHeaderStorage)
: m_precompiledHeaderStorage(precompiledHeaderStorage)
{
}
void PchManagerClient::alive() void PchManagerClient::alive()
{ {
if (m_connectionClient) if (m_connectionClient)
@@ -42,17 +47,23 @@ void PchManagerClient::alive()
void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message)
{ {
for (const ClangBackEnd::ProjectPartPch &projectPartPch : message.projectPartPchs()) { for (ClangBackEnd::ProjectPartPch &projectPartPch : message.takeProjectPartPchs()) {
precompiledHeaderUpdated(QString(projectPartPch.projectPartId), const QString projectPartId{projectPartPch.projectPartId};
QString(projectPartPch.pchPath), const QString pchPath{projectPartPch.pchPath};
projectPartPch.lastModified); addPchToDatabase(projectPartPch);
addProjectPartPch(std::move(projectPartPch));
precompiledHeaderUpdated(projectPartId, pchPath, projectPartPch.lastModified);
} }
} }
void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId) 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); notifier->precompiledHeaderRemoved(projectPartId);
}
} }
void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectionClient) void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectionClient)
@@ -60,6 +71,21 @@ void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectio
m_connectionClient = connectionClient; m_connectionClient = connectionClient;
} }
Utils::optional<ClangBackEnd::ProjectPartPch> 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) void PchManagerClient::attach(PchManagerNotifierInterface *notifier)
{ {
m_notifiers.push_back(notifier); m_notifiers.push_back(notifier);
@@ -76,6 +102,48 @@ void PchManagerClient::detach(PchManagerNotifierInterface *notifierToBeDeleted)
m_notifiers.erase(newEnd, m_notifiers.end()); 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<PchManagerNotifierInterface *> &PchManagerClient::notifiers() const const std::vector<PchManagerNotifierInterface *> &PchManagerClient::notifiers() const
{ {
return m_notifiers; return m_notifiers;

View File

@@ -25,7 +25,11 @@
#pragma once #pragma once
#include "clangpchmanager_global.h"
#include "precompiledheaderstorageinterface.h"
#include <pchmanagerclientinterface.h> #include <pchmanagerclientinterface.h>
#include <projectpartpchproviderinterface.h>
#include <vector> #include <vector>
@@ -34,10 +38,12 @@ class PchManagerConnectionClient;
class PchManagerNotifierInterface; class PchManagerNotifierInterface;
class PchManagerClient final : public ClangBackEnd::PchManagerClientInterface class CLANGPCHMANAGER_EXPORT PchManagerClient final : public ClangBackEnd::PchManagerClientInterface,
public ClangBackEnd::ProjectPartPchProviderInterface
{ {
friend class PchManagerNotifierInterface; friend class PchManagerNotifierInterface;
public: public:
PchManagerClient(PrecompiledHeaderStorageInterface &precompiledHeaderStorage);
void alive() override; void alive() override;
void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override; void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override;
@@ -45,6 +51,14 @@ public:
void setConnectionClient(PchManagerConnectionClient *connectionClient); void setConnectionClient(PchManagerConnectionClient *connectionClient);
Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch(
Utils::SmallStringView projectPartId) const override;
const ClangBackEnd::ProjectPartPchs &projectPartPchs() const override
{
return m_projectPartPchs;
}
unittest_public: unittest_public:
const std::vector<PchManagerNotifierInterface*> &notifiers() const; const std::vector<PchManagerNotifierInterface*> &notifiers() const;
void precompiledHeaderUpdated(const QString &projectPartId, void precompiledHeaderUpdated(const QString &projectPartId,
@@ -54,9 +68,17 @@ unittest_public:
void attach(PchManagerNotifierInterface *notifier); void attach(PchManagerNotifierInterface *notifier);
void detach(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: private:
ClangBackEnd::ProjectPartPchs m_projectPartPchs;
std::vector<PchManagerNotifierInterface*> m_notifiers; std::vector<PchManagerNotifierInterface*> m_notifiers;
PchManagerConnectionClient *m_connectionClient=nullptr; PchManagerConnectionClient *m_connectionClient=nullptr;
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
}; };
} // namespace ClangPchManager } // namespace ClangPchManager

View File

@@ -25,7 +25,7 @@
#pragma once #pragma once
#include <QtGlobal> #include "clangpchmanager_global.h"
QT_FORWARD_DECLARE_CLASS(QString) QT_FORWARD_DECLARE_CLASS(QString)
@@ -33,10 +33,10 @@ namespace ClangPchManager {
class PchManagerClient; class PchManagerClient;
class PchManagerNotifierInterface class CLANGPCHMANAGER_EXPORT PchManagerNotifierInterface
{ {
public: public:
PchManagerNotifierInterface(PchManagerClient &pchManagerClientso); PchManagerNotifierInterface(PchManagerClient &pchManagerClient);
virtual ~PchManagerNotifierInterface(); virtual ~PchManagerNotifierInterface();
virtual void precompiledHeaderUpdated(const QString &projectPartId, virtual void precompiledHeaderUpdated(const QString &projectPartId,
@@ -44,6 +44,9 @@ public:
long long lastModified) = 0; long long lastModified) = 0;
virtual void precompiledHeaderRemoved(const QString &projectPartId) = 0; virtual void precompiledHeaderRemoved(const QString &projectPartId) = 0;
PchManagerNotifierInterface(const PchManagerNotifierInterface &) = delete;
void operator=(const PchManagerNotifierInterface &) const = delete;
PchManagerClient &m_pchManagerClient; PchManagerClient &m_pchManagerClient;
}; };

View File

@@ -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 <sqlitetransaction.h>
#include <utils/smallstringview.h>
namespace ClangPchManager {
template<typename Database=Sqlite::Database>
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
};
};
}

View File

@@ -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

View File

@@ -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 <utils/smallstringview.h>
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

View File

@@ -29,8 +29,8 @@
#include <filepathid.h> #include <filepathid.h>
#include <pchmanagerserverinterface.h> #include <pchmanagerserverinterface.h>
#include <removepchprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
#include <cpptools/compileroptionsbuilder.h> #include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectpart.h> #include <cpptools/projectpart.h>
@@ -67,17 +67,17 @@ void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart
{ {
m_excludedPaths = createExcludedPaths(generatedFiles); m_excludedPaths = createExcludedPaths(generatedFiles);
ClangBackEnd::UpdatePchProjectPartsMessage message{toProjectPartContainers(projectParts), ClangBackEnd::UpdateProjectPartsMessage message{toProjectPartContainers(projectParts),
std::move(generatedFiles)}; std::move(generatedFiles)};
m_server.updatePchProjectParts(std::move(message)); m_server.updateProjectParts(std::move(message));
} }
void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds) void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
{ {
ClangBackEnd::RemovePchProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)}; ClangBackEnd::RemoveProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)};
m_server.removePchProjectParts(std::move(message)); m_server.removeProjectParts(std::move(message));
} }
void ProjectUpdater::setExcludedPaths(Utils::PathStringVector &&excludedPaths) void ProjectUpdater::setExcludedPaths(Utils::PathStringVector &&excludedPaths)

View File

@@ -23,7 +23,8 @@ HEADERS += \
$$PWD/class.h \ $$PWD/class.h \
$$PWD/enum.h \ $$PWD/enum.h \
$$PWD/function.h \ $$PWD/function.h \
$$PWD/include.h $$PWD/include.h \
$$PWD/projectpartproviderinterface.h
SOURCES += \ SOURCES += \
$$PWD/clangqueryexamplehighlighter.cpp \ $$PWD/clangqueryexamplehighlighter.cpp \
@@ -40,4 +41,5 @@ SOURCES += \
$$PWD/refactoringprojectupdater.cpp \ $$PWD/refactoringprojectupdater.cpp \
$$PWD/searchinterface.cpp \ $$PWD/searchinterface.cpp \
$$PWD/searchhandle.cpp \ $$PWD/searchhandle.cpp \
$$PWD/symbolsfindfilter.cpp $$PWD/symbolsfindfilter.cpp \
$$PWD/projectpartproviderinterface.cpp

View File

@@ -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 "projectpartproviderinterface.h"
namespace ClangRefactoring {
ProjectPartProviderInterface::~ProjectPartProviderInterface() = default;
} // namespace ClangRefactoring

View File

@@ -0,0 +1,54 @@
/****************************************************************************
**
** 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 "filecontainerv2.h"
#include <QString>
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

View File

@@ -27,8 +27,8 @@
#include <pchmanagerclientinterface.h> #include <pchmanagerclientinterface.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
#include <utils/smallstring.h> #include <utils/smallstring.h>
@@ -52,7 +52,7 @@ void PchManagerServer::end()
} }
void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
{ {
m_pchCreator.setGeneratedFiles(message.takeGeneratedFiles()); m_pchCreator.setGeneratedFiles(message.takeGeneratedFiles());
@@ -61,7 +61,7 @@ void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&mess
m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes()); m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
} }
void PchManagerServer::removePchProjectParts(RemovePchProjectPartsMessage &&message) void PchManagerServer::removeProjectParts(RemoveProjectPartsMessage &&message)
{ {
m_fileSystemWatcher.removeIds(message.projectsPartIds()); m_fileSystemWatcher.removeIds(message.projectsPartIds());

View File

@@ -51,8 +51,8 @@ public:
void end() override; void end() override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; void updateProjectParts(UpdateProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; void removeProjectParts(RemoveProjectPartsMessage &&message) override;
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override; void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
void pathsChanged(const FilePathIds &filePathIds) override; void pathsChanged(const FilePathIds &filePathIds) override;

View File

@@ -95,12 +95,12 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo
message.takeQuery()); message.takeQuery());
} }
void RefactoringServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message) void RefactoringServer::updateProjectParts(UpdateProjectPartsMessage &&message)
{ {
m_symbolIndexing.updateProjectParts(message.takeProjectsParts(), message.takeGeneratedFiles()); m_symbolIndexing.updateProjectParts(message.takeProjectsParts(), message.takeGeneratedFiles());
} }
void RefactoringServer::removePchProjectParts(RemovePchProjectPartsMessage &&) void RefactoringServer::removeProjectParts(RemoveProjectPartsMessage &&)
{ {
} }

View File

@@ -61,8 +61,8 @@ public:
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override; void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override; void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override; void updateProjectParts(UpdateProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override; void removeProjectParts(RemoveProjectPartsMessage &&message) override;
void cancel() override; void cancel() override;
bool isCancelingJobs() const; bool isCancelingJobs() const;

View File

@@ -30,15 +30,13 @@
namespace ClangBackEnd { namespace ClangBackEnd {
template<typename Database, template<typename DatabaseType>
typename ReadStatement,
typename WriteStatement>
class StorageSqliteStatementFactory class StorageSqliteStatementFactory
{ {
public: public:
using DatabaseType = Database; using Database = DatabaseType;
using ReadStatementType = ReadStatement; using ReadStatement = typename Database::ReadStatement;
using WriteStatementType = WriteStatement; using WriteStatement = typename Database::WriteStatement;
StorageSqliteStatementFactory(Database &database) StorageSqliteStatementFactory(Database &database)
: transaction(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", "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 database
}; };
ReadStatement getPrecompiledHeader{
"SELECT pchPath, pchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
database
};
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -54,10 +54,14 @@ void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart,
{ {
m_symbolsCollector.clear(); m_symbolsCollector.clear();
FilePathIds sourcePathIds = updatableFilePathIds(projectPart); const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(
projectPart.projectPartId());
FilePathIds sourcePathIds = updatableFilePathIds(projectPart, optionalArtefact);
if (!sourcePathIds.empty()) { if (!sourcePathIds.empty()) {
m_symbolsCollector.addFiles(projectPart.sourcePathIds(), projectPart.arguments()); m_symbolsCollector.addFiles(projectPart.sourcePathIds(),
compilerArguments(projectPart, optionalArtefact));
m_symbolsCollector.addUnsavedFiles(generatedFiles); m_symbolsCollector.addUnsavedFiles(generatedFiles);
@@ -102,10 +106,11 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId)
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(filePathId); const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(filePathId);
if (optionalArtefact) { if (optionalArtefact && !optionalArtefact.value().compilerArguments.empty()) {
const ProjectPartArtefact &artefact = optionalArtefact.value(); const ProjectPartArtefact &artefact = optionalArtefact.value();
m_symbolsCollector.addFiles({filePathId}, artefact.compilerArguments); m_symbolsCollector.addFiles({filePathId},
compilerArguments(artefact.compilerArguments, artefact.projectPartId));
m_symbolsCollector.collectSymbols(); 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<ProjectPartArtefact> &optionalArtefact) const
{ {
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(
projectPart.projectPartId());
if (optionalArtefact) { if (optionalArtefact) {
const ProjectPartArtefact &artefact = optionalArtefact.value(); const ProjectPartArtefact &artefact = optionalArtefact.value();
return projectPart.compilerMacros() != artefact.compilerMacros return projectPart.compilerMacros() != artefact.compilerMacros
@@ -156,12 +160,40 @@ FilePathIds SymbolIndexer::filterChangedFiles(const V2::ProjectPartContainer &pr
return ids; return ids;
} }
FilePathIds SymbolIndexer::updatableFilePathIds(const V2::ProjectPartContainer &projectPart) const FilePathIds SymbolIndexer::updatableFilePathIds(const V2::ProjectPartContainer &projectPart,
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const
{ {
if (compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart)) if (compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart, optionalArtefact))
return projectPart.sourcePathIds(); return projectPart.sourcePathIds();
return filterChangedFiles(projectPart); return filterChangedFiles(projectPart);
} }
Utils::SmallStringVector SymbolIndexer::compilerArguments(
Utils::SmallStringVector arguments,
int projectPartId) const
{
Utils::optional<ProjectPartPch> 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<ProjectPartArtefact> &optionalProjectPartArtefact) const
{
if (optionalProjectPartArtefact)
return compilerArguments(projectPart.arguments(),
optionalProjectPartArtefact.value().projectPartId);
return projectPart.arguments();
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -55,12 +55,19 @@ public:
void updateChangedPath(FilePathId filePath); void updateChangedPath(FilePathId filePath);
bool compilerMacrosOrIncludeSearchPathsAreDifferent( bool compilerMacrosOrIncludeSearchPathsAreDifferent(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart,
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const;
FilePathIds filterChangedFiles( FilePathIds filterChangedFiles(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
FilePathIds updatableFilePathIds(const V2::ProjectPartContainer &projectPart) const; FilePathIds updatableFilePathIds(const V2::ProjectPartContainer &projectPart,
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const;
Utils::SmallStringVector compilerArguments(const V2::ProjectPartContainer &projectPart,
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const;
Utils::SmallStringVector compilerArguments(Utils::SmallStringVector arguments,
int projectPartId) const;
private: private:
SymbolsCollectorInterface &m_symbolsCollector; SymbolsCollectorInterface &m_symbolsCollector;

View File

@@ -46,9 +46,7 @@ namespace ClangBackEnd {
class SymbolIndexing final : public SymbolIndexingInterface class SymbolIndexing final : public SymbolIndexingInterface
{ {
public: public:
using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<Sqlite::Database, using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<Sqlite::Database>;
Sqlite::ReadStatement,
Sqlite::WriteStatement>;
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>; using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
SymbolIndexing(Sqlite::Database &database, SymbolIndexing(Sqlite::Database &database,

View File

@@ -40,9 +40,9 @@ namespace ClangBackEnd {
template <typename StatementFactory> template <typename StatementFactory>
class SymbolStorage final : public SymbolStorageInterface class SymbolStorage final : public SymbolStorageInterface
{ {
using ReadStatement = typename StatementFactory::ReadStatementType; using ReadStatement = typename StatementFactory::ReadStatement;
using WriteStatement = typename StatementFactory::WriteStatementType; using WriteStatement = typename StatementFactory::WriteStatement;
using Database = typename StatementFactory::DatabaseType; using Database = typename StatementFactory::Database;
public: public:
SymbolStorage(StatementFactory &statementFactory, SymbolStorage(StatementFactory &statementFactory,
@@ -87,8 +87,8 @@ public:
WriteStatement &updateStatement = m_statementFactory.updateProjectPartStatement; WriteStatement &updateStatement = m_statementFactory.updateProjectPartStatement;
updateStatement.write(compilerArguementsAsJson, updateStatement.write(compilerArguementsAsJson,
compilerMacrosAsJson, compilerMacrosAsJson,
projectPartName, includeSearchPathsAsJason,
includeSearchPathsAsJason); projectPartName);
} }
} }
@@ -252,6 +252,11 @@ public:
m_statementFactory.deleteNewLocationsTableStatement.execute(); m_statementFactory.deleteNewLocationsTableStatement.execute();
} }
Utils::optional<ProjectPartPch> fetchPrecompiledHeader(int projectPartId) const
{
return m_statementFactory.getPrecompiledHeader.template value<ProjectPartPch, 2>(projectPartId);
}
SourceLocationEntries sourceLocations() const SourceLocationEntries sourceLocations() const
{ {
return SourceLocationEntries(); return SourceLocationEntries();

View File

@@ -27,6 +27,7 @@
#include "filestatus.h" #include "filestatus.h"
#include "projectpartentry.h" #include "projectpartentry.h"
#include "projectpartpch.h"
#include "projectpartartefact.h" #include "projectpartartefact.h"
#include "sourcelocationentry.h" #include "sourcelocationentry.h"
#include "sourcedependency.h" #include "sourcedependency.h"
@@ -63,6 +64,7 @@ public:
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0; virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(Utils::SmallStringView projectPartName) const = 0; virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(Utils::SmallStringView projectPartName) const = 0;
virtual long long fetchLowestLastModifiedTime(FilePathId sourceId) const = 0; virtual long long fetchLowestLastModifiedTime(FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartPch> fetchPrecompiledHeader(int projectPartId) const = 0;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -35,9 +35,7 @@
namespace { namespace {
using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>, using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>>;
MockSqliteReadStatement,
MockSqliteWriteStatement>;
using Storage = ClangBackEnd::FilePathStorage<StatementFactory>; using Storage = ClangBackEnd::FilePathStorage<StatementFactory>;
using ClangBackEnd::Sources::Directory; using ClangBackEnd::Sources::Directory;
using ClangBackEnd::Sources::Source; using ClangBackEnd::Sources::Source;

View File

@@ -34,9 +34,7 @@
namespace { namespace {
using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>, using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>>;
MockSqliteReadStatement,
MockSqliteWriteStatement>;
class FilePathStorageSqliteStatementFactory : public testing::Test class FilePathStorageSqliteStatementFactory : public testing::Test
{ {

View File

@@ -617,7 +617,7 @@ std::ostream &operator<<(std::ostream &os, const RequestDocumentAnnotationsMessa
return os; return os;
} }
std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &message) std::ostream &operator<<(std::ostream &out, const RemoveProjectPartsMessage &message)
{ {
return out << "(" << message.projectsPartIds() << ")"; return out << "(" << message.projectsPartIds() << ")";
} }
@@ -792,7 +792,7 @@ std::ostream &operator<<(std::ostream &os, const UnregisterUnsavedFilesForEditor
return os; return os;
} }
std::ostream &operator<<(std::ostream &out, const UpdatePchProjectPartsMessage &message) std::ostream &operator<<(std::ostream &out, const UpdateProjectPartsMessage &message)
{ {
return out << "(" return out << "("
<< message.projectsParts() << message.projectsParts()
@@ -945,7 +945,8 @@ std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &containe
<< container.projectPartId() << ", " << container.projectPartId() << ", "
<< container.arguments() << ", " << container.arguments() << ", "
<< container.headerPathIds() << ", " << container.headerPathIds() << ", "
<< container.sourcePathIds()<< ")"; << container.compilerMacros() << ", "
<< container.includeSearchPaths() << ")";
return out; return out;
} }

View File

@@ -122,7 +122,7 @@ class PrecompiledHeadersUpdatedMessage;
class ProjectPartContainer; class ProjectPartContainer;
class ProjectPartPch; class ProjectPartPch;
class RegisterUnsavedFilesForEditorMessage; class RegisterUnsavedFilesForEditorMessage;
class RemovePchProjectPartsMessage; class RemoveProjectPartsMessage;
class RequestDocumentAnnotationsMessage; class RequestDocumentAnnotationsMessage;
class RequestFollowSymbolMessage; class RequestFollowSymbolMessage;
class RequestReferencesMessage; class RequestReferencesMessage;
@@ -141,7 +141,7 @@ class TokenInfo;
template<class T> template<class T>
class TokenProcessor; class TokenProcessor;
class UnregisterUnsavedFilesForEditorMessage; class UnregisterUnsavedFilesForEditorMessage;
class UpdatePchProjectPartsMessage; class UpdateProjectPartsMessage;
class UpdateTranslationUnitsForEditorMessage; class UpdateTranslationUnitsForEditorMessage;
class UpdateVisibleTranslationUnitsMessage; class UpdateVisibleTranslationUnitsMessage;
class FilePath; 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 ProjectPartContainer &container);
std::ostream &operator<<(std::ostream &out, const ProjectPartPch &projectPartPch); 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 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 RequestDocumentAnnotationsMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestFollowSymbolMessage &message); std::ostream &operator<<(std::ostream &out, const RequestFollowSymbolMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestReferencesMessage &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 SourceRangesForQueryMessage &message);
std::ostream &operator<<(std::ostream &out, const SourceRangeWithTextContainer &container); 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 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 UpdateTranslationUnitsForEditorMessage &message);
std::ostream &operator<<(std::ostream &out, const UpdateVisibleTranslationUnitsMessage &message); std::ostream &operator<<(std::ostream &out, const UpdateVisibleTranslationUnitsMessage &message);
std::ostream &operator<<(std::ostream &out, const FilePath &filePath); std::ostream &operator<<(std::ostream &out, const FilePath &filePath);

View File

@@ -32,8 +32,8 @@
class MockPchManagerNotifier : public ClangPchManager::PchManagerNotifierInterface class MockPchManagerNotifier : public ClangPchManager::PchManagerNotifierInterface
{ {
public: public:
MockPchManagerNotifier(ClangPchManager::PchManagerClient &pchManagerClient) MockPchManagerNotifier(const ClangPchManager::PchManagerClient &pchManagerClient)
: ClangPchManager::PchManagerNotifierInterface(pchManagerClient) : ClangPchManager::PchManagerNotifierInterface(const_cast<ClangPchManager::PchManagerClient&>(pchManagerClient))
{} {}
MOCK_METHOD3(precompiledHeaderUpdated, MOCK_METHOD3(precompiledHeaderUpdated,

View File

@@ -34,18 +34,18 @@ class MockPchManagerServer : public ClangBackEnd::PchManagerServerInterface
public: public:
MOCK_METHOD0(end, MOCK_METHOD0(end,
void()); void());
MOCK_METHOD1(updatePchProjectParts, MOCK_METHOD1(updateProjectParts,
void (const ClangBackEnd::UpdatePchProjectPartsMessage&)); void (const ClangBackEnd::UpdateProjectPartsMessage&));
MOCK_METHOD1(removePchProjectParts, MOCK_METHOD1(removeProjectParts,
void (const ClangBackEnd::RemovePchProjectPartsMessage&)); 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);
} }
}; };

View File

@@ -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 <precompiledheaderstorageinterface.h>
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));
};

View File

@@ -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 <projectpartproviderinterface.h>
class MockProjectPartProvider : public ClangRefactoring::ProjectPartProviderInterface
{
public:
MOCK_CONST_METHOD0(generatedFiles,
ClangBackEnd::V2::FileContainers());
MOCK_CONST_METHOD1(projectPart,
CppTools::ProjectPart*(const QString &projectPartId));
};

View File

@@ -44,11 +44,11 @@ public:
MOCK_METHOD1(requestSourceRangesForQueryMessage, MOCK_METHOD1(requestSourceRangesForQueryMessage,
void (const ClangBackEnd::RequestSourceRangesForQueryMessage&)); void (const ClangBackEnd::RequestSourceRangesForQueryMessage&));
MOCK_METHOD1(updatePchProjectParts, MOCK_METHOD1(updateProjectParts,
void (const ClangBackEnd::UpdatePchProjectPartsMessage&)); void (const ClangBackEnd::UpdateProjectPartsMessage&));
MOCK_METHOD1(removePchProjectParts, MOCK_METHOD1(removeProjectParts,
void (const ClangBackEnd::RemovePchProjectPartsMessage&)); void (const ClangBackEnd::RemoveProjectPartsMessage&));
MOCK_METHOD0(cancel, MOCK_METHOD0(cancel,
void()); void());
@@ -68,13 +68,13 @@ public:
requestSourceRangesForQueryMessage(message); 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);
} }
}; };

View File

@@ -27,7 +27,9 @@
#include "googletest.h" #include "googletest.h"
#include "mocksqlitereadstatement.h"
#include "mocksqlitetransactionbackend.h" #include "mocksqlitetransactionbackend.h"
#include "mocksqlitewritestatement.h"
#include <sqlitetable.h> #include <sqlitetable.h>
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
@@ -37,6 +39,9 @@
class MockSqliteDatabase : public MockSqliteTransactionBackend class MockSqliteDatabase : public MockSqliteTransactionBackend
{ {
public: public:
using ReadStatement = MockSqliteReadStatement;
using WriteStatement = MockSqliteWriteStatement;
MOCK_METHOD1(execute, MOCK_METHOD1(execute,
void (Utils::SmallStringView sqlStatement)); void (Utils::SmallStringView sqlStatement));

View File

@@ -107,6 +107,13 @@ MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const Utils
return valueReturnProjectPartArtefact(projectPartName); return valueReturnProjectPartArtefact(projectPartName);
} }
template <>
Utils::optional<ClangBackEnd::ProjectPartPch>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 2>(const int &projectPartId)
{
return valueReturnProjectPartPch(projectPartId);
}
template <> template <>
Utils::optional<Utils::SmallString> Utils::optional<Utils::SmallString>
MockSqliteReadStatement::value<Utils::SmallString>(const int &sourceId) MockSqliteReadStatement::value<Utils::SmallString>(const int &sourceId)

View File

@@ -25,13 +25,14 @@
#pragma once #pragma once
#include "mocksqlitedatabase.h" #include "googletest.h"
#include <sourcelocations.h> #include <sourcelocations.h>
#include <filepathstoragesources.h> #include <filepathstoragesources.h>
#include <stringcachefwd.h> #include <stringcachefwd.h>
#include <projectpartartefact.h> #include <projectpartartefact.h>
#include <projectpartpch.h>
#include <cpptools/usages.h> #include <cpptools/usages.h>
@@ -47,6 +48,8 @@ using ClangRefactoring::SourceLocation;
using ClangRefactoring::SourceLocations; using ClangRefactoring::SourceLocations;
namespace Sources = ClangBackEnd::Sources; namespace Sources = ClangBackEnd::Sources;
class MockSqliteDatabase;
class MockSqliteReadStatement class MockSqliteReadStatement
{ {
public: public:
@@ -88,6 +91,9 @@ public:
MOCK_METHOD1(valueReturnProjectPartArtefact, MOCK_METHOD1(valueReturnProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>(Utils::SmallStringView)); Utils::optional<ClangBackEnd::ProjectPartArtefact>(Utils::SmallStringView));
MOCK_METHOD1(valueReturnProjectPartPch,
Utils::optional<ClangBackEnd::ProjectPartPch>(int));
template <typename ResultType, template <typename ResultType,
int ResultTypeCount = 1, int ResultTypeCount = 1,
typename... QueryType> typename... QueryType>
@@ -164,6 +170,10 @@ template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact> Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const int&); MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const int&);
template <>
Utils::optional<ClangBackEnd::ProjectPartPch>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 2>(const int&);
template <> template <>
Utils::optional<Utils::SmallString> Utils::optional<Utils::SmallString>
MockSqliteReadStatement::value<Utils::SmallString>(const int&); MockSqliteReadStatement::value<Utils::SmallString>(const int&);

View File

@@ -25,10 +25,12 @@
#pragma once #pragma once
#include "mocksqlitedatabase.h" #include "googletest.h"
#include <utils/smallstring.h> #include <utils/smallstring.h>
class MockSqliteDatabase;
class MockSqliteWriteStatement class MockSqliteWriteStatement
{ {
public: public:
@@ -61,6 +63,9 @@ public:
MOCK_METHOD2(write, MOCK_METHOD2(write,
void (Utils::SmallStringView, Utils::SmallStringView)); void (Utils::SmallStringView, Utils::SmallStringView));
MOCK_METHOD3(write,
void (Utils::SmallStringView, Utils::SmallStringView, long long));
MOCK_METHOD3(write, MOCK_METHOD3(write,
void (Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView)); void (Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView));

View File

@@ -60,4 +60,6 @@ public:
Utils::optional<ClangBackEnd::ProjectPartArtefact> (Utils::SmallStringView projectPartName)); Utils::optional<ClangBackEnd::ProjectPartArtefact> (Utils::SmallStringView projectPartName));
MOCK_CONST_METHOD1(fetchLowestLastModifiedTime, MOCK_CONST_METHOD1(fetchLowestLastModifiedTime,
long long (ClangBackEnd::FilePathId sourceId)); long long (ClangBackEnd::FilePathId sourceId));
MOCK_CONST_METHOD1(fetchPrecompiledHeader,
Utils::optional<ClangBackEnd::ProjectPartPch> (int projectPartId));
}; };

View File

@@ -27,6 +27,7 @@
#include "mockpchmanagernotifier.h" #include "mockpchmanagernotifier.h"
#include "mockpchmanagerserver.h" #include "mockpchmanagerserver.h"
#include "mockprecompiledheaderstorage.h"
#include <pchmanagerclient.h> #include <pchmanagerclient.h>
#include <pchmanagerprojectupdater.h> #include <pchmanagerprojectupdater.h>
@@ -34,8 +35,8 @@
#include <filepathcaching.h> #include <filepathcaching.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
namespace { namespace {
@@ -48,9 +49,10 @@ using testing::Not;
class PchManagerClient : public ::testing::Test class PchManagerClient : public ::testing::Test
{ {
protected: protected:
MockPchManagerServer mockPchManagerServer; NiceMock<MockPchManagerServer> mockPchManagerServer;
ClangPchManager::PchManagerClient client; NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
MockPchManagerNotifier mockPchManagerNotifier{client}; ClangPchManager::PchManagerClient client{mockPrecompiledHeaderStorage};
NiceMock<MockPchManagerNotifier> mockPchManagerNotifier{client};
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
@@ -58,6 +60,9 @@ protected:
Utils::SmallString projectPartId{"projectPartId"}; Utils::SmallString projectPartId{"projectPartId"};
Utils::SmallString pchFilePath{"/path/to/pch"}; Utils::SmallString pchFilePath{"/path/to/pch"};
PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone(), 1}}}; 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) TEST_F(PchManagerClient, NotifierAttached)
@@ -95,4 +100,75 @@ TEST_F(PchManagerClient, Remove)
QString(projectPartId.clone())}); 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<Utils::SmallStringView>(projectPartId),
TypedEq<Utils::SmallStringView>(pchFilePath),
TypedEq<long long>(1)));
client.precompiledHeadersUpdated(message.clone());
}
TEST_F(PchManagerClient, ProjectPartPchRemovedFromDatabase)
{
EXPECT_CALL(mockPrecompiledHeaderStorage, deletePrecompiledHeader(TypedEq<Utils::SmallStringView>(projectPartId)));
projectUpdater.removeProjectParts({QString(projectPartId)});
}
} }

View File

@@ -32,8 +32,8 @@
#include <pchmanagerclientproxy.h> #include <pchmanagerclientproxy.h>
#include <pchmanagerserverproxy.h> #include <pchmanagerserverproxy.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
#include <QBuffer> #include <QBuffer>
#include <QString> #include <QString>
@@ -41,10 +41,10 @@
#include <vector> #include <vector>
using ClangBackEnd::UpdatePchProjectPartsMessage; using ClangBackEnd::UpdateProjectPartsMessage;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::ProjectPartContainer; using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::RemovePchProjectPartsMessage; using ClangBackEnd::RemoveProjectPartsMessage;
using ClangBackEnd::PrecompiledHeadersUpdatedMessage; using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
using ::testing::Args; using ::testing::Args;
@@ -90,7 +90,7 @@ TEST_F(PchManagerClientServerInProcess, SendAliveMessage)
scheduleClientMessages(); scheduleClientMessages();
} }
TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage) TEST_F(PchManagerClientServerInProcess, SendUpdateProjectPartsMessage)
{ {
ProjectPartContainer projectPart2{"projectPartId", ProjectPartContainer projectPart2{"projectPartId",
{"-x", "c++-header", "-Wno-pragma-once-outside-header"}, {"-x", "c++-header", "-Wno-pragma-once-outside-header"},
@@ -99,21 +99,21 @@ TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage)
{{1, 1}}, {{1, 1}},
{{1, 2}}}; {{1, 2}}};
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; 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(); 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(); scheduleServerMessages();
} }

View File

@@ -34,8 +34,8 @@
#include <pchmanagerserver.h> #include <pchmanagerserver.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <removepchprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
namespace { namespace {
using Utils::PathString; using Utils::PathString;
@@ -82,14 +82,14 @@ protected:
{id(main2Path)}}; {id(main2Path)}};
std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2}; std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2};
FileContainer generatedFile{{"/path/to/", "file"}, "content", {}}; FileContainer generatedFile{{"/path/to/", "file"}, "content", {}};
ClangBackEnd::UpdatePchProjectPartsMessage updatePchProjectPartsMessage{Utils::clone(projectParts), ClangBackEnd::UpdateProjectPartsMessage UpdateProjectPartsMessage{Utils::clone(projectParts),
{generatedFile}}; {generatedFile}};
ClangBackEnd::ProjectPartPch projectPartPch1{projectPart1.projectPartId().clone(), "/path1/to/pch", 1}; ClangBackEnd::ProjectPartPch projectPartPch1{projectPart1.projectPartId().clone(), "/path1/to/pch", 1};
ClangBackEnd::ProjectPartPch projectPartPch2{projectPart2.projectPartId().clone(), "/path2/to/pch", 1}; ClangBackEnd::ProjectPartPch projectPartPch2{projectPart2.projectPartId().clone(), "/path2/to/pch", 1};
std::vector<ClangBackEnd::ProjectPartPch> projectPartPchs{projectPartPch1, projectPartPch2}; std::vector<ClangBackEnd::ProjectPartPch> projectPartPchs{projectPartPch1, projectPartPch2};
ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage1{{projectPartPch1}}; ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage1{{projectPartPch1}};
ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage2{{projectPartPch2}}; ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage2{{projectPartPch2}};
ClangBackEnd::RemovePchProjectPartsMessage removePchProjectPartsMessage{{projectPart1.projectPartId().clone(), ClangBackEnd::RemoveProjectPartsMessage RemoveProjectPartsMessage{{projectPart1.projectPartId().clone(),
projectPart2.projectPartId().clone()}}; projectPart2.projectPartId().clone()}};
}; };
@@ -111,39 +111,39 @@ TEST_F(PchManagerServer, DoNotCallPrecompiledHeadersForUnsuccessfullyFinishedTas
TEST_F(PchManagerServer, CallBuildInPchCreator) TEST_F(PchManagerServer, CallBuildInPchCreator)
{ {
auto &&callSetGeneratedFiles = EXPECT_CALL(mockPchCreator, auto &&callSetGeneratedFiles = EXPECT_CALL(mockPchCreator,
setGeneratedFiles(updatePchProjectPartsMessage.generatedFiles())); setGeneratedFiles(UpdateProjectPartsMessage.generatedFiles()));
EXPECT_CALL(mockPchCreator, generatePchs(updatePchProjectPartsMessage.projectsParts())) EXPECT_CALL(mockPchCreator, generatePchs(UpdateProjectPartsMessage.projectsParts()))
.After(callSetGeneratedFiles); .After(callSetGeneratedFiles);
server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); server.updateProjectParts(UpdateProjectPartsMessage.clone());
} }
TEST_F(PchManagerServer, UpdateIncludesOfFileWatcher) TEST_F(PchManagerServer, UpdateIncludesOfFileWatcher)
{ {
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths)); EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths));
server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); server.updateProjectParts(UpdateProjectPartsMessage.clone());
} }
TEST_F(PchManagerServer, GetChangedProjectPartsFromProjectParts) TEST_F(PchManagerServer, GetChangedProjectPartsFromProjectParts)
{ {
EXPECT_CALL(mockProjectParts, update(_)); EXPECT_CALL(mockProjectParts, update(_));
server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); server.updateProjectParts(UpdateProjectPartsMessage.clone());
} }
TEST_F(PchManagerServer, RemoveIncludesFromFileWatcher) 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) 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) TEST_F(PchManagerServer, SetPathWatcherNotifier)
@@ -155,7 +155,7 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange) TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange)
{ {
server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); server.updateProjectParts(UpdateProjectPartsMessage.clone());
EXPECT_CALL(mockProjectParts, projects(ElementsAre(projectPart1.projectPartId()))); EXPECT_CALL(mockProjectParts, projects(ElementsAre(projectPart1.projectPartId())));
@@ -164,7 +164,7 @@ TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange)
TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange) TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange)
{ {
server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); server.updateProjectParts(UpdateProjectPartsMessage.clone());
EXPECT_CALL(mockPchCreator, generatePchs(ElementsAre(projectPart1))); EXPECT_CALL(mockPchCreator, generatePchs(ElementsAre(projectPart1)));
@@ -173,7 +173,7 @@ TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange)
TEST_F(PchManagerServer, CallUpdateIdPathsInFileSystemWatcherForIncludeChange) TEST_F(PchManagerServer, CallUpdateIdPathsInFileSystemWatcherForIncludeChange)
{ {
server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); server.updateProjectParts(UpdateProjectPartsMessage.clone());
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths)); EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths));

View File

@@ -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 <precompiledheaderstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitewritestatement.h>
namespace {
using Storage = ClangPchManager::PrecompiledHeaderStorage<NiceMock<MockSqliteDatabase>>;
class PrecompiledHeaderStorage : public testing::Test
{
protected:
NiceMock<MockSqliteDatabase> 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<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
storage.insertPrecompiledHeader("project1", "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeader)
{
InSequence s;
EXPECT_CALL(deletePrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("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<Sqlite::Database> initializer{database};
ASSERT_NO_THROW(ClangPchManager::PrecompiledHeaderStorage<>{database});
}
}

View File

@@ -28,15 +28,17 @@
#include "mockpchmanagerclient.h" #include "mockpchmanagerclient.h"
#include "mockpchmanagernotifier.h" #include "mockpchmanagernotifier.h"
#include "mockpchmanagerserver.h" #include "mockpchmanagerserver.h"
#include "mockprecompiledheaderstorage.h"
#include <pchmanagerprojectupdater.h> #include <pchmanagerprojectupdater.h>
#include <filepathcaching.h> #include <filepathcaching.h>
#include <pchmanagerclient.h> #include <pchmanagerclient.h>
#include <precompiledheaderstorage.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <removepchprojectpartsmessage.h> #include <removeprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
#include <cpptools/compileroptionsbuilder.h> #include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectpart.h> #include <cpptools/projectpart.h>
@@ -97,7 +99,8 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
ClangPchManager::PchManagerClient pchManagerClient; MockPrecompiledHeaderStorage mockPrecompiledHeaderStorage;
ClangPchManager::PchManagerClient pchManagerClient{mockPrecompiledHeaderStorage};
MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient}; MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient};
NiceMock<MockPchManagerServer> mockPchManagerServer; NiceMock<MockPchManagerServer> mockPchManagerServer;
ClangPchManager::ProjectUpdater updater{mockPchManagerServer, filePathCache}; ClangPchManager::ProjectUpdater updater{mockPchManagerServer, filePathCache};
@@ -115,23 +118,22 @@ protected:
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}}; FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}};
}; };
TEST_F(ProjectUpdater, CallUpdatePchProjectParts) TEST_F(ProjectUpdater, CallUpdateProjectParts)
{ {
std::vector<CppTools::ProjectPart*> projectParts = {&projectPart, &projectPart}; std::vector<CppTools::ProjectPart*> projectParts = {&projectPart, &projectPart};
ClangBackEnd::UpdatePchProjectPartsMessage message{{expectedContainer.clone(), expectedContainer.clone()}, ClangBackEnd::UpdateProjectPartsMessage message{{expectedContainer.clone(), expectedContainer.clone()},
{generatedFile}}; {generatedFile}};
EXPECT_CALL(mockPchManagerServer, updatePchProjectParts(message)); EXPECT_CALL(mockPchManagerServer, updateProjectParts(message));
updater.updateProjectParts(projectParts, {generatedFile}); 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, removeProjectParts(message));
EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message));
updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)});
} }
@@ -139,7 +141,7 @@ TEST_F(ProjectUpdater, CallRemovePchProjectParts)
TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater) TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater)
{ {
ClangPchManager::PchManagerProjectUpdater pchUpdater{mockPchManagerServer, pchManagerClient, filePathCache}; 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(projectPartId.toQString()));
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString())); EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString()));

View File

@@ -47,10 +47,10 @@ using ::testing::Args;
using ::testing::Property; using ::testing::Property;
using ::testing::Eq; using ::testing::Eq;
using ClangBackEnd::UpdatePchProjectPartsMessage; using ClangBackEnd::UpdateProjectPartsMessage;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::ProjectPartContainer; using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::RemovePchProjectPartsMessage; using ClangBackEnd::RemoveProjectPartsMessage;
class RefactoringClientServerInProcess : public ::testing::Test class RefactoringClientServerInProcess : public ::testing::Test
{ {
@@ -174,7 +174,7 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage)
scheduleServerMessages(); scheduleServerMessages();
} }
TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage) TEST_F(RefactoringClientServerInProcess, SendUpdateProjectPartsMessage)
{ {
ProjectPartContainer projectPart2{"projectPartId", ProjectPartContainer projectPart2{"projectPartId",
{"-x", "c++-header", "-Wno-pragma-once-outside-header"}, {"-x", "c++-header", "-Wno-pragma-once-outside-header"},
@@ -183,21 +183,21 @@ TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage)
{{1, 1}}, {{1, 1}},
{{1, 2}}}; {{1, 2}}};
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; 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(); 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(); scheduleServerMessages();
} }

View File

@@ -133,6 +133,15 @@ TEST_F(RefactoringDatabaseInitializer, AddSourceDependenciesTable)
initializer.createSourceDependenciesTable(); 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) TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
{ {
InSequence s; 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 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 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 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()); EXPECT_CALL(mockDatabase, commit());
Initializer initializer{mockDatabase}; Initializer initializer{mockDatabase};

View File

@@ -297,7 +297,7 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message));
} }
TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectParts) TEST_F(RefactoringServer, UpdateProjectPartsCallsSymbolIndexingUpdateProjectParts)
{ {
ProjectPartContainers projectParts{{{"projectPartId", ProjectPartContainers projectParts{{{"projectPartId",
{"-I", TESTDATA_DIR}, {"-I", TESTDATA_DIR},
@@ -313,7 +313,7 @@ TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectP
EXPECT_CALL(mockSymbolIndexing, EXPECT_CALL(mockSymbolIndexing,
updateProjectParts(projectParts, unsaved)); updateProjectParts(projectParts, unsaved));
refactoringServer.updatePchProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)}); refactoringServer.updateProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)});
} }
void RefactoringServer::SetUp() void RefactoringServer::SetUp()

View File

@@ -33,9 +33,7 @@
namespace { namespace {
using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>, using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>>;
MockSqliteReadStatement,
MockSqliteWriteStatement>;
using Sqlite::Table; using Sqlite::Table;
@@ -274,4 +272,11 @@ TEST_F(StorageSqliteStatementFactory, GetLowestLastModifiedTimeOfDependencies)
ASSERT_THAT(factory.getLowestLastModifiedTimeOfDependencies.sqlStatement, 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")); 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 = ?"));
}
} }

View File

@@ -35,7 +35,7 @@
#include <projectpartcontainerv2.h> #include <projectpartcontainerv2.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <symbolindexer.h> #include <symbolindexer.h>
#include <updatepchprojectpartsmessage.h> #include <updateprojectpartsmessage.h>
#include <QDateTime> #include <QDateTime>
@@ -59,6 +59,7 @@ using ClangBackEnd::SourceLocationEntries;
using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::SymbolType; using ClangBackEnd::SymbolType;
using ClangBackEnd::UsedMacros; using ClangBackEnd::UsedMacros;
using OptionalProjectPartArtefact = Utils::optional<ClangBackEnd::ProjectPartArtefact>;
MATCHER_P2(IsFileId, directoryId, fileNameId, MATCHER_P2(IsFileId, directoryId, fileNameId,
std::string(negation ? "isn't " : "is ") std::string(negation ? "isn't " : "is ")
@@ -148,6 +149,8 @@ protected:
FileStatuses fileStatus{{{1, 2}, 3, 4, false}}; FileStatuses fileStatus{{{1, 2}, 3, 4, false}};
SourceDependencies sourceDependencies{{{1, 1}, {1, 2}}, {{1, 1}, {1, 3}}}; SourceDependencies sourceDependencies{{{1, 1}, {1, 2}}, {{1, 1}, {1, 3}}};
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\",\"BAR\":\"1\"}", "[\"/includes\"]", 74}; ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\",\"BAR\":\"1\"}", "[\"/includes\"]", 74};
ClangBackEnd::ProjectPartArtefact emptyArtefact{"", "", "", 74};
ClangBackEnd::ProjectPartPch projectPartPch{"/path/to/pch", 4};
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend; NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockSymbolsCollector> mockCollector; NiceMock<MockSymbolsCollector> mockCollector;
NiceMock<MockSymbolStorage> mockStorage; NiceMock<MockSymbolStorage> mockStorage;
@@ -170,6 +173,35 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved)); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInCollector)
{
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(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<Utils::SmallStringView>(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) TEST_F(SymbolIndexer, UpdateProjectPartsCallsClearInCollector)
{ {
EXPECT_CALL(mockCollector, clear()).Times(2); EXPECT_CALL(mockCollector, clear()).Times(2);
@@ -340,8 +372,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
{ {
ON_CALL(mockStorage, fetchProjectPartArtefact(A<FilePathId>())) ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(Utils::optional<ClangBackEnd::ProjectPartArtefact>())); .WillByDefault(Return(emptyArtefact));
EXPECT_CALL(mockCollector, clear()); EXPECT_CALL(mockCollector, clear());
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0])); EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0]));
@@ -358,11 +390,41 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
indexer.updateChangedPath(sourceFileIds[0]); indexer.updateChangedPath(sourceFileIds[0]);
} }
TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
{
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(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<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(artefact));
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds(),
ElementsAre(Eq("-DFOO"))));
indexer.updateChangedPath(sourceFileIds[0]);
}
TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent) TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent)
{ {
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact)); ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart1); auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart1,
artefact);
ASSERT_FALSE(areDifferent); ASSERT_FALSE(areDifferent);
} }
@@ -371,7 +433,8 @@ TEST_F(SymbolIndexer, CompilerMacrosAreDifferent)
{ {
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact)); ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart2); auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart2,
artefact);
ASSERT_TRUE(areDifferent); ASSERT_TRUE(areDifferent);
} }
@@ -386,7 +449,8 @@ TEST_F(SymbolIndexer, IncludeSearchPathsAreDifferent)
{main1PathId}}; {main1PathId}};
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact)); ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart3); auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart3,
artefact);
ASSERT_TRUE(areDifferent); ASSERT_TRUE(areDifferent);
} }
@@ -425,7 +489,7 @@ TEST_F(SymbolIndexer, GetUpdatableFilePathIdsIfCompilerMacrosAreDifferent)
{ {
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact)); ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto filePathIds = indexer.updatableFilePathIds(projectPart2); auto filePathIds = indexer.updatableFilePathIds(projectPart2, artefact);
ASSERT_THAT(filePathIds, projectPart2.sourcePathIds()); ASSERT_THAT(filePathIds, projectPart2.sourcePathIds());
} }
@@ -434,7 +498,7 @@ TEST_F(SymbolIndexer, GetUpdatableFilePathIdsIfIncludeSearchPathsAreDifferent)
{ {
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact)); ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto filePathIds = indexer.updatableFilePathIds(projectPart3); auto filePathIds = indexer.updatableFilePathIds(projectPart3, artefact);
ASSERT_THAT(filePathIds, projectPart3.sourcePathIds()); ASSERT_THAT(filePathIds, projectPart3.sourcePathIds());
} }
@@ -443,7 +507,7 @@ TEST_F(SymbolIndexer, GetNoUpdatableFilePathIdsIfArtefactsAreTheSame)
{ {
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact)); ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto filePathIds = indexer.updatableFilePathIds(projectPart1); auto filePathIds = indexer.updatableFilePathIds(projectPart1, artefact);
ASSERT_THAT(filePathIds, IsEmpty()); ASSERT_THAT(filePathIds, IsEmpty());
} }
@@ -455,7 +519,7 @@ TEST_F(SymbolIndexer, OutdatedFilesPassUpdatableFilePathIds)
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>())) ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>()))
.WillByDefault(Return(0)); .WillByDefault(Return(0));
auto filePathIds = indexer.updatableFilePathIds(projectPart1); auto filePathIds = indexer.updatableFilePathIds(projectPart1, artefact);
ASSERT_THAT(filePathIds, ElementsAre(main1PathId)); ASSERT_THAT(filePathIds, ElementsAre(main1PathId));
} }
@@ -467,7 +531,7 @@ TEST_F(SymbolIndexer, UpToDateFilesDontPassFilteredUpdatableFilePathIds)
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>())) ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>()))
.WillByDefault(Return(QDateTime::currentSecsSinceEpoch())); .WillByDefault(Return(QDateTime::currentSecsSinceEpoch()));
auto filePathIds = indexer.updatableFilePathIds(projectPart1); auto filePathIds = indexer.updatableFilePathIds(projectPart1, artefact);
ASSERT_THAT(filePathIds, IsEmpty()); ASSERT_THAT(filePathIds, IsEmpty());
} }

View File

@@ -115,6 +115,4 @@ TEST_F(SymbolIndexing, DISABLED_TemplateFunction)
IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 6, 5))); IsLocation(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 6, 5)));
} }
} }

View File

@@ -26,8 +26,7 @@
#include "googletest.h" #include "googletest.h"
#include "mockfilepathcaching.h" #include "mockfilepathcaching.h"
#include "mocksqlitereadstatement.h" #include "mocksqlitedatabase.h"
#include "mocksqlitewritestatement.h"
#include <storagesqlitestatementfactory.h> #include <storagesqlitestatementfactory.h>
#include <symbolstorage.h> #include <symbolstorage.h>
@@ -52,9 +51,7 @@ using ClangBackEnd::SymbolType;
using Sqlite::Database; using Sqlite::Database;
using Sqlite::Table; using Sqlite::Table;
using StatementFactory = StorageSqliteStatementFactory<MockSqliteDatabase, using StatementFactory = StorageSqliteStatementFactory<MockSqliteDatabase>;
MockSqliteReadStatement,
MockSqliteWriteStatement>;
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>; using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
class SymbolStorage : public testing::Test class SymbolStorage : public testing::Test
@@ -90,6 +87,8 @@ protected:
MockSqliteReadStatement &getProjectPartArtefactsBySourceId = statementFactory.getProjectPartArtefactsBySourceId; MockSqliteReadStatement &getProjectPartArtefactsBySourceId = statementFactory.getProjectPartArtefactsBySourceId;
MockSqliteReadStatement &getProjectPartArtefactsByProjectPartName = statementFactory.getProjectPartArtefactsByProjectPartName; MockSqliteReadStatement &getProjectPartArtefactsByProjectPartName = statementFactory.getProjectPartArtefactsByProjectPartName;
MockSqliteReadStatement &getLowestLastModifiedTimeOfDependencies = statementFactory.getLowestLastModifiedTimeOfDependencies; MockSqliteReadStatement &getLowestLastModifiedTimeOfDependencies = statementFactory.getLowestLastModifiedTimeOfDependencies;
MockSqliteReadStatement &getPrecompiledHeader = statementFactory.getPrecompiledHeader;
SymbolEntries symbolEntries{{1, {"functionUSR", "function"}}, SymbolEntries symbolEntries{{1, {"functionUSR", "function"}},
{2, {"function2USR", "function2"}}}; {2, {"function2USR", "function2"}}};
SourceLocationEntries sourceLocations{{1, {1, 3}, {42, 23}, SymbolType::Declaration}, SourceLocationEntries sourceLocations{{1, {1, 3}, {42, 23}, SymbolType::Declaration},
@@ -215,8 +214,8 @@ TEST_F(SymbolStorage, UpdateProjectPart)
EXPECT_CALL(updateProjectPartStatement, EXPECT_CALL(updateProjectPartStatement,
write(TypedEq<Utils::SmallStringView>("[\"foo\"]"), write(TypedEq<Utils::SmallStringView>("[\"foo\"]"),
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"), TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
TypedEq<Utils::SmallStringView>("project"), TypedEq<Utils::SmallStringView>("[\"/includes\"]"),
TypedEq<Utils::SmallStringView>("[\"/includes\"]"))); TypedEq<Utils::SmallStringView>("project")));
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"}); storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
} }
@@ -321,6 +320,24 @@ TEST_F(SymbolStorage, FetchLowestLastModifiedTime)
ASSERT_THAT(lowestLastModified, Eq(12)); 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));
}
} }

View File

@@ -94,7 +94,8 @@ SOURCES += \
tokenprocessor-test.cpp \ tokenprocessor-test.cpp \
projectpartartefact-test.cpp \ projectpartartefact-test.cpp \
filestatuscache-test.cpp \ filestatuscache-test.cpp \
highlightingresultreporter-test.cpp highlightingresultreporter-test.cpp \
precompiledheaderstorage-test.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \
@@ -229,7 +230,9 @@ HEADERS += \
runprojectcreateorupdate-utility.h \ runprojectcreateorupdate-utility.h \
rundocumentparse-utility.h \ rundocumentparse-utility.h \
mocktimer.h \ mocktimer.h \
mocksqlitetransactionbackend.h mocksqlitetransactionbackend.h \
mockprojectpartprovider.h \
mockprecompiledheaderstorage.h
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
HEADERS += \ HEADERS += \
chunksreportedmonitor.h \ chunksreportedmonitor.h \