forked from qt-creator/qt-creator
CodeAssistant: add cancel to asynchronous processors
Fixes crash when the processor reports a result after the code assistant was destroyed. Change-Id: I8588d3d6acad69f1ec6302e8ba09d642ebbb77f1 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -278,13 +278,14 @@ public:
|
|||||||
IAssistProposal *perform(const AssistInterface *interface) override;
|
IAssistProposal *perform(const AssistInterface *interface) override;
|
||||||
bool running() override;
|
bool running() override;
|
||||||
bool needsRestart() const override { return true; }
|
bool needsRestart() const override { return true; }
|
||||||
|
void cancel() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleCompletionResponse(const CompletionRequest::Response &response);
|
void handleCompletionResponse(const CompletionRequest::Response &response);
|
||||||
|
|
||||||
QPointer<QTextDocument> m_document;
|
QPointer<QTextDocument> m_document;
|
||||||
QPointer<Client> m_client;
|
QPointer<Client> m_client;
|
||||||
bool m_running = false;
|
MessageId m_currentRequest;
|
||||||
int m_pos = -1;
|
int m_pos = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -336,7 +337,7 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(const AssistIn
|
|||||||
});
|
});
|
||||||
completionRequest.setParams(params);
|
completionRequest.setParams(params);
|
||||||
m_client->sendContent(completionRequest);
|
m_client->sendContent(completionRequest);
|
||||||
m_running = true;
|
m_currentRequest = completionRequest.id();
|
||||||
m_document = interface->textDocument();
|
m_document = interface->textDocument();
|
||||||
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
|
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
|
||||||
<< " : request completions at " << m_pos
|
<< " : request completions at " << m_pos
|
||||||
@@ -346,14 +347,22 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(const AssistIn
|
|||||||
|
|
||||||
bool LanguageClientCompletionAssistProcessor::running()
|
bool LanguageClientCompletionAssistProcessor::running()
|
||||||
{
|
{
|
||||||
return m_running;
|
return m_currentRequest.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageClientCompletionAssistProcessor::cancel()
|
||||||
|
{
|
||||||
|
if (running()) {
|
||||||
|
m_client->cancelRequest(m_currentRequest);
|
||||||
|
m_currentRequest = MessageId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
|
void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
|
||||||
const CompletionRequest::Response &response)
|
const CompletionRequest::Response &response)
|
||||||
{
|
{
|
||||||
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : got completions";
|
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : got completions";
|
||||||
m_running = false;
|
m_currentRequest = MessageId();
|
||||||
QTC_ASSERT(m_client, return);
|
QTC_ASSERT(m_client, return);
|
||||||
if (auto error = response.error()) {
|
if (auto error = response.error()) {
|
||||||
m_client->log(error.value());
|
m_client->log(error.value());
|
||||||
|
@@ -65,14 +65,15 @@ class FunctionHintProcessor : public IAssistProcessor
|
|||||||
public:
|
public:
|
||||||
explicit FunctionHintProcessor(Client *client) : m_client(client) {}
|
explicit FunctionHintProcessor(Client *client) : m_client(client) {}
|
||||||
IAssistProposal *perform(const AssistInterface *interface) override;
|
IAssistProposal *perform(const AssistInterface *interface) override;
|
||||||
bool running() override { return m_running; }
|
bool running() override { return m_currentRequest.isValid(); }
|
||||||
bool needsRestart() const override { return true; }
|
bool needsRestart() const override { return true; }
|
||||||
|
void cancel() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleSignatureResponse(const SignatureHelpRequest::Response &response);
|
void handleSignatureResponse(const SignatureHelpRequest::Response &response);
|
||||||
|
|
||||||
QPointer<Client> m_client;
|
QPointer<Client> m_client;
|
||||||
bool m_running = false;
|
MessageId m_currentRequest;
|
||||||
int m_pos = -1;
|
int m_pos = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -87,13 +88,21 @@ IAssistProposal *FunctionHintProcessor::perform(const AssistInterface *interface
|
|||||||
request.setParams(TextDocumentPositionParams(TextDocumentIdentifier(uri), Position(cursor)));
|
request.setParams(TextDocumentPositionParams(TextDocumentIdentifier(uri), Position(cursor)));
|
||||||
request.setResponseCallback([this](auto response) { this->handleSignatureResponse(response); });
|
request.setResponseCallback([this](auto response) { this->handleSignatureResponse(response); });
|
||||||
m_client->sendContent(request);
|
m_client->sendContent(request);
|
||||||
m_running = true;
|
m_currentRequest = request.id();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FunctionHintProcessor::cancel()
|
||||||
|
{
|
||||||
|
if (running()) {
|
||||||
|
m_client->cancelRequest(m_currentRequest);
|
||||||
|
m_currentRequest = MessageId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FunctionHintProcessor::handleSignatureResponse(const SignatureHelpRequest::Response &response)
|
void FunctionHintProcessor::handleSignatureResponse(const SignatureHelpRequest::Response &response)
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_currentRequest = MessageId();
|
||||||
if (auto error = response.error())
|
if (auto error = response.error())
|
||||||
m_client->log(error.value());
|
m_client->log(error.value());
|
||||||
FunctionHintProposalModelPtr model(
|
FunctionHintProposalModelPtr model(
|
||||||
|
@@ -84,15 +84,16 @@ class LanguageClientQuickFixAssistProcessor : public IAssistProcessor
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
|
explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
|
||||||
bool running() override { return m_running; }
|
bool running() override { return m_currentRequest.isValid(); }
|
||||||
IAssistProposal *perform(const AssistInterface *interface) override;
|
IAssistProposal *perform(const AssistInterface *interface) override;
|
||||||
|
void cancel() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleCodeActionResponse(const CodeActionRequest::Response &response);
|
void handleCodeActionResponse(const CodeActionRequest::Response &response);
|
||||||
|
|
||||||
QSharedPointer<const AssistInterface> m_assistInterface;
|
QSharedPointer<const AssistInterface> m_assistInterface;
|
||||||
Client *m_client = nullptr; // not owned
|
Client *m_client = nullptr; // not owned
|
||||||
bool m_running = false;
|
MessageId m_currentRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInterface *interface)
|
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInterface *interface)
|
||||||
@@ -123,14 +124,22 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInte
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_client->requestCodeActions(request);
|
m_client->requestCodeActions(request);
|
||||||
m_running = true;
|
m_currentRequest = request.id();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LanguageClientQuickFixAssistProcessor::cancel()
|
||||||
|
{
|
||||||
|
if (running()) {
|
||||||
|
m_client->cancelRequest(m_currentRequest);
|
||||||
|
m_currentRequest = MessageId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
|
void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
|
||||||
const CodeActionRequest::Response &response)
|
const CodeActionRequest::Response &response)
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_currentRequest = MessageId();
|
||||||
if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
|
if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
|
||||||
m_client->log(*error);
|
m_client->log(*error);
|
||||||
QuickFixOperations ops;
|
QuickFixOperations ops;
|
||||||
|
@@ -288,6 +288,8 @@ void CodeAssistantPrivate::cancelCurrentRequest()
|
|||||||
m_requestRunner->setDiscardProposal(true);
|
m_requestRunner->setDiscardProposal(true);
|
||||||
disconnect(m_runnerConnection);
|
disconnect(m_runnerConnection);
|
||||||
}
|
}
|
||||||
|
if (m_asyncProcessor)
|
||||||
|
m_asyncProcessor->cancel();
|
||||||
invalidateCurrentRequestData();
|
invalidateCurrentRequestData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,14 +43,15 @@
|
|||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
class DocumentContentCompletionProcessor : public IAssistProcessor
|
class DocumentContentCompletionProcessor final : public IAssistProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DocumentContentCompletionProcessor(const QString &snippetGroupId);
|
DocumentContentCompletionProcessor(const QString &snippetGroupId);
|
||||||
~DocumentContentCompletionProcessor() override;
|
~DocumentContentCompletionProcessor() final;
|
||||||
|
|
||||||
IAssistProposal *perform(const AssistInterface *interface) override;
|
IAssistProposal *perform(const AssistInterface *interface) override;
|
||||||
bool running() final { return m_watcher.isRunning(); }
|
bool running() final { return m_watcher.isRunning(); }
|
||||||
|
void cancel() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_snippetGroup;
|
QString m_snippetGroup;
|
||||||
@@ -77,8 +78,7 @@ DocumentContentCompletionProcessor::DocumentContentCompletionProcessor(const QSt
|
|||||||
|
|
||||||
DocumentContentCompletionProcessor::~DocumentContentCompletionProcessor()
|
DocumentContentCompletionProcessor::~DocumentContentCompletionProcessor()
|
||||||
{
|
{
|
||||||
if (m_watcher.isRunning())
|
cancel();
|
||||||
m_watcher.cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createProposal(QFutureInterface<QStringList> &future, const QString &text,
|
static void createProposal(QFutureInterface<QStringList> &future, const QString &text,
|
||||||
@@ -149,3 +149,9 @@ IAssistProposal *DocumentContentCompletionProcessor::perform(const AssistInterfa
|
|||||||
});
|
});
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DocumentContentCompletionProcessor::cancel()
|
||||||
|
{
|
||||||
|
if (running())
|
||||||
|
m_watcher.cancel();
|
||||||
|
}
|
||||||
|
@@ -51,6 +51,7 @@ public:
|
|||||||
|
|
||||||
virtual bool running() { return false; }
|
virtual bool running() { return false; }
|
||||||
virtual bool needsRestart() const { return false; }
|
virtual bool needsRestart() const { return false; }
|
||||||
|
virtual void cancel() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AsyncCompletionsAvailableHandler m_asyncCompletionsAvailableHandler;
|
AsyncCompletionsAvailableHandler m_asyncCompletionsAvailableHandler;
|
||||||
|
Reference in New Issue
Block a user