summaryrefslogtreecommitdiff
path: root/src/plugins/python/pythonlanguageclient.cpp
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2022-06-09 13:41:41 +0200
committerDavid Schulz <david.schulz@qt.io>2022-06-10 12:47:23 +0000
commit4c20a880e6395f43e5fc9770c53c1034d08847a4 (patch)
tree5e05d87f84ea896fede9ec939f3dd9c044a87dbf /src/plugins/python/pythonlanguageclient.cpp
parented22ef78543a41e334687b4c70493b8bd21ed7b3 (diff)
downloadqt-creator-4c20a880e6395f43e5fc9770c53c1034d08847a4.tar.gz
Python: remove python specific language client settings
Change-Id: Ic993d525f29c1925f7e64dfc6f5e053234fb4904 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/python/pythonlanguageclient.cpp')
-rw-r--r--src/plugins/python/pythonlanguageclient.cpp308
1 files changed, 47 insertions, 261 deletions
diff --git a/src/plugins/python/pythonlanguageclient.cpp b/src/plugins/python/pythonlanguageclient.cpp
index b689792620..b129a06904 100644
--- a/src/plugins/python/pythonlanguageclient.cpp
+++ b/src/plugins/python/pythonlanguageclient.cpp
@@ -69,9 +69,7 @@ using namespace Utils;
namespace Python {
namespace Internal {
-static constexpr char startPylsInfoBarId[] = "Python::StartPyls";
static constexpr char installPylsInfoBarId[] = "Python::InstallPyls";
-static constexpr char enablePylsInfoBarId[] = "Python::EnablePyls";
class PythonLanguageServerState
{
@@ -79,13 +77,17 @@ public:
enum {
CanNotBeInstalled,
CanBeInstalled,
- AlreadyInstalled,
- AlreadyConfigured,
- ConfiguredButDisabled
+ AlreadyInstalled
} state;
FilePath pylsModulePath;
};
+static QHash<FilePath, PyLSClient*> &pythonClients()
+{
+ static QHash<FilePath, PyLSClient*> clients;
+ return clients;
+}
+
FilePath getPylsModulePath(CommandLine pylsCommand)
{
static QMutex mutex; // protect the access to the cache
@@ -125,29 +127,11 @@ FilePath getPylsModulePath(CommandLine pylsCommand)
return {};
}
-QList<const StdIOSettings *> configuredPythonLanguageServer()
-{
- using namespace LanguageClient;
- QList<const StdIOSettings *> result;
- for (const BaseSettings *setting : LanguageClientManager::currentSettings()) {
- if (setting->m_languageFilter.isSupported("foo.py", Constants::C_PY_MIMETYPE))
- result << dynamic_cast<const StdIOSettings *>(setting);
- }
- return result;
-}
-
static PythonLanguageServerState checkPythonLanguageServer(const FilePath &python)
{
using namespace LanguageClient;
const CommandLine pythonLShelpCommand(python, {"-m", "pylsp", "-h"});
const FilePath &modulePath = getPylsModulePath(pythonLShelpCommand);
- for (const StdIOSettings *serverSetting : configuredPythonLanguageServer()) {
- if (modulePath == getPylsModulePath(serverSetting->command())) {
- return {serverSetting->m_enabled ? PythonLanguageServerState::AlreadyConfigured
- : PythonLanguageServerState::ConfiguredButDisabled,
- FilePath()};
- }
- }
QtcProcess pythonProcess;
pythonProcess.setCommand(pythonLShelpCommand);
@@ -163,137 +147,6 @@ static PythonLanguageServerState checkPythonLanguageServer(const FilePath &pytho
return {PythonLanguageServerState::CanNotBeInstalled, FilePath()};
}
-class PyLSSettingsWidget : public QWidget
-{
- Q_DECLARE_TR_FUNCTIONS(PyLSSettingsWidget)
-public:
- PyLSSettingsWidget(const PyLSSettings *settings, QWidget *parent)
- : QWidget(parent)
- , m_name(new QLineEdit(settings->m_name, this))
- , m_interpreter(new QComboBox(this))
- , m_configure(new QPushButton(tr("Configure..."), this))
- {
- int row = 0;
- auto *mainLayout = new QGridLayout;
- mainLayout->addWidget(new QLabel(tr("Name:")), row, 0);
- mainLayout->addWidget(m_name, row, 1);
- auto chooser = new VariableChooser(this);
- chooser->addSupportedWidget(m_name);
-
- mainLayout->addWidget(new QLabel(tr("Python:")), ++row, 0);
- QString settingsId = settings->interpreterId();
- if (settingsId.isEmpty())
- settingsId = PythonSettings::defaultInterpreter().id;
- updateInterpreters(PythonSettings::interpreters(), settingsId);
- mainLayout->addWidget(m_interpreter, row, 1);
- setLayout(mainLayout);
-
- mainLayout->addWidget(m_configure, ++row, 0);
-
- connect(PythonSettings::instance(),
- &PythonSettings::interpretersChanged,
- this,
- &PyLSSettingsWidget::updateInterpreters);
-
- connect(m_configure, &QPushButton::clicked, this, &PyLSSettingsWidget::switchToPylsConfigurePage);
- }
-
- void updateInterpreters(const QList<Interpreter> &interpreters, const QString &defaultId)
- {
- QString currentId = interpreterId();
- if (currentId.isEmpty())
- currentId = defaultId;
- m_interpreter->clear();
- for (const Interpreter &interpreter : interpreters) {
- if (!interpreter.command.exists())
- continue;
- const QString name = QString(interpreter.name + " (%1)")
- .arg(interpreter.command.toUserOutput());
- m_interpreter->addItem(name, interpreter.id);
- if (!currentId.isEmpty() && currentId == interpreter.id)
- m_interpreter->setCurrentIndex(m_interpreter->count() - 1);
- }
- }
-
- QString name() const { return m_name->text(); }
- QString interpreterId() const { return m_interpreter->currentData().toString(); }
-
-private:
- void switchToPylsConfigurePage()
- {
- Core::ICore::showOptionsDialog(Constants::C_PYLSCONFIGURATION_PAGE_ID);
- }
-
- QLineEdit *m_name = nullptr;
- QComboBox *m_interpreter = nullptr;
- QPushButton *m_configure = nullptr;
-};
-
-PyLSSettings::PyLSSettings()
-{
- m_settingsTypeId = Constants::PYLS_SETTINGS_ID;
- m_name = "Python Language Server";
- m_startBehavior = RequiresFile;
- m_languageFilter.mimeTypes = QStringList()
- << Constants::C_PY_MIMETYPE << Constants::C_PY3_MIMETYPE;
- m_arguments = "-m pylsp";
-}
-
-bool PyLSSettings::isValid() const
-{
- return !m_interpreterId.isEmpty() && StdIOSettings::isValid();
-}
-
-static const char interpreterKey[] = "interpreter";
-
-QVariantMap PyLSSettings::toMap() const
-{
- QVariantMap map = StdIOSettings::toMap();
- map.insert(interpreterKey, m_interpreterId);
- return map;
-}
-
-void PyLSSettings::fromMap(const QVariantMap &map)
-{
- StdIOSettings::fromMap(map);
- m_languageFilter.mimeTypes = QStringList()
- << Constants::C_PY_MIMETYPE << Constants::C_PY3_MIMETYPE;
- setInterpreter(map[interpreterKey].toString());
-}
-
-bool PyLSSettings::applyFromSettingsWidget(QWidget *widget)
-{
- bool changed = false;
- auto pylswidget = static_cast<PyLSSettingsWidget *>(widget);
-
- changed |= m_name != pylswidget->name();
- m_name = pylswidget->name();
-
- changed |= m_interpreterId != pylswidget->interpreterId();
- setInterpreter(pylswidget->interpreterId());
-
- return changed;
-}
-
-QWidget *PyLSSettings::createSettingsWidget(QWidget *parent) const
-{
- return new PyLSSettingsWidget(this, parent);
-}
-
-BaseSettings *PyLSSettings::copy() const
-{
- return new PyLSSettings(*this);
-}
-
-void PyLSSettings::setInterpreter(const QString &interpreterId)
-{
- m_interpreterId = interpreterId;
- if (m_interpreterId.isEmpty())
- return;
- Interpreter interpreter = Utils::findOrDefault(PythonSettings::interpreters(),
- Utils::equal(&Interpreter::id, interpreterId));
- m_executable = interpreter.command;
-}
class PyLSInterface : public StdIOClientInterface
{
@@ -310,13 +163,22 @@ public:
TemporaryDirectory m_extraPythonPath;
};
-BaseClientInterface *PyLSSettings::createInterface(ProjectExplorer::Project *project) const
+PyLSClient *clientForPython(const FilePath &python)
{
+ if (auto client = pythonClients()[python])
+ return client;
auto interface = new PyLSInterface;
- interface->setCommandLine(command());
- if (project)
- interface->setWorkingDirectory(project->projectDirectory());
- return interface;
+ interface->setCommandLine(CommandLine(python, {"-m", "pylsp"}));
+ auto client = new PyLSClient(interface);
+ client->setName(PyLSClient::tr("Python Language Server (%1)").arg(python.toUserOutput()));
+ client->setActivateDocumentAutomatically(true);
+ client->updateConfiguration();
+ LanguageFilter filter;
+ filter.mimeTypes = QStringList() << Constants::C_PY_MIMETYPE << Constants::C_PY3_MIMETYPE;
+ client->setSupportedLanguage(filter);
+ client->start();
+ pythonClients()[python] = client;
+ return client;
}
PyLSClient::PyLSClient(BaseClientInterface *interface)
@@ -326,6 +188,17 @@ PyLSClient::PyLSClient(BaseClientInterface *interface)
connect(this, &Client::initialized, this, &PyLSClient::updateConfiguration);
connect(PythonSettings::instance(), &PythonSettings::pylsConfigurationChanged,
this, &PyLSClient::updateConfiguration);
+ connect(PythonSettings::instance(), &PythonSettings::pylsEnabledChanged,
+ this, [this](const bool enabled){
+ if (!enabled)
+ LanguageClientManager::shutdownClient(this);
+ });
+
+}
+
+PyLSClient::~PyLSClient()
+{
+ pythonClients().remove(pythonClients().key(this));
}
void PyLSClient::updateConfiguration()
@@ -413,16 +286,7 @@ void PyLSClient::closeExtraCompiler(ProjectExplorer::ExtraCompiler *compiler)
PyLSClient *PyLSClient::clientForPython(const FilePath &python)
{
- if (auto setting = PyLSConfigureAssistant::languageServerForPython(python)) {
- if (auto client = LanguageClientManager::clientsForSetting(setting).value(0))
- return qobject_cast<PyLSClient *>(client);
- }
- return nullptr;
-}
-
-Client *PyLSSettings::createClient(BaseClientInterface *interface) const
-{
- return new PyLSClient(interface);
+ return pythonClients()[python];
}
PyLSConfigureAssistant *PyLSConfigureAssistant::instance()
@@ -431,40 +295,6 @@ PyLSConfigureAssistant *PyLSConfigureAssistant::instance()
return instance;
}
-const StdIOSettings *PyLSConfigureAssistant::languageServerForPython(const FilePath &python)
-{
- const FilePath pythonModulePath = getPylsModulePath({python, {"-m", "pylsp"}});
- return findOrDefault(configuredPythonLanguageServer(),
- [pythonModulePath](const StdIOSettings *setting) {
- return getPylsModulePath(setting->command()) == pythonModulePath;
- });
-}
-
-static Client *registerLanguageServer(const FilePath &python)
-{
- Interpreter interpreter = Utils::findOrDefault(PythonSettings::interpreters(),
- Utils::equal(&Interpreter::command, python));
- StdIOSettings *settings = nullptr;
- if (!interpreter.id.isEmpty()) {
- auto *pylsSettings = new PyLSSettings();
- pylsSettings->setInterpreter(interpreter.id);
- settings = pylsSettings;
- } else {
- // cannot find a matching interpreter in settings for the python path add a generic server
- auto *settings = new StdIOSettings();
- settings->m_executable = python;
- settings->m_arguments = "-m pylsp";
- settings->m_languageFilter.mimeTypes = QStringList() << Constants::C_PY_MIMETYPE
- << Constants::C_PY3_MIMETYPE;
- }
- settings->m_name = PyLSConfigureAssistant::tr("Python Language Server (%1)")
- .arg(pythonName(python));
- LanguageClientManager::registerClientSettings(settings);
- Client *client = LanguageClientManager::clientsForSetting(settings).value(0);
- PyLSConfigureAssistant::updateEditorInfoBars(python, client);
- return client;
-}
-
void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
QPointer<TextEditor::TextDocument> document)
{
@@ -479,8 +309,8 @@ void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
connect(install, &PipInstallTask::finished, this, [=](const bool success) {
if (success) {
- if (Client *client = registerLanguageServer(python)) {
- if (document)
+ if (document) {
+ if (PyLSClient *client = clientForPython(python))
LanguageClientManager::openDocumentWithClient(document, client);
}
}
@@ -491,34 +321,18 @@ void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
install->run();
}
-static void setupPythonLanguageServer(const FilePath &python,
- QPointer<TextEditor::TextDocument> document)
+void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
+ TextEditor::TextDocument *document)
{
- document->infoBar()->removeInfo(startPylsInfoBarId);
- if (Client *client = registerLanguageServer(python))
- LanguageClientManager::openDocumentWithClient(document, client);
-}
+ if (!PythonSettings::pylsEnabled())
+ return;
-static void enablePythonLanguageServer(const FilePath &python,
- QPointer<TextEditor::TextDocument> document)
-{
- document->infoBar()->removeInfo(enablePylsInfoBarId);
- if (const StdIOSettings *setting = PyLSConfigureAssistant::languageServerForPython(python)) {
- LanguageClientManager::enableClientSettings(setting->m_id);
- if (const StdIOSettings *setting = PyLSConfigureAssistant::languageServerForPython(python)) {
- if (Client *client = LanguageClientManager::clientsForSetting(setting).value(0)) {
- LanguageClientManager::openDocumentWithClient(document, client);
- PyLSConfigureAssistant::updateEditorInfoBars(python, client);
- }
- }
+ if (auto client = pythonClients().value(python)) {
+ LanguageClientManager::openDocumentWithClient(document, client);
+ return;
}
-}
-void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
- TextEditor::TextDocument *document)
-{
using CheckPylsWatcher = QFutureWatcher<PythonLanguageServerState>;
-
QPointer<CheckPylsWatcher> watcher = new CheckPylsWatcher();
// cancel and delete watcher after a 10 second timeout
@@ -547,19 +361,12 @@ void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
{
if (state.state == PythonLanguageServerState::CanNotBeInstalled)
return;
- if (state.state == PythonLanguageServerState::AlreadyConfigured) {
- if (const StdIOSettings *setting = languageServerForPython(python)) {
- if (Client *client = LanguageClientManager::clientsForSetting(setting).value(0))
- LanguageClientManager::openDocumentWithClient(document, client);
- }
- return;
- }
resetEditorInfoBar(document);
Utils::InfoBar *infoBar = document->infoBar();
if (state.state == PythonLanguageServerState::CanBeInstalled
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
- auto message = tr("Install and set up Python language server (PyLS) for %1 (%2). "
+ auto message = tr("Install Python language server (PyLS) for %1 (%2). "
"The language server provides Python specific completion and annotation.")
.arg(pythonName(python), python.toUserOutput());
Utils::InfoBarEntry info(installPylsInfoBarId,
@@ -569,27 +376,9 @@ void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
[=]() { installPythonLanguageServer(python, document); });
infoBar->addInfo(info);
m_infoBarEntries[python] << document;
- } else if (state.state == PythonLanguageServerState::AlreadyInstalled
- && infoBar->canInfoBeAdded(startPylsInfoBarId)) {
- auto message = tr("Found a Python language server for %1 (%2). "
- "Set it up for this document?")
- .arg(pythonName(python), python.toUserOutput());
- Utils::InfoBarEntry info(startPylsInfoBarId,
- message,
- Utils::InfoBarEntry::GlobalSuppression::Enabled);
- info.addCustomButton(tr("Set Up"), [=]() { setupPythonLanguageServer(python, document); });
- infoBar->addInfo(info);
- m_infoBarEntries[python] << document;
- } else if (state.state == PythonLanguageServerState::ConfiguredButDisabled
- && infoBar->canInfoBeAdded(enablePylsInfoBarId)) {
- auto message = tr("Enable Python language server for %1 (%2)?")
- .arg(pythonName(python), python.toUserOutput());
- Utils::InfoBarEntry info(enablePylsInfoBarId,
- message,
- Utils::InfoBarEntry::GlobalSuppression::Enabled);
- info.addCustomButton(tr("Enable"), [=]() { enablePythonLanguageServer(python, document); });
- infoBar->addInfo(info);
- m_infoBarEntries[python] << document;
+ } else if (state.state == PythonLanguageServerState::AlreadyInstalled) {
+ if (auto client = clientForPython(python))
+ LanguageClientManager::openDocumentWithClient(document, client);
}
}
@@ -606,10 +395,7 @@ void PyLSConfigureAssistant::resetEditorInfoBar(TextEditor::TextDocument *docume
{
for (QList<TextEditor::TextDocument *> &documents : m_infoBarEntries)
documents.removeAll(document);
- Utils::InfoBar *infoBar = document->infoBar();
- infoBar->removeInfo(installPylsInfoBarId);
- infoBar->removeInfo(startPylsInfoBarId);
- infoBar->removeInfo(enablePylsInfoBarId);
+ document->infoBar()->removeInfo(installPylsInfoBarId);
}
PyLSConfigureAssistant::PyLSConfigureAssistant(QObject *parent)