diff options
author | David Schulz <david.schulz@qt.io> | 2022-06-09 13:41:41 +0200 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2022-06-10 12:47:23 +0000 |
commit | 4c20a880e6395f43e5fc9770c53c1034d08847a4 (patch) | |
tree | 5e05d87f84ea896fede9ec939f3dd9c044a87dbf /src/plugins/python/pythonlanguageclient.cpp | |
parent | ed22ef78543a41e334687b4c70493b8bd21ed7b3 (diff) | |
download | qt-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.cpp | 308 |
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) |