LSP: split out settings specific for std io clients

Change-Id: I25eebfc15a9d0d5665e57137f016e54a069ca849
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2018-09-18 10:43:17 +02:00
parent 0ebe8402c7
commit c37bedfb02
5 changed files with 165 additions and 85 deletions

View File

@@ -499,6 +499,11 @@ bool BaseClient::isSupportedMimeType(const QString &mimeType) const
return m_supportedMimeTypes.isEmpty() || m_supportedMimeTypes.contains(mimeType);
}
bool BaseClient::needsRestart(const BaseSettings *) const
{
return false;
}
bool BaseClient::reset()
{
if (!m_restartsLeft)
@@ -756,6 +761,11 @@ StdIOClient::~StdIOClient()
Utils::SynchronousProcess::stopProcess(m_process);
}
bool StdIOClient::needsRestart(const StdIOSettings *settings)
{
return m_executable != settings->m_executable || m_arguments != settings->m_arguments;
}
bool StdIOClient::start()
{
m_process.start();
@@ -771,11 +781,6 @@ void StdIOClient::setWorkingDirectory(const QString &workingDirectory)
m_process.setWorkingDirectory(workingDirectory);
}
bool StdIOClient::matches(const BaseSettings *setting)
{
return setting->m_executable == m_executable && setting->m_arguments == m_arguments;
}
void StdIOClient::sendData(const QByteArray &data)
{
if (m_process.state() != QProcess::Running) {

View File

@@ -112,8 +112,9 @@ public:
Core::Id id() const { return m_id; }
bool needsRestart(const BaseSettings *) const;
virtual bool start() { return true; }
virtual bool matches(const BaseSettings * /*setting*/) { return false; }
virtual bool reset();
void log(const QString &message,
@@ -175,12 +176,12 @@ public:
StdIOClient &operator=(const StdIOClient &) = delete;
StdIOClient &operator=(StdIOClient &&) = delete;
bool needsRestart(const StdIOSettings *settings);
bool start() override;
void setWorkingDirectory(const QString &workingDirectory);
bool matches(const BaseSettings *setting) override;
protected:
void sendData(const QByteArray &data) final;
QProcess m_process;

View File

@@ -167,6 +167,7 @@ void LanguageClientManager::removeMarks(const Core::Id &id)
void LanguageClientManager::startClient(BaseClient *client)
{
QTC_ASSERT(client, return);
if (managerInstance->m_shuttingDown) {
managerInstance->clientFinished(client);
return;

View File

@@ -23,8 +23,10 @@
**
****************************************************************************/
#include "languageclientmanager.h"
#include "languageclientsettings.h"
#include "baseclient.h"
#include "languageclientmanager.h"
#include "languageclient_global.h"
#include <coreplugin/icore.h>
@@ -71,8 +73,9 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
void reset(const QList<BaseSettings *> &settings);
QList<BaseSettings *> settings() const { return m_settings; }
void reset(const QList<StdIOSettings *> &settings);
QList<StdIOSettings *> settings() const { return m_settings; }
QList<StdIOSettings *> removed() const { return m_removed; }
enum Columns {
DisplayNameColumn = 0,
@@ -84,7 +87,8 @@ public:
};
private:
QList<BaseSettings *> m_settings; // owned
QList<StdIOSettings *> m_settings; // owned
QList<StdIOSettings *> m_removed;
};
class LanguageClientSettingsPageWidget : public QWidget
@@ -115,7 +119,7 @@ public:
private:
LanguageClientSettingsModel m_model;
QList<BaseSettings *> m_settings; // owned
QList<StdIOSettings *> m_settings; // owned
QPointer<LanguageClientSettingsPageWidget> m_widget;
};
@@ -229,43 +233,33 @@ QWidget *LanguageClientSettingsPage::widget()
void LanguageClientSettingsPage::apply()
{
qDeleteAll(m_settings);
m_settings = Utils::transform(m_model.settings(), [](const BaseSettings *other){
return new BaseSettings(*other);
m_settings = Utils::transform(m_model.settings(), [](const StdIOSettings *other){
return dynamic_cast<StdIOSettings *>(other->copy());
});
LanguageClientSettings::toSettings(Core::ICore::settings(), m_settings);
const QVector<BaseClient *> interfaces(LanguageClientManager::clients());
QVector<BaseClient *> toShutdown;
QList<BaseSettings *> toStart = m_settings;
// check currently registered interfaces
for (auto interface : interfaces) {
auto setting = Utils::findOr(m_settings, nullptr,
[interface](const BaseSettings *setting){
return interface->matches(setting);
});
if (setting && setting->isValid() && setting->m_enabled) {
toStart.removeAll(setting);
if (!interface->isSupportedMimeType(setting->m_mimeType))
interface->setSupportedMimeType({setting->m_mimeType});
} else {
toShutdown << interface;
QList<StdIOSettings *> restarts = Utils::filtered(m_settings, &StdIOSettings::needsRestart);
for (auto setting : restarts + m_model.removed()) {
if (auto client = setting->m_client) {
if (client->reachable())
client->shutdown();
else
LanguageClientManager::deleteClient(client);
}
}
for (auto interface : toShutdown) {
if (interface->reachable())
interface->shutdown();
else
LanguageClientManager::deleteClient(interface);
}
for (auto setting : toStart) {
if (setting && setting->isValid() && setting->m_enabled)
LanguageClientManager::startClient(setting->createClient());
for (StdIOSettings *setting : restarts) {
if (setting && setting->isValid() && setting->m_enabled) {
if (auto client = setting->createClient()) {
setting->m_client = client;
LanguageClientManager::startClient(client);
}
}
}
m_model.reset(m_settings);
}
void LanguageClientSettingsPage::finish()
{
m_model.reset(m_settings);
}
LanguageClientSettingsModel::~LanguageClientSettingsModel()
@@ -277,7 +271,7 @@ QVariant LanguageClientSettingsModel::data(const QModelIndex &index, int role) c
{
if (!index.isValid())
return QVariant();
BaseSettings *setting = m_settings[index.row()];
StdIOSettings *setting = m_settings[index.row()];
QTC_ASSERT(setting, return false);
if (role == Qt::DisplayRole || role == Qt::EditRole) {
switch (index.column()) {
@@ -314,7 +308,7 @@ bool LanguageClientSettingsModel::removeRows(int row, int count, const QModelInd
const int end = qMin(row + count - 1, int(m_settings.size()) - 1);
beginRemoveRows(parent, row, end);
for (auto i = end; i >= row; --i)
delete m_settings.takeAt(i);
m_removed << m_settings.takeAt(i);
endRemoveRows();
return true;
}
@@ -325,7 +319,7 @@ bool LanguageClientSettingsModel::insertRows(int row, int count, const QModelInd
return false;
beginInsertRows(parent, row, row + count - 1);
for (int i = 0; i < count; ++i)
m_settings.insert(row + i, new BaseSettings());
m_settings.insert(row + i, new StdIOSettings());
endInsertRows();
return true;
}
@@ -334,23 +328,31 @@ bool LanguageClientSettingsModel::setData(const QModelIndex &index, const QVaria
{
if (!index.isValid())
return false;
BaseSettings *setting = m_settings[index.row()];
StdIOSettings *setting = m_settings[index.row()];
QTC_ASSERT(setting, return false);
if (role == Qt::DisplayRole || role == Qt::EditRole) {
const QString strVal(value.toString());
QString *settingsValue = nullptr;
switch (index.column()) {
case DisplayNameColumn: setting->m_name = value.toString(); break;
case MimeTypeColumn: setting->m_mimeType = value.toString(); break;
case ExecutableColumn: setting->m_executable = value.toString(); break;
case ArgumentsColumn: setting->m_arguments = value.toString(); break;
default:
return false;
case DisplayNameColumn: settingsValue = &setting->m_name; break;
case MimeTypeColumn: settingsValue = &setting->m_mimeType; break;
case ExecutableColumn: settingsValue = &setting->m_executable; break;
case ArgumentsColumn: settingsValue = &setting->m_arguments; break;
}
if (settingsValue) {
if (strVal != *settingsValue) {
*settingsValue = value.toString();
emit dataChanged(index, index, { Qt::EditRole, Qt::DisplayRole });
}
return true;
}
emit dataChanged(index, index, { Qt::EditRole, Qt::DisplayRole });
return true;
}
if (role == Qt::CheckStateRole && index.column() == EnabledColumn) {
setting->m_enabled = value.toBool();
emit dataChanged(index, index, { Qt::CheckStateRole });
if (setting->m_enabled != value.toBool()) {
setting->m_enabled = !setting->m_enabled;
emit dataChanged(index, index, { Qt::CheckStateRole });
}
return true;
}
return false;
@@ -364,28 +366,31 @@ Qt::ItemFlags LanguageClientSettingsModel::flags(const QModelIndex &index) const
return defaultFlags;
}
void LanguageClientSettingsModel::reset(const QList<BaseSettings *> &settings)
void LanguageClientSettingsModel::reset(const QList<StdIOSettings *> &settings)
{
beginResetModel();
qDeleteAll(m_settings);
m_settings = Utils::transform(settings, [](const BaseSettings *setting){
return new BaseSettings(*setting);
qDeleteAll(m_removed);
m_removed.clear();
m_settings = Utils::transform(settings, [](const StdIOSettings *other){
return dynamic_cast<StdIOSettings *>(other->copy());
});
endResetModel();
}
bool BaseSettings::isValid()
bool BaseSettings::needsRestart() const
{
return !m_name.isEmpty() && !m_executable.isEmpty() && QFile::exists(m_executable);
return m_client ? !m_enabled || m_client->needsRestart(this) : m_enabled;
}
BaseClient *BaseSettings::createClient()
bool BaseSettings::isValid() const
{
auto client = new StdIOClient(m_executable, m_arguments);
client->setName(m_name);
if (m_mimeType != noLanguageFilter)
client->setSupportedMimeType({m_mimeType});
return client;
return !m_name.isEmpty();
}
BaseClient *BaseSettings::createClient() const
{
return nullptr;
}
QVariantMap BaseSettings::toMap() const
@@ -394,8 +399,6 @@ QVariantMap BaseSettings::toMap() const
map.insert(nameKey, m_name);
map.insert(enabledKey, m_enabled);
map.insert(mimeTypeKey, m_mimeType);
map.insert(executableKey, m_executable);
map.insert(argumentsKey, m_arguments);
return map;
}
@@ -404,8 +407,6 @@ void BaseSettings::fromMap(const QVariantMap &map)
m_name = map[nameKey].toString();
m_enabled = map[enabledKey].toBool();
m_mimeType = map[mimeTypeKey].toString();
m_executable = map[executableKey].toString();
m_arguments = map[argumentsKey].toString();
}
void LanguageClientSettings::init()
@@ -414,12 +415,12 @@ void LanguageClientSettings::init()
settingsPage.init();
}
QList<BaseSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn)
QList<StdIOSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn)
{
settingsIn->beginGroup(settingsGroupKey);
auto variants = settingsIn->value(clientsKey).toList();
auto settings = Utils::transform(variants, [](const QVariant& var){
auto settings = new BaseSettings();
auto settings = new StdIOSettings();
settings->fromMap(var.toMap());
return settings;
});
@@ -427,14 +428,52 @@ QList<BaseSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn
return settings;
}
void LanguageClientSettings::toSettings(QSettings *settings, const QList<BaseSettings *> &languageClientSettings)
void LanguageClientSettings::toSettings(QSettings *settings, const QList<StdIOSettings *> &languageClientSettings)
{
settings->beginGroup(settingsGroupKey);
settings->setValue(clientsKey, Utils::transform(languageClientSettings,
[](const BaseSettings *setting){
[](const StdIOSettings *setting){
return QVariant(setting->toMap());
}));
settings->endGroup();
}
bool StdIOSettings::needsRestart() const
{
if (BaseSettings::needsRestart())
return true;
if (auto stdIOClient = qobject_cast<StdIOClient *>(m_client))
return stdIOClient->needsRestart(this);
return false;
}
bool StdIOSettings::isValid() const
{
return BaseSettings::isValid() && !m_executable.isEmpty();
}
BaseClient *StdIOSettings::createClient() const
{
auto client = new StdIOClient(m_executable, m_arguments);
client->setName(m_name);
if (m_mimeType != noLanguageFilter)
client->setSupportedMimeType({m_mimeType});
return client;
}
QVariantMap StdIOSettings::toMap() const
{
QVariantMap map = BaseSettings::toMap();
map.insert(executableKey, m_executable);
map.insert(argumentsKey, m_arguments);
return map;
}
void StdIOSettings::fromMap(const QVariantMap &map)
{
BaseSettings::fromMap(map);
m_executable = map[executableKey].toString();
m_arguments = map[argumentsKey].toString();
}
} // namespace LanguageClient

View File

@@ -41,35 +41,69 @@ class BaseSettings
{
public:
BaseSettings() = default;
BaseSettings(const QString &name, bool enabled, const QString &mimeTypeName,
const QString &executable, const QString &arguments)
BaseSettings(const QString &name, bool enabled, const QString &mimeTypeName)
: m_name(name)
, m_enabled(enabled)
, m_mimeType(mimeTypeName)
, m_executable(executable)
, m_arguments(arguments)
{}
virtual ~BaseSettings() = default;
QString m_name = QString("New Language Server");
bool m_enabled = true;
QString m_mimeType = QLatin1String(noLanguageFilter);
QPointer<BaseClient> m_client; // not owned
virtual BaseSettings *copy() const { return new BaseSettings(*this); }
virtual bool needsRestart() const;
virtual bool isValid() const ;
virtual BaseClient *createClient() const;
virtual QVariantMap toMap() const;
virtual void fromMap(const QVariantMap &map);
protected:
BaseSettings(const BaseSettings &other) = default;
BaseSettings(BaseSettings &&other) = default;
BaseSettings &operator=(const BaseSettings &other) = default;
BaseSettings &operator=(BaseSettings &&other) = default;
};
class StdIOSettings : public BaseSettings
{
public:
StdIOSettings() = default;
StdIOSettings(const QString &name, bool enabled, const QString &mimeTypeName,
const QString &executable, const QString &arguments)
: BaseSettings(name, enabled, mimeTypeName)
, m_executable(executable)
, m_arguments(arguments)
{}
~StdIOSettings() override = default;
QString m_executable;
QString m_arguments;
bool isValid();
BaseSettings *copy() const override { return new StdIOSettings(*this); }
bool needsRestart() const override;
bool isValid() const override;
BaseClient *createClient() const override;
QVariantMap toMap() const override;
void fromMap(const QVariantMap &map) override;
BaseClient *createClient();
QVariantMap toMap() const;
void fromMap(const QVariantMap &map);
protected:
StdIOSettings(const StdIOSettings &other) = default;
StdIOSettings(StdIOSettings &&other) = default;
StdIOSettings &operator=(const StdIOSettings &other) = default;
StdIOSettings &operator=(StdIOSettings &&other) = default;
};
class LanguageClientSettings
{
public:
static void init();
static QList<BaseSettings *> fromSettings(QSettings *settings);
static void toSettings(QSettings *settings, const QList<BaseSettings *> &languageClientSettings);
static QList<StdIOSettings *> fromSettings(QSettings *settings);
static void toSettings(QSettings *settings, const QList<StdIOSettings *> &languageClientSettings);
};
} // namespace LanguageClient