forked from qt-creator/qt-creator
Clang: Move QLocalServer in ConnectionClient
Before the QLocalServer was in the ConnectionServer so more than one client could connect to the server. But we never used that possibility which made the hand shaking much more difficult. It is now moved in the client, so that there is always a QLocalServer. Change-Id: Ifa357074b0c0809434c49d23b1cee38496f72f43 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
61
src/libs/clangsupport/baseserverproxy.cpp
Normal file
61
src/libs/clangsupport/baseserverproxy.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "baseserverproxy.h"
|
||||
#include "messageenvelop.h"
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
BaseServerProxy::BaseServerProxy(IpcClientInterface *client, QIODevice *ioDevice)
|
||||
: m_writeMessageBlock(ioDevice),
|
||||
m_readMessageBlock(ioDevice),
|
||||
m_client(client)
|
||||
{
|
||||
if (ioDevice)
|
||||
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { BaseServerProxy::readMessages(); });
|
||||
}
|
||||
|
||||
void BaseServerProxy::readMessages()
|
||||
{
|
||||
for (const auto &message : m_readMessageBlock.readAll())
|
||||
m_client->dispatch(message);
|
||||
}
|
||||
|
||||
void BaseServerProxy::resetCounter()
|
||||
{
|
||||
m_writeMessageBlock.resetCounter();
|
||||
m_readMessageBlock.resetCounter();
|
||||
}
|
||||
|
||||
void BaseServerProxy::setIoDevice(QIODevice *ioDevice)
|
||||
{
|
||||
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { BaseServerProxy::readMessages(); });
|
||||
m_writeMessageBlock.setIoDevice(ioDevice);
|
||||
m_readMessageBlock.setIoDevice(ioDevice);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
54
src/libs/clangsupport/baseserverproxy.h
Normal file
54
src/libs/clangsupport/baseserverproxy.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ipcclientinterface.h"
|
||||
#include "readmessageblock.h"
|
||||
#include "writemessageblock.h"
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class CLANGSUPPORT_EXPORT BaseServerProxy
|
||||
{
|
||||
BaseServerProxy(const BaseServerProxy&) = delete;
|
||||
BaseServerProxy &operator=(const BaseServerProxy&) = delete;
|
||||
|
||||
public:
|
||||
BaseServerProxy(IpcClientInterface *client, QIODevice *ioDevice);
|
||||
|
||||
void readMessages();
|
||||
|
||||
void resetCounter();
|
||||
|
||||
void setIoDevice(QIODevice *ioDevice);
|
||||
|
||||
protected:
|
||||
ClangBackEnd::WriteMessageBlock m_writeMessageBlock;
|
||||
ClangBackEnd::ReadMessageBlock m_readMessageBlock;
|
||||
IpcClientInterface *m_client;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "clangcodemodelconnectionclient.h"
|
||||
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
@@ -40,8 +42,14 @@ QString currentProcessId()
|
||||
|
||||
ClangCodeModelConnectionClient::ClangCodeModelConnectionClient(
|
||||
ClangCodeModelClientInterface *client)
|
||||
: serverProxy_(client, ioDevice())
|
||||
: ConnectionClient(Utils::TemporaryDirectory::masterDirectoryPath()
|
||||
+ QStringLiteral("/ClangBackEnd-")
|
||||
+ currentProcessId()),
|
||||
m_serverProxy(client, nullptr),
|
||||
m_client(client)
|
||||
{
|
||||
m_processCreator.setTemporaryDirectoryPattern("clangbackend-XXXXXX");
|
||||
|
||||
stdErrPrefixer().setPrefix("clangbackend.stderr: ");
|
||||
stdOutPrefixer().setPrefix("clangbackend.stdout: ");
|
||||
}
|
||||
@@ -53,22 +61,17 @@ ClangCodeModelConnectionClient::~ClangCodeModelConnectionClient()
|
||||
|
||||
ClangCodeModelServerProxy &ClangCodeModelConnectionClient::serverProxy()
|
||||
{
|
||||
return serverProxy_;
|
||||
return m_serverProxy;
|
||||
}
|
||||
|
||||
void ClangCodeModelConnectionClient::sendEndCommand()
|
||||
{
|
||||
serverProxy_.end();
|
||||
m_serverProxy.end();
|
||||
}
|
||||
|
||||
void ClangCodeModelConnectionClient::resetCounter()
|
||||
{
|
||||
serverProxy_.resetCounter();
|
||||
}
|
||||
|
||||
QString ClangCodeModelConnectionClient::connectionName() const
|
||||
{
|
||||
return temporaryDirectory().path() + QStringLiteral("/ClangBackEnd-") + currentProcessId();
|
||||
m_serverProxy.resetCounter();
|
||||
}
|
||||
|
||||
QString ClangCodeModelConnectionClient::outputName() const
|
||||
@@ -76,4 +79,9 @@ QString ClangCodeModelConnectionClient::outputName() const
|
||||
return QStringLiteral("ClangCodeModelConnectionClient");
|
||||
}
|
||||
|
||||
void ClangCodeModelConnectionClient::newConnectedServer(QIODevice *ioDevice)
|
||||
{
|
||||
m_serverProxy.setIoDevice(ioDevice);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -35,17 +35,17 @@ public:
|
||||
ClangCodeModelConnectionClient(ClangCodeModelClientInterface *client);
|
||||
~ClangCodeModelConnectionClient();
|
||||
|
||||
|
||||
ClangCodeModelServerProxy &serverProxy();
|
||||
|
||||
protected:
|
||||
void sendEndCommand() override;
|
||||
void resetCounter() override;
|
||||
QString connectionName() const override;
|
||||
QString outputName() const override;
|
||||
void newConnectedServer(QIODevice *ioDevice) override;
|
||||
|
||||
private:
|
||||
ClangCodeModelServerProxy serverProxy_;
|
||||
ClangCodeModelServerProxy m_serverProxy;
|
||||
ClangCodeModelClientInterface *m_client;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -29,30 +29,11 @@
|
||||
#include <clangcodemodelservermessages.h>
|
||||
#include <messageenvelop.h>
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QProcess>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
ClangCodeModelServerProxy::ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QIODevice *ioDevice)
|
||||
: m_writeMessageBlock(ioDevice),
|
||||
m_readMessageBlock(ioDevice),
|
||||
m_client(client)
|
||||
: BaseServerProxy(client, ioDevice)
|
||||
{
|
||||
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () {ClangCodeModelServerProxy::readMessages();});
|
||||
}
|
||||
|
||||
void ClangCodeModelServerProxy::readMessages()
|
||||
{
|
||||
for (const auto &message : m_readMessageBlock.readAll())
|
||||
m_client->dispatch(message);
|
||||
}
|
||||
|
||||
void ClangCodeModelServerProxy::resetCounter()
|
||||
{
|
||||
m_writeMessageBlock.resetCounter();
|
||||
m_readMessageBlock.resetCounter();
|
||||
}
|
||||
|
||||
void ClangCodeModelServerProxy::end()
|
||||
|
@@ -24,9 +24,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseserverproxy.h"
|
||||
#include "clangcodemodelserverinterface.h"
|
||||
#include "readmessageblock.h"
|
||||
#include "writemessageblock.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QTimer>
|
||||
@@ -42,12 +42,11 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class CLANGSUPPORT_EXPORT ClangCodeModelServerProxy : public ClangCodeModelServerInterface
|
||||
class CLANGSUPPORT_EXPORT ClangCodeModelServerProxy : public BaseServerProxy,
|
||||
public ClangCodeModelServerInterface
|
||||
{
|
||||
public:
|
||||
ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QIODevice *ioDevice);
|
||||
ClangCodeModelServerProxy(const ClangCodeModelServerProxy&) = delete;
|
||||
ClangCodeModelServerProxy &operator=(const ClangCodeModelServerProxy&) = delete;
|
||||
|
||||
void end() override;
|
||||
void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) override;
|
||||
@@ -62,15 +61,6 @@ public:
|
||||
void requestReferences(const RequestReferencesMessage &message) override;
|
||||
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
|
||||
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
|
||||
|
||||
void readMessages();
|
||||
|
||||
void resetCounter();
|
||||
|
||||
private:
|
||||
ClangBackEnd::WriteMessageBlock m_writeMessageBlock;
|
||||
ClangBackEnd::ReadMessageBlock m_readMessageBlock;
|
||||
ClangCodeModelClientInterface *m_client;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -74,6 +74,9 @@ SOURCES += \
|
||||
$$PWD/sourcelocationscontainer.cpp \
|
||||
$$PWD/sourcelocationsforrenamingmessage.cpp \
|
||||
$$PWD/sourcerangecontainer.cpp \
|
||||
$$PWD/processcreator.cpp \
|
||||
$$PWD/processexception.cpp \
|
||||
$$PWD/processstartedevent.cpp \
|
||||
$$PWD/sourcerangecontainerv2.cpp \
|
||||
$$PWD/sourcerangesanddiagnosticsforquerymessage.cpp \
|
||||
$$PWD/sourcerangescontainer.cpp \
|
||||
@@ -85,7 +88,8 @@ SOURCES += \
|
||||
$$PWD/updatevisibletranslationunitsmessage.cpp \
|
||||
$$PWD/writemessageblock.cpp \
|
||||
$$PWD/filepathcaching.cpp \
|
||||
$$PWD/filepathid.cpp
|
||||
$$PWD/filepathid.cpp \
|
||||
$$PWD/baseserverproxy.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/cancelmessage.h \
|
||||
@@ -161,6 +165,11 @@ HEADERS += \
|
||||
$$PWD/sourcelocationscontainer.h \
|
||||
$$PWD/sourcelocationsforrenamingmessage.h \
|
||||
$$PWD/sourcerangecontainer.h \
|
||||
$$PWD/filepath.h \
|
||||
$$PWD/processcreator.h \
|
||||
$$PWD/processexception.h \
|
||||
$$PWD/processhandle.h \
|
||||
$$PWD/processstartedevent.h \
|
||||
$$PWD/sourcerangecontainerv2.h \
|
||||
$$PWD/sourcerangesanddiagnosticsforquerymessage.h \
|
||||
$$PWD/sourcerangescontainer.h \
|
||||
@@ -187,6 +196,7 @@ HEADERS += \
|
||||
$$PWD/filepathcachinginterface.h \
|
||||
$$PWD/filepathcaching.h \
|
||||
$$PWD/filepathcachingfwd.h \
|
||||
$$PWD/baseserverproxy.h \
|
||||
$$PWD/nativefilepathview.h \
|
||||
$$PWD/filepath.h \
|
||||
$$PWD/nativefilepath.h \
|
||||
|
@@ -26,6 +26,10 @@
|
||||
#include "connectionclient.h"
|
||||
|
||||
#include "clangsupportdebugutils.h"
|
||||
#include "processstartedevent.h"
|
||||
#include "processexception.h"
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMetaMethod>
|
||||
@@ -34,50 +38,52 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
ConnectionClient::ConnectionClient()
|
||||
ConnectionClient::ConnectionClient(const QString &connectionName)
|
||||
: m_connectionName(connectionName)
|
||||
{
|
||||
m_processCreator.setArguments({connectionName});
|
||||
m_processCreator.setObserver(this);
|
||||
|
||||
listenForConnections();
|
||||
|
||||
m_processAliveTimer.setInterval(10000);
|
||||
resetTemporaryDir();
|
||||
resetTemporaryDirectory();
|
||||
|
||||
static const bool startAliveTimer = !qEnvironmentVariableIntValue("QTC_CLANG_NO_ALIVE_TIMER");
|
||||
|
||||
if (startAliveTimer)
|
||||
connectAliveTimer();
|
||||
|
||||
connectLocalSocketError();
|
||||
connectLocalSocketConnected();
|
||||
connectLocalSocketDisconnected();
|
||||
connectNewConnection();
|
||||
}
|
||||
|
||||
ConnectionClient::~ConnectionClient()
|
||||
{
|
||||
QLocalServer::removeServer(connectionName());
|
||||
}
|
||||
|
||||
void ConnectionClient::startProcessAndConnectToServerAsynchronously()
|
||||
{
|
||||
m_process = startProcess();
|
||||
}
|
||||
m_processIsStarting = true;
|
||||
|
||||
bool ConnectionClient::disconnectFromServer()
|
||||
{
|
||||
localSocket.disconnectFromServer();
|
||||
if (localSocket.state() != QLocalSocket::UnconnectedState)
|
||||
return localSocket.waitForDisconnected();
|
||||
|
||||
return true;
|
||||
m_processFuture = m_processCreator.createProcess();
|
||||
}
|
||||
|
||||
bool ConnectionClient::isConnected() const
|
||||
{
|
||||
return localSocket.state() == QLocalSocket::ConnectedState;
|
||||
return m_localSocket && m_localSocket->state() == QLocalSocket::ConnectedState;
|
||||
}
|
||||
|
||||
void ConnectionClient::ensureMessageIsWritten()
|
||||
{
|
||||
while (isConnected() && localSocket.bytesToWrite() > 0)
|
||||
localSocket.waitForBytesWritten(50);
|
||||
while (isConnected() && m_localSocket->bytesToWrite() > 0)
|
||||
m_localSocket->waitForBytesWritten(50);
|
||||
}
|
||||
|
||||
void ConnectionClient::sendEndMessage()
|
||||
{
|
||||
sendEndCommand();
|
||||
localSocket.flush();
|
||||
m_localSocket->flush();
|
||||
ensureMessageIsWritten();
|
||||
}
|
||||
|
||||
@@ -108,7 +114,7 @@ QProcessEnvironment ConnectionClient::processEnvironment() const
|
||||
|
||||
const QTemporaryDir &ConnectionClient::temporaryDirectory() const
|
||||
{
|
||||
return *m_temporaryDirectory;
|
||||
return m_processCreator.temporaryDirectory();
|
||||
}
|
||||
|
||||
LinePrefixer &ConnectionClient::stdErrPrefixer()
|
||||
@@ -121,29 +127,31 @@ LinePrefixer &ConnectionClient::stdOutPrefixer()
|
||||
return m_stdOutPrefixer;
|
||||
}
|
||||
|
||||
std::unique_ptr<QProcess> ConnectionClient::startProcess()
|
||||
QString ConnectionClient::connectionName() const
|
||||
{
|
||||
m_processIsStarting = true;
|
||||
return m_connectionName;
|
||||
}
|
||||
|
||||
auto process = std::unique_ptr<QProcess>(new QProcess);
|
||||
connectProcessFinished(process.get());
|
||||
connectProcessStarted(process.get());
|
||||
connectStandardOutputAndError(process.get());
|
||||
process->setProcessEnvironment(processEnvironment());
|
||||
process->start(processPath(), {connectionName()});
|
||||
resetProcessAliveTimer();
|
||||
bool ConnectionClient::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == int(ProcessStartedEvent::ProcessStarted)) {
|
||||
getProcessFromFuture();
|
||||
|
||||
return process;
|
||||
return true;
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionClient::restartProcessAsynchronously()
|
||||
{
|
||||
if (!m_processIsStarting) {
|
||||
finishProcess(std::move(m_process));
|
||||
resetTemporaryDir(); // clear left-over preambles
|
||||
getProcessFromFuture();
|
||||
|
||||
finishProcess(std::move(m_process));
|
||||
resetTemporaryDirectory(); // clear left-over preambles
|
||||
|
||||
startProcessAndConnectToServerAsynchronously();
|
||||
|
||||
startProcessAndConnectToServerAsynchronously();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty()
|
||||
@@ -153,23 +161,15 @@ void ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty()
|
||||
return; // Already reset, but we were scheduled after.
|
||||
}
|
||||
|
||||
if (localSocket.bytesAvailable() > 0)
|
||||
if (!m_localSocket || m_localSocket->bytesAvailable() > 0)
|
||||
return; // We come first, the incoming data was not yet processed.
|
||||
|
||||
restartProcessAsynchronously();
|
||||
}
|
||||
|
||||
void ConnectionClient::connectToLocalSocket()
|
||||
{
|
||||
if (!isConnected()) {
|
||||
localSocket.connectToServer(connectionName());
|
||||
QTimer::singleShot(20, this, &ConnectionClient::connectToLocalSocket);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionClient::endProcess(QProcess *process)
|
||||
{
|
||||
if (isProcessIsRunning() && isConnected()) {
|
||||
if (isProcessRunning(process) && isConnected()) {
|
||||
sendEndMessage();
|
||||
process->waitForFinished();
|
||||
}
|
||||
@@ -177,32 +177,33 @@ void ConnectionClient::endProcess(QProcess *process)
|
||||
|
||||
void ConnectionClient::terminateProcess(QProcess *process)
|
||||
{
|
||||
Q_UNUSED(process)
|
||||
#ifndef Q_OS_WIN32
|
||||
if (isProcessIsRunning()) {
|
||||
if (!Utils::HostOsInfo::isWindowsHost() && isProcessRunning()) {
|
||||
process->terminate();
|
||||
process->waitForFinished();
|
||||
process->waitForFinished(1000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConnectionClient::killProcess(QProcess *process)
|
||||
{
|
||||
if (isProcessIsRunning()) {
|
||||
if (isProcessRunning(process)) {
|
||||
process->kill();
|
||||
process->waitForFinished();
|
||||
process->waitForFinished(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionClient::resetProcessIsStarting()
|
||||
void ConnectionClient::finishConnection()
|
||||
{
|
||||
m_processIsStarting = false;
|
||||
if (m_localSocket) {
|
||||
if (m_localSocket->state() != QLocalSocket::UnconnectedState)
|
||||
m_localSocket->disconnectFromServer();
|
||||
m_localSocket = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionClient::printLocalSocketError(QLocalSocket::LocalSocketError socketError)
|
||||
{
|
||||
if (socketError != QLocalSocket::ServerNotFoundError)
|
||||
qWarning() << outputName() << "LocalSocket Error:" << localSocket.errorString();
|
||||
if (m_localSocket && socketError != QLocalSocket::ServerNotFoundError)
|
||||
qWarning() << outputName() << "LocalSocket Error:" << m_localSocket->errorString();
|
||||
}
|
||||
|
||||
void ConnectionClient::printStandardOutput()
|
||||
@@ -215,55 +216,74 @@ void ConnectionClient::printStandardError()
|
||||
qDebug("%s", m_stdErrPrefixer.prefix(m_process->readAllStandardError()).constData());
|
||||
}
|
||||
|
||||
void ConnectionClient::resetTemporaryDir()
|
||||
void ConnectionClient::resetTemporaryDirectory()
|
||||
{
|
||||
m_temporaryDirectory = std::make_unique<Utils::TemporaryDirectory>("clang-XXXXXX");
|
||||
m_processCreator.resetTemporaryDirectory();
|
||||
}
|
||||
|
||||
void ConnectionClient::connectLocalSocketConnected()
|
||||
void ConnectionClient::initializeProcess(QProcess *process)
|
||||
{
|
||||
connect(&localSocket,
|
||||
&QLocalSocket::connected,
|
||||
this,
|
||||
&ConnectionClient::connectedToLocalSocket);
|
||||
connectStandardOutputAndError(process);
|
||||
|
||||
connect(&localSocket,
|
||||
&QLocalSocket::connected,
|
||||
this,
|
||||
&ConnectionClient::resetProcessIsStarting);
|
||||
resetProcessAliveTimer();
|
||||
}
|
||||
|
||||
void ConnectionClient::connectLocalSocketDisconnected()
|
||||
{
|
||||
connect(&localSocket,
|
||||
connect(m_localSocket,
|
||||
&QLocalSocket::disconnected,
|
||||
this,
|
||||
&ConnectionClient::disconnectedFromLocalSocket);
|
||||
connect(m_localSocket,
|
||||
&QLocalSocket::disconnected,
|
||||
this,
|
||||
&ConnectionClient::restartProcessAsynchronously);
|
||||
}
|
||||
|
||||
void ConnectionClient::disconnectLocalSocketDisconnected()
|
||||
{
|
||||
if (m_localSocket) {
|
||||
disconnect(m_localSocket,
|
||||
&QLocalSocket::disconnected,
|
||||
this,
|
||||
&ConnectionClient::restartProcessAsynchronously);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionClient::finishProcess()
|
||||
{
|
||||
finishProcess(std::move(m_process));
|
||||
emit processFinished();
|
||||
}
|
||||
|
||||
void ConnectionClient::finishProcess(std::unique_ptr<QProcess> &&process)
|
||||
bool ConnectionClient::isProcessRunning()
|
||||
{
|
||||
getProcessFromFuture();
|
||||
|
||||
return isProcessRunning(m_process.get());
|
||||
}
|
||||
|
||||
void ConnectionClient::finishProcess(QProcessUniquePointer &&process)
|
||||
{
|
||||
disconnectLocalSocketDisconnected();
|
||||
|
||||
if (process) {
|
||||
m_processAliveTimer.stop();
|
||||
|
||||
disconnectProcessFinished(process.get());
|
||||
endProcess(process.get());
|
||||
disconnectFromServer();
|
||||
finishConnection();
|
||||
terminateProcess(process.get());
|
||||
killProcess(process.get());
|
||||
|
||||
resetCounter();
|
||||
} else {
|
||||
finishConnection();
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectionClient::waitForEcho()
|
||||
{
|
||||
return localSocket.waitForReadyRead();
|
||||
return m_localSocket->waitForReadyRead();
|
||||
}
|
||||
|
||||
bool ConnectionClient::waitForConnected()
|
||||
@@ -271,7 +291,7 @@ bool ConnectionClient::waitForConnected()
|
||||
bool isConnected = false;
|
||||
|
||||
for (int counter = 0; counter < 100; counter++) {
|
||||
isConnected = localSocket.waitForConnected(20);
|
||||
isConnected = m_localSocket && m_localSocket->waitForConnected(20);
|
||||
if (isConnected)
|
||||
return isConnected;
|
||||
else {
|
||||
@@ -280,52 +300,28 @@ bool ConnectionClient::waitForConnected()
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << outputName() << "cannot connect:" << localSocket.errorString();
|
||||
if (m_localSocket)
|
||||
qWarning() << outputName() << "cannot connect:" << m_localSocket->errorString();
|
||||
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
|
||||
QProcess *ConnectionClient::processForTestOnly() const
|
||||
QProcess *ConnectionClient::processForTestOnly()
|
||||
{
|
||||
getProcessFromFuture();
|
||||
|
||||
return m_process.get();
|
||||
}
|
||||
|
||||
QIODevice *ConnectionClient::ioDevice()
|
||||
{
|
||||
return &localSocket;
|
||||
return m_localSocket;
|
||||
}
|
||||
|
||||
bool ConnectionClient::isProcessIsRunning() const
|
||||
bool ConnectionClient::isProcessRunning(QProcess *process)
|
||||
{
|
||||
return m_process && m_process->state() == QProcess::Running;
|
||||
}
|
||||
|
||||
void ConnectionClient::connectProcessFinished(QProcess *process) const
|
||||
{
|
||||
connect(process,
|
||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
this,
|
||||
&ConnectionClient::restartProcessAsynchronously);
|
||||
|
||||
}
|
||||
|
||||
void ConnectionClient::connectProcessStarted(QProcess *process) const
|
||||
{
|
||||
connect(process,
|
||||
&QProcess::started,
|
||||
this,
|
||||
&ConnectionClient::connectToLocalSocket);
|
||||
}
|
||||
|
||||
void ConnectionClient::disconnectProcessFinished(QProcess *process) const
|
||||
{
|
||||
if (process) {
|
||||
disconnect(process,
|
||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
this,
|
||||
&ConnectionClient::restartProcessAsynchronously);
|
||||
}
|
||||
return process && process->state() == QProcess::Running;
|
||||
}
|
||||
|
||||
void ConnectionClient::connectStandardOutputAndError(QProcess *process) const
|
||||
@@ -336,7 +332,7 @@ void ConnectionClient::connectStandardOutputAndError(QProcess *process) const
|
||||
|
||||
void ConnectionClient::connectLocalSocketError() const
|
||||
{
|
||||
connect(&localSocket,
|
||||
connect(m_localSocket,
|
||||
static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
|
||||
this,
|
||||
&ConnectionClient::printLocalSocketError);
|
||||
@@ -350,14 +346,52 @@ void ConnectionClient::connectAliveTimer()
|
||||
&ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty);
|
||||
}
|
||||
|
||||
const QString &ConnectionClient::processPath() const
|
||||
void ConnectionClient::connectNewConnection()
|
||||
{
|
||||
return m_processPath;
|
||||
QObject::connect(&m_localServer,
|
||||
&QLocalServer::newConnection,
|
||||
this,
|
||||
&ConnectionClient::handleNewConnection);
|
||||
}
|
||||
|
||||
void ConnectionClient::handleNewConnection()
|
||||
{
|
||||
m_localSocket = m_localServer.nextPendingConnection();
|
||||
|
||||
connectLocalSocketError();
|
||||
connectLocalSocketDisconnected();
|
||||
|
||||
newConnectedServer(m_localSocket);
|
||||
|
||||
emit connectedToLocalSocket();
|
||||
}
|
||||
|
||||
void ConnectionClient::getProcessFromFuture()
|
||||
{
|
||||
try {
|
||||
if (m_processFuture.valid()) {
|
||||
m_process = m_processFuture.get();
|
||||
m_processIsStarting = false;
|
||||
|
||||
initializeProcess(m_process.get());
|
||||
}
|
||||
} catch (const ProcessException &processExeption) {
|
||||
qWarning() << "Clang backend process is not working."
|
||||
<< QLatin1String(processExeption.what());
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionClient::listenForConnections()
|
||||
{
|
||||
bool isListing = m_localServer.listen(connectionName());
|
||||
|
||||
if (!isListing)
|
||||
qWarning() << "ConnectionClient: QLocalServer is not listing for connections!";
|
||||
}
|
||||
|
||||
void ConnectionClient::setProcessPath(const QString &processPath)
|
||||
{
|
||||
m_processPath = processPath;
|
||||
m_processCreator.setProcessPath(processPath);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -27,14 +27,15 @@
|
||||
|
||||
#include "clangcodemodelserverproxy.h"
|
||||
#include "lineprefixer.h"
|
||||
#include "processcreator.h"
|
||||
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QScopedPointer>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
#include <future>
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -53,10 +54,10 @@ class CLANGSUPPORT_EXPORT ConnectionClient : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConnectionClient();
|
||||
ConnectionClient(const QString &connectionName);
|
||||
virtual ~ConnectionClient();
|
||||
|
||||
void startProcessAndConnectToServerAsynchronously();
|
||||
bool disconnectFromServer();
|
||||
bool isConnected() const;
|
||||
|
||||
void sendEndMessage();
|
||||
@@ -64,18 +65,17 @@ public:
|
||||
void resetProcessAliveTimer();
|
||||
void setProcessAliveTimerInterval(int processTimerInterval);
|
||||
|
||||
const QString &processPath() const;
|
||||
void setProcessPath(const QString &processPath);
|
||||
|
||||
void restartProcessAsynchronously();
|
||||
void restartProcessIfTimerIsNotResettedAndSocketIsEmpty();
|
||||
void finishProcess();
|
||||
bool isProcessIsRunning() const;
|
||||
bool isProcessRunning();
|
||||
|
||||
bool waitForEcho();
|
||||
bool waitForConnected();
|
||||
|
||||
QProcess *processForTestOnly() const;
|
||||
QProcess *processForTestOnly();
|
||||
|
||||
signals:
|
||||
void connectedToLocalSocket();
|
||||
@@ -90,48 +90,55 @@ protected:
|
||||
|
||||
virtual void sendEndCommand() = 0;
|
||||
virtual void resetCounter() = 0;
|
||||
virtual QString connectionName() const = 0;
|
||||
virtual QString outputName() const = 0;
|
||||
|
||||
QString connectionName() const;
|
||||
bool event(QEvent* event);
|
||||
|
||||
virtual void newConnectedServer(QIODevice *ioDevice) = 0;
|
||||
|
||||
private:
|
||||
std::unique_ptr<QProcess> startProcess();
|
||||
void finishProcess(std::unique_ptr<QProcess> &&process);
|
||||
void connectToLocalSocket();
|
||||
static bool isProcessRunning(QProcess *process);
|
||||
void finishProcess(QProcessUniquePointer &&process);
|
||||
void endProcess(QProcess *process);
|
||||
void terminateProcess(QProcess *process);
|
||||
void killProcess(QProcess *process);
|
||||
void resetProcessIsStarting();
|
||||
void finishConnection();
|
||||
void printLocalSocketError(QLocalSocket::LocalSocketError socketError);
|
||||
void printStandardOutput();
|
||||
void printStandardError();
|
||||
void initializeProcess(QProcess *process);
|
||||
|
||||
void resetTemporaryDir();
|
||||
void resetTemporaryDirectory();
|
||||
|
||||
void connectLocalSocketConnected();
|
||||
void connectLocalSocketDisconnected();
|
||||
void connectProcessFinished(QProcess *process) const;
|
||||
void connectProcessStarted(QProcess *process) const;
|
||||
void disconnectProcessFinished(QProcess *process) const;
|
||||
void disconnectLocalSocketDisconnected();
|
||||
void connectStandardOutputAndError(QProcess *process) const;
|
||||
void connectLocalSocketError() const;
|
||||
void connectAliveTimer();
|
||||
void connectNewConnection();
|
||||
void handleNewConnection();
|
||||
void getProcessFromFuture();
|
||||
void listenForConnections();
|
||||
|
||||
void ensureMessageIsWritten();
|
||||
|
||||
QProcessEnvironment processEnvironment() const;
|
||||
|
||||
protected:
|
||||
ProcessCreator m_processCreator;
|
||||
|
||||
private:
|
||||
LinePrefixer m_stdErrPrefixer;
|
||||
LinePrefixer m_stdOutPrefixer;
|
||||
|
||||
mutable std::unique_ptr<QProcess> m_process;
|
||||
QLocalSocket localSocket;
|
||||
std::unique_ptr<Utils::TemporaryDirectory> m_temporaryDirectory;
|
||||
QLocalServer m_localServer;
|
||||
std::future<QProcessUniquePointer> m_processFuture;
|
||||
mutable QProcessUniquePointer m_process;
|
||||
QLocalSocket *m_localSocket = nullptr;
|
||||
QTimer m_processAliveTimer;
|
||||
QString m_processPath;
|
||||
QString m_connectionName;
|
||||
bool m_isAliveTimerResetted = false;
|
||||
bool m_processIsStarting = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -27,7 +27,5 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
QString ConnectionName::connectionName;
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
@@ -41,46 +42,28 @@ namespace ClangBackEnd {
|
||||
class ClangCodeModelServerInterface;
|
||||
class ClangCodeModelClientProxy;
|
||||
|
||||
struct CLANGSUPPORT_EXPORT ConnectionName {
|
||||
static QString connectionName;
|
||||
};
|
||||
|
||||
template <typename ServerInterface,
|
||||
typename ClientProxy>
|
||||
class ConnectionServer
|
||||
{
|
||||
public:
|
||||
ConnectionServer(const QString &connectionName)
|
||||
ConnectionServer()
|
||||
{
|
||||
ConnectionName::connectionName = connectionName;
|
||||
|
||||
m_aliveTimer.start(5000);
|
||||
|
||||
m_localServer.setMaxPendingConnections(1);
|
||||
|
||||
QObject::connect(&m_localServer,
|
||||
&QLocalServer::newConnection,
|
||||
[&] { handleNewConnection(); });
|
||||
QObject::connect(&m_aliveTimer,
|
||||
&QTimer::timeout,
|
||||
[&] { sendAliveMessage(); });
|
||||
|
||||
std::atexit(&ConnectionServer::removeServer);
|
||||
#if defined(_GLIBCXX_HAVE_AT_QUICK_EXIT)
|
||||
std::at_quick_exit(&ConnectionServer::removeServer);
|
||||
#endif
|
||||
std::set_terminate(&ConnectionServer::removeServer);
|
||||
connectAliveTimer();
|
||||
connectLocalSocketDisconnet();
|
||||
}
|
||||
|
||||
~ConnectionServer()
|
||||
{
|
||||
removeServer();
|
||||
if (m_localSocket.state() != QLocalSocket::UnconnectedState)
|
||||
m_localSocket.disconnectFromServer();
|
||||
}
|
||||
|
||||
void start()
|
||||
void start(const QString &connectionName)
|
||||
{
|
||||
QLocalServer::removeServer(ConnectionName::connectionName);
|
||||
m_localServer.listen(ConnectionName::connectionName);
|
||||
connectToLocalServer(connectionName);
|
||||
}
|
||||
|
||||
void setServer(ServerInterface *ipcServer)
|
||||
@@ -89,17 +72,17 @@ public:
|
||||
|
||||
}
|
||||
|
||||
static void removeServer()
|
||||
{
|
||||
QLocalServer::removeServer(ConnectionName::connectionName);
|
||||
}
|
||||
|
||||
private:
|
||||
void handleNewConnection()
|
||||
void connectToLocalServer(const QString &connectionName)
|
||||
{
|
||||
m_localSocket = nextPendingConnection();
|
||||
QObject::connect(&m_localSocket,
|
||||
static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
|
||||
[&] (QLocalSocket::LocalSocketError) {
|
||||
qWarning() << "ConnectionServer error:" << m_localSocket.errorString() << connectionName;
|
||||
});
|
||||
|
||||
m_ipcClientProxy.reset(new ClientProxy(m_ipcServer, m_localSocket));
|
||||
m_localSocket.connectToServer(connectionName);
|
||||
m_ipcClientProxy = std::make_unique<ClientProxy>(m_ipcServer, &m_localSocket);
|
||||
|
||||
m_ipcServer->setClient(m_ipcClientProxy.get());
|
||||
}
|
||||
@@ -114,40 +97,40 @@ private:
|
||||
{
|
||||
m_ipcClientProxy.reset();
|
||||
|
||||
m_localSocket = nullptr;
|
||||
|
||||
delayedExitApplicationIfNoSockedIsConnected();
|
||||
}
|
||||
|
||||
QLocalSocket *nextPendingConnection()
|
||||
{
|
||||
QLocalSocket *localSocket = m_localServer.nextPendingConnection();
|
||||
|
||||
QObject::connect(localSocket,
|
||||
&QLocalSocket::disconnected,
|
||||
[&] { handleSocketDisconnect(); });
|
||||
|
||||
return localSocket;
|
||||
}
|
||||
|
||||
void delayedExitApplicationIfNoSockedIsConnected()
|
||||
{
|
||||
if (m_localSocket == nullptr)
|
||||
QTimer::singleShot(60000, [&] { exitApplicationIfNoSockedIsConnected(); });
|
||||
QTimer::singleShot(60000, [&] { exitApplicationIfNoSockedIsConnected(); });
|
||||
}
|
||||
|
||||
void exitApplicationIfNoSockedIsConnected()
|
||||
{
|
||||
if (m_localSocket == nullptr)
|
||||
QCoreApplication::exit();
|
||||
if (m_localSocket.state() != QLocalSocket::UnconnectedState)
|
||||
m_localSocket.disconnectFromServer();
|
||||
QCoreApplication::exit();
|
||||
}
|
||||
|
||||
void connectAliveTimer()
|
||||
{
|
||||
QObject::connect(&m_aliveTimer,
|
||||
&QTimer::timeout,
|
||||
[&] { sendAliveMessage(); });
|
||||
}
|
||||
|
||||
void connectLocalSocketDisconnet()
|
||||
{
|
||||
QObject::connect(&m_localSocket,
|
||||
&QLocalSocket::disconnected,
|
||||
[&] { handleSocketDisconnect(); });
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<ClientProxy> m_ipcClientProxy;
|
||||
QLocalSocket* m_localSocket;
|
||||
ServerInterface *m_ipcServer;
|
||||
QLocalServer m_localServer;
|
||||
QLocalSocket m_localSocket;
|
||||
QTimer m_aliveTimer;
|
||||
std::unique_ptr<ClientProxy> m_ipcClientProxy;
|
||||
ServerInterface *m_ipcServer;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -37,38 +37,23 @@
|
||||
namespace ClangBackEnd {
|
||||
|
||||
PchManagerServerProxy::PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice)
|
||||
: writeMessageBlock(ioDevice),
|
||||
readMessageBlock(ioDevice),
|
||||
client(client)
|
||||
: BaseServerProxy(client, ioDevice)
|
||||
{
|
||||
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { readMessages(); });
|
||||
}
|
||||
|
||||
void PchManagerServerProxy::end()
|
||||
{
|
||||
writeMessageBlock.write(EndMessage());
|
||||
m_writeMessageBlock.write(EndMessage());
|
||||
}
|
||||
|
||||
void PchManagerServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
|
||||
{
|
||||
writeMessageBlock.write(message);
|
||||
m_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();
|
||||
m_writeMessageBlock.write(message);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseserverproxy.h"
|
||||
#include "clangsupport_global.h"
|
||||
#include "pchmanagerserverinterface.h"
|
||||
#include "readmessageblock.h"
|
||||
@@ -42,25 +43,15 @@ namespace ClangBackEnd {
|
||||
|
||||
class PchManagerClientInterface;
|
||||
|
||||
class CLANGSUPPORT_EXPORT PchManagerServerProxy final : public PchManagerServerInterface
|
||||
class CLANGSUPPORT_EXPORT PchManagerServerProxy final : public BaseServerProxy,
|
||||
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
|
||||
|
173
src/libs/clangsupport/processcreator.cpp
Normal file
173
src/libs/clangsupport/processcreator.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 "processcreator.h"
|
||||
|
||||
#include "processexception.h"
|
||||
#include "processstartedevent.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
ProcessCreator::ProcessCreator()
|
||||
{
|
||||
}
|
||||
|
||||
void ProcessCreator::setTemporaryDirectoryPattern(const QString &temporaryDirectoryPattern)
|
||||
{
|
||||
m_temporaryDirectoryPattern = temporaryDirectoryPattern;
|
||||
resetTemporaryDirectory();
|
||||
}
|
||||
|
||||
void ProcessCreator::setProcessPath(const QString &processPath)
|
||||
{
|
||||
m_processPath = processPath;
|
||||
}
|
||||
|
||||
void ProcessCreator::setArguments(const QStringList &arguments)
|
||||
{
|
||||
m_arguments = arguments;
|
||||
}
|
||||
|
||||
std::future<QProcessUniquePointer> ProcessCreator::createProcess() const
|
||||
{
|
||||
return std::async(std::launch::async, [&] {
|
||||
checkIfProcessPathExists();
|
||||
auto process = QProcessUniquePointer(new QProcess);
|
||||
process->setProcessChannelMode(QProcess::QProcess::ForwardedChannels);
|
||||
process->setProcessEnvironment(processEnvironment());
|
||||
process->start(m_processPath, m_arguments);
|
||||
process->waitForStarted(5000);
|
||||
|
||||
checkIfProcessWasStartingSuccessful(process.get());
|
||||
|
||||
postProcessStartedEvent();
|
||||
|
||||
process->moveToThread(QCoreApplication::instance()->thread());
|
||||
|
||||
return process;
|
||||
});
|
||||
}
|
||||
|
||||
void ProcessCreator::setObserver(QObject *observer)
|
||||
{
|
||||
this->m_observer = observer;
|
||||
}
|
||||
|
||||
void ProcessCreator::checkIfProcessPathExists() const
|
||||
{
|
||||
if (!QFileInfo::exists(m_processPath)) {
|
||||
const QString messageTemplate = QCoreApplication::translate("ProcessCreator",
|
||||
"Executable does not exists: %1");
|
||||
throwProcessException(messageTemplate.arg(m_processPath));
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessCreator::checkIfProcessWasStartingSuccessful(QProcess *process) const
|
||||
{
|
||||
if (process->exitStatus() == QProcess::CrashExit || process->exitCode() != 0)
|
||||
dispatchProcessError(process);
|
||||
}
|
||||
|
||||
void ProcessCreator::dispatchProcessError(QProcess *process) const
|
||||
{
|
||||
switch (process->error()) {
|
||||
case QProcess::UnknownError: {
|
||||
const QString message = QCoreApplication::translate("ProcessCreator",
|
||||
"Unknown error happend.");
|
||||
throwProcessException(message);
|
||||
};
|
||||
case QProcess::Crashed: {
|
||||
const QString message = QCoreApplication::translate("ProcessCreator",
|
||||
"Process crashed.");
|
||||
throwProcessException(message);
|
||||
};
|
||||
case QProcess::FailedToStart: {
|
||||
const QString message = QCoreApplication::translate("ProcessCreator",
|
||||
"Process failed at startup.");
|
||||
throwProcessException(message);
|
||||
};
|
||||
case QProcess::Timedout: {
|
||||
const QString message = QCoreApplication::translate("ProcessCreator",
|
||||
"Process timeouted.");
|
||||
throwProcessException(message);
|
||||
};
|
||||
case QProcess::WriteError: {
|
||||
const QString message = QCoreApplication::translate("ProcessCreator",
|
||||
"Cannot write to process.");
|
||||
throwProcessException(message);
|
||||
};
|
||||
case QProcess::ReadError: {
|
||||
const QString message = QCoreApplication::translate("ProcessCreator",
|
||||
"Cannot read from process.");
|
||||
throwProcessException(message);
|
||||
};
|
||||
}
|
||||
|
||||
throwProcessException("Internal impossible error!");
|
||||
}
|
||||
|
||||
void ProcessCreator::postProcessStartedEvent() const
|
||||
{
|
||||
if (m_observer)
|
||||
QCoreApplication::postEvent(m_observer, new ProcessStartedEvent);
|
||||
}
|
||||
|
||||
void ProcessCreator::throwProcessException(const QString &message) const
|
||||
{
|
||||
postProcessStartedEvent();
|
||||
throw ProcessException(message);
|
||||
}
|
||||
|
||||
const QTemporaryDir &ProcessCreator::temporaryDirectory() const
|
||||
{
|
||||
return *m_temporaryDirectory.get();
|
||||
}
|
||||
|
||||
void ProcessCreator::resetTemporaryDirectory()
|
||||
{
|
||||
m_temporaryDirectory = std::make_unique<Utils::TemporaryDirectory>(m_temporaryDirectoryPattern);
|
||||
}
|
||||
|
||||
QProcessEnvironment ProcessCreator::processEnvironment() const
|
||||
{
|
||||
auto processEnvironment = QProcessEnvironment::systemEnvironment();
|
||||
|
||||
if (temporaryDirectory().isValid()) {
|
||||
const QString temporaryDirectoryPath = temporaryDirectory().path();
|
||||
processEnvironment.insert("TMPDIR", temporaryDirectoryPath);
|
||||
processEnvironment.insert("TMP", temporaryDirectoryPath);
|
||||
processEnvironment.insert("TEMP", temporaryDirectoryPath);
|
||||
}
|
||||
|
||||
return processEnvironment;
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
78
src/libs/clangsupport/processcreator.h
Normal file
78
src/libs/clangsupport/processcreator.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 <clangsupport_global.h>
|
||||
|
||||
#include "processhandle.h"
|
||||
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include <future>
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTemporaryDir;
|
||||
class QProcessEnvironment;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class CLANGSUPPORT_EXPORT ProcessCreator
|
||||
{
|
||||
public:
|
||||
ProcessCreator();
|
||||
|
||||
void setTemporaryDirectoryPattern(const QString &temporaryDirectoryPattern);
|
||||
void setProcessPath(const QString &m_processPath);
|
||||
void setArguments(const QStringList &m_arguments);
|
||||
void setObserver(QObject *m_observer);
|
||||
|
||||
std::future<QProcessUniquePointer> createProcess() const;
|
||||
|
||||
const QTemporaryDir &temporaryDirectory() const;
|
||||
void resetTemporaryDirectory();
|
||||
|
||||
private:
|
||||
void checkIfProcessPathExists() const;
|
||||
void checkIfProcessWasStartingSuccessful(QProcess *process) const;
|
||||
[[noreturn]] void dispatchProcessError(QProcess *process) const;
|
||||
void postProcessStartedEvent() const;
|
||||
[[noreturn]] void throwProcessException(const QString &message) const;
|
||||
|
||||
QProcessEnvironment processEnvironment() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Utils::TemporaryDirectory> m_temporaryDirectory;
|
||||
QString m_processPath;
|
||||
QString m_temporaryDirectoryPattern;
|
||||
QStringList m_arguments;
|
||||
QObject *m_observer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
40
src/libs/clangsupport/processexception.cpp
Normal file
40
src/libs/clangsupport/processexception.cpp
Normal 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "processexception.h"
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
ProcessException::ProcessException(Utils::SmallString &&what)
|
||||
: what_(std::move(what))
|
||||
{
|
||||
}
|
||||
|
||||
const char *ProcessException::what() const noexcept
|
||||
{
|
||||
return what_.data();
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
46
src/libs/clangsupport/processexception.h
Normal file
46
src/libs/clangsupport/processexception.h
Normal 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 <utils/smallstring.h>
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class ProcessException : public std::exception
|
||||
{
|
||||
public:
|
||||
ProcessException() = default;
|
||||
ProcessException(Utils::SmallString &&what);
|
||||
|
||||
const char *what() const noexcept final;
|
||||
|
||||
private:
|
||||
Utils::SmallString what_;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
46
src/libs/clangsupport/processhandle.h
Normal file
46
src/libs/clangsupport/processhandle.h
Normal 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 <QProcess>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class QProcessUniquePointerDeleter
|
||||
{
|
||||
public:
|
||||
void operator()(QProcess* process)
|
||||
{
|
||||
process->kill();
|
||||
process->waitForFinished();
|
||||
}
|
||||
};
|
||||
|
||||
using QProcessUniquePointer = std::unique_ptr<QProcess, QProcessUniquePointerDeleter>;
|
||||
|
||||
} // namespace ClangBackEnd
|
34
src/libs/clangsupport/processstartedevent.cpp
Normal file
34
src/libs/clangsupport/processstartedevent.cpp
Normal 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 "processstartedevent.h"
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
ProcessStartedEvent::~ProcessStartedEvent()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
44
src/libs/clangsupport/processstartedevent.h
Normal file
44
src/libs/clangsupport/processstartedevent.h
Normal 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class ProcessStartedEvent : public QEvent
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
ProcessStarted = QEvent::User + 3456
|
||||
};
|
||||
|
||||
ProcessStartedEvent()
|
||||
: QEvent(static_cast<QEvent::Type>(ProcessStarted))
|
||||
{}
|
||||
|
||||
~ProcessStartedEvent() override;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
@@ -77,14 +77,14 @@ MessageEnvelop ReadMessageBlock::read()
|
||||
return message;
|
||||
}
|
||||
|
||||
QVector<MessageEnvelop> ReadMessageBlock::readAll()
|
||||
std::vector<MessageEnvelop> ReadMessageBlock::readAll()
|
||||
{
|
||||
QVector<MessageEnvelop> messages;
|
||||
std::vector<MessageEnvelop> messages;
|
||||
|
||||
while (true) {
|
||||
const MessageEnvelop message = read();
|
||||
MessageEnvelop message = read();
|
||||
if (message.isValid())
|
||||
messages.append(message);
|
||||
messages.push_back(std::move(message));
|
||||
else
|
||||
return messages;
|
||||
}
|
||||
@@ -97,6 +97,11 @@ void ReadMessageBlock::resetCounter()
|
||||
m_messageCounter = 0;
|
||||
}
|
||||
|
||||
void ReadMessageBlock::setIoDevice(QIODevice *ioDevice)
|
||||
{
|
||||
m_ioDevice = ioDevice;
|
||||
}
|
||||
|
||||
bool ReadMessageBlock::isTheWholeMessageReadable(QDataStream &in)
|
||||
{
|
||||
if (m_ioDevice->bytesAvailable() < qint64(sizeof(m_blockSize)))
|
||||
|
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <vector>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDataStream;
|
||||
class QIODevice;
|
||||
@@ -42,10 +44,12 @@ public:
|
||||
ReadMessageBlock(QIODevice *ioDevice = nullptr);
|
||||
|
||||
MessageEnvelop read();
|
||||
QVector<MessageEnvelop> readAll();
|
||||
std::vector<MessageEnvelop> readAll();
|
||||
|
||||
void resetCounter();
|
||||
|
||||
void setIoDevice(QIODevice *ioDevice);
|
||||
|
||||
private:
|
||||
bool isTheWholeMessageReadable(QDataStream &in);
|
||||
bool checkIfMessageIsLost(QDataStream &in);
|
||||
|
@@ -35,58 +35,43 @@
|
||||
namespace ClangBackEnd {
|
||||
|
||||
RefactoringServerProxy::RefactoringServerProxy(RefactoringClientInterface *client, QIODevice *ioDevice)
|
||||
: writeMessageBlock(ioDevice),
|
||||
readMessageBlock(ioDevice),
|
||||
client(client)
|
||||
: BaseServerProxy(client, ioDevice)
|
||||
{
|
||||
QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { readMessages(); });
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::end()
|
||||
{
|
||||
writeMessageBlock.write(EndMessage());
|
||||
m_writeMessageBlock.write(EndMessage());
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message)
|
||||
{
|
||||
writeMessageBlock.write(message);
|
||||
m_writeMessageBlock.write(message);
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message)
|
||||
{
|
||||
writeMessageBlock.write(message);
|
||||
m_writeMessageBlock.write(message);
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message)
|
||||
{
|
||||
writeMessageBlock.write(message);
|
||||
m_writeMessageBlock.write(message);
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
|
||||
{
|
||||
writeMessageBlock.write(message);
|
||||
m_writeMessageBlock.write(message);
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message)
|
||||
{
|
||||
writeMessageBlock.write(message);
|
||||
m_writeMessageBlock.write(message);
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::cancel()
|
||||
{
|
||||
writeMessageBlock.write(CancelMessage());
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::readMessages()
|
||||
{
|
||||
for (const auto &message : readMessageBlock.readAll())
|
||||
client->dispatch(message);
|
||||
}
|
||||
|
||||
void RefactoringServerProxy::resetCounter()
|
||||
{
|
||||
writeMessageBlock.resetCounter();
|
||||
readMessageBlock.resetCounter();
|
||||
m_writeMessageBlock.write(CancelMessage());
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseserverproxy.h"
|
||||
#include "clangsupport_global.h"
|
||||
#include "refactoringserverinterface.h"
|
||||
#include "readmessageblock.h"
|
||||
@@ -42,12 +43,11 @@ namespace ClangBackEnd {
|
||||
|
||||
class RefactoringClientInterface;
|
||||
|
||||
class CLANGSUPPORT_EXPORT RefactoringServerProxy final : public RefactoringServerInterface
|
||||
class CLANGSUPPORT_EXPORT RefactoringServerProxy final : public BaseServerProxy,
|
||||
public RefactoringServerInterface
|
||||
{
|
||||
public:
|
||||
explicit RefactoringServerProxy(RefactoringClientInterface *client, QIODevice *ioDevice);
|
||||
RefactoringServerProxy(const RefactoringServerProxy&) = delete;
|
||||
const RefactoringServerProxy &operator=(const RefactoringServerProxy&) = delete;
|
||||
|
||||
void end() override;
|
||||
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
|
||||
@@ -56,15 +56,6 @@ public:
|
||||
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
|
||||
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
|
||||
void cancel() override;
|
||||
|
||||
void readMessages();
|
||||
|
||||
void resetCounter();
|
||||
|
||||
private:
|
||||
ClangBackEnd::WriteMessageBlock writeMessageBlock;
|
||||
ClangBackEnd::ReadMessageBlock readMessageBlock;
|
||||
RefactoringClientInterface *client = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -72,6 +72,10 @@ void WriteMessageBlock::resetCounter()
|
||||
m_messageCounter = 0;
|
||||
}
|
||||
|
||||
void WriteMessageBlock::setIoDevice(QIODevice *ioDevice)
|
||||
{
|
||||
m_ioDevice = ioDevice;
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
|
@@ -48,6 +48,8 @@ public:
|
||||
|
||||
void resetCounter();
|
||||
|
||||
void setIoDevice(QIODevice *ioDevice);
|
||||
|
||||
private:
|
||||
qint64 m_messageCounter;
|
||||
QIODevice *m_ioDevice;
|
||||
|
@@ -25,8 +25,9 @@
|
||||
|
||||
#include "pchmanagerconnectionclient.h"
|
||||
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
namespace ClangPchManager {
|
||||
|
||||
@@ -41,30 +42,35 @@ QString currentProcessId()
|
||||
|
||||
ClangPchManager::PchManagerConnectionClient::PchManagerConnectionClient(
|
||||
ClangBackEnd::PchManagerClientInterface *client)
|
||||
: serverProxy_(client, ioDevice())
|
||||
: ConnectionClient(Utils::TemporaryDirectory::masterDirectoryPath()
|
||||
+ QStringLiteral("/ClangPchManagerBackEnd-")
|
||||
+ currentProcessId()),
|
||||
m_serverProxy(client, ioDevice())
|
||||
{
|
||||
m_processCreator.setTemporaryDirectoryPattern("clangpchmanagerbackend-XXXXXX");
|
||||
|
||||
stdErrPrefixer().setPrefix("PchManagerConnectionClient.stderr: ");
|
||||
stdOutPrefixer().setPrefix("PchManagerConnectionClient.stdout: ");
|
||||
}
|
||||
|
||||
PchManagerConnectionClient::~PchManagerConnectionClient()
|
||||
{
|
||||
finishProcess();
|
||||
}
|
||||
|
||||
ClangBackEnd::PchManagerServerProxy &ClangPchManager::PchManagerConnectionClient::serverProxy()
|
||||
{
|
||||
return serverProxy_;
|
||||
return m_serverProxy;
|
||||
}
|
||||
|
||||
void ClangPchManager::PchManagerConnectionClient::sendEndCommand()
|
||||
{
|
||||
serverProxy_.end();
|
||||
m_serverProxy.end();
|
||||
}
|
||||
|
||||
void PchManagerConnectionClient::resetCounter()
|
||||
{
|
||||
serverProxy_.resetCounter();
|
||||
}
|
||||
|
||||
QString ClangPchManager::PchManagerConnectionClient::connectionName() const
|
||||
{
|
||||
return temporaryDirectory().path() + QStringLiteral("/ClangPchManagerBackEnd-") + currentProcessId();
|
||||
m_serverProxy.resetCounter();
|
||||
}
|
||||
|
||||
QString PchManagerConnectionClient::outputName() const
|
||||
@@ -72,4 +78,9 @@ QString PchManagerConnectionClient::outputName() const
|
||||
return QStringLiteral("PchManagerConnectionClient");
|
||||
}
|
||||
|
||||
void PchManagerConnectionClient::newConnectedServer(QIODevice *ioDevice)
|
||||
{
|
||||
m_serverProxy.setIoDevice(ioDevice);
|
||||
}
|
||||
|
||||
} // namespace ClangPchManager
|
||||
|
@@ -34,17 +34,18 @@ class PchManagerConnectionClient : public ClangBackEnd::ConnectionClient
|
||||
{
|
||||
public:
|
||||
PchManagerConnectionClient(ClangBackEnd::PchManagerClientInterface *client);
|
||||
~PchManagerConnectionClient();
|
||||
|
||||
ClangBackEnd::PchManagerServerProxy &serverProxy();
|
||||
|
||||
protected:
|
||||
void sendEndCommand() override;
|
||||
void resetCounter() override;
|
||||
QString connectionName() const override;
|
||||
QString outputName() const override;
|
||||
void newConnectedServer(QIODevice *ioDevice) override;
|
||||
|
||||
private:
|
||||
ClangBackEnd::PchManagerServerProxy serverProxy_;
|
||||
ClangBackEnd::PchManagerServerProxy m_serverProxy;
|
||||
};
|
||||
|
||||
} // namespace ClangPchManager
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "refactoringconnectionclient.h"
|
||||
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
@@ -39,8 +41,13 @@ QString currentProcessId()
|
||||
}
|
||||
|
||||
RefactoringConnectionClient::RefactoringConnectionClient(RefactoringClientInterface *client)
|
||||
: serverProxy_(client, ioDevice())
|
||||
: ConnectionClient(Utils::TemporaryDirectory::masterDirectoryPath()
|
||||
+ QStringLiteral("/ClangRefactoringBackEnd-")
|
||||
+ currentProcessId()),
|
||||
m_serverProxy(client, nullptr)
|
||||
{
|
||||
m_processCreator.setTemporaryDirectoryPattern("clangrefactoringbackend-XXXXXX");
|
||||
|
||||
stdErrPrefixer().setPrefix("RefactoringConnectionClient.stderr: ");
|
||||
stdOutPrefixer().setPrefix("RefactoringConnectionClient.stdout: ");
|
||||
}
|
||||
@@ -52,22 +59,17 @@ RefactoringConnectionClient::~RefactoringConnectionClient()
|
||||
|
||||
RefactoringServerProxy &RefactoringConnectionClient::serverProxy()
|
||||
{
|
||||
return serverProxy_;
|
||||
return m_serverProxy;
|
||||
}
|
||||
|
||||
void RefactoringConnectionClient::sendEndCommand()
|
||||
{
|
||||
serverProxy_.end();
|
||||
m_serverProxy.end();
|
||||
}
|
||||
|
||||
void RefactoringConnectionClient::resetCounter()
|
||||
{
|
||||
serverProxy_.resetCounter();
|
||||
}
|
||||
|
||||
QString RefactoringConnectionClient::connectionName() const
|
||||
{
|
||||
return temporaryDirectory().path() + QStringLiteral("/ClangRefactoringBackEnd-") + currentProcessId();
|
||||
m_serverProxy.resetCounter();
|
||||
}
|
||||
|
||||
QString RefactoringConnectionClient::outputName() const
|
||||
@@ -75,4 +77,9 @@ QString RefactoringConnectionClient::outputName() const
|
||||
return QStringLiteral("RefactoringConnectionClient");
|
||||
}
|
||||
|
||||
void RefactoringConnectionClient::newConnectedServer(QIODevice *ioDevice)
|
||||
{
|
||||
m_serverProxy.setIoDevice(ioDevice);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -43,11 +43,11 @@ public:
|
||||
protected:
|
||||
void sendEndCommand() override;
|
||||
void resetCounter() override;
|
||||
QString connectionName() const override;
|
||||
QString outputName() const override;
|
||||
void newConnectedServer(QIODevice *ioDevice) override;
|
||||
|
||||
private:
|
||||
RefactoringServerProxy serverProxy_;
|
||||
RefactoringServerProxy m_serverProxy;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -41,8 +41,8 @@ namespace ClangRefactoring {
|
||||
class RefactoringEngine : public CppTools::RefactoringEngineInterface
|
||||
{
|
||||
public:
|
||||
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &m_server,
|
||||
ClangBackEnd::RefactoringClientInterface &m_client,
|
||||
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
|
||||
ClangBackEnd::RefactoringClientInterface &client,
|
||||
ClangBackEnd::FilePathCachingInterface &filePathCache,
|
||||
SymbolQueryInterface &symbolQuery);
|
||||
~RefactoringEngine() override;
|
||||
|
@@ -72,9 +72,9 @@ int main(int argc, char *argv[])
|
||||
clang_enableStackTraces();
|
||||
|
||||
ClangCodeModelServer clangCodeModelServer;
|
||||
ConnectionServer<ClangCodeModelServer, ClangCodeModelClientProxy> connectionServer(connection);
|
||||
connectionServer.start();
|
||||
ConnectionServer<ClangCodeModelServer, ClangCodeModelClientProxy> connectionServer;
|
||||
connectionServer.setServer(&clangCodeModelServer);
|
||||
connectionServer.start(connection);
|
||||
|
||||
return application.exec();
|
||||
}
|
||||
|
@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
QCoreApplication application(argc, argv);
|
||||
|
||||
const QString connection = processArguments(application);
|
||||
const QString connectionName = processArguments(application);
|
||||
|
||||
Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
@@ -120,9 +120,9 @@ int main(int argc, char *argv[])
|
||||
includeWatcher.setNotifier(&clangPchManagerServer);
|
||||
pchGenerator.setNotifier(&clangPchManagerServer);
|
||||
|
||||
ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer(connection);
|
||||
connectionServer.start();
|
||||
ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer;
|
||||
connectionServer.setServer(&clangPchManagerServer);
|
||||
connectionServer.start(connectionName);
|
||||
|
||||
return application.exec();
|
||||
}
|
||||
|
@@ -76,9 +76,9 @@ try {
|
||||
FilePathCaching filePathCache{database};
|
||||
SymbolIndexing symbolIndexing{database, filePathCache};
|
||||
RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache};
|
||||
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection);
|
||||
connectionServer.start();
|
||||
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer;
|
||||
connectionServer.setServer(&clangCodeModelServer);
|
||||
connectionServer.start(connection);
|
||||
|
||||
|
||||
return application.exec();
|
||||
|
@@ -31,7 +31,6 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
void EchoClangCodeModelServer::dispatch(const MessageEnvelop &message)
|
||||
@@ -41,7 +40,6 @@ void EchoClangCodeModelServer::dispatch(const MessageEnvelop &message)
|
||||
|
||||
void EchoClangCodeModelServer::end()
|
||||
{
|
||||
ConnectionServer<EchoClangCodeModelServer, ClangCodeModelClientProxy>::removeServer();
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
|
@@ -43,15 +43,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
QCoreApplication application(argc, argv);
|
||||
|
||||
if (application.arguments().count() != 2) {
|
||||
qWarning() << "wrong argument count";
|
||||
|
||||
if (application.arguments().count() < 2)
|
||||
return 1;
|
||||
}
|
||||
else if (application.arguments().count() == 3)
|
||||
*(int*)0 = 0;
|
||||
else if (application.arguments().contains("connectionName"))
|
||||
return 0;
|
||||
|
||||
EchoClangCodeModelServer echoClangCodeModelServer;
|
||||
ConnectionServer<EchoClangCodeModelServer, ClangCodeModelClientProxy> connectionServer(application.arguments()[1]);
|
||||
connectionServer.start();
|
||||
ConnectionServer<EchoClangCodeModelServer, ClangCodeModelClientProxy> connectionServer;
|
||||
connectionServer.setServer(&echoClangCodeModelServer);
|
||||
connectionServer.start(application.arguments()[1]);
|
||||
|
||||
return application.exec();
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ using ::testing::SizeIs;
|
||||
struct Data {
|
||||
Data() : client(&mockClangCodeModelClient) {}
|
||||
|
||||
MockClangCodeModelClient mockClangCodeModelClient;
|
||||
NiceMock<MockClangCodeModelClient> mockClangCodeModelClient;
|
||||
ClangBackEnd::ClangCodeModelConnectionClient client;
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAsynchronously)
|
||||
client.restartProcessAsynchronously();
|
||||
|
||||
ASSERT_TRUE(clientSpy.wait(100000));
|
||||
ASSERT_TRUE(client.isProcessIsRunning());
|
||||
ASSERT_TRUE(client.isProcessRunning());
|
||||
ASSERT_TRUE(client.isConnected());
|
||||
}
|
||||
|
||||
@@ -200,6 +200,6 @@ void ClientServerOutsideProcess::TearDown()
|
||||
client.setProcessAliveTimerInterval(1000000);
|
||||
client.waitForConnected();
|
||||
|
||||
ASSERT_TRUE(client.isProcessIsRunning());
|
||||
ASSERT_TRUE(client.isProcessRunning());
|
||||
ASSERT_TRUE(client.isConnected());
|
||||
}
|
||||
|
62
tests/unit/unittest/eventspy.cpp
Normal file
62
tests/unit/unittest/eventspy.cpp
Normal 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "eventspy.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QEvent>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
EventSpy::EventSpy(uint eventType)
|
||||
: startTime(std::chrono::steady_clock::now()),
|
||||
eventType(eventType)
|
||||
{
|
||||
}
|
||||
|
||||
bool EventSpy::waitForEvent()
|
||||
{
|
||||
while (shouldRun())
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
return eventHappened;
|
||||
}
|
||||
|
||||
bool EventSpy::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == eventType) {
|
||||
eventHappened = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventSpy::shouldRun() const
|
||||
{
|
||||
return !eventHappened
|
||||
&& (std::chrono::steady_clock::now() - startTime) < 1s;
|
||||
}
|
51
tests/unit/unittest/eventspy.h
Normal file
51
tests/unit/unittest/eventspy.h
Normal 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 <QObject>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class EventSpy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EventSpy(uint eventType);
|
||||
|
||||
bool waitForEvent();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
private:
|
||||
bool shouldRun() const;
|
||||
|
||||
private:
|
||||
std::chrono::steady_clock::time_point startTime;
|
||||
uint eventType;
|
||||
bool eventHappened = false;
|
||||
};
|
@@ -33,7 +33,6 @@ using testing::AnyNumber;
|
||||
using testing::AnyOf;
|
||||
using testing::Contains;
|
||||
using testing::ElementsAre;
|
||||
using testing::Eq;
|
||||
using testing::Field;
|
||||
using testing::HasSubstr;
|
||||
using testing::InSequence;
|
||||
@@ -51,3 +50,10 @@ using testing::SizeIs;
|
||||
using testing::StrEq;
|
||||
using testing::Throw;
|
||||
using testing::UnorderedElementsAre;
|
||||
|
||||
using testing::Eq;
|
||||
using testing::Ge;
|
||||
using testing::Gt;
|
||||
using testing::Le;
|
||||
using testing::Lt;
|
||||
using testing::Ne;
|
||||
|
121
tests/unit/unittest/processcreator-test.cpp
Normal file
121
tests/unit/unittest/processcreator-test.cpp
Normal 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 "googletest.h"
|
||||
|
||||
#include "eventspy.h"
|
||||
|
||||
#include <processcreator.h>
|
||||
#include <processexception.h>
|
||||
#include <processstartedevent.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
#include <future>
|
||||
|
||||
using testing::NotNull;
|
||||
|
||||
using ClangBackEnd::ProcessCreator;
|
||||
using ClangBackEnd::ProcessException;
|
||||
using ClangBackEnd::ProcessStartedEvent;
|
||||
|
||||
namespace {
|
||||
|
||||
class ProcessCreator : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp();
|
||||
|
||||
protected:
|
||||
::ProcessCreator processCreator;
|
||||
QStringList m_arguments = {QStringLiteral("connectionName")};
|
||||
};
|
||||
|
||||
TEST_F(ProcessCreator, ProcessIsNotNull)
|
||||
{
|
||||
auto future = processCreator.createProcess();
|
||||
auto process = future.get();
|
||||
|
||||
ASSERT_THAT(process.get(), NotNull());
|
||||
}
|
||||
|
||||
TEST_F(ProcessCreator, ProcessIsRunning)
|
||||
{
|
||||
auto future = processCreator.createProcess();
|
||||
auto process = future.get();
|
||||
|
||||
ASSERT_THAT(process->state(), QProcess::Running);
|
||||
}
|
||||
|
||||
TEST_F(ProcessCreator, ProcessPathIsNotExisting)
|
||||
{
|
||||
processCreator.setProcessPath(Utils::HostOsInfo::withExecutableSuffix(ECHOSERVER"fail"));
|
||||
|
||||
auto future = processCreator.createProcess();
|
||||
ASSERT_THROW(future.get(), ProcessException);
|
||||
}
|
||||
|
||||
TEST_F(ProcessCreator, ProcessStartIsSucessfull)
|
||||
{
|
||||
auto future = processCreator.createProcess();
|
||||
ASSERT_NO_THROW(future.get());
|
||||
}
|
||||
|
||||
TEST_F(ProcessCreator, ProcessObserverGetsEvent)
|
||||
{
|
||||
EventSpy eventSpy(ProcessStartedEvent::ProcessStarted);
|
||||
processCreator.setObserver(&eventSpy);
|
||||
auto future = processCreator.createProcess();
|
||||
|
||||
eventSpy.waitForEvent();
|
||||
}
|
||||
|
||||
TEST_F(ProcessCreator, TemporayPathIsSetForDefaultInitialization)
|
||||
{
|
||||
QString path = processCreator.temporaryDirectory().path();
|
||||
|
||||
ASSERT_THAT(path.size(), Gt(0));
|
||||
}
|
||||
|
||||
TEST_F(ProcessCreator, TemporayPathIsResetted)
|
||||
{
|
||||
std::string oldPath = processCreator.temporaryDirectory().path().toStdString();
|
||||
|
||||
processCreator.resetTemporaryDirectory();
|
||||
|
||||
ASSERT_THAT(processCreator.temporaryDirectory().path().toStdString(),
|
||||
AllOf(Not(IsEmpty()), Ne(oldPath)));
|
||||
}
|
||||
|
||||
void ProcessCreator::SetUp()
|
||||
{
|
||||
processCreator.setTemporaryDirectoryPattern("process-XXXXXXX");
|
||||
processCreator.resetTemporaryDirectory();
|
||||
processCreator.setProcessPath(Utils::HostOsInfo::withExecutableSuffix(ECHOSERVER));
|
||||
processCreator.setArguments(m_arguments);
|
||||
}
|
||||
}
|
@@ -119,7 +119,7 @@ TEST_F(ReadAndWriteMessageBlock, ReadThreeMessagesAndTestCount)
|
||||
writeMessageBlock.write(ClangBackEnd::EndMessage());
|
||||
buffer.seek(0);
|
||||
|
||||
ASSERT_EQ(3, readMessageBlock.readAll().count());
|
||||
ASSERT_THAT(readMessageBlock.readAll(), SizeIs(3));
|
||||
}
|
||||
|
||||
TEST_F(ReadAndWriteMessageBlock, CompareEndMessage)
|
||||
|
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocument>
|
||||
|
||||
@@ -74,9 +75,10 @@ protected:
|
||||
NiceMock<MockSearchHandle> mockSearchHandle;
|
||||
NiceMock<MockSymbolQuery> mockSymbolQuery;
|
||||
MockRefactoringClientCallBack callbackMock;
|
||||
QBuffer ioDevice;
|
||||
ClangRefactoring::RefactoringClient client;
|
||||
ClangBackEnd::RefactoringConnectionClient connectionClient{&client};
|
||||
RefactoringEngine engine{connectionClient.serverProxy(), client, mockFilePathCaching, mockSymbolQuery};
|
||||
ClangBackEnd::RefactoringServerProxy serverProxy{&client, &ioDevice};
|
||||
RefactoringEngine engine{serverProxy, client, mockFilePathCaching, mockSymbolQuery};
|
||||
QString fileContent{QStringLiteral("int x;\nint y;")};
|
||||
QTextDocument textDocument{fileContent};
|
||||
QTextCursor cursor{&textDocument};
|
||||
|
@@ -70,6 +70,7 @@ SOURCES += \
|
||||
spydummy.cpp \
|
||||
symbolindexer-test.cpp \
|
||||
stringcache-test.cpp \
|
||||
eventspy.cpp \
|
||||
unittests-main.cpp \
|
||||
utf8-test.cpp \
|
||||
symbolstorage-test.cpp \
|
||||
@@ -82,6 +83,7 @@ SOURCES += \
|
||||
filepathcache-test.cpp \
|
||||
filepathstorage-test.cpp \
|
||||
filepathstoragesqlitestatementfactory-test.cpp \
|
||||
processcreator-test.cpp \
|
||||
nativefilepath-test.cpp \
|
||||
nativefilepathview-test.cpp
|
||||
|
||||
@@ -176,6 +178,7 @@ HEADERS += \
|
||||
conditionally-disabled-tests.h \
|
||||
dummyclangipcclient.h \
|
||||
dynamicastmatcherdiagnosticcontainer-matcher.h \
|
||||
eventspy.h \
|
||||
fakeprocess.h \
|
||||
faketimer.h \
|
||||
filesystem-utilities.h \
|
||||
|
Reference in New Issue
Block a user