forked from qt-creator/qt-creator
Python: detect language server for python asynchron
Change-Id: I775e4cc21dc443b9ec6af81fabef9cf2bfd4e7d2 Fixes: QTCREATORBUG-23599 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/runextensions.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -144,20 +145,19 @@ static PythonLanguageServerState checkPythonLanguageServer(const FilePath &pytho
|
|||||||
using namespace LanguageClient;
|
using namespace LanguageClient;
|
||||||
SynchronousProcess pythonProcess;
|
SynchronousProcess pythonProcess;
|
||||||
const CommandLine pythonLShelpCommand(python, {"-m", "pyls", "-h"});
|
const CommandLine pythonLShelpCommand(python, {"-m", "pyls", "-h"});
|
||||||
SynchronousProcessResponse response = pythonProcess.runBlocking(pythonLShelpCommand);
|
const FilePath &modulePath = getPylsModulePath(pythonLShelpCommand);
|
||||||
if (response.allOutput().contains("Python Language Server")) {
|
for (const StdIOSettings *serverSetting : configuredPythonLanguageServer()) {
|
||||||
const FilePath &modulePath = getPylsModulePath(pythonLShelpCommand);
|
if (modulePath == getPylsModulePath(serverSetting->command())) {
|
||||||
for (const StdIOSettings *serverSetting : configuredPythonLanguageServer()) {
|
return {serverSetting->m_enabled ? PythonLanguageServerState::AlreadyConfigured
|
||||||
if (modulePath == getPylsModulePath(serverSetting->command())) {
|
: PythonLanguageServerState::ConfiguredButDisabled,
|
||||||
return {serverSetting->m_enabled ? PythonLanguageServerState::AlreadyConfigured
|
FilePath()};
|
||||||
: PythonLanguageServerState::ConfiguredButDisabled,
|
|
||||||
FilePath()};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {PythonLanguageServerState::AlreadyInstalled, modulePath};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SynchronousProcessResponse response = pythonProcess.runBlocking(pythonLShelpCommand);
|
||||||
|
if (response.allOutput().contains("Python Language Server"))
|
||||||
|
return {PythonLanguageServerState::AlreadyInstalled, modulePath};
|
||||||
|
|
||||||
const CommandLine pythonPipVersionCommand(python, {"-m", "pip", "-V"});
|
const CommandLine pythonPipVersionCommand(python, {"-m", "pip", "-V"});
|
||||||
response = pythonProcess.runBlocking(pythonPipVersionCommand);
|
response = pythonProcess.runBlocking(pythonPipVersionCommand);
|
||||||
if (response.allOutput().startsWith("pip "))
|
if (response.allOutput().startsWith("pip "))
|
||||||
@@ -368,11 +368,38 @@ void PyLSConfigureAssistant::documentOpened(Core::IDocument *document)
|
|||||||
void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
|
void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
|
||||||
TextEditor::TextDocument *document)
|
TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
const PythonLanguageServerState &lsState = checkPythonLanguageServer(python);
|
using CheckPylsWatcher = QFutureWatcher<PythonLanguageServerState>;
|
||||||
|
|
||||||
if (lsState.state == PythonLanguageServerState::CanNotBeInstalled)
|
QPointer<CheckPylsWatcher> watcher = new CheckPylsWatcher();
|
||||||
|
watcher->setFuture(Utils::runAsync(&checkPythonLanguageServer, python));
|
||||||
|
|
||||||
|
// cancel and delete watcher after a 10 second timeout
|
||||||
|
QTimer::singleShot(10000, this, [watcher]() {
|
||||||
|
if (watcher) {
|
||||||
|
watcher->cancel();
|
||||||
|
watcher->deleteLater();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(
|
||||||
|
watcher,
|
||||||
|
&CheckPylsWatcher::resultReadyAt,
|
||||||
|
this,
|
||||||
|
[=, document = QPointer<TextEditor::TextDocument>(document)]() {
|
||||||
|
if (!document || !watcher)
|
||||||
|
return;
|
||||||
|
handlePyLSState(python, watcher->result(), document);
|
||||||
|
watcher->deleteLater();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
|
||||||
|
const PythonLanguageServerState &state,
|
||||||
|
TextEditor::TextDocument *document)
|
||||||
|
{
|
||||||
|
if (state.state == PythonLanguageServerState::CanNotBeInstalled)
|
||||||
return;
|
return;
|
||||||
if (lsState.state == PythonLanguageServerState::AlreadyConfigured) {
|
if (state.state == PythonLanguageServerState::AlreadyConfigured) {
|
||||||
if (const StdIOSettings *setting = languageServerForPython(python)) {
|
if (const StdIOSettings *setting = languageServerForPython(python)) {
|
||||||
if (Client *client = LanguageClientManager::clientForSetting(setting).value(0))
|
if (Client *client = LanguageClientManager::clientForSetting(setting).value(0))
|
||||||
LanguageClientManager::reOpenDocumentWithClient(document, client);
|
LanguageClientManager::reOpenDocumentWithClient(document, client);
|
||||||
@@ -382,12 +409,11 @@ void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
|
|||||||
|
|
||||||
resetEditorInfoBar(document);
|
resetEditorInfoBar(document);
|
||||||
Core::InfoBar *infoBar = document->infoBar();
|
Core::InfoBar *infoBar = document->infoBar();
|
||||||
if (lsState.state == PythonLanguageServerState::CanBeInstalled
|
if (state.state == PythonLanguageServerState::CanBeInstalled
|
||||||
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
|
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
|
||||||
auto message
|
auto message = tr("Install and set up Python language server (PyLS) for %1 (%2). "
|
||||||
= tr("Install and set up Python language server (PyLS) for %1 (%2). "
|
"The language server provides Python specific completion and annotation.")
|
||||||
"The language server provides Python specific completion and annotation.")
|
.arg(pythonName(python), python.toUserOutput());
|
||||||
.arg(pythonName(python), python.toUserOutput());
|
|
||||||
Core::InfoBarEntry info(installPylsInfoBarId,
|
Core::InfoBarEntry info(installPylsInfoBarId,
|
||||||
message,
|
message,
|
||||||
Core::InfoBarEntry::GlobalSuppression::Enabled);
|
Core::InfoBarEntry::GlobalSuppression::Enabled);
|
||||||
@@ -395,7 +421,7 @@ void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
|
|||||||
[=]() { installPythonLanguageServer(python, document); });
|
[=]() { installPythonLanguageServer(python, document); });
|
||||||
infoBar->addInfo(info);
|
infoBar->addInfo(info);
|
||||||
m_infoBarEntries[python] << document;
|
m_infoBarEntries[python] << document;
|
||||||
} else if (lsState.state == PythonLanguageServerState::AlreadyInstalled
|
} else if (state.state == PythonLanguageServerState::AlreadyInstalled
|
||||||
&& infoBar->canInfoBeAdded(startPylsInfoBarId)) {
|
&& infoBar->canInfoBeAdded(startPylsInfoBarId)) {
|
||||||
auto message = tr("Found a Python language server for %1 (%2). "
|
auto message = tr("Found a Python language server for %1 (%2). "
|
||||||
"Set it up for this document?")
|
"Set it up for this document?")
|
||||||
@@ -407,7 +433,7 @@ void PyLSConfigureAssistant::openDocumentWithPython(const FilePath &python,
|
|||||||
[=]() { setupPythonLanguageServer(python, document); });
|
[=]() { setupPythonLanguageServer(python, document); });
|
||||||
infoBar->addInfo(info);
|
infoBar->addInfo(info);
|
||||||
m_infoBarEntries[python] << document;
|
m_infoBarEntries[python] << document;
|
||||||
} else if (lsState.state == PythonLanguageServerState::ConfiguredButDisabled
|
} else if (state.state == PythonLanguageServerState::ConfiguredButDisabled
|
||||||
&& infoBar->canInfoBeAdded(enablePylsInfoBarId)) {
|
&& infoBar->canInfoBeAdded(enablePylsInfoBarId)) {
|
||||||
auto message = tr("Enable Python language server for %1 (%2)?")
|
auto message = tr("Enable Python language server for %1 (%2)?")
|
||||||
.arg(pythonName(python), python.toUserOutput());
|
.arg(pythonName(python), python.toUserOutput());
|
||||||
|
@@ -40,6 +40,8 @@ namespace TextEditor { class TextDocument; }
|
|||||||
namespace Python {
|
namespace Python {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class PythonLanguageServerState;
|
||||||
|
|
||||||
class PyLSConfigureAssistant : public QObject
|
class PyLSConfigureAssistant : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -56,6 +58,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
explicit PyLSConfigureAssistant(QObject *parent);
|
explicit PyLSConfigureAssistant(QObject *parent);
|
||||||
|
|
||||||
|
void handlePyLSState(const Utils::FilePath &python,
|
||||||
|
const PythonLanguageServerState &state,
|
||||||
|
TextEditor::TextDocument *document);
|
||||||
void resetEditorInfoBar(TextEditor::TextDocument *document);
|
void resetEditorInfoBar(TextEditor::TextDocument *document);
|
||||||
void installPythonLanguageServer(const Utils::FilePath &python,
|
void installPythonLanguageServer(const Utils::FilePath &python,
|
||||||
QPointer<TextEditor::TextDocument> document);
|
QPointer<TextEditor::TextDocument> document);
|
||||||
|
Reference in New Issue
Block a user