forked from qt-creator/qt-creator
CodeAssist: Fix leaking asynchronous processors
Currently the ownership of the processor is unknown to the codeassist when running an async operation. Move the ownership of the processor to the assist and delete the processor after the proposal was completed. Change-Id: I6a2e023c47cbc876669dba866bee12b481447cb7 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -190,8 +190,7 @@ void BackendReceiver::completions(const CompletionsMessage &message)
|
|||||||
<< "items";
|
<< "items";
|
||||||
|
|
||||||
const quint64 ticket = message.ticketNumber;
|
const quint64 ticket = message.ticketNumber;
|
||||||
QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket));
|
if (ClangCompletionAssistProcessor *processor = m_assistProcessorsTable.take(ticket))
|
||||||
if (processor)
|
|
||||||
processor->handleAvailableCompletions(message.codeCompletions);
|
processor->handleAvailableCompletions(message.codeCompletions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
#include <texteditor/codeassist/documentcontentcompletion.h>
|
#include <texteditor/codeassist/documentcontentcompletion.h>
|
||||||
|
#include <texteditor/codeassist/iassistprocessor.h>
|
||||||
#include <texteditor/syntaxhighlighter.h>
|
#include <texteditor/syntaxhighlighter.h>
|
||||||
#include <texteditor/tabsettings.h>
|
#include <texteditor/tabsettings.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
@@ -146,6 +147,8 @@ Client::~Client()
|
|||||||
highlighter->clearAllExtraFormats();
|
highlighter->clearAllExtraFormats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (IAssistProcessor *processor : m_runningAssistProcessors)
|
||||||
|
processor->setAsyncProposalAvailable(nullptr);
|
||||||
updateEditorToolBar(m_openedDocument.keys());
|
updateEditorToolBar(m_openedDocument.keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,6 +905,16 @@ bool Client::isSupportedUri(const DocumentUri &uri) const
|
|||||||
Utils::mimeTypeForFile(uri.toFilePath().fileName()).name());
|
Utils::mimeTypeForFile(uri.toFilePath().fileName()).name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::addAssistProcessor(TextEditor::IAssistProcessor *processor)
|
||||||
|
{
|
||||||
|
m_runningAssistProcessors.insert(processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::removeAssistProcessor(TextEditor::IAssistProcessor *processor)
|
||||||
|
{
|
||||||
|
m_runningAssistProcessors.remove(processor);
|
||||||
|
}
|
||||||
|
|
||||||
bool Client::needsRestart(const BaseSettings *settings) const
|
bool Client::needsRestart(const BaseSettings *settings) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(settings, return false);
|
QTC_ASSERT(settings, return false);
|
||||||
@@ -942,6 +955,9 @@ bool Client::reset()
|
|||||||
document->disconnect(this);
|
document->disconnect(this);
|
||||||
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
|
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
|
||||||
resetAssistProviders(document);
|
resetAssistProviders(document);
|
||||||
|
for (TextEditor::IAssistProcessor *processor : m_runningAssistProcessors)
|
||||||
|
processor->setAsyncProposalAvailable(nullptr);
|
||||||
|
m_runningAssistProcessors.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,6 +59,7 @@ namespace Core { class IDocument; }
|
|||||||
namespace ProjectExplorer { class Project; }
|
namespace ProjectExplorer { class Project; }
|
||||||
namespace TextEditor
|
namespace TextEditor
|
||||||
{
|
{
|
||||||
|
class IAssistProcessor;
|
||||||
class TextDocument;
|
class TextDocument;
|
||||||
class TextEditorWidget;
|
class TextEditorWidget;
|
||||||
class TextMark;
|
class TextMark;
|
||||||
@@ -141,6 +142,9 @@ public:
|
|||||||
bool isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const;
|
bool isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const;
|
||||||
bool isSupportedUri(const LanguageServerProtocol::DocumentUri &uri) const;
|
bool isSupportedUri(const LanguageServerProtocol::DocumentUri &uri) const;
|
||||||
|
|
||||||
|
void addAssistProcessor(TextEditor::IAssistProcessor *processor);
|
||||||
|
void removeAssistProcessor(TextEditor::IAssistProcessor *processor);
|
||||||
|
|
||||||
void setName(const QString &name) { m_displayName = name; }
|
void setName(const QString &name) { m_displayName = name; }
|
||||||
QString name() const { return m_displayName; }
|
QString name() const { return m_displayName; }
|
||||||
|
|
||||||
@@ -233,6 +237,7 @@ private:
|
|||||||
HoverHandler m_hoverHandler;
|
HoverHandler m_hoverHandler;
|
||||||
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
|
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
|
||||||
const ProjectExplorer::Project *m_project = nullptr;
|
const ProjectExplorer::Project *m_project = nullptr;
|
||||||
|
QSet<TextEditor::IAssistProcessor *> m_runningAssistProcessors;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LanguageClient
|
} // namespace LanguageClient
|
||||||
|
@@ -342,6 +342,7 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(const AssistIn
|
|||||||
});
|
});
|
||||||
completionRequest.setParams(params);
|
completionRequest.setParams(params);
|
||||||
m_client->sendContent(completionRequest);
|
m_client->sendContent(completionRequest);
|
||||||
|
m_client->addAssistProcessor(this);
|
||||||
m_currentRequest = completionRequest.id();
|
m_currentRequest = completionRequest.id();
|
||||||
m_document = interface->textDocument();
|
m_document = interface->textDocument();
|
||||||
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
|
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
|
||||||
@@ -359,6 +360,7 @@ void LanguageClientCompletionAssistProcessor::cancel()
|
|||||||
{
|
{
|
||||||
if (running()) {
|
if (running()) {
|
||||||
m_client->cancelRequest(m_currentRequest);
|
m_client->cancelRequest(m_currentRequest);
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
m_currentRequest = MessageId();
|
m_currentRequest = MessageId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,6 +378,7 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
|
|||||||
const Utils::optional<CompletionResult> &result = response.result();
|
const Utils::optional<CompletionResult> &result = response.result();
|
||||||
if (!result || Utils::holds_alternative<std::nullptr_t>(*result)) {
|
if (!result || Utils::holds_alternative<std::nullptr_t>(*result)) {
|
||||||
setAsyncProposalAvailable(nullptr);
|
setAsyncProposalAvailable(nullptr);
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +399,7 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
|
|||||||
proposal->setFragile(true);
|
proposal->setFragile(true);
|
||||||
proposal->setSupportsPrefix(false);
|
proposal->setSupportsPrefix(false);
|
||||||
setAsyncProposalAvailable(proposal);
|
setAsyncProposalAvailable(proposal);
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : "
|
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : "
|
||||||
<< items.count() << " completions handled";
|
<< items.count() << " completions handled";
|
||||||
}
|
}
|
||||||
|
@@ -96,6 +96,7 @@ void FunctionHintProcessor::cancel()
|
|||||||
{
|
{
|
||||||
if (running()) {
|
if (running()) {
|
||||||
m_client->cancelRequest(m_currentRequest);
|
m_client->cancelRequest(m_currentRequest);
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
m_currentRequest = MessageId();
|
m_currentRequest = MessageId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,6 +108,7 @@ void FunctionHintProcessor::handleSignatureResponse(const SignatureHelpRequest::
|
|||||||
m_client->log(error.value());
|
m_client->log(error.value());
|
||||||
FunctionHintProposalModelPtr model(
|
FunctionHintProposalModelPtr model(
|
||||||
new FunctionHintProposalModel(response.result().value().value()));
|
new FunctionHintProposalModel(response.result().value().value()));
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
setAsyncProposalAvailable(new FunctionHintProposal(m_pos, model));
|
setAsyncProposalAvailable(new FunctionHintProposal(m_pos, model));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -132,6 +132,7 @@ void LanguageClientQuickFixAssistProcessor::cancel()
|
|||||||
{
|
{
|
||||||
if (running()) {
|
if (running()) {
|
||||||
m_client->cancelRequest(m_currentRequest);
|
m_client->cancelRequest(m_currentRequest);
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
m_currentRequest = MessageId();
|
m_currentRequest = MessageId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,6 +155,7 @@ void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_client->removeAssistProcessor(this);
|
||||||
setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
|
setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -252,8 +252,9 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IAssistProvider::Asynchronous: {
|
case IAssistProvider::Asynchronous: {
|
||||||
processor->setAsyncCompletionAvailableHandler(
|
processor->setAsyncCompletionAvailableHandler([this, reason](IAssistProposal *newProposal) {
|
||||||
[this, reason](IAssistProposal *newProposal){
|
// do not delete this processor directly since this function is called from within the processor
|
||||||
|
QTimer::singleShot(0, [processor = m_asyncProcessor]() { delete processor; });
|
||||||
if (m_asyncProcessor && m_asyncProcessor->needsRestart() && m_receivedContentWhileWaiting) {
|
if (m_asyncProcessor && m_asyncProcessor->needsRestart() && m_receivedContentWhileWaiting) {
|
||||||
delete newProposal;
|
delete newProposal;
|
||||||
m_receivedContentWhileWaiting = false;
|
m_receivedContentWhileWaiting = false;
|
||||||
@@ -288,8 +289,10 @@ void CodeAssistantPrivate::cancelCurrentRequest()
|
|||||||
m_requestRunner->setDiscardProposal(true);
|
m_requestRunner->setDiscardProposal(true);
|
||||||
disconnect(m_runnerConnection);
|
disconnect(m_runnerConnection);
|
||||||
}
|
}
|
||||||
if (m_asyncProcessor)
|
if (m_asyncProcessor) {
|
||||||
m_asyncProcessor->cancel();
|
m_asyncProcessor->cancel();
|
||||||
|
m_asyncProcessor->setAsyncProposalAvailable(nullptr);
|
||||||
|
}
|
||||||
invalidateCurrentRequestData();
|
invalidateCurrentRequestData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user