Clang: Add ClangPchManager

Compiling every header file again and again is quite time comsuming. There
are technics to improve this like preambles(a kind of automated
precompiled header) but they don't share their data between translation
units. This approach provides an automatically generated precompiled
header for every project and subproject to improve the loading time.

Change-Id: I34f5bd4db21951175920e2a9bbf6b97b1d705969
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-01-30 11:24:46 +01:00
parent d4b1cb4a65
commit c072cdfb88
105 changed files with 6925 additions and 20 deletions

View File

@@ -68,7 +68,16 @@ SOURCES += $$PWD/clangcodemodelserverinterface.cpp \
$$PWD/sourcerangesanddiagnosticsforquerymessage.cpp \ $$PWD/sourcerangesanddiagnosticsforquerymessage.cpp \
$$PWD/sourcerangewithtextcontainer.cpp \ $$PWD/sourcerangewithtextcontainer.cpp \
$$PWD/filecontainerv2.cpp \ $$PWD/filecontainerv2.cpp \
$$PWD/cancelmessage.cpp $$PWD/cancelmessage.cpp \
$$PWD/pchmanagerclientinterface.cpp \
$$PWD/pchmanagerserverinterface.cpp \
$$PWD/projectpartcontainerv2.cpp \
$$PWD/updatepchprojectpartsmessage.cpp \
$$PWD/pchmanagerserverproxy.cpp \
$$PWD/pchmanagerclientproxy.cpp \
$$PWD/projectpartpch.cpp \
$$PWD/precompiledheadersupdatedmessage.cpp \
$$PWD/removepchprojectpartsmessage.cpp
HEADERS += \ HEADERS += \
$$PWD/clangcodemodelserverinterface.h \ $$PWD/clangcodemodelserverinterface.h \
@@ -133,6 +142,15 @@ HEADERS += \
$$PWD/sourcerangesanddiagnosticsforquerymessage.h \ $$PWD/sourcerangesanddiagnosticsforquerymessage.h \
$$PWD/sourcerangewithtextcontainer.h \ $$PWD/sourcerangewithtextcontainer.h \
$$PWD/filecontainerv2.h \ $$PWD/filecontainerv2.h \
$$PWD/cancelmessage.h $$PWD/cancelmessage.h \
$$PWD/pchmanagerclientinterface.h \
$$PWD/pchmanagerserverinterface.h \
$$PWD/projectpartcontainerv2.h \
$$PWD/updatepchprojectpartsmessage.h \
$$PWD/pchmanagerserverproxy.h \
$$PWD/pchmanagerclientproxy.h \
$$PWD/projectpartpch.h \
$$PWD/precompiledheadersupdatedmessage.h \
$$PWD/removepchprojectpartsmessage.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -45,10 +45,17 @@
# define CLANGBACKENDPROCESSPATH "" # define CLANGBACKENDPROCESSPATH ""
#endif #endif
#ifdef UNIT_TESTS
#define unitttest_public public
#else
#define unitttest_public private
#endif
namespace Utils { namespace Utils {
template <uint Size> template <uint Size>
class BasicSmallString; class BasicSmallString;
using SmallString = BasicSmallString<31>; using SmallString = BasicSmallString<31>;
using PathString = BasicSmallString<191>;
} }
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -124,7 +131,10 @@ enum class MessageType : quint8 {
RequestSourceRangesAndDiagnosticsForQueryMessage, RequestSourceRangesAndDiagnosticsForQueryMessage,
SourceRangesAndDiagnosticsForQueryMessage, SourceRangesAndDiagnosticsForQueryMessage,
CancelMessage CancelMessage,
UpdatePchProjectPartsMessage,
RemovePchProjectPartsMessage,
PrecompiledHeadersUpdatedMessage
}; };
template<MessageType messageEnumeration> template<MessageType messageEnumeration>

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** 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 "pchmanagerclientinterface.h"
#include "messageenvelop.h"
#include <precompiledheadersupdatedmessage.h>
#include <QDebug>
namespace ClangBackEnd {
void PchManagerClientInterface::dispatch(const MessageEnvelop &messageEnvelop)
{
switch (messageEnvelop.messageType()) {
case MessageType::AliveMessage:
alive();
break;
case MessageType::PrecompiledHeadersUpdatedMessage:
precompiledHeadersUpdated(messageEnvelop.message<PrecompiledHeadersUpdatedMessage>());
break;
default:
qWarning() << "Unknown IpcClientMessage";
}
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,43 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "ipcclientinterface.h"
namespace ClangBackEnd {
class PrecompiledHeadersUpdatedMessage;
class CMBIPC_EXPORT PchManagerClientInterface : public IpcClientInterface
{
public:
void dispatch(const MessageEnvelop &messageEnvelop) override;
virtual void alive() = 0;
virtual void precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage &&message) = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** 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 "pchmanagerclientproxy.h"
#include "cmbalivemessage.h"
#include "messageenvelop.h"
#include "pchmanagerserverinterface.h"
#include "precompiledheadersupdatedmessage.h"
#include <QDebug>
#include <QIODevice>
namespace ClangBackEnd {
PchManagerClientProxy::PchManagerClientProxy(PchManagerServerInterface *server, QIODevice *ioDevice)
: writeMessageBlock(ioDevice),
readMessageBlock(ioDevice),
server(server),
ioDevice(ioDevice)
{
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () {PchManagerClientProxy::readMessages();});
}
PchManagerClientProxy::PchManagerClientProxy(PchManagerClientProxy &&other)
: writeMessageBlock(std::move(other.writeMessageBlock)),
readMessageBlock(std::move(other.readMessageBlock)),
server(std::move(other.server)),
ioDevice(std::move(other.ioDevice))
{
}
PchManagerClientProxy &PchManagerClientProxy::operator=(PchManagerClientProxy &&other)
{
writeMessageBlock = std::move(other.writeMessageBlock);
readMessageBlock = std::move(other.readMessageBlock);
server = std::move(other.server);
ioDevice = std::move(other.ioDevice);
return *this;
}
void PchManagerClientProxy::readMessages()
{
for (const MessageEnvelop &message : readMessageBlock.readAll())
server->dispatch(message);
}
void PchManagerClientProxy::alive()
{
writeMessageBlock.write(AliveMessage());
}
void PchManagerClientProxy::precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage &&message)
{
writeMessageBlock.write(message);
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangbackendipc_global.h"
#include "pchmanagerclientinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
namespace ClangBackEnd {
class PchManagerServerInterface;
class CMBIPC_EXPORT PchManagerClientProxy : public PchManagerClientInterface
{
public:
explicit PchManagerClientProxy(PchManagerServerInterface *server, QIODevice *ioDevice);
PchManagerClientProxy(const PchManagerClientProxy&) = delete;
const PchManagerClientProxy &operator=(const PchManagerClientProxy&) = delete;
PchManagerClientProxy(PchManagerClientProxy&&other);
PchManagerClientProxy &operator=(PchManagerClientProxy&&other);
void readMessages();
void alive() override;
void precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage &&message) override;
private:
ClangBackEnd::WriteMessageBlock writeMessageBlock;
ClangBackEnd::ReadMessageBlock readMessageBlock;
PchManagerServerInterface *server = nullptr;
QIODevice *ioDevice = nullptr;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,53 @@
/****************************************************************************
**
** 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 "pchmanagerserverinterface.h"
#include "messageenvelop.h"
#include "removepchprojectpartsmessage.h"
#include "updatepchprojectpartsmessage.h"
#include <QDebug>
namespace ClangBackEnd {
void PchManagerServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
{
switch (messageEnvelop.messageType()) {
case MessageType::EndMessage:
end();
break;
case MessageType::UpdatePchProjectPartsMessage:
updatePchProjectParts(messageEnvelop.message<UpdatePchProjectPartsMessage>());
break;
case MessageType::RemovePchProjectPartsMessage:
removePchProjectParts(messageEnvelop.message<RemovePchProjectPartsMessage>());
break;
default:
qWarning() << "Unknown IpcClientMessage";
}
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "ipcserverinterface.h"
#include <memory>
namespace ClangBackEnd {
class PchManagerClientInterface;
class RemovePchProjectPartsMessage;
class UpdatePchProjectPartsMessage;
class CMBIPC_EXPORT PchManagerServerInterface : public IpcServerInterface<PchManagerClientInterface>
{
public:
void dispatch(const MessageEnvelop &messageEnvelop) override;
virtual void end() = 0;
virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0;
virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** 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 "pchmanagerserverproxy.h"
#include "cmbendmessage.h"
#include "messageenvelop.h"
#include "pchmanagerclientinterface.h"
#include "removepchprojectpartsmessage.h"
#include "updatepchprojectpartsmessage.h"
#include <QIODevice>
#include <QVector>
namespace ClangBackEnd {
PchManagerServerProxy::PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice)
: writeMessageBlock(ioDevice),
readMessageBlock(ioDevice),
client(client)
{
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { readMessages(); });
}
void PchManagerServerProxy::end()
{
writeMessageBlock.write(EndMessage());
}
void PchManagerServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
{
writeMessageBlock.write(message);
}
void PchManagerServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message)
{
writeMessageBlock.write(message);
}
void PchManagerServerProxy::readMessages()
{
for (const auto &message : readMessageBlock.readAll())
client->dispatch(message);
}
void PchManagerServerProxy::resetCounter()
{
writeMessageBlock.resetCounter();
readMessageBlock.resetCounter();
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangbackendipc_global.h"
#include "pchmanagerserverinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
#include <QtGlobal>
#include <memory>
QT_BEGIN_NAMESPACE
class QIODevice;
QT_END_NAMESPACE
namespace ClangBackEnd {
class PchManagerClientInterface;
class CMBIPC_EXPORT PchManagerServerProxy final : public PchManagerServerInterface
{
public:
explicit PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice);
PchManagerServerProxy(const PchManagerServerProxy&) = delete;
const PchManagerServerProxy &operator=(const PchManagerServerProxy&) = delete;
void end() override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
void readMessages();
void resetCounter();
private:
ClangBackEnd::WriteMessageBlock writeMessageBlock;
ClangBackEnd::ReadMessageBlock readMessageBlock;
PchManagerClientInterface *client = nullptr;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** 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 "precompiledheadersupdatedmessage.h"
#include <QDebug>
namespace ClangBackEnd {
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const PrecompiledHeadersUpdatedMessage &)
{
debug.nospace() << "PrecompiledHeaderUpdatedMessage()";
return debug;
}
std::ostream &operator<<(std::ostream &out, const PrecompiledHeadersUpdatedMessage &message)
{
out << "("
<< message.projectPartPchs()
<< ")";
return out;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "projectpartpch.h"
namespace ClangBackEnd {
class PrecompiledHeadersUpdatedMessage
{
public:
PrecompiledHeadersUpdatedMessage() = default;
PrecompiledHeadersUpdatedMessage(std::vector<ProjectPartPch> &&projectPartPchs)
: projectPartPchs_(std::move(projectPartPchs))
{}
const std::vector<ProjectPartPch> &projectPartPchs() const
{
return projectPartPchs_;
}
friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message)
{
out << message.projectPartPchs_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, PrecompiledHeadersUpdatedMessage &message)
{
in >> message.projectPartPchs_;
return in;
}
friend bool operator==(const PrecompiledHeadersUpdatedMessage &first,
const PrecompiledHeadersUpdatedMessage &second)
{
return first.projectPartPchs_ == second.projectPartPchs_;
}
PrecompiledHeadersUpdatedMessage clone() const
{
return PrecompiledHeadersUpdatedMessage(Utils::clone(projectPartPchs_));
}
private:
std::vector<ProjectPartPch> projectPartPchs_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const PrecompiledHeadersUpdatedMessage &message);
std::ostream &operator<<(std::ostream &out, const PrecompiledHeadersUpdatedMessage &message);
DECLARE_MESSAGE(PrecompiledHeadersUpdatedMessage)
} // namespace ClangBackEnd

View File

@@ -0,0 +1,55 @@
/****************************************************************************
**
** 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 "projectpartcontainerv2.h"
namespace ClangBackEnd {
namespace V2 {
QDebug operator<<(QDebug debug, const ProjectPartContainer &container)
{
debug.nospace() << "ProjectPartContainer("
<< container.projectPartId() << ","
<< container.arguments() << ", "
<< container.headerPaths() << ", "
<< container.sourcePaths()
<< ")";
return debug;
}
std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container)
{
out << "("
<< container.projectPartId() << ", "
<< container.arguments() << ", "
<< container.headerPaths() << ", "
<< container.sourcePaths()<< ")";
return out;
}
} // namespace V2
} // namespace ClangBackEnd

View File

@@ -0,0 +1,124 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangbackendipc_global.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd {
namespace V2 {
class ProjectPartContainer
{
public:
ProjectPartContainer() = default;
ProjectPartContainer(Utils::SmallString &&projectPartId,
Utils::SmallStringVector &&arguments,
Utils::SmallStringVector &&headerPaths,
Utils::SmallStringVector &&sourcePaths)
: projectPartId_(std::move(projectPartId)),
arguments_(std::move(arguments)),
headerPaths_(std::move(headerPaths)),
sourcePaths_(std::move(sourcePaths))
{
}
const Utils::SmallString &projectPartId() const
{
return projectPartId_;
}
const Utils::SmallStringVector &arguments() const
{
return arguments_;
}
const Utils::SmallStringVector &sourcePaths() const
{
return sourcePaths_;
}
const Utils::SmallStringVector &headerPaths() const
{
return headerPaths_;
}
friend QDataStream &operator<<(QDataStream &out, const ProjectPartContainer &container)
{
out << container.projectPartId_;
out << container.arguments_;
out << container.headerPaths_;
out << container.sourcePaths_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, ProjectPartContainer &container)
{
in >> container.projectPartId_;
in >> container.arguments_;
in >> container.headerPaths_;
in >> container.sourcePaths_;
return in;
}
friend bool operator==(const ProjectPartContainer &first, const ProjectPartContainer &second)
{
return first.projectPartId_ == second.projectPartId_
&& first.arguments_ == second.arguments_
&& first.headerPaths_ == second.headerPaths_
&& first.sourcePaths_ == second.sourcePaths_;
}
friend bool operator<(const ProjectPartContainer &first, const ProjectPartContainer &second)
{
return std::tie(first.projectPartId_, first.arguments_, first.headerPaths_, first.sourcePaths_)
< std::tie(second.projectPartId_, second.arguments_, second.headerPaths_, second.sourcePaths_);
}
ProjectPartContainer clone() const
{
return ProjectPartContainer(projectPartId_.clone(),
arguments_.clone(),
headerPaths_.clone(),
sourcePaths_.clone());
}
private:
Utils::SmallString projectPartId_;
Utils::SmallStringVector arguments_;
Utils::SmallStringVector headerPaths_;
Utils::SmallStringVector sourcePaths_;
};
using ProjectPartContainers = std::vector<ProjectPartContainer>;
QDebug operator<<(QDebug debug, const ProjectPartContainer &container);
std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container);
} // namespace V2
} // namespace ClangBackEnd

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** 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 "projectpartpch.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch)
{
debug.nospace() << "FileContainer("
<< projectPartPch.id() << ", "
<< projectPartPch.path() << ")";
return debug;
}
std::ostream &operator<<(std::ostream &out, const ProjectPartPch &projectPartPch)
{
out << "("
<< projectPartPch.id() << ", "
<< projectPartPch.path() << ")";
return out;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangbackendipc_global.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd {
class ProjectPartPch
{
public:
ProjectPartPch() = default;
ProjectPartPch(Utils::SmallString &&projectPartId, Utils::SmallString &&pchPath)
: projectPartId(std::move(projectPartId)),
pchPath(std::move(pchPath))
{}
const Utils::SmallString &id() const
{
return projectPartId;
}
const Utils::SmallString &path() const
{
return pchPath;
}
friend QDataStream &operator<<(QDataStream &out, const ProjectPartPch &container)
{
out << container.projectPartId;
out << container.pchPath;
return out;
}
friend QDataStream &operator>>(QDataStream &in, ProjectPartPch &container)
{
in >> container.projectPartId;
in >> container.pchPath;
return in;
}
friend bool operator==(const ProjectPartPch &first,
const ProjectPartPch &second)
{
return first.projectPartId == second.projectPartId
&& first.pchPath == second.pchPath;
}
ProjectPartPch clone() const
{
return ProjectPartPch(projectPartId.clone(), pchPath.clone());
}
private:
Utils::SmallString projectPartId;
Utils::SmallString pchPath;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch);
std::ostream &operator<<(std::ostream &out, const ProjectPartPch &projectPartPch);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** 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 "removepchprojectpartsmessage.h"
namespace ClangBackEnd {
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RemovePchProjectPartsMessage &message)
{
debug.nospace() << "RemoveProjectPartsMessage("
<< message.projectsPartIds() << ")";
return debug;
}
std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &message)
{
return out << "(" << message.projectsPartIds() << ")";
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "projectpartcontainerv2.h"
namespace ClangBackEnd {
class RemovePchProjectPartsMessage
{
public:
RemovePchProjectPartsMessage() = default;
RemovePchProjectPartsMessage(Utils::SmallStringVector &&projectsPartIds)
: projectsPartIds_(std::move(projectsPartIds))
{}
const Utils::SmallStringVector &projectsPartIds() const
{
return projectsPartIds_;
}
Utils::SmallStringVector takeProjectsPartIds()
{
return std::move(projectsPartIds_);
}
friend QDataStream &operator<<(QDataStream &out, const RemovePchProjectPartsMessage &message)
{
out << message.projectsPartIds_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, RemovePchProjectPartsMessage &message)
{
in >> message.projectsPartIds_;
return in;
}
friend bool operator==(const RemovePchProjectPartsMessage &first,
const RemovePchProjectPartsMessage &second)
{
return first.projectsPartIds_ == second.projectsPartIds_;
}
RemovePchProjectPartsMessage clone() const
{
return RemovePchProjectPartsMessage(projectsPartIds_.clone());
}
private:
Utils::SmallStringVector projectsPartIds_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RemovePchProjectPartsMessage &message);
std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &message);
DECLARE_MESSAGE(RemovePchProjectPartsMessage)
} // namespace ClangBackEnd

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** 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 "updatepchprojectpartsmessage.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const UpdatePchProjectPartsMessage &message)
{
debug.nospace() << "UpdatePchProjectPartsMessage("
<< message.projectsParts() << ")";
return debug;
}
std::ostream &operator<<(std::ostream &out, const UpdatePchProjectPartsMessage &message)
{
return out << "("
<< message.projectsParts()
<< ")";
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "projectpartcontainerv2.h"
namespace ClangBackEnd {
class UpdatePchProjectPartsMessage
{
public:
UpdatePchProjectPartsMessage() = default;
UpdatePchProjectPartsMessage(V2::ProjectPartContainers &&projectsParts)
: projectsParts_(std::move(projectsParts))
{}
const V2::ProjectPartContainers &projectsParts() const
{
return projectsParts_;
}
V2::ProjectPartContainers takeProjectsParts()
{
return std::move(projectsParts_);
}
friend QDataStream &operator<<(QDataStream &out, const UpdatePchProjectPartsMessage &message)
{
out << message.projectsParts_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, UpdatePchProjectPartsMessage &message)
{
in >> message.projectsParts_;
return in;
}
friend bool operator==(const UpdatePchProjectPartsMessage &first,
const UpdatePchProjectPartsMessage &second)
{
return first.projectsParts_ == second.projectsParts_;
}
UpdatePchProjectPartsMessage clone() const
{
return UpdatePchProjectPartsMessage(Utils::clone(projectsParts_));
}
private:
V2::ProjectPartContainers projectsParts_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const UpdatePchProjectPartsMessage &message);
std::ostream &operator<<(std::ostream &out, const UpdatePchProjectPartsMessage &message);
DECLARE_MESSAGE(UpdatePchProjectPartsMessage)
} // namespace ClangBackEnd

View File

@@ -0,0 +1,21 @@
{
\"Name\" : \"ClangPchManager\",
\"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"Experimental\" : true,
\"HiddenByDefault\": true,
\"Vendor\" : \"The Qt Company Ltd\",
\"Copyright\" : \"(C) 2016 The Qt Company Ltd\",
\"License\" : [ \"Commercial Usage\",
\"\",
\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt 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.\",
\"\",
\"GNU General Public License Usage\",
\"\",
\"Alternatively, this plugin 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 plugin. 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.\"
],
\"Category\" : \"C++\",
\"Description\" : \"Clang precompiled header plugin.\",
\"Url\" : \"http://www.qt.io\",
$$dependencyList
}

View File

@@ -0,0 +1,22 @@
shared|dll {
DEFINES += CLANGPCHMANAGER_LIB
} else {
DEFINES += CLANGPCHMANAGER_STATIC_LIB
}
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/pchmanagerclient.h \
$$PWD/pchmanagernotifierinterface.h \
$$PWD/pchmanagerconnectionclient.h \
$$PWD/clangpchmanager_global.h \
$$PWD/projectupdater.h
SOURCES += \
$$PWD/pchmanagerclient.cpp \
$$PWD/pchmanagernotifierinterface.cpp \
$$PWD/pchmanagerconnectionclient.cpp \
$$PWD/projectupdater.cpp

View File

@@ -0,0 +1,13 @@
include(../../qtcreatorplugin.pri)
include(clangpchmanager-source.pri)
include(../../shared/clang/clang_installation.pri)
DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\"
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include\\\"\""
HEADERS += \
$$PWD/clangpchmanagerplugin.h \
qtcreatorprojectupdater.h
SOURCES += \
$$PWD/clangpchmanagerplugin.cpp \
qtcreatorprojectupdater.cpp

View File

@@ -0,0 +1,8 @@
QTC_PLUGIN_NAME = ClangPchManager
QTC_LIB_DEPENDS += \
utils \
clangbackendipc
QTC_PLUGIN_DEPENDS += \
coreplugin \
cpptools

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <qglobal.h>
#if defined(CLANGPCHMANAGER_LIB)
# define CLANGPCHMANAGER_EXPORT Q_DECL_EXPORT
#elif defined(CLANGPCHMANAGER_STATIC_LIB) // Abuse single files for manual tests
# define CLANGPCHMANAGER_EXPORT
#else
# define CLANGPCHMANAGER_EXPORT Q_DECL_IMPORT
#endif
#ifdef UNIT_TESTS
#define unittest_public public
#else
#define unittest_public private
#endif

View File

@@ -0,0 +1,100 @@
/****************************************************************************
**
** 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 "clangpchmanagerplugin.h"
#include "pchmanagerconnectionclient.h"
#include "pchmanagerclient.h"
#include "qtcreatorprojectupdater.h"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/hostosinfo.h>
namespace ClangPchManager {
namespace {
QString backendProcessPath()
{
return Core::ICore::libexecPath()
+ QStringLiteral("/clangpchmanagerbackend")
+ QStringLiteral(QTC_HOST_EXE_SUFFIX);
}
} // anonymous namespace
class ClangPchManagerPluginData
{
public:
PchManagerClient pchManagerClient;
PchManagerConnectionClient connectionClient{&pchManagerClient};
QtCreatorProjectUpdater projectUpdate{connectionClient.serverProxy(), pchManagerClient};
};
std::unique_ptr<ClangPchManagerPluginData> ClangPchManagerPlugin::d;
ClangPchManagerPlugin::ClangPchManagerPlugin() = default;
ClangPchManagerPlugin::~ClangPchManagerPlugin() = default;
bool ClangPchManagerPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorMessage*/)
{
d.reset(new ClangPchManagerPluginData);
startBackend();
return true;
}
void ClangPchManagerPlugin::extensionsInitialized()
{
}
ExtensionSystem::IPlugin::ShutdownFlag ClangPchManagerPlugin::aboutToShutdown()
{
d->connectionClient.finishProcess();
d.reset();
return SynchronousShutdown;
}
void ClangPchManagerPlugin::startBackend()
{
d->pchManagerClient.setConnectionClient(&d->connectionClient);
d->connectionClient.setProcessPath(backendProcessPath());
d->connectionClient.startProcessAndConnectToServerAsynchronously();
}
PchManagerClient &ClangPchManagerPlugin::pchManagerClient()
{
return d->pchManagerClient;
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <extensionsystem/iplugin.h>
#include <memory>
namespace ClangPchManager {
class ClangPchManagerPluginData;
class PchManagerClient;
class ClangPchManagerPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangPchManager.json")
public:
ClangPchManagerPlugin();
~ClangPchManagerPlugin();
bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized();
ShutdownFlag aboutToShutdown();
static PchManagerClient &pchManagerClient();
private:
void startBackend();
private:
static std::unique_ptr<ClangPchManagerPluginData> d;
};
} // namespace ClangRefactoring

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** 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 "pchmanagerclient.h"
#include <precompiledheadersupdatedmessage.h>
#include <pchmanagerconnectionclient.h>
#include <pchmanagernotifierinterface.h>
#include <algorithm>
namespace ClangPchManager {
void PchManagerClient::alive()
{
if (m_connectionClient)
m_connectionClient->resetProcessAliveTimer();
}
void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message)
{
for (const ClangBackEnd::ProjectPartPch &projectPartPch : message.projectPartPchs())
precompiledHeaderUpdated(projectPartPch.id(), projectPartPch.path());
}
void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId)
{
for (auto notifier : m_notifiers)
notifier->precompiledHeaderRemoved(projectPartId);
}
void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectionClient)
{
m_connectionClient = connectionClient;
}
void PchManagerClient::attach(PchManagerNotifierInterface *notifier)
{
m_notifiers.push_back(notifier);
}
void PchManagerClient::detach(PchManagerNotifierInterface *notifierToBeDeleted)
{
auto newEnd = std::partition(m_notifiers.begin(),
m_notifiers.end(),
[&] (PchManagerNotifierInterface *notifier) {
return notifier != notifierToBeDeleted;
});
m_notifiers.erase(newEnd, m_notifiers.end());
}
const std::vector<PchManagerNotifierInterface *> &PchManagerClient::notifiers() const
{
return m_notifiers;
}
void PchManagerClient::precompiledHeaderUpdated(const QString &projectPartId, const QString &pchFilePath)
{
for (auto notifier : m_notifiers)
notifier->precompiledHeaderUpdated(projectPartId, pchFilePath);
}
} // namespace ClangPchManager

View File

@@ -0,0 +1,60 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <pchmanagerclientinterface.h>
#include <vector>
namespace ClangPchManager {
class PchManagerConnectionClient;
class PchManagerNotifierInterface;
class PchManagerClient final : public ClangBackEnd::PchManagerClientInterface
{
friend class PchManagerNotifierInterface;
public:
void alive() override;
void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override;
void precompiledHeaderRemoved(const QString &projectPartId);
void setConnectionClient(PchManagerConnectionClient *connectionClient);
unitttest_public:
const std::vector<PchManagerNotifierInterface*> &notifiers() const;
void precompiledHeaderUpdated(const QString &projectPartId, const QString &pchFilePath);
void attach(PchManagerNotifierInterface *notifier);
void detach(PchManagerNotifierInterface *notifier);
private:
std::vector<PchManagerNotifierInterface*> m_notifiers;
PchManagerConnectionClient *m_connectionClient=nullptr;
};
} // namespace ClangPchManager

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** 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 "pchmanagerconnectionclient.h"
#include <QCoreApplication>
#include <QTemporaryDir>
namespace ClangPchManager {
namespace {
QString currentProcessId()
{
return QString::number(QCoreApplication::applicationPid());
}
}
ClangPchManager::PchManagerConnectionClient::PchManagerConnectionClient(
ClangBackEnd::PchManagerClientInterface *client)
: serverProxy_(client, ioDevice())
{
stdErrPrefixer().setPrefix("PchManagerConnectionClient.stderr: ");
stdOutPrefixer().setPrefix("PchManagerConnectionClient.stdout: ");
}
ClangBackEnd::PchManagerServerProxy &ClangPchManager::PchManagerConnectionClient::serverProxy()
{
return serverProxy_;
}
void ClangPchManager::PchManagerConnectionClient::sendEndCommand()
{
serverProxy_.end();
}
void PchManagerConnectionClient::resetCounter()
{
serverProxy_.resetCounter();
}
QString ClangPchManager::PchManagerConnectionClient::connectionName() const
{
return temporaryDirectory().path() + QStringLiteral("/ClangPchManagerBackEnd-") + currentProcessId();
}
QString PchManagerConnectionClient::outputName() const
{
return QStringLiteral("PchManagerConnectionClient");
}
} // namespace ClangPchManager

View File

@@ -0,0 +1,50 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <connectionclient.h>
#include <pchmanagerserverproxy.h>
namespace ClangPchManager {
class PchManagerConnectionClient : public ClangBackEnd::ConnectionClient
{
public:
PchManagerConnectionClient(ClangBackEnd::PchManagerClientInterface *client);
ClangBackEnd::PchManagerServerProxy &serverProxy();
protected:
void sendEndCommand() override;
void resetCounter() override;
QString connectionName() const override;
QString outputName() const override;
private:
ClangBackEnd::PchManagerServerProxy serverProxy_;
};
} // namespace ClangPchManager

View File

@@ -0,0 +1,43 @@
/****************************************************************************
**
** 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 "pchmanagernotifierinterface.h"
#include <pchmanagerclient.h>
namespace ClangPchManager {
PchManagerNotifierInterface::PchManagerNotifierInterface(PchManagerClient &pchManagerClient)
: m_pchManagerClient(pchManagerClient)
{
m_pchManagerClient.attach(this);
}
PchManagerNotifierInterface::~PchManagerNotifierInterface()
{
m_pchManagerClient.detach(this);
}
} // namespace ClangPchManager

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <QtGlobal>
QT_FORWARD_DECLARE_CLASS(QString)
namespace ClangPchManager {
class PchManagerClient;
class PchManagerNotifierInterface
{
public:
PchManagerNotifierInterface(PchManagerClient &pchManagerClient);
virtual ~PchManagerNotifierInterface();
virtual void precompiledHeaderUpdated(const QString &projectPartId,
const QString &pchFilePath) = 0;
virtual void precompiledHeaderRemoved(const QString &projectPartId) = 0;
PchManagerClient &m_pchManagerClient;
};
} // namespace ClangPchManager

View File

@@ -0,0 +1,126 @@
/****************************************************************************
**
** 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 "projectupdater.h"
#include "pchmanagerclient.h"
#include <pchmanagerserverinterface.h>
#include <removepchprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h>
#include <cpptools/clangcompileroptionsbuilder.h>
#include <cpptools/projectpart.h>
namespace ClangPchManager {
ProjectUpdater::ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
PchManagerClient &client)
: m_server(server),
m_client(client)
{
}
void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts)
{
ClangBackEnd::UpdatePchProjectPartsMessage message{toProjectPartContainers(projectParts)};
m_server.updatePchProjectParts(std::move(message));
}
void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
{
ClangBackEnd::RemovePchProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)};
m_server.removePchProjectParts(std::move(message));
for (const QString &projectPartiId : projectPartIds)
m_client.precompiledHeaderRemoved(projectPartiId);
}
namespace {
class HeaderAndSources
{
public:
void reserve(std::size_t size)
{
headers.reserve(size);
sources.reserve(size);
}
Utils::SmallStringVector headers;
Utils::SmallStringVector sources;
};
HeaderAndSources headerAndSourcesFromProjectPart(CppTools::ProjectPart *projectPart)
{
HeaderAndSources headerAndSources;
headerAndSources.reserve(std::size_t(projectPart->files.size()) * 3 / 2);
for (const CppTools::ProjectFile &projectFile : projectPart->files) {
if (projectFile.isSource())
headerAndSources.sources.push_back(projectFile.path);
else if (projectFile.isHeader())
headerAndSources.headers.push_back(projectFile.path);
}
return headerAndSources;
}
}
ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer(CppTools::ProjectPart *projectPart)
{
using CppTools::ClangCompilerOptionsBuilder;
QStringList arguments = ClangCompilerOptionsBuilder::build(
projectPart,
CppTools::ProjectFile::CXXHeader,
ClangCompilerOptionsBuilder::PchUsage::None,
CLANG_VERSION,
CLANG_RESOURCE_DIR);
HeaderAndSources headerAndSources = headerAndSourcesFromProjectPart(projectPart);
return ClangBackEnd::V2::ProjectPartContainer(projectPart->displayName,
Utils::SmallStringVector(arguments),
std::move(headerAndSources.headers),
std::move(headerAndSources.sources));
}
std::vector<ClangBackEnd::V2::ProjectPartContainer> ProjectUpdater::toProjectPartContainers(
std::vector<CppTools::ProjectPart *> projectParts)
{
std::vector<ClangBackEnd::V2::ProjectPartContainer> projectPartContainers;
projectPartContainers.reserve(projectParts.size());
std::transform(projectParts.begin(),
projectParts.end(),
std::back_inserter(projectPartContainers),
ProjectUpdater::toProjectPartContainer);
return projectPartContainers;
}
} // namespace ClangPchManager

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <clangpchmanager_global.h>
namespace CppTools {
class ProjectPart;
}
namespace ClangBackEnd {
class PchManagerServerInterface;
namespace V2 {
class ProjectPartContainer;
}
}
QT_FORWARD_DECLARE_CLASS(QStringList)
#include <vector>
namespace ClangPchManager {
class PchManagerClient;
class ProjectUpdater
{
public:
ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
PchManagerClient &client);
void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts);
void removeProjectParts(const QStringList &projectPartIds);
unittest_public:
static ClangBackEnd::V2::ProjectPartContainer toProjectPartContainer(
CppTools::ProjectPart *projectPart);
static std::vector<ClangBackEnd::V2::ProjectPartContainer> toProjectPartContainers(
std::vector<CppTools::ProjectPart *> projectParts);
private:
ClangBackEnd::PchManagerServerInterface &m_server;
PchManagerClient &m_client;
};
} // namespace ClangPchManager

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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 "qtcreatorprojectupdater.h"
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/project.h>
namespace ClangPchManager {
static CppTools::CppModelManager *cppModelManager()
{
return CppTools::CppModelManager::instance();
}
QtCreatorProjectUpdater::QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
PchManagerClient &client)
: ProjectUpdater(server, client)
{
connectToCppModelManager();
}
void QtCreatorProjectUpdater::projectPartsUpdated(ProjectExplorer::Project *project)
{
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
const QVector<CppTools::ProjectPart::Ptr> projectPartSharedPointers = projectInfo.projectParts();
std::vector<CppTools::ProjectPart*> projectParts;
projectParts.reserve(std::size_t(projectPartSharedPointers.size()));
auto convertToRawPointer = [] (const CppTools::ProjectPart::Ptr &sharedPointer) {
return sharedPointer.data();
};
std::transform(projectPartSharedPointers.begin(),
projectPartSharedPointers.end(),
std::back_inserter(projectParts),
convertToRawPointer);
updateProjectParts(projectParts);
}
void QtCreatorProjectUpdater::projectPartsRemoved(const QStringList &projectPartIds)
{
removeProjectParts(projectPartIds);
}
void QtCreatorProjectUpdater::connectToCppModelManager()
{
connect(cppModelManager(),
&CppTools::CppModelManager::projectPartsUpdated,
this,
&QtCreatorProjectUpdater::projectPartsUpdated);
connect(cppModelManager(),
&CppTools::CppModelManager::projectPartsRemoved,
this,
&QtCreatorProjectUpdater::projectPartsRemoved);
}
} // namespace ClangPchManager

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "projectupdater.h"
#include <QObject>
namespace ProjectExplorer {
class Project;
}
namespace ClangPchManager {
class QtCreatorProjectUpdater : public QObject, public ProjectUpdater
{
public:
QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
PchManagerClient &client);
void projectPartsUpdated(ProjectExplorer::Project *project);
void projectPartsRemoved(const QStringList &projectPartIds);
private:
void connectToCppModelManager();
};
} // namespace ClangPchManager

View File

@@ -5,5 +5,5 @@ QTC_LIB_DEPENDS += \
QTC_PLUGIN_DEPENDS += \ QTC_PLUGIN_DEPENDS += \
coreplugin \ coreplugin \
cpptools \ cpptools \
texteditor texteditor \
clangpchmanager

View File

@@ -45,14 +45,14 @@ namespace ClangRefactoring {
class RefactoringClient final : public ClangBackEnd::RefactoringClientInterface class RefactoringClient final : public ClangBackEnd::RefactoringClientInterface
{ {
public: public:
void alive() final; void alive() override;
void sourceLocationsForRenamingMessage( void sourceLocationsForRenamingMessage(
ClangBackEnd::SourceLocationsForRenamingMessage &&message) final; ClangBackEnd::SourceLocationsForRenamingMessage &&message) override;
void sourceRangesAndDiagnosticsForQueryMessage( void sourceRangesAndDiagnosticsForQueryMessage(
ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) final; ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) override;
void setLocalRenamingCallback( void setLocalRenamingCallback(
CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) final; CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) override;
void setRefactoringEngine(ClangRefactoring::RefactoringEngine *refactoringEngine); void setRefactoringEngine(ClangRefactoring::RefactoringEngine *refactoringEngine);
void setSearchHandle(ClangRefactoring::SearchHandle *searchHandleInterface); void setSearchHandle(ClangRefactoring::SearchHandle *searchHandleInterface);
ClangRefactoring::SearchHandle *searchHandle() const; ClangRefactoring::SearchHandle *searchHandle() const;

View File

@@ -109,6 +109,16 @@ bool ProjectFile::isSource(ProjectFile::Kind kind)
} }
} }
bool ProjectFile::isHeader() const
{
return isHeader(kind);
}
bool ProjectFile::isSource() const
{
return isSource(kind);
}
#define RETURN_TEXT_FOR_CASE(enumValue) case ProjectFile::enumValue: return #enumValue #define RETURN_TEXT_FOR_CASE(enumValue) case ProjectFile::enumValue: return #enumValue
static const char *projectFileKindToText(ProjectFile::Kind kind) static const char *projectFileKindToText(ProjectFile::Kind kind)
{ {

View File

@@ -55,6 +55,9 @@ public:
static bool isHeader(Kind kind); static bool isHeader(Kind kind);
static bool isAmbiguousHeader(const QString &filePath); static bool isAmbiguousHeader(const QString &filePath);
bool isHeader() const;
bool isSource() const;
public: public:
ProjectFile() = default; ProjectFile() = default;
ProjectFile(const QString &filePath, Kind kind); ProjectFile(const QString &filePath, Kind kind);

View File

@@ -81,8 +81,9 @@ exists($$LLVM_INSTALL_DIR) {
win32-msvc2015:lessThan(QT_CL_PATCH_VERSION, 24210): QTC_NO_CLANG_LIBTOOLING = 1 win32-msvc2015:lessThan(QT_CL_PATCH_VERSION, 24210): QTC_NO_CLANG_LIBTOOLING = 1
isEmpty(QTC_NO_CLANG_LIBTOOLING) { isEmpty(QTC_NO_CLANG_LIBTOOLING) {
SUBDIRS += clangrefactoring SUBDIRS += clangrefactoring
SUBDIRS += clangpchmanager
} else { } else {
warning("Building the Clang refactoring plugin is disabled.") warning("Building the Clang refactoring and the pch manager plugins are disabled.")
} }
} else { } else {
warning("Set LLVM_INSTALL_DIR to build the Clang Code Model. " \ warning("Set LLVM_INSTALL_DIR to build the Clang Code Model. " \

View File

@@ -115,6 +115,7 @@ LLVM_CXXFLAGS ~= s,-O2,
LLVM_CXXFLAGS ~= s,/W4, LLVM_CXXFLAGS ~= s,/W4,
LLVM_CXXFLAGS ~= s,/EHc-, LLVM_CXXFLAGS ~= s,/EHc-,
LLVM_CXXFLAGS ~= s,-Werror=date-time, LLVM_CXXFLAGS ~= s,-Werror=date-time,
LLVM_CXXFLAGS ~= s,-fPIC,
# split-dwarf needs objcopy which does not work via icecc out-of-the-box # split-dwarf needs objcopy which does not work via icecc out-of-the-box
LLVM_CXXFLAGS ~= s,-gsplit-dwarf, LLVM_CXXFLAGS ~= s,-gsplit-dwarf,

View File

@@ -0,0 +1,34 @@
QTC_LIB_DEPENDS += \
clangbackendipc
include(../../qtcreatortool.pri)
include(../../shared/clang/clang_installation.pri)
include(source/clangpchmanagerbackend-source.pri)
win32 {
LLVM_BUILDMODE = $$system($$llvm_config --build-mode, lines)
CONFIG(debug, debug|release):requires(equals(LLVM_BUILDMODE, "Debug"))
}
QT += core network
QT -= gui
LIBS += $$LIBTOOLING_LIBS
INCLUDEPATH += $$LLVM_INCLUDEPATH
QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS
INCLUDEPATH += ../clangrefactoringbackend/source
SOURCES += \
clangpchmanagerbackendmain.cpp \
../clangrefactoringbackend/source/clangtool.cpp \
../clangrefactoringbackend/source/refactoringcompilationdatabase.cpp
unix {
!macos: QMAKE_LFLAGS += -Wl,-z,origin
!disable_external_rpath: QMAKE_LFLAGS += -Wl,-rpath,$$shell_quote($${LLVM_LIBDIR})
}
DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_INSTALL_DIR/bin/clang)xxx\\\"\"

View File

@@ -0,0 +1,108 @@
/****************************************************************************
**
** 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 <clangpathwatcher.h>
#include <connectionserver.h>
#include <environment.h>
#include <pchcreator.h>
#include <pchmanagerserver.h>
#include <pchmanagerclientproxy.h>
#include <projectparts.h>
#include <stringcache.h>
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QFileSystemWatcher>
#include <QLoggingCategory>
#include <QTemporaryDir>
using ClangBackEnd::ClangPathWatcher;
using ClangBackEnd::ConnectionServer;
using ClangBackEnd::PchCreator;
using ClangBackEnd::PchManagerClientProxy;
using ClangBackEnd::PchManagerServer;
using ClangBackEnd::ProjectParts;
using ClangBackEnd::StringCache;
class ApplicationEnvironment : public ClangBackEnd::Environment
{
public:
QString pchBuildDirectory() const override
{
return temporaryDirectory.path();
}
QString clangCompilerPath() const override
{
return QString(CLANG_COMPILER_PATH);
}
private:
QTemporaryDir temporaryDirectory;
};
QString processArguments(QCoreApplication &application)
{
QCommandLineParser parser;
parser.setApplicationDescription(QStringLiteral("Qt Creator Clang PchManager Backend"));
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument(QStringLiteral("connection"), QStringLiteral("Connection"));
parser.process(application);
if (parser.positionalArguments().isEmpty())
parser.showHelp(1);
return parser.positionalArguments().first();
}
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false"));
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
QCoreApplication::setApplicationName(QStringLiteral("ClangPchManagerBackend"));
QCoreApplication::setApplicationVersion(QStringLiteral("0.1.0"));
QCoreApplication application(argc, argv);
const QString connection = processArguments(application);
StringCache<Utils::SmallString> filePathCache;
ClangPathWatcher<QFileSystemWatcher> includeWatcher(filePathCache);
ApplicationEnvironment environment;
PchCreator pchCreator(environment, filePathCache);
ProjectParts projectParts;
PchManagerServer clangPchManagerServer(filePathCache, includeWatcher, pchCreator, projectParts);
ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer(connection);
connectionServer.start();
connectionServer.setServer(&clangPchManagerServer);
return application.exec();
}

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** 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 "clangpathwatcher.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd {
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry)
{
out << "("
<< entry.id << ", "
<< entry.path
<< ")";
return out;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,392 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangpathwatcherinterface.h"
#include "clangpathwatchernotifier.h"
#include "stringcache.h"
#include <QObject>
namespace ClangBackEnd {
class WatcherEntry
{
public:
uint id;
uint path;
friend bool operator==(const WatcherEntry &first, const WatcherEntry &second)
{
return first.id == second.id && first.path == second.path;
}
friend bool operator<(const WatcherEntry &first, const WatcherEntry &second)
{
return std::tie(first.path, first.id) < std::tie(second.path, second.id);
}
friend bool operator<(const WatcherEntry &entry, uint path)
{
return entry.path < path;
}
friend bool operator<(uint path, const WatcherEntry &entry)
{
return path < entry.path;
}
};
template <typename FileSystemWatcher>
class ClangPathWatcher : public ClangPathWatcherInterface
{
public:
ClangPathWatcher(StringCache<Utils::SmallString> &pathCache,
ClangPathWatcherNotifier *notifier=nullptr)
: m_pathCache(pathCache),
m_notifier(notifier)
{
QObject::connect(&m_fileSystemWatcher,
&FileSystemWatcher::fileChanged,
[&] (const QString &filePath) { addChangedPathForFilePath(filePath); });
}
void updateIdPaths(const std::vector<IdPaths> &idPaths) override
{
auto entriesAndIds = convertIdPathsToWatcherEntriesAndIds(idPaths);
addEntries(entriesAndIds.first);
removeUnusedEntries(entriesAndIds.first, entriesAndIds.second);
}
void removeIds(const Utils::SmallStringVector &ids) override
{
auto removedEntries = removeIdsFromWatchedEntries(convertToIdNumbers(ids));
auto filteredPaths = filterNotWatchedPaths(removedEntries);
if (!filteredPaths.empty())
m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
}
void setNotifier(ClangPathWatcherNotifier *notifier) override
{
m_notifier = notifier;
}
unitttest_public:
static std::vector<uint> idsFromIdPaths(const std::vector<IdPaths> &idPaths)
{
std::vector<uint> ids;
ids.reserve(idPaths.size());
auto extractId = [] (const IdPaths &idPath) {
return idPath.id;
};
std::transform(idPaths.begin(),
idPaths.end(),
std::back_inserter(ids),
extractId);
std::sort(ids.begin(), ids.end());
return ids;
}
std::vector<uint> convertToIdNumbers(const Utils::SmallStringVector &ids)
{
std::vector<uint> idNumbers = m_idCache.stringIds(ids);
std::sort(idNumbers.begin(), idNumbers.end());
return idNumbers;
}
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
{
auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
return size + idPath.paths.size();
};
return std::accumulate(idPaths.begin(), idPaths.end(), 0u, sumSize);
}
std::pair<std::vector<WatcherEntry>,std::vector<uint>>
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
{
std::vector<WatcherEntry> entries;
entries.reserve(sizeOfIdPaths(idPaths));
std::vector<uint> ids;
ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths)
{
uint id = m_idCache.stringId(idPath.id);
ids.push_back(id);
outputIterator = std::transform(idPath.paths.begin(),
idPath.paths.end(),
outputIterator,
[&] (uint path) { return WatcherEntry{id, path}; });
}
std::sort(entries.begin(), entries.end());
std::sort(ids.begin(), ids.end());
return {entries, ids};
}
void addEntries(const std::vector<WatcherEntry> &entries)
{
auto newEntries = notWatchedEntries(entries);
auto filteredPaths = filterNotWatchedPaths(newEntries);
mergeToWatchedEntries(newEntries);
if (!filteredPaths.empty())
m_fileSystemWatcher.addPaths(convertWatcherEntriesToQStringList(filteredPaths));
}
void removeUnusedEntries(const std::vector<WatcherEntry> &entries,
const std::vector<uint> &ids)
{
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
removeFromWatchedEntries(oldEntries);
auto filteredPaths = filterNotWatchedPaths(oldEntries);
if (!filteredPaths.empty())
m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
}
FileSystemWatcher &fileSystemWatcher()
{
return m_fileSystemWatcher;
}
QStringList convertWatcherEntriesToQStringList(
const std::vector<WatcherEntry> &watcherEntries)
{
QStringList paths;
paths.reserve(int(watcherEntries.size()));
std::transform(watcherEntries.begin(),
watcherEntries.end(),
std::back_inserter(paths),
[&] (const WatcherEntry &entry) { return m_pathCache.string(entry.path); });
return paths;
}
template <typename Compare>
std::vector<WatcherEntry> notWatchedEntries(const std::vector<WatcherEntry> &entries,
Compare compare) const
{
std::vector<WatcherEntry> notWatchedEntries;
notWatchedEntries.reserve(entries.size());
std::set_difference(entries.begin(),
entries.end(),
m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
std::back_inserter(notWatchedEntries),
compare);
return notWatchedEntries;
}
std::vector<WatcherEntry> notWatchedEntries(const std::vector<WatcherEntry> &entries) const
{
return notWatchedEntries(entries, std::less<WatcherEntry>());
}
std::vector<WatcherEntry> notWatchedPaths(const std::vector<WatcherEntry> &entries) const
{
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
return first.path < second.path;
};
return notWatchedEntries(entries, compare);
}
template <typename Compare>
std::vector<WatcherEntry> notAnymoreWatchedEntries(
const std::vector<WatcherEntry> &newEntries,
Compare compare) const
{
std::vector<WatcherEntry> notAnymoreWatchedEntries;
notAnymoreWatchedEntries.reserve(m_watchedEntries.size());
std::set_difference(m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
newEntries.begin(),
newEntries.end(),
std::back_inserter(notAnymoreWatchedEntries),
compare);
return notAnymoreWatchedEntries;
}
std::vector<WatcherEntry> notAnymoreWatchedEntriesWithIds(
const std::vector<WatcherEntry> &newEntries,
const std::vector<uint> &ids) const
{
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
auto newEnd = std::remove_if(oldEntries.begin(),
oldEntries.end(),
[&] (WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
});
oldEntries.erase(newEnd, oldEntries.end());
return oldEntries;
}
void mergeToWatchedEntries(const std::vector<WatcherEntry> &newEntries)
{
std::vector<WatcherEntry> newWatchedEntries;
newWatchedEntries.reserve(m_watchedEntries.size() + newEntries.size());
std::merge(m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
newEntries.begin(),
newEntries.end(),
std::back_inserter(newWatchedEntries));
m_watchedEntries = std::move(newWatchedEntries);
}
static
std::vector<WatcherEntry> uniquePaths(const std::vector<WatcherEntry> &pathEntries)
{
std::vector<WatcherEntry> uniqueEntries;
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
return first.path == second.path;
};
std::unique_copy(pathEntries.begin(),
pathEntries.end(),
std::back_inserter(uniqueEntries),
compare);
return uniqueEntries;
}
std::vector<WatcherEntry> filterNotWatchedPaths(const std::vector<WatcherEntry> &entries)
{
return notWatchedPaths(uniquePaths(entries));
}
const std::vector<WatcherEntry> &watchedEntries() const
{
return m_watchedEntries;
}
std::vector<WatcherEntry> removeIdsFromWatchedEntries(const std::vector<uint> &ids)
{
auto keep = [&] (const WatcherEntry &entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
};
auto found = std::stable_partition(m_watchedEntries.begin(),
m_watchedEntries.end(),
keep);
std::vector<WatcherEntry> removedEntries(found, m_watchedEntries.end());
m_watchedEntries.erase(found, m_watchedEntries.end());
return removedEntries;
}
void removeFromWatchedEntries(const std::vector<WatcherEntry> &oldEntries)
{
std::vector<WatcherEntry> newWatchedEntries;
newWatchedEntries.reserve(m_watchedEntries.size() - oldEntries.size());
std::set_difference(m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
oldEntries.begin(),
oldEntries.end(),
std::back_inserter(newWatchedEntries));
m_watchedEntries = newWatchedEntries;
}
void addChangedPathForFilePath(const QString &filePath)
{
uint pathId = m_pathCache.stringId(Utils::SmallString(filePath));
auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
Utils::SmallStringVector changedIds;
std::transform(range.first,
range.second,
std::back_inserter(changedIds),
[&] (const WatcherEntry &entry) {
return m_idCache.string(entry.id);
});
std::sort(changedIds.begin(), changedIds.end());
if (m_notifier)
m_notifier->pathsWithIdsChanged(changedIds);
}
StringCache<Utils::SmallString> &pathCache()
{
return m_pathCache;
}
StringCache<Utils::SmallString> &idCache()
{
return m_idCache;
}
private:
StringCache<Utils::SmallString> m_idCache;
std::vector<WatcherEntry> m_watchedEntries;
FileSystemWatcher m_fileSystemWatcher;
StringCache<Utils::SmallString> &m_pathCache;
ClangPathWatcherNotifier *m_notifier;
};
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,35 @@
/****************************************************************************
**
** 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 "clangpathwatcherinterface.h"
namespace ClangBackEnd {
ClangPathWatcherInterface::~ClangPathWatcherInterface()
{
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "idpaths.h"
#include <utils/smallstringvector.h>
namespace ClangBackEnd {
class ClangPathWatcherNotifier;
class ClangPathWatcherInterface
{
public:
virtual ~ClangPathWatcherInterface();
virtual void updateIdPaths(const std::vector<IdPaths> &idPaths) = 0;
virtual void removeIds(const Utils::SmallStringVector &ids) = 0;
virtual void setNotifier(ClangPathWatcherNotifier *notifier) = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,35 @@
/****************************************************************************
**
** 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 "clangpathwatchernotifier.h"
namespace ClangBackEnd {
ClangPathWatcherNotifier::~ClangPathWatcherNotifier()
{
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,40 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <utils/smallstringvector.h>
namespace ClangBackEnd {
class ClangPathWatcherNotifier
{
public:
virtual ~ClangPathWatcherNotifier();
virtual void pathsWithIdsChanged(const Utils::SmallStringVector &ids) = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,32 @@
INCLUDEPATH += $$PWD
SOURCES += \
$$PWD/includecollector.cpp \
$$PWD/pchmanagerserver.cpp \
$$PWD/pchcreator.cpp \
$$PWD/clangpathwatcher.cpp \
$$PWD/projectparts.cpp \
$$PWD/idpaths.cpp \
$$PWD/pchcreatorinterface.cpp \
$$PWD/clangpathwatcherinterface.cpp \
$$PWD/projectpartsinterface.cpp \
$$PWD/clangpathwatchernotifier.cpp
HEADERS += \
$$PWD/clangpchmanagerbackend_global.h \
$$PWD/includecollector.h \
$$PWD/collectincludestoolaction.h \
$$PWD/collectincludesaction.h \
$$PWD/collectincludespreprocessorcallbacks.h \
$$PWD/pchmanagerserver.h \
$$PWD/pchcreator.h \
$$PWD/pchnotcreatederror.h \
$$PWD/environment.h \
$$PWD/clangpathwatcher.h \
$$PWD/projectparts.h \
$$PWD/stringcache.h \
$$PWD/idpaths.h \
$$PWD/pchcreatorinterface.h \
$$PWD/clangpathwatcherinterface.h \
$$PWD/projectpartsinterface.h \
$$PWD/clangpathwatchernotifier.h

View File

@@ -0,0 +1,52 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#ifdef UNIT_TESTS
#define unitttest_public public
#else
#define unitttest_public private
#endif
namespace llvm {
template <typename T, unsigned N>
class SmallVector;
}
using uint = unsigned int;
namespace Utils {
template <uint Size>
class BasicSmallString;
using SmallString = BasicSmallString<31>;
using PathString = BasicSmallString<191>;
}
namespace ClangBackEnd {
using USRName = llvm::SmallVector<char, 128>;
}

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "stringcache.h"
#include <collectincludespreprocessorcallbacks.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/Preprocessor.h>
namespace ClangBackEnd {
class CollectIncludesAction final : public clang::PreprocessOnlyAction
{
public:
CollectIncludesAction(std::vector<uint> &includeIds,
StringCache<Utils::SmallString> &filePathCache,
const std::vector<uint> &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs)
: m_includeIds(includeIds),
m_filePathCache(filePathCache),
m_excludedIncludeUID(excludedIncludeUID),
m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
{
}
bool BeginSourceFileAction(clang::CompilerInstance &compilerInstance,
llvm::StringRef filename) override
{
if (clang::PreprocessOnlyAction::BeginSourceFileAction(compilerInstance, filename)) {
auto &preprocessor = compilerInstance.getPreprocessor();
auto &headerSearch = preprocessor.getHeaderSearchInfo();
auto macroPreprocessorCallbacks = new CollectIncludesPreprocessorCallbacks(headerSearch,
m_includeIds,
m_filePathCache,
m_excludedIncludeUID,
m_alreadyIncludedFileUIDs);
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
return true;
}
return false;
}
void EndSourceFileAction() override
{
clang::PreprocessOnlyAction::EndSourceFileAction();
}
private:
std::vector<uint> &m_includeIds;
StringCache<Utils::SmallString> &m_filePathCache;
const std::vector<uint> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "stringcache.h"
#include <clang/Basic/SourceManager.h>
#include <clang/Lex/MacroInfo.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/PPCallbacks.h>
#include <clang/Lex/Preprocessor.h>
#include <utils/smallstringvector.h>
#include <algorithm>
namespace ClangBackEnd {
class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks
{
public:
CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch,
std::vector<uint> &includeIds,
StringCache<Utils::SmallString> &filePathCache,
const std::vector<uint> &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs)
: m_headerSearch(headerSearch),
m_includeIds(includeIds),
m_filePathCache(filePathCache),
m_excludedIncludeUID(excludedIncludeUID),
m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
{}
void InclusionDirective(clang::SourceLocation /*hashLocation*/,
const clang::Token &/*includeToken*/,
llvm::StringRef fileName,
bool /*isAngled*/,
clang::CharSourceRange /*fileNameRange*/,
const clang::FileEntry *file,
llvm::StringRef /*searchPath*/,
llvm::StringRef /*relativePath*/,
const clang::Module */*imported*/) override
{
auto fileUID = file->getUID();
flagIncludeAlreadyRead(file);
if (isNotInExcludedIncludeUID(fileUID)) {
auto notAlreadyIncluded = isNotAlreadyIncluded(fileUID);
if (notAlreadyIncluded.first) {
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
uint includeId = m_filePathCache.stringId({fileName.data(), fileName.size()});
m_includeIds.emplace_back(includeId);
}
}
}
bool isNotInExcludedIncludeUID(uint uid) const
{
return !std::binary_search(m_excludedIncludeUID.begin(),
m_excludedIncludeUID.end(),
uid);
}
std::pair<bool, std::vector<uint>::iterator> isNotAlreadyIncluded(uint uid) const
{
auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(),
m_alreadyIncludedFileUIDs.end(),
uid);
return {range.first == range.second, range.first};
}
void flagIncludeAlreadyRead(const clang::FileEntry *file)
{
auto &headerFileInfo = m_headerSearch.getFileInfo(file);
headerFileInfo.isImport = true;
++headerFileInfo.NumIncludes;
}
private:
clang::HeaderSearch &m_headerSearch;
std::vector<uint> &m_includeIds;
StringCache<Utils::SmallString> &m_filePathCache;
const std::vector<uint> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "stringcache.h"
#include "collectincludesaction.h"
#include <clang/Tooling/Tooling.h>
namespace ClangBackEnd {
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
{
public:
CollectIncludesToolAction(std::vector<uint> &includeIds,
StringCache<Utils::SmallString> &filePathCache,
const std::vector<uint> &excludedIncludeUIDs)
: m_includeIds(includeIds),
m_filePathCache(filePathCache),
m_excludedIncludeUIDs(excludedIncludeUIDs)
{}
clang::FrontendAction *create()
{
return new CollectIncludesAction(m_includeIds,
m_filePathCache,
m_excludedIncludeUIDs,
m_alreadyIncludedFileUIDs);
}
private:
std::vector<uint> m_alreadyIncludedFileUIDs;
std::vector<uint> &m_includeIds;
StringCache<Utils::SmallString> &m_filePathCache;
const std::vector<uint> &m_excludedIncludeUIDs;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,39 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <QString>
namespace ClangBackEnd {
class Environment
{
public:
virtual QString pchBuildDirectory() const = 0;
virtual QString clangCompilerPath() const = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,41 @@
/****************************************************************************
**
** 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 "idpaths.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd {
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths)
{
out << "("
<< idPaths.id << ", "
<< idPaths.paths << ")";
return out;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <utils/smallstring.h>
#include <iosfwd>
namespace ClangBackEnd {
class IdPaths
{
public:
Utils::SmallString id;
std::vector<uint> paths;
friend bool operator==(const IdPaths &first, const IdPaths &second)
{
return first.id == second.id && first.paths == second.paths;
}
};
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** 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 "includecollector.h"
#include "collectincludestoolaction.h"
#include <utils/smallstring.h>
namespace ClangBackEnd {
IncludeCollector::IncludeCollector(StringCache<Utils::SmallString> &filePathCache)
: m_filePathCache(filePathCache)
{
}
void IncludeCollector::collectIncludes()
{
clang::tooling::ClangTool tool = createTool();
auto excludedIncludeFileUIDs = generateExcludedIncludeFileUIDs(tool.getFiles());
auto action = std::unique_ptr<CollectIncludesToolAction>(
new CollectIncludesToolAction(m_includeIds, m_filePathCache, excludedIncludeFileUIDs));
tool.run(action.get());
}
void IncludeCollector::setExcludedIncludes(Utils::SmallStringVector &&excludedIncludes)
{
this->m_excludedIncludes = std::move(excludedIncludes);
}
std::vector<uint> IncludeCollector::takeIncludeIds()
{
std::sort(m_includeIds.begin(), m_includeIds.end());
return std::move(m_includeIds);
}
std::vector<uint> IncludeCollector::generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
{
std::vector<uint> fileUIDs;
fileUIDs.reserve(m_excludedIncludes.size());
auto generateUID = [&] (const Utils::SmallString &filePath) {
return fileManager.getFile({filePath.data(), filePath.size()})->getUID();
};
std::transform(m_excludedIncludes.begin(),
m_excludedIncludes.end(),
std::back_inserter(fileUIDs),
generateUID);
std::sort(fileUIDs.begin(), fileUIDs.end());
return fileUIDs;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,55 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "stringcache.h"
#include <clangtool.h>
namespace ClangBackEnd {
class IncludeCollector : public ClangTool
{
public:
IncludeCollector(StringCache<Utils::SmallString> &filePathCache);
void collectIncludes();
void setExcludedIncludes(Utils::SmallStringVector &&excludedIncludes);
std::vector<uint> takeIncludeIds();
private:
std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const;
private:
Utils::SmallStringVector m_excludedIncludes;
std::vector<uint> m_includeIds;
Utils::SmallStringVector m_directories;
StringCache<Utils::SmallString> &m_filePathCache;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,518 @@
/****************************************************************************
**
** 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 "pchcreator.h"
#include "environment.h"
#include "includecollector.h"
#include "pchnotcreatederror.h"
#include <projectpartpch.h>
#include <QCryptographicHash>
#include <QFile>
#include <QProcess>
namespace ClangBackEnd {
PchCreator::PchCreator(Environment &environment, StringCache<Utils::SmallString> &filePathCache)
: m_environment(environment),
m_filePathCache(filePathCache)
{
}
PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment,
StringCache<Utils::SmallString> &filePathCache)
: m_projectParts(std::move(projectsParts)),
m_environment(environment),
m_filePathCache(filePathCache)
{
}
namespace {
template <typename Source,
typename Target>
void append(Target &target, const Source &source)
{
Source clonedSource = source.clone();
target.reserve(target.size() + source.size());
std::move(clonedSource.begin(),
clonedSource.end(),
std::back_inserter(target));
}
template <typename Source,
typename Target>
void append(Target &target, Source &source)
{
target.reserve(target.size() + source.size());
std::move(source.begin(),
source.end(),
std::back_inserter(target));
}
template <typename GetterFunction>
std::size_t globalCount(const V2::ProjectPartContainers &projectsParts,
GetterFunction getterFunction)
{
auto sizeFunction = [&] (std::size_t size, const V2::ProjectPartContainer &projectContainer) {
return size + getterFunction(projectContainer).size();
};
return std::accumulate(projectsParts.begin(),
projectsParts.end(),
std::size_t(0),
sizeFunction);
}
template <typename GetterFunction>
void generateGlobal(Utils::SmallStringVector &entries,
const V2::ProjectPartContainers &projectsParts,
GetterFunction getterFunction)
{
entries.reserve(entries.size() + globalCount(projectsParts, getterFunction));
for (const V2::ProjectPartContainer &projectPart : projectsParts) {
const auto &projectPartPaths = getterFunction(projectPart);
append(entries, projectPartPaths);
};
}
template <typename GetterFunction>
Utils::SmallStringVector generateGlobal(
const V2::ProjectPartContainers &projectsParts,
GetterFunction getterFunction)
{
Utils::SmallStringVector entries;
generateGlobal(entries, projectsParts, getterFunction);
return entries;
}
}
Utils::SmallStringVector PchCreator::generateGlobalHeaderPaths() const
{
auto includeFunction = [] (const V2::ProjectPartContainer &projectPart)
-> const Utils::SmallStringVector & {
return projectPart.headerPaths();
};
return generateGlobal(m_projectParts, includeFunction);
}
Utils::SmallStringVector PchCreator::generateGlobalSourcePaths() const
{
auto sourceFunction = [] (const V2::ProjectPartContainer &projectPart)
-> const Utils::SmallStringVector & {
return projectPart.sourcePaths();
};
return generateGlobal(m_projectParts, sourceFunction);
}
Utils::SmallStringVector PchCreator::generateGlobalHeaderAndSourcePaths() const
{
const auto &sourcePaths = generateGlobalSourcePaths();
auto includePaths = generateGlobalHeaderPaths();
append(includePaths, sourcePaths);
return includePaths;
}
Utils::SmallStringVector PchCreator::generateGlobalArguments() const
{
Utils::SmallStringVector arguments;
auto argumentFunction = [] (const V2::ProjectPartContainer &projectPart)
-> const Utils::SmallStringVector & {
return projectPart.arguments();
};
generateGlobal(arguments, m_projectParts, argumentFunction);
return arguments;
}
Utils::SmallStringVector PchCreator::generateGlobalCommandLine() const
{
Utils::SmallStringVector commandLine;
commandLine.emplace_back(m_environment.clangCompilerPath());
auto argumentFunction = [] (const V2::ProjectPartContainer &projectPart)
-> const Utils::SmallStringVector & {
return projectPart.arguments();
};
generateGlobal(commandLine, m_projectParts, argumentFunction);
return commandLine;
}
Utils::SmallStringVector PchCreator::generateGlobalPchCompilerArguments() const
{
Utils::SmallStringVector arguments;
arguments.reserve(5);
arguments.emplace_back("-x");
arguments.emplace_back("c++-header");
arguments.emplace_back("-Xclang");
arguments.emplace_back("-emit-pch");
arguments.emplace_back("-o");
arguments.emplace_back(generateGlobalPchFilePath());
arguments.emplace_back(generateGlobalPchHeaderFilePath());
return arguments;
}
Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() const
{
auto compilerArguments = generateGlobalArguments();
const auto pchArguments = generateGlobalPchCompilerArguments();
append(compilerArguments, pchArguments);
return compilerArguments;
}
std::vector<uint> PchCreator::generateGlobalPchIncludeIds() const
{
IncludeCollector collector(m_filePathCache);
collector.setExcludedIncludes(generateGlobalHeaderPaths());
collector.addFiles(generateGlobalHeaderAndSourcePaths(), generateGlobalCommandLine());
collector.collectIncludes();
return collector.takeIncludeIds();
}
namespace {
std::size_t contentSize(const std::vector<Utils::SmallString> &includes)
{
auto countIncludeSize = [] (std::size_t size, const Utils::SmallString &include) {
return size + include.size();
};
return std::accumulate(includes.begin(), includes.end(), std::size_t(0), countIncludeSize);
}
}
Utils::SmallString PchCreator::generatePchIncludeFileContent(
const std::vector<uint> &includeIds) const
{
Utils::SmallString fileContent;
const std::size_t lineTemplateSize = 12;
auto includes = m_filePathCache.strings(includeIds);
fileContent.reserve(includes.size() * lineTemplateSize + contentSize(includes));
for (const Utils::SmallString &include : includes) {
fileContent += "#include <";
fileContent += include;
fileContent += ">\n";
}
return fileContent;
}
Utils::SmallString PchCreator::generateGlobalPchHeaderFileContent() const
{
return generatePchIncludeFileContent(generateGlobalPchIncludeIds());
}
std::unique_ptr<QFile> PchCreator::generateGlobalPchHeaderFile()
{
return generatePchHeaderFile(generateGlobalPchHeaderFilePath(),
generateGlobalPchHeaderFileContent());
}
void PchCreator::generatePch(const Utils::SmallStringVector &clangCompilerArguments)
{
QProcess process;
process.setProcessChannelMode(QProcess::ForwardedChannels);
process.start(m_environment.clangCompilerPath(),
convertToQStringList(clangCompilerArguments));
process.waitForFinished(100000);
checkIfProcessHasError(process);
}
void PchCreator::generateGlobalPch()
{
generateGlobalPchHeaderFile();
generatePch(generateGlobalClangCompilerArguments());
}
QStringList PchCreator::convertToQStringList(const Utils::SmallStringVector &compilerArguments)
{
QStringList qStringList;
append(qStringList, compilerArguments);
return qStringList;
}
namespace {
void hashProjectPart(QCryptographicHash &hash, const V2::ProjectPartContainer &projectPart)
{
const auto &projectPartId = projectPart.projectPartId();
hash.addData(projectPartId.data(), projectPartId.size());
for (const auto &argument : projectPart.arguments())
hash.addData(argument.data(), argument.size());
}
}
QByteArray PchCreator::globalProjectHash() const
{
QCryptographicHash hash(QCryptographicHash::Sha1);
for (const auto &projectPart : m_projectParts)
hashProjectPart(hash, projectPart);
auto result = hash.result();
return result.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
}
void PchCreator::checkIfProcessHasError(const QProcess &process)
{
if (process.exitCode()) {
const std::string errorString = process.errorString().toStdString();
throw PchNotCreatedError(errorString);
}
}
Utils::SmallString PchCreator::generateGlobalPchFilePathWithoutExtension() const
{
QByteArray fileName = m_environment.pchBuildDirectory().toUtf8();
fileName += '/';
fileName += globalProjectHash();
return Utils::SmallString::fromQByteArray(fileName);
}
Utils::SmallString PchCreator::generateGlobalPchHeaderFilePath() const
{
Utils::SmallString filePath = generateGlobalPchFilePathWithoutExtension();
filePath += ".h";
return filePath;
}
Utils::SmallString PchCreator::generateGlobalPchFilePath() const
{
Utils::SmallString filePath = generateGlobalPchFilePathWithoutExtension();
filePath += ".pch";
return filePath;
}
Utils::SmallStringVector PchCreator::generateProjectPartCommandLine(
const V2::ProjectPartContainer &projectPart) const
{
const Utils::SmallStringVector &arguments = projectPart.arguments();
Utils::SmallStringVector commandLine;
commandLine.reserve(arguments.size() + 1);
commandLine.emplace_back(m_environment.clangCompilerPath());
append(commandLine , arguments);
return commandLine;
}
Utils::SmallString PchCreator::generateProjectPartPchFilePathWithoutExtension(
const V2::ProjectPartContainer &projectPart) const
{
QByteArray fileName = m_environment.pchBuildDirectory().toUtf8();
fileName += '/';
fileName += projectPartHash(projectPart);
return Utils::SmallString::fromQByteArray(fileName);
}
Utils::SmallStringVector PchCreator::generateProjectPartHeaderAndSourcePaths(
const V2::ProjectPartContainer &projectPart)
{
Utils::SmallStringVector includeAndSources;
includeAndSources.reserve(projectPart.headerPaths().size() + projectPart.sourcePaths().size());
append(includeAndSources, projectPart.headerPaths());
append(includeAndSources, projectPart.sourcePaths());
return includeAndSources;
}
std::vector<uint> PchCreator::generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const
{
IncludeCollector collector(m_filePathCache);
collector.setExcludedIncludes(projectPart.headerPaths().clone());
collector.addFiles(generateProjectPartHeaderAndSourcePaths(projectPart),
generateProjectPartCommandLine(projectPart));
collector.collectIncludes();
return collector.takeIncludeIds();
}
Utils::SmallString PchCreator::generateProjectPathPchHeaderFilePath(
const V2::ProjectPartContainer &projectPart) const
{
Utils::SmallString filePath = generateProjectPartPchFilePathWithoutExtension(projectPart);
filePath += ".h";
return filePath;
}
Utils::SmallString PchCreator::generateProjectPartPchFilePath(
const V2::ProjectPartContainer &projectPart) const
{
Utils::SmallString filePath = generateProjectPartPchFilePathWithoutExtension(projectPart);
filePath += ".pch";
return filePath;
}
Utils::SmallStringVector PchCreator::generateProjectPartPchCompilerArguments(
const V2::ProjectPartContainer &projectPart) const
{
Utils::SmallStringVector arguments;
arguments.reserve(5);
arguments.emplace_back("-x");
arguments.emplace_back("c++-header");
// arguments.emplace_back("-Xclang");
// arguments.emplace_back("-include-pch");
// arguments.emplace_back("-Xclang");
// arguments.emplace_back(generateGlobalPchFilePath());
arguments.emplace_back("-Xclang");
arguments.emplace_back("-emit-pch");
arguments.emplace_back("-o");
arguments.emplace_back(generateProjectPartPchFilePath(projectPart));
arguments.emplace_back(generateProjectPathPchHeaderFilePath(projectPart));
return arguments;
}
Utils::SmallStringVector PchCreator::generateProjectPartClangCompilerArguments(
const V2::ProjectPartContainer &projectPart) const
{
Utils::SmallStringVector compilerArguments = projectPart.arguments().clone();
const auto pchArguments = generateProjectPartPchCompilerArguments(projectPart);
append(compilerArguments, pchArguments);
return compilerArguments;
}
std::pair<ProjectPartPch, IdPaths> PchCreator::generateProjectPartPch(
const V2::ProjectPartContainer &projectPart)
{
auto includes = generateProjectPartPchIncludes(projectPart);
auto content = generatePchIncludeFileContent(includes);
auto pchIncludeFilePath = generateProjectPathPchHeaderFilePath(projectPart);
auto pchFilePath = generateProjectPartPchFilePath(projectPart);
auto file = generatePchHeaderFile(pchIncludeFilePath, content);
generatePch(generateProjectPartClangCompilerArguments(projectPart));
return {{projectPart.projectPartId().clone(), std::move(pchFilePath)},
{projectPart.projectPartId().clone(), includes}};
}
void PchCreator::generatePchs()
{
for (const V2::ProjectPartContainer &projectPart : m_projectParts) {
auto projectInfos = generateProjectPartPch(projectPart);
m_projectPartPchs.push_back(projectInfos.first);
m_projectsIncludeIds.push_back(projectInfos.second);
}
}
void PchCreator::generatePchs(V2::ProjectPartContainers &&projectsParts)
{
m_projectParts = std::move(projectsParts);
generatePchs();
}
std::vector<ProjectPartPch> PchCreator::takeProjectPartPchs()
{
return std::move(m_projectPartPchs);
}
std::vector<IdPaths> PchCreator::takeProjectsIncludes()
{
return std::move(m_projectsIncludeIds);
}
std::unique_ptr<QFile> PchCreator::generatePchHeaderFile(
const Utils::SmallString &filePath,
const Utils::SmallString &content)
{
std::unique_ptr<QFile> precompiledIncludeFile(new QFile(filePath));
precompiledIncludeFile->open(QIODevice::WriteOnly);
precompiledIncludeFile->write(content.data(), content.size());
precompiledIncludeFile->close();
return precompiledIncludeFile;
}
QByteArray PchCreator::projectPartHash(const V2::ProjectPartContainer &projectPart)
{
QCryptographicHash hash(QCryptographicHash::Sha1);
hashProjectPart(hash, projectPart);
auto result = hash.result();
return result.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "pchcreatorinterface.h"
#include "stringcache.h"
#include "idpaths.h"
#include <projectpartpch.h>
#include <projectpartcontainerv2.h>
#include <vector>
QT_FORWARD_DECLARE_CLASS(QFile)
QT_FORWARD_DECLARE_CLASS(QCryptographicHash)
QT_FORWARD_DECLARE_CLASS(QProcess)
namespace ClangBackEnd {
class Environment;
class PchCreator final : public PchCreatorInterface
{
public:
PchCreator(Environment &environment,
StringCache<Utils::SmallString> &filePathCache);
PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment,
StringCache<Utils::SmallString> &filePathCache);
void generatePchs(V2::ProjectPartContainers &&projectsParts) override;
std::vector<ProjectPartPch> takeProjectPartPchs() override;
std::vector<IdPaths> takeProjectsIncludes() override;
unitttest_public:
Utils::SmallStringVector generateGlobalHeaderPaths() const;
Utils::SmallStringVector generateGlobalSourcePaths() const;
Utils::SmallStringVector generateGlobalHeaderAndSourcePaths() const;
Utils::SmallStringVector generateGlobalArguments() const;
Utils::SmallStringVector generateGlobalCommandLine() const;
Utils::SmallStringVector generateGlobalPchCompilerArguments() const;
Utils::SmallStringVector generateGlobalClangCompilerArguments() const;
std::vector<uint> generateGlobalPchIncludeIds() const;
Utils::SmallString generatePchIncludeFileContent(const std::vector<uint> &includeIds) const;
Utils::SmallString generateGlobalPchHeaderFileContent() const;
std::unique_ptr<QFile> generateGlobalPchHeaderFile();
void generatePch(const Utils::SmallStringVector &commandLineArguments);
void generateGlobalPch();
Utils::SmallString globalPchContent() const;
static QStringList convertToQStringList(const Utils::SmallStringVector &convertToQStringList);
Utils::SmallString generateGlobalPchFilePathWithoutExtension() const;
Utils::SmallString generateGlobalPchHeaderFilePath() const;
Utils::SmallString generateGlobalPchFilePath() const;
Utils::SmallStringVector generateProjectPartCommandLine(
const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPartPchFilePathWithoutExtension(
const V2::ProjectPartContainer &projectPart) const;
static Utils::SmallStringVector generateProjectPartHeaderAndSourcePaths(
const V2::ProjectPartContainer &projectPart);
std::vector<uint> generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPathPchHeaderFilePath(
const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPartPchFilePath(
const V2::ProjectPartContainer &projectPart) const;
Utils::SmallStringVector generateProjectPartPchCompilerArguments(
const V2::ProjectPartContainer &projectPart) const;
Utils::SmallStringVector generateProjectPartClangCompilerArguments(
const V2::ProjectPartContainer &projectPart) const;
std::pair<ProjectPartPch, IdPaths> generateProjectPartPch(
const V2::ProjectPartContainer &projectPart);
static std::unique_ptr<QFile> generatePchHeaderFile(
const Utils::SmallString &filePath,
const Utils::SmallString &content);
void generatePchs();
private:
static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart);
QByteArray globalProjectHash() const;
static void checkIfProcessHasError(const QProcess &process);
private:
V2::ProjectPartContainers m_projectParts;
std::vector<ProjectPartPch> m_projectPartPchs;
std::vector<IdPaths> m_projectsIncludeIds;
Environment &m_environment;
StringCache<Utils::SmallString> &m_filePathCache;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,35 @@
/****************************************************************************
**
** 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 "pchcreatorinterface.h"
namespace ClangBackEnd {
PchCreatorInterface::~PchCreatorInterface()
{
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "idpaths.h"
#include "projectpartpch.h"
#include <projectpartcontainerv2.h>
namespace ClangBackEnd {
class PchCreatorInterface
{
public:
virtual ~PchCreatorInterface();
virtual void generatePchs(V2::ProjectPartContainers &&projectsParts) = 0;
virtual std::vector<ProjectPartPch> takeProjectPartPchs() = 0;
virtual std::vector<IdPaths> takeProjectsIncludes() = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** 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 "pchmanagerserver.h"
#include <pchmanagerclientinterface.h>
#include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h>
#include <utils/smallstring.h>
#include <QApplication>
namespace ClangBackEnd {
PchManagerServer::PchManagerServer(StringCache<Utils::SmallString> &filePathCache,
ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts)
: m_filePathCache(filePathCache),
m_fileSystemWatcher(fileSystemWatcher),
m_pchCreator(pchCreator),
m_projectParts(projectParts)
{
m_fileSystemWatcher.setNotifier(this);
}
void PchManagerServer::end()
{
QCoreApplication::exit();
}
void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
{
m_pchCreator.generatePchs(m_projectParts.update(message.takeProjectsParts()));
client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage(m_pchCreator.takeProjectPartPchs()));
m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
}
void PchManagerServer::removePchProjectParts(RemovePchProjectPartsMessage &&message)
{
m_fileSystemWatcher.removeIds(message.projectsPartIds());
m_projectParts.remove(message.projectsPartIds());
}
void PchManagerServer::pathsWithIdsChanged(const Utils::SmallStringVector &ids)
{
m_pchCreator.generatePchs(m_projectParts.projects(ids));
client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage(m_pchCreator.takeProjectPartPchs()));
m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangpathwatcherinterface.h"
#include "clangpathwatchernotifier.h"
#include "pchcreatorinterface.h"
#include "pchmanagerserverinterface.h"
#include "projectpartsinterface.h"
#include "stringcache.h"
namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage;
class PchManagerServer : public PchManagerServerInterface, public ClangPathWatcherNotifier
{
public:
PchManagerServer(StringCache<Utils::SmallString> &filePathCache,
ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts);
void end() override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
private:
StringCache<Utils::SmallString> &m_filePathCache;
ClangPathWatcherInterface &m_fileSystemWatcher;
PchCreatorInterface &m_pchCreator;
ProjectPartsInterface &m_projectParts;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,36 @@
/****************************************************************************
**
** 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 <stdexcept>
namespace ClangBackEnd {
class PchNotCreatedError : public std::runtime_error
{
using std::runtime_error::runtime_error;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** 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 "projectparts.h"
#include <projectpartcontainerv2.h>
#include <algorithm>
namespace ClangBackEnd {
inline namespace Pch {
V2::ProjectPartContainers ProjectParts::update(V2::ProjectPartContainers &&projectsParts)
{
auto uniqueProjectParts = ProjectParts::uniqueProjectParts(std::move(projectsParts));
auto updatedProjectPartContainers = newProjectParts(std::move(uniqueProjectParts));
mergeProjectParts(updatedProjectPartContainers);
return updatedProjectPartContainers;
}
void ProjectParts::remove(const Utils::SmallStringVector &ids)
{
auto shouldRemove = [&] (const V2::ProjectPartContainer &projectPart) {
return std::find(ids.begin(), ids.end(), projectPart.projectPartId()) != ids.end();
};
auto newEnd = std::remove_if(m_projectParts.begin(), m_projectParts.end(), shouldRemove);
m_projectParts.erase(newEnd, m_projectParts.end());
}
V2::ProjectPartContainers ProjectParts::projects(const Utils::SmallStringVector &projectPartIds) const
{
V2::ProjectPartContainers projectPartsWithIds;
std::copy_if(m_projectParts.begin(),
m_projectParts.end(),
std::back_inserter(projectPartsWithIds),
[&] (const V2::ProjectPartContainer &projectPart) {
return std::binary_search(projectPartIds.begin(), projectPartIds.end(), projectPart.projectPartId());
});
return projectPartsWithIds;
}
V2::ProjectPartContainers ProjectParts::uniqueProjectParts(V2::ProjectPartContainers &&projectsParts)
{
std::sort(projectsParts.begin(), projectsParts.end());
auto newEnd = std::unique(projectsParts.begin(), projectsParts.end());
projectsParts.erase(newEnd, projectsParts.end());
return std::move(projectsParts);
}
V2::ProjectPartContainers ProjectParts::newProjectParts(V2::ProjectPartContainers &&projectsParts) const
{
V2::ProjectPartContainers updatedProjectPartContainers;
updatedProjectPartContainers.reserve(projectsParts.size());
std::set_difference(std::make_move_iterator(projectsParts.begin()),
std::make_move_iterator(projectsParts.end()),
m_projectParts.begin(),
m_projectParts.end(),
std::back_inserter(updatedProjectPartContainers));
return updatedProjectPartContainers;
}
void ProjectParts::mergeProjectParts(const V2::ProjectPartContainers &projectsParts)
{
V2::ProjectPartContainers newProjectParts;
newProjectParts.reserve(m_projectParts.size() + projectsParts.size());
auto compare = [] (const V2::ProjectPartContainer &first, const V2::ProjectPartContainer &second) {
return first.projectPartId() < second.projectPartId();
};
std::set_union(projectsParts.begin(),
projectsParts.end(),
m_projectParts.begin(),
m_projectParts.end(),
std::back_inserter(newProjectParts),
compare);
m_projectParts = newProjectParts;
}
const V2::ProjectPartContainers &ProjectParts::projectParts() const
{
return m_projectParts;
}
} // namespace Pch
} // namespace ClangBackEnd

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangpchmanagerbackend_global.h"
#include <projectpartsinterface.h>
#include <utils/smallstringvector.h>
namespace ClangBackEnd {
inline namespace Pch {
class ProjectParts final : public ProjectPartsInterface
{
public:
V2::ProjectPartContainers update(V2::ProjectPartContainers &&projectsParts) override;
void remove(const Utils::SmallStringVector &projectPartIds) override;
V2::ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const override;
unitttest_public:
static V2::ProjectPartContainers uniqueProjectParts(V2::ProjectPartContainers &&projectsParts);
V2::ProjectPartContainers newProjectParts(V2::ProjectPartContainers &&projectsParts) const;
void mergeProjectParts(const V2::ProjectPartContainers &projectsParts);
const V2::ProjectPartContainers &projectParts() const;
private:
V2::ProjectPartContainers m_projectParts;
};
} // namespace Pch
} // 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 "projectpartsinterface.h"
namespace ClangBackEnd {
ProjectPartsInterface::~ProjectPartsInterface()
{
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <projectpartcontainerv2.h>
namespace ClangBackEnd {
class ProjectPartsInterface
{
public:
virtual ~ProjectPartsInterface();
virtual V2::ProjectPartContainers update(V2::ProjectPartContainers &&projectsParts) = 0;
virtual void remove(const Utils::SmallStringVector &projectPartIds) = 0;
virtual V2::ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const = 0;
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,160 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "clangpchmanagerbackend_global.h"
#include <utils/smallstringview.h>
#include <algorithm>
#include <vector>
namespace ClangBackEnd {
template <typename StringType>
class StringCache
{
class StringCacheEntry
{
public:
StringCacheEntry(StringType &&string, uint id)
: string(std::move(string)),
id(id)
{}
friend bool operator<(const StringCacheEntry &entry, Utils::SmallStringView stringView)
{
return entry.string < stringView;
}
friend bool operator<(Utils::SmallStringView stringView, const StringCacheEntry &entry)
{
return stringView < entry.string;
}
StringType string;
uint id;
};
using StringCacheEntries = std::vector<StringCacheEntry>;
using const_iterator = typename StringCacheEntries::const_iterator;
class Found
{
public:
typename StringCacheEntries::const_iterator iterator;
bool wasFound;
};
public:
StringCache()
{
m_strings.reserve(1024);
m_indices.reserve(1024);
}
uint stringId(Utils::SmallStringView stringView)
{
Found found = find(stringView);
if (!found.wasFound)
return insertString(found.iterator, stringView);
return found.iterator->id;
}
std::vector<uint> stringIds(const std::vector<StringType> &strings)
{
std::vector<uint> ids;
ids.reserve(strings.size());
std::transform(strings.begin(),
strings.end(),
std::back_inserter(ids),
[&] (const StringType &string) { return stringId(string); });
return ids;
}
const StringType &string(uint id) const
{
return m_strings.at(m_indices.at(id)).string;
}
std::vector<StringType> strings(const std::vector<uint> &ids) const
{
std::vector<StringType> strings;
strings.reserve(ids.size());
std::transform(ids.begin(),
ids.end(),
std::back_inserter(strings),
[&] (uint id) { return m_strings.at(m_indices.at(id)).string; });
return strings;
}
private:
Found find(Utils::SmallStringView stringView)
{
auto range = std::equal_range(m_strings.cbegin(), m_strings.cend(), stringView);
return {range.first, range.first != range.second};
}
void incrementLargerOrEqualIndicesByOne(uint newIndex)
{
std::transform(m_indices.begin(),
m_indices.end(),
m_indices.begin(),
[&] (uint index) {
return index >= newIndex ? ++index : index;
});
}
uint insertString(const_iterator beforeIterator,
Utils::SmallStringView stringView)
{
auto id = uint(m_strings.size());
auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id);
auto newIndex = uint(std::distance(m_strings.begin(), inserted));
incrementLargerOrEqualIndicesByOne(newIndex);
m_indices.push_back(newIndex);
return id;
}
private:
StringCacheEntries m_strings;
std::vector<uint> m_indices;
};
} // namespace ClangBackEnd

View File

@@ -26,8 +26,9 @@ exists($$LLVM_INSTALL_DIR) {
win32-msvc2015:lessThan(QT_CL_PATCH_VERSION, 24210): QTC_NO_CLANG_LIBTOOLING = 1 win32-msvc2015:lessThan(QT_CL_PATCH_VERSION, 24210): QTC_NO_CLANG_LIBTOOLING = 1
isEmpty(QTC_NO_CLANG_LIBTOOLING) { isEmpty(QTC_NO_CLANG_LIBTOOLING) {
SUBDIRS += clangrefactoringbackend SUBDIRS += clangrefactoringbackend
SUBDIRS += clangpchmanagerbackend
} else { } else {
warning("Building the Clang refactoring back end is disabled.") warning("Building the Clang refactoring back end and the pch manager plugins are disabled.")
} }
} }

View File

@@ -20,3 +20,5 @@ win32 {
LIBS += $$LIBTOOLING_LIBS $$LIBCLANG_LIBS LIBS += $$LIBTOOLING_LIBS $$LIBCLANG_LIBS
QMAKE_RPATHDIR += $$LLVM_LIBDIR QMAKE_RPATHDIR += $$LLVM_LIBDIR
} }
DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_INSTALL_DIR/bin/clang)xxx\\\"\"

View File

@@ -0,0 +1,313 @@
/****************************************************************************
**
** 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 "googletest.h"
#include "mockqfilesystemwatcher.h"
#include "mockclangpathwatchernotifier.h"
#include <clangpathwatcher.h>
#include <stringcache.h>
namespace {
using testing::_;
using testing::ElementsAre;
using testing::IsEmpty;
using testing::SizeIs;
using testing::NiceMock;
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>>;
using ClangBackEnd::WatcherEntry;
class ClangPathWatcher : public testing::Test
{
protected:
ClangBackEnd::StringCache<Utils::SmallString> pathCache;
NiceMock<MockClangPathWatcherNotifier> notifier;
Watcher watcher{pathCache, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
Utils::SmallString id1{"id4"};
Utils::SmallString id2{"id2"};
Utils::SmallString id3{"id3"};
Utils::SmallString path1{"/path/path1"};
Utils::SmallString path2{"/path/path2"};
std::vector<uint> paths = watcher.pathCache().stringIds({path1, path2});
std::vector<uint> ids = watcher.idCache().stringIds({id1, id2, id3});
WatcherEntry watcherEntry1{ids[0], paths[0]};
WatcherEntry watcherEntry2{ids[1], paths[0]};
WatcherEntry watcherEntry3{ids[0], paths[1]};
WatcherEntry watcherEntry4{ids[1], paths[1]};
WatcherEntry watcherEntry5{ids[2], paths[1]};
};
TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList)
{
auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3});
ASSERT_THAT(convertedList, ElementsAre(path1, path2));
}
TEST_F(ClangPathWatcher, UniquePaths)
{
auto uniqueEntries = watcher.uniquePaths({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4});
ASSERT_THAT(uniqueEntries, ElementsAre(watcherEntry1, watcherEntry3));
}
TEST_F(ClangPathWatcher, NotWatchedEntries)
{
watcher.addEntries({watcherEntry1, watcherEntry4});
auto newEntries = watcher.notWatchedEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4});
ASSERT_THAT(newEntries, ElementsAre(watcherEntry2, watcherEntry3));
}
TEST_F(ClangPathWatcher, AddIdPaths)
{
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1, path2}));
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}});
}
TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher)
{
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}});
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path2}));
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}});
}
TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileWatcher)
{
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2}));
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}});
}
TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathInFileWatcher)
{
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2}))
.Times(0);
watcher.updateIdPaths({{id1, {paths[1]}}, {id2, {paths[0]}}});
}
TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPaths)
{
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[1]}}});
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[1]}}});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5));
}
TEST_F(ClangPathWatcher, ExtractSortedEntriesFromConvertIdPaths)
{
auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {paths[0], paths[1]}}, {id1, {paths[0], paths[1]}}});
ASSERT_THAT(entriesAndIds.first, ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4));
}
TEST_F(ClangPathWatcher, ExtractSortedIdsFromConvertIdPaths)
{
auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {}}, {id1, {}}, {id3, {}}});
ASSERT_THAT(entriesAndIds.second, ElementsAre(ids[0], ids[1], ids[2]));
}
TEST_F(ClangPathWatcher, NotWatchedPaths)
{
watcher.mergeToWatchedEntries({watcherEntry1});
auto newEntries = watcher.notWatchedPaths({watcherEntry2, watcherEntry3});
ASSERT_THAT(newEntries, ElementsAre(watcherEntry3));
}
TEST_F(ClangPathWatcher, AddedPaths)
{
watcher.mergeToWatchedEntries({watcherEntry1, watcherEntry2});
auto filteredEntries = watcher.filterNotWatchedPaths({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4});
ASSERT_THAT(filteredEntries, ElementsAre(watcherEntry3));
}
TEST_F(ClangPathWatcher, MergeEntries)
{
watcher.mergeToWatchedEntries({watcherEntry1, watcherEntry4});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4));
}
TEST_F(ClangPathWatcher, MergeMoreEntries)
{
watcher.mergeToWatchedEntries({watcherEntry1, watcherEntry4});
watcher.mergeToWatchedEntries({watcherEntry2, watcherEntry3});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4));
}
TEST_F(ClangPathWatcher, AddEmptyEntries)
{
EXPECT_CALL(mockQFileSytemWatcher, addPaths(_))
.Times(0);
watcher.addEntries({});
}
TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths)
{
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1, path2}));
watcher.addEntries({watcherEntry1, watcherEntry3});
}
TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths)
{
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1}));
watcher.addEntries({watcherEntry1, watcherEntry2});
}
TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths)
{
watcher.addEntries({watcherEntry1});
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1}))
.Times(0);
watcher.addEntries({watcherEntry1});
}
TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
{
watcher.addEntries({watcherEntry1});
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1}))
.Times(0);
watcher.addEntries({watcherEntry2});
}
TEST_F(ClangPathWatcher, RemoveEntriesWithId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
watcher.removeIdsFromWatchedEntries({ids[0]});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry2, watcherEntry4, watcherEntry5));
}
TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds)
{
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_))
.Times(0);
watcher.removeIds({});
}
TEST_F(ClangPathWatcher, RemoveNoPathsForOneId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_))
.Times(0);
watcher.removeIds({id1});
}
TEST_F(ClangPathWatcher, RemovePathForOneId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2}));
watcher.removeIds({id1});
}
TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1, path2}));
watcher.removeIds({id1, id2, id3});
}
TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1}));
watcher.removeIds({id1, id2});
}
TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
auto oldEntries = watcher.notAnymoreWatchedEntriesWithIds({watcherEntry1, watcherEntry4}, {ids[0], ids[1]});
ASSERT_THAT(oldEntries, ElementsAre(watcherEntry2, watcherEntry3));
}
TEST_F(ClangPathWatcher, RemoveUnusedEntries)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
watcher.removeFromWatchedEntries({watcherEntry2, watcherEntry3});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5));
}
TEST_F(ClangPathWatcher, EmptyVectorNotifyFileChange)
{
watcher.addEntries({watcherEntry3});
EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty())).Times(1);
mockQFileSytemWatcher.fileChanged(path1.toQString());
}
TEST_F(ClangPathWatcher, NotifyFileChange)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1)));
mockQFileSytemWatcher.fileChanged(path1.toQString());
}
}

View File

@@ -13,9 +13,11 @@ include($$PWD/../../../src/shared/clang/clang_defines.pri)
include($$PWD/../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri) include($$PWD/../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri)
!isEmpty(LIBTOOLING_LIBS):include($$PWD/../../../src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri) !isEmpty(LIBTOOLING_LIBS):include($$PWD/../../../src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri)
include($$PWD/../../../src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri)
include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri)
!isEmpty(LIBTOOLING_LIBS):include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri) !isEmpty(LIBTOOLING_LIBS):include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri)
include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri)
include(cplusplus.pri) include(cplusplus.pri)
} }

View File

@@ -0,0 +1,3 @@
#pragma once
#include <algorithm>

View File

@@ -0,0 +1 @@
#pragma once

View File

@@ -0,0 +1 @@
#pragma once

View File

@@ -0,0 +1,2 @@
#pragma once

View File

@@ -0,0 +1,3 @@
#pragma once
#include <includecollector_external3.h>

View File

@@ -0,0 +1,4 @@
#include "includecollector_header1.h"
#include "includecollector_header2.h"
#include "includecollector_external1.h"
#include "../data/includecollector_external2.h"

View File

@@ -0,0 +1,4 @@
#include "includecollector_header1.h"
#include "includecollector_header2.h"
#include "includecollector_external1.h"
#include "../data/includecollector_external2.h"

View File

@@ -0,0 +1,4 @@
#include <includecollector_header1.h>
#include <includecollector_header2.h>
#include <includecollector_external1.h>
#include <includecollector_external2.h>

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** 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 "googletest.h"
#include <includecollector.h>
#include <stringcache.h>
using testing::AllOf;
using testing::Contains;
using testing::Not;
using testing::ElementsAre;
using testing::UnorderedElementsAre;
namespace {
class IncludeCollector : public ::testing::Test
{
protected:
void SetUp();
uint id(const Utils::SmallString &path);
protected:
ClangBackEnd::StringCache<Utils::SmallString> filePathCache;
ClangBackEnd::IncludeCollector collector{filePathCache};
};
TEST_F(IncludeCollector, IncludesExternalHeader)
{
collector.collectIncludes();
ASSERT_THAT(collector.takeIncludeIds(),
AllOf(Contains(id("includecollector_external1.h")),
Contains(id("../data/includecollector_external2.h"))));
}
TEST_F(IncludeCollector, DoesNotIncludesInternalHeader)
{
collector.collectIncludes();
ASSERT_THAT(collector.takeIncludeIds(), Not(Contains(id("includecollector_header1.h"))));
}
TEST_F(IncludeCollector, NoDuplicate)
{
collector.collectIncludes();
ASSERT_THAT(collector.takeIncludeIds(),
UnorderedElementsAre(id("includecollector_external1.h"),
id("../data/includecollector_external2.h")));
}
TEST_F(IncludeCollector, IncludesAreSorted)
{
collector.collectIncludes();
ASSERT_THAT(collector.takeIncludeIds(),
ElementsAre(id("includecollector_external1.h"),
id("../data/includecollector_external2.h")));
}
void IncludeCollector::SetUp()
{
collector.addFile(TESTDATA_DIR, "includecollector_main.cpp", "", {"cc", "includecollector_main.cpp"});
collector.addFile(TESTDATA_DIR, "includecollector_main2.cpp", "", {"cc", "includecollector_main2.cpp"});
collector.setExcludedIncludes({TESTDATA_DIR "/includecollector_header1.h",
TESTDATA_DIR "/includecollector_header2.h"});
}
uint IncludeCollector::id(const Utils::SmallString &path)
{
return filePathCache.stringId(path);
}
}

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <clangpathwatcherinterface.h>
class MockClangPathWatcher : public ClangBackEnd::ClangPathWatcherInterface
{
public:
MOCK_METHOD1(updateIdPaths,
void (const std::vector<ClangBackEnd::IdPaths> &idPaths));
MOCK_METHOD1(removeIds,
void (const Utils::SmallStringVector &ids));
MOCK_METHOD1(setNotifier,
void (ClangBackEnd::ClangPathWatcherNotifier *notifier));
};

View File

@@ -0,0 +1,38 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <clangpathwatchernotifier.h>
class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier
{
public:
MOCK_METHOD1(pathsWithIdsChanged,
void (const Utils::SmallStringVector &ids));
};

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <pchcreatorinterface.h>
#include <projectpartpch.h>
#include <projectpartcontainerv2.h>
class MockPchCreator : public ClangBackEnd::PchCreatorInterface
{
public:
MOCK_METHOD1(generatePchs,
void(const std::vector<ClangBackEnd::V2::ProjectPartContainer> &projectParts));
MOCK_METHOD0(takeProjectPartPchs,
std::vector<ClangBackEnd::ProjectPartPch>());
MOCK_METHOD0(takeProjectsIncludes,
std::vector<ClangBackEnd::IdPaths>());
void generatePchs(std::vector<ClangBackEnd::V2::ProjectPartContainer> &&projectParts)
{
generatePchs(projectParts);
}
};

View File

@@ -0,0 +1,44 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <pchmanagerclientinterface.h>
class MockPchManagerClient : public ClangBackEnd::PchManagerClientInterface
{
public:
MOCK_METHOD0(alive,
void());
MOCK_METHOD1(precompiledHeadersUpdated,
void(const ClangBackEnd::PrecompiledHeadersUpdatedMessage &message));
void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override
{
precompiledHeadersUpdated(message);
}
};

View File

@@ -0,0 +1,43 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <pchmanagernotifierinterface.h>
class MockPchManagerNotifier : public ClangPchManager::PchManagerNotifierInterface
{
public:
MockPchManagerNotifier(ClangPchManager::PchManagerClient &pchManagerClient)
: ClangPchManager::PchManagerNotifierInterface(pchManagerClient)
{}
MOCK_METHOD2(precompiledHeaderUpdated,
void (const QString &projectPartId, const QString &pchFilePath));
MOCK_METHOD1(precompiledHeaderRemoved,
void (const QString &projectPartId));
};

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <pchmanagerserverinterface.h>
class MockPchManagerServer : public ClangBackEnd::PchManagerServerInterface
{
public:
MOCK_METHOD0(end,
void());
MOCK_METHOD1(updatePchProjectParts,
void (const ClangBackEnd::UpdatePchProjectPartsMessage&));
MOCK_METHOD1(removePchProjectParts,
void (const ClangBackEnd::RemovePchProjectPartsMessage&));
void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override
{
updatePchProjectParts(message);
}
void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override
{
removePchProjectParts(message);
}
};

View File

@@ -0,0 +1,46 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <projectpartsinterface.h>
class MockProjectParts : public ClangBackEnd::ProjectPartsInterface
{
public:
MOCK_METHOD1(update,
ClangBackEnd::V2::ProjectPartContainers(const ClangBackEnd::V2::ProjectPartContainers &projectsParts));
MOCK_METHOD1(remove,
void(const Utils::SmallStringVector &projectPartIds));
MOCK_CONST_METHOD1(projects,
ClangBackEnd::V2::ProjectPartContainers(const Utils::SmallStringVector &projectPartIds));
ClangBackEnd::V2::ProjectPartContainers update(ClangBackEnd::V2::ProjectPartContainers &&projectsParts) override
{
return update(projectsParts);
}
};

View File

@@ -0,0 +1,44 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <QObject>
class MockQFileSytemWatcher : public QObject
{
Q_OBJECT
public:
MOCK_METHOD1(addPaths,
void (const QStringList&));
MOCK_METHOD1(removePaths,
void (const QStringList&));
signals:
void fileChanged(const QString &);
};

View File

@@ -25,12 +25,9 @@
#pragma once #pragma once
#include <refactoringclientinterface.h> #include "googletest.h"
#include <gmock/gmock.h> #include <refactoringclientinterface.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
class MockRefactoringClient : public ClangBackEnd::RefactoringClientInterface class MockRefactoringClient : public ClangBackEnd::RefactoringClientInterface
{ {

View File

@@ -0,0 +1,298 @@
/****************************************************************************
**
** 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 "googletest.h"
#include "testenvironment.h"
#include <pchcreator.h>
#include <stringcache.h>
#include <QFileInfo>
namespace {
using ClangBackEnd::IdPaths;
using ClangBackEnd::ProjectPartPch;
using ClangBackEnd::V2::ProjectPartContainer;
using Utils::SmallString;
using testing::_;
using testing::AllOf;
using testing::Contains;
using testing::ElementsAre;
using testing::EndsWith;
using testing::NiceMock;
using testing::Not;
using testing::UnorderedElementsAre;
using testing::Property;
using testing::Field;
class PchCreator: public ::testing::Test
{
protected:
uint id(const Utils::SmallString &path);
protected:
ClangBackEnd::StringCache<Utils::SmallString> filePathCache;
SmallString main1Path = TESTDATA_DIR "/includecollector_main3.cpp";
SmallString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
SmallString header1Path = TESTDATA_DIR "/includecollector_header1.h";
SmallString header2Path = TESTDATA_DIR "/includecollector_header2.h";
ProjectPartContainer projectPart1{"project1",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{header1Path.clone()},
{main1Path.clone()}};
ProjectPartContainer projectPart2{"project2",
{"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"},
{header2Path.clone()},
{main2Path.clone()}};
TestEnvironment environment;
ClangBackEnd::PchCreator creator{{projectPart1.clone(),projectPart2.clone()},
environment,
filePathCache};
};
using PchCreatorSlowTest = PchCreator;
using PchCreatorVerySlowTest = PchCreator;
TEST_F(PchCreator, CreateGlobalHeaderPaths)
{
auto filePaths = creator.generateGlobalHeaderPaths();
ASSERT_THAT(filePaths,
UnorderedElementsAre(header1Path, header2Path));
}
TEST_F(PchCreator, CreateGlobalSourcePaths)
{
auto filePaths = creator.generateGlobalSourcePaths();
ASSERT_THAT(filePaths,
UnorderedElementsAre(main1Path, main2Path));
}
TEST_F(PchCreator, CreateGlobalHeaderAndSourcePaths)
{
auto filePaths = creator.generateGlobalHeaderAndSourcePaths();
ASSERT_THAT(filePaths,
UnorderedElementsAre(main1Path, main2Path, header1Path, header2Path));
}
TEST_F(PchCreator, CreateGlobalArguments)
{
auto arguments = creator.generateGlobalArguments();
ASSERT_THAT(arguments, ElementsAre("-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header", "-I", TESTDATA_DIR, "-x" , "c++-header", "-Wno-pragma-once-outside-header"));
}
TEST_F(PchCreator, CreateGlobalCommandLine)
{
auto arguments = creator.generateGlobalCommandLine();
ASSERT_THAT(arguments, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header", "-I", TESTDATA_DIR, "-x" , "c++-header", "-Wno-pragma-once-outside-header"));
}
TEST_F(PchCreator, CreateGlobalPchIncludes)
{
auto includeIds = creator.generateGlobalPchIncludeIds();
ASSERT_THAT(includeIds,
UnorderedElementsAre(id("includecollector_external3.h"),
id("includecollector_external1.h"),
id("includecollector_external2.h")));
}
TEST_F(PchCreatorVerySlowTest, CreateGlobalPchFileContent)
{
auto content = creator.generateGlobalPchHeaderFileContent();
ASSERT_THAT(content, "#include <includecollector_external3.h>\n#include <includecollector_external1.h>\n#include <includecollector_external2.h>\n");
}
TEST_F(PchCreatorVerySlowTest, CreateGlobalPchHeaderFile)
{
auto file = creator.generateGlobalPchHeaderFile();
file->open(QIODevice::ReadOnly);
auto content = file->readAll();
ASSERT_THAT(content, "#include <includecollector_external3.h>\n#include <includecollector_external1.h>\n#include <includecollector_external2.h>\n");
}
TEST_F(PchCreator, ConvertToQStringList)
{
auto arguments = creator.convertToQStringList({"-I", TESTDATA_DIR});
ASSERT_THAT(arguments, ElementsAre(QString("-I"), QString(TESTDATA_DIR)));
}
TEST_F(PchCreator, CreateGlobalPchCompilerArguments)
{
auto arguments = creator.generateGlobalPchCompilerArguments();
ASSERT_THAT(arguments, ElementsAre("-x","c++-header", "-Xclang", "-emit-pch", "-o", EndsWith(".pch"), EndsWith(".h")));
}
TEST_F(PchCreator, CreateGlobalClangCompilerArguments)
{
auto arguments = creator.generateGlobalClangCompilerArguments();
ASSERT_THAT(arguments, AllOf(Contains("-Wno-pragma-once-outside-header"),
Contains("-emit-pch"),
Contains("-o"),
Not(Contains(environment.clangCompilerPath()))));
}
TEST_F(PchCreatorVerySlowTest, CreateGlobalPch)
{
creator.generateGlobalPch();
ASSERT_TRUE(QFileInfo::exists(creator.generateGlobalPchFilePath()));
}
TEST_F(PchCreator, CreateProjectPartCommandLine)
{
auto commandLine = creator.generateProjectPartCommandLine(projectPart1);
ASSERT_THAT(commandLine, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"));
}
TEST_F(PchCreator, CreateProjectPartHeaderAndSources)
{
auto includeIds = creator.generateProjectPartHeaderAndSourcePaths(projectPart1);
ASSERT_THAT(includeIds, UnorderedElementsAre(main1Path, header1Path));
}
TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludes)
{
auto includeIds = creator.generateProjectPartPchIncludes(projectPart1);
ASSERT_THAT(includeIds, UnorderedElementsAre(id("includecollector_external1.h"),
id("includecollector_external2.h"),
id("includecollector_header2.h")));
}
TEST_F(PchCreatorSlowTest, CreateProjectPartPchFileContent)
{
auto includes = creator.generateProjectPartPchIncludes(projectPart1);
auto content = creator.generatePchIncludeFileContent(includes);
ASSERT_THAT(content, "#include <includecollector_header2.h>\n#include <includecollector_external1.h>\n#include <includecollector_external2.h>\n");
}
TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile)
{
auto includeIds = creator.generateProjectPartPchIncludes(projectPart1);
auto content = creator.generatePchIncludeFileContent(includeIds);
auto pchIncludeFilePath = creator.generateProjectPathPchHeaderFilePath(projectPart1);
auto file = creator.generatePchHeaderFile(pchIncludeFilePath, content);
file->open(QIODevice::ReadOnly);
auto fileContent = file->readAll();
ASSERT_THAT(fileContent, "#include <includecollector_header2.h>\n#include <includecollector_external1.h>\n#include <includecollector_external2.h>\n");
}
TEST_F(PchCreator, CreateProjectPartPchCompilerArguments)
{
auto arguments = creator.generateProjectPartPchCompilerArguments(projectPart1);
ASSERT_THAT(arguments, AllOf(Contains("-x"),
Contains("c++-header"),
// Contains("-Xclang"),
// Contains("-include-pch"),
// Contains("-Xclang"),
// Contains(EndsWith(".pch")),
Contains("-Xclang"),
Contains("-emit-pch"),
Contains("-o"),
Contains(EndsWith(".pch"))));
}
TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
{
auto arguments = creator.generateProjectPartClangCompilerArguments(projectPart1);
ASSERT_THAT(arguments, AllOf(Contains(TESTDATA_DIR),
Contains("-emit-pch"),
Contains("-o"),
Not(Contains(environment.clangCompilerPath()))));
}
TEST_F(PchCreatorVerySlowTest, ProjectPartPchsExistsAfterCreation)
{
creator.generateGlobalPch();
creator.generateProjectPartPch(projectPart1);
ASSERT_TRUE(QFileInfo::exists(creator.generateProjectPathPchHeaderFilePath(projectPart1)));
}
TEST_F(PchCreatorVerySlowTest, CreatePartPchs)
{
creator.generateGlobalPch();
auto projectPartPchAndIdPath = creator.generateProjectPartPch(projectPart1);
ASSERT_THAT(projectPartPchAndIdPath.first.id(), projectPart1.projectPartId());
ASSERT_THAT(projectPartPchAndIdPath.first.path(), creator.generateProjectPartPchFilePath(projectPart1));
ASSERT_THAT(projectPartPchAndIdPath.second.id, projectPart1.projectPartId());
ASSERT_THAT(projectPartPchAndIdPath.second.paths, UnorderedElementsAre(1, 2, 3));
}
TEST_F(PchCreatorVerySlowTest, ProjectPartPchsForCreatePchsForProjectParts)
{
creator.generatePchs();
ASSERT_THAT(creator.takeProjectPartPchs(),
ElementsAre(Property(&ProjectPartPch::id, "project1"),
Property(&ProjectPartPch::id, "project2")));
}
TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts)
{
creator.generatePchs();
ASSERT_THAT(creator.takeProjectsIncludes(),
ElementsAre(AllOf(Field(&IdPaths::id, "project1"),
Field(&IdPaths::paths, UnorderedElementsAre(id("includecollector_header2.h"),
id("includecollector_external1.h"),
id("includecollector_external2.h")))),
AllOf(Field(&IdPaths::id, "project2"),
Field(&IdPaths::paths, UnorderedElementsAre(id("includecollector_external1.h"),
id("includecollector_external3.h"),
id("includecollector_header1.h"),
id("../data/includecollector_external2.h"))))));
}
uint PchCreator::id(const Utils::SmallString &path)
{
return filePathCache.stringId(path);
}
}

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** 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 "googletest.h"
#include "mockpchmanagernotifier.h"
#include "mockpchmanagerserver.h"
#include <pchmanagerclient.h>
#include <projectupdater.h>
#include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h>
namespace {
using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
using testing::_;
using testing::Contains;
using testing::Not;
class PchManagerClient : public ::testing::Test
{
protected:
MockPchManagerServer mockPchManagerServer;
ClangPchManager::PchManagerClient client;
MockPchManagerNotifier mockPchManagerNotifier{client};
ClangPchManager::ProjectUpdater projectUpdater{mockPchManagerServer, client};
Utils::SmallString projectPartId{"projectPartId"};
Utils::SmallString pchFilePath{"/path/to/pch"};
PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone()}}};
};
TEST_F(PchManagerClient, NotifierAttached)
{
MockPchManagerNotifier notifier(client);
ASSERT_THAT(client.notifiers(), Contains(&notifier));
}
TEST_F(PchManagerClient, NotifierDetached)
{
MockPchManagerNotifier *notifierPointer = nullptr;
{
MockPchManagerNotifier notifier(client);
notifierPointer = &notifier;
}
ASSERT_THAT(client.notifiers(), Not(Contains(notifierPointer)));
}
TEST_F(PchManagerClient, Update)
{
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderUpdated(projectPartId.toQString(), pchFilePath.toQString()));
client.precompiledHeadersUpdated(message.clone());
}
TEST_F(PchManagerClient, Remove)
{
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString()))
.Times(2);
projectUpdater.removeProjectParts({projectPartId.clone(), projectPartId.clone()});
}
}

View File

@@ -0,0 +1,157 @@
/****************************************************************************
**
** 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 "googletest.h"
#include "mockpchmanagerclient.h"
#include "mockpchmanagerserver.h"
#include <writemessageblock.h>
#include <pchmanagerclientproxy.h>
#include <pchmanagerserverproxy.h>
#include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h>
#include <QBuffer>
#include <QString>
#include <QVariant>
#include <vector>
using ClangBackEnd::UpdatePchProjectPartsMessage;
using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::RemovePchProjectPartsMessage;
using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
using ::testing::Args;
using ::testing::Property;
using ::testing::Eq;
namespace {
class PchManagerClientServerInProcess : public ::testing::Test
{
protected:
PchManagerClientServerInProcess();
void SetUp();
void TearDown();
void scheduleServerMessages();
void scheduleClientMessages();
protected:
QBuffer buffer;
MockPchManagerClient mockPchManagerClient;
MockPchManagerServer mockPchManagerServer;
ClangBackEnd::PchManagerServerProxy serverProxy;
ClangBackEnd::PchManagerClientProxy clientProxy;
};
TEST_F(PchManagerClientServerInProcess, SendEndMessage)
{
EXPECT_CALL(mockPchManagerServer, end());
serverProxy.end();
scheduleServerMessages();
}
TEST_F(PchManagerClientServerInProcess, SendAliveMessage)
{
EXPECT_CALL(mockPchManagerClient, alive());
clientProxy.alive();
scheduleClientMessages();
}
TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage)
{
ProjectPartContainer projectPart2{"projectPartId",
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{TESTDATA_DIR "/includecollector_header.h"},
{TESTDATA_DIR "/includecollector_main.cpp"}};
UpdatePchProjectPartsMessage message{{projectPart2}};
EXPECT_CALL(mockPchManagerServer, updatePchProjectParts(message));
serverProxy.updatePchProjectParts(message.clone());
scheduleServerMessages();
}
TEST_F(PchManagerClientServerInProcess, SendRemovePchProjectPartsMessage)
{
RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}};
EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message));
serverProxy.removePchProjectParts(message.clone());
scheduleServerMessages();
}
TEST_F(PchManagerClientServerInProcess, SendPrecompiledHeaderUpdatedMessage)
{
PrecompiledHeadersUpdatedMessage message{{{"projectPartId", "/path/to/pch"}}};
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(message));
clientProxy.precompiledHeadersUpdated(message.clone());
scheduleClientMessages();
}
PchManagerClientServerInProcess::PchManagerClientServerInProcess()
: serverProxy(&mockPchManagerClient, &buffer),
clientProxy(&mockPchManagerServer, &buffer)
{
}
void PchManagerClientServerInProcess::SetUp()
{
buffer.open(QIODevice::ReadWrite);
}
void PchManagerClientServerInProcess::TearDown()
{
buffer.close();
}
void PchManagerClientServerInProcess::scheduleServerMessages()
{
buffer.seek(0);
clientProxy.readMessages();
buffer.buffer().clear();
}
void PchManagerClientServerInProcess::scheduleClientMessages()
{
buffer.seek(0);
serverProxy.readMessages();
buffer.buffer().clear();
}
}

View File

@@ -0,0 +1,184 @@
/****************************************************************************
**
** 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 "googletest.h"
#include "mockclangpathwatcher.h"
#include "mockpchmanagerclient.h"
#include "mockpchcreator.h"
#include "mockprojectparts.h"
#include <pchmanagerserver.h>
#include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h>
#include <updatepchprojectpartsmessage.h>
namespace {
using testing::ElementsAre;
using testing::UnorderedElementsAre;
using testing::ByMove;
using testing::NiceMock;
using testing::Return;
using testing::_;
using testing::IsEmpty;
using Utils::SmallString;
using ClangBackEnd::V2::ProjectPartContainer;
class PchManagerServer : public ::testing::Test
{
void SetUp() override;
protected:
NiceMock<MockPchCreator> mockPchCreator;
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockProjectParts> mockProjectParts;
ClangBackEnd::StringCache<Utils::SmallString> filePathCache;
ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts};
NiceMock<MockPchManagerClient> mockPchManagerClient;
SmallString projectPartId1 = "project1";
SmallString projectPartId2 = "project2";
SmallString main1Path = TESTDATA_DIR "/includecollector_main3.cpp";
SmallString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
SmallString header1Path = TESTDATA_DIR "/includecollector_header1.h";
SmallString header2Path = TESTDATA_DIR "/includecollector_header2.h";
std::vector<ClangBackEnd::IdPaths> idPaths = {{projectPartId1, {1, 2}}};
ProjectPartContainer projectPart1{projectPartId1.clone(),
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{header1Path.clone()},
{main1Path.clone()}};
ProjectPartContainer projectPart2{projectPartId2.clone(),
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{header2Path.clone()},
{main2Path.clone()}};
std::vector<ClangBackEnd::V2::ProjectPartContainer> projectParts{projectPart1, projectPart2};
ClangBackEnd::UpdatePchProjectPartsMessage updatePchProjectPartsMessage{Utils::clone(projectParts)};
std::vector<ClangBackEnd::ProjectPartPch> projectPartPchs{{projectPart1.projectPartId().clone(), "/path1/to/pch"},
{projectPart2.projectPartId().clone(), "/path2/to/pch"}};
ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage{Utils::clone(projectPartPchs)};
ClangBackEnd::RemovePchProjectPartsMessage removePchProjectPartsMessage{{projectPart1.projectPartId().clone(),
projectPart2.projectPartId().clone()}};
};
TEST_F(PchManagerServer, CallPrecompiledHeadersUpdatedInClientForUpdate)
{
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage));
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
}
TEST_F(PchManagerServer, CallBuildInPchCreator)
{
EXPECT_CALL(mockPchCreator, generatePchs(updatePchProjectPartsMessage.projectsParts()));
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
}
TEST_F(PchManagerServer, UpdateIncludesOfFileWatcher)
{
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths));
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
}
TEST_F(PchManagerServer, GetChangedProjectPartsFromProjectParts)
{
EXPECT_CALL(mockProjectParts, update(_));
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
}
TEST_F(PchManagerServer, RemoveIncludesFromFileWatcher)
{
EXPECT_CALL(mockClangPathWatcher, removeIds(removePchProjectPartsMessage.projectsPartIds()));
server.removePchProjectParts(removePchProjectPartsMessage.clone());
}
TEST_F(PchManagerServer, RemoveProjectPartsFromProjectParts)
{
EXPECT_CALL(mockProjectParts, remove(removePchProjectPartsMessage.projectsPartIds()));
server.removePchProjectParts(removePchProjectPartsMessage.clone());
}
TEST_F(PchManagerServer, SetPathWatcherNotifier)
{
EXPECT_CALL(mockClangPathWatcher, setNotifier(_));
ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts};
}
TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange)
{
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
EXPECT_CALL(mockProjectParts, projects(ElementsAre(projectPart1.projectPartId())));
server.pathsWithIdsChanged({projectPartId1});
}
TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange)
{
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
EXPECT_CALL(mockPchCreator, generatePchs(ElementsAre(projectPart1)));
server.pathsWithIdsChanged({projectPartId1});
}
TEST_F(PchManagerServer, CallPrecompiledHeadersUpdatedInClientForIncludeChange)
{
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage));
server.pathsWithIdsChanged({projectPartId1});
}
TEST_F(PchManagerServer, CallUpdateIdPathsInFileSystemWatcherForIncludeChange)
{
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths));
server.pathsWithIdsChanged({projectPartId1});
}
void PchManagerServer::SetUp()
{
server.setClient(&mockPchManagerClient);
ON_CALL(mockPchCreator, takeProjectPartPchs())
.WillByDefault(Return(projectPartPchs));
ON_CALL(mockProjectParts, update(projectParts))
.WillByDefault(Return(projectParts));
ON_CALL(mockProjectParts, projects(Utils::SmallStringVector{{projectPartId1}}))
.WillByDefault(Return(std::vector<ClangBackEnd::V2::ProjectPartContainer>{{projectPart1}}));
ON_CALL(mockPchCreator, takeProjectsIncludes())
.WillByDefault(Return(idPaths));
}
}

View File

@@ -0,0 +1,189 @@
/****************************************************************************
**
** 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 "googletest.h"
#include <projectparts.h>
#include <projectpartcontainerv2.h>
namespace {
using testing::ElementsAre;
using testing::UnorderedElementsAre;
using testing::IsEmpty;
using ClangBackEnd::V2::ProjectPartContainer;
class ProjectParts : public testing::Test
{
protected:
ClangBackEnd::ProjectParts projectParts;
ProjectPartContainer projectPartContainer1{"id",
{"-DUNIX", "-O2"},
{"headers1.h", "header2.h"},
{"source1.cpp", "source2.cpp"}};
ProjectPartContainer updatedProjectPartContainer1{"id",
{"-DUNIX", "-O2"},
{"headers1.h", "header2.h"},
{"source1.cpp", "source2.cpp", "source3.cpp" }};
ProjectPartContainer projectPartContainer2{"id2",
{"-DUNIX", "-O2"},
{"headers1.h", "header2.h"},
{"source1.cpp", "source2.cpp"}};
};
TEST_F(ProjectParts, GetNoProjectPartsForAddingEmptyProjectParts)
{
auto updatedProjectParts = projectParts.update({});
ASSERT_THAT(updatedProjectParts, IsEmpty());
}
TEST_F(ProjectParts, GetProjectPartForAddingProjectPart)
{
auto updatedProjectParts = projectParts.update({projectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, ProjectPartAdded)
{
projectParts.update({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, FilterDublicateProjectPartsForUpdating)
{
auto updatedProjectParts = projectParts.update({projectPartContainer1, projectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, FilteredProjectPartAdded)
{
projectParts.update({projectPartContainer1, projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, DoNotUpdateNotNewProjectPart)
{
projectParts.update({projectPartContainer1});
auto updatedProjectParts = projectParts.update({projectPartContainer1});
ASSERT_THAT(updatedProjectParts, IsEmpty());
}
TEST_F(ProjectParts, NoDuplicateProjectPartAfterUpdatingWithNotNewProjectPart)
{
projectParts.update({projectPartContainer1});
auto updatedProjectParts = projectParts.update({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, FilterUniqueProjectParts)
{
auto updatedProjectParts = projectParts.uniqueProjectParts({projectPartContainer1, projectPartContainer2, projectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, MergeProjectParts)
{
projectParts.mergeProjectParts({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, MergeProjectMultipleTimesParts)
{
projectParts.mergeProjectParts({projectPartContainer2});
projectParts.mergeProjectParts({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, GetNewProjectParts)
{
projectParts.mergeProjectParts({projectPartContainer2});
auto newProjectParts = projectParts.newProjectParts({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(newProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, GetUpdatedProjectPart)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
auto updatedProjectParts = projectParts.update({updatedProjectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1));
}
TEST_F(ProjectParts, ProjectPartIsReplacedWithUpdatedProjectPart)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
projectParts.update({updatedProjectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(updatedProjectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, Remove)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
projectParts.remove({projectPartContainer1.projectPartId()});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer2));
}
TEST_F(ProjectParts, GetProjectById)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
auto projectPartContainers = projectParts.projects({projectPartContainer1.projectPartId()});
ASSERT_THAT(projectPartContainers, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, GetProjectsByIds)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
auto projectPartContainers = projectParts.projects({projectPartContainer1.projectPartId(), projectPartContainer2.projectPartId()});
ASSERT_THAT(projectPartContainers, UnorderedElementsAre(projectPartContainer1, projectPartContainer2));
}
}

Some files were not shown because too many files have changed in this diff Show More