aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2020-03-26 09:21:57 +0100
committerDavid Schulz <david.schulz@qt.io>2020-05-12 08:24:41 +0000
commit8bde432dfe40ff9b9491acd62a7854c060cad01d (patch)
treea9d5c2d21c992ddb26c6ff288d7fa2f202156774
parentda3b14faee5bcc0f0238aa35d768c2d71a34b24c (diff)
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>
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.cpp3
-rw-r--r--src/plugins/languageclient/client.cpp16
-rw-r--r--src/plugins/languageclient/client.h5
-rw-r--r--src/plugins/languageclient/languageclientcompletionassist.cpp4
-rw-r--r--src/plugins/languageclient/languageclientfunctionhint.cpp2
-rw-r--r--src/plugins/languageclient/languageclientquickfix.cpp2
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp9
7 files changed, 36 insertions, 5 deletions
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
index 39edf46c447..a0fac088541 100644
--- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
@@ -190,8 +190,7 @@ void BackendReceiver::completions(const CompletionsMessage &message)
<< "items";
const quint64 ticket = message.ticketNumber;
- QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket));
- if (processor)
+ if (ClangCompletionAssistProcessor *processor = m_assistProcessorsTable.take(ticket))
processor->handleAvailableCompletions(message.codeCompletions);
}
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index ebb4b0802af..48ea15bb803 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -40,6 +40,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <texteditor/codeassist/documentcontentcompletion.h>
+#include <texteditor/codeassist/iassistprocessor.h>
#include <texteditor/syntaxhighlighter.h>
#include <texteditor/tabsettings.h>
#include <texteditor/textdocument.h>
@@ -146,6 +147,8 @@ Client::~Client()
highlighter->clearAllExtraFormats();
}
}
+ for (IAssistProcessor *processor : m_runningAssistProcessors)
+ processor->setAsyncProposalAvailable(nullptr);
updateEditorToolBar(m_openedDocument.keys());
}
@@ -902,6 +905,16 @@ bool Client::isSupportedUri(const DocumentUri &uri) const
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
{
QTC_ASSERT(settings, return false);
@@ -942,6 +955,9 @@ bool Client::reset()
document->disconnect(this);
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
resetAssistProviders(document);
+ for (TextEditor::IAssistProcessor *processor : m_runningAssistProcessors)
+ processor->setAsyncProposalAvailable(nullptr);
+ m_runningAssistProcessors.clear();
return true;
}
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index 2b75602817c..1f682555415 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -59,6 +59,7 @@ namespace Core { class IDocument; }
namespace ProjectExplorer { class Project; }
namespace TextEditor
{
+class IAssistProcessor;
class TextDocument;
class TextEditorWidget;
class TextMark;
@@ -141,6 +142,9 @@ public:
bool isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) 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; }
QString name() const { return m_displayName; }
@@ -233,6 +237,7 @@ private:
HoverHandler m_hoverHandler;
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
const ProjectExplorer::Project *m_project = nullptr;
+ QSet<TextEditor::IAssistProcessor *> m_runningAssistProcessors;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp
index 3055092c064..a5d0c9774f5 100644
--- a/src/plugins/languageclient/languageclientcompletionassist.cpp
+++ b/src/plugins/languageclient/languageclientcompletionassist.cpp
@@ -342,6 +342,7 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(const AssistIn
});
completionRequest.setParams(params);
m_client->sendContent(completionRequest);
+ m_client->addAssistProcessor(this);
m_currentRequest = completionRequest.id();
m_document = interface->textDocument();
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime()
@@ -359,6 +360,7 @@ void LanguageClientCompletionAssistProcessor::cancel()
{
if (running()) {
m_client->cancelRequest(m_currentRequest);
+ m_client->removeAssistProcessor(this);
m_currentRequest = MessageId();
}
}
@@ -376,6 +378,7 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
const Utils::optional<CompletionResult> &result = response.result();
if (!result || Utils::holds_alternative<std::nullptr_t>(*result)) {
setAsyncProposalAvailable(nullptr);
+ m_client->removeAssistProcessor(this);
return;
}
@@ -396,6 +399,7 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
proposal->setFragile(true);
proposal->setSupportsPrefix(false);
setAsyncProposalAvailable(proposal);
+ m_client->removeAssistProcessor(this);
qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : "
<< items.count() << " completions handled";
}
diff --git a/src/plugins/languageclient/languageclientfunctionhint.cpp b/src/plugins/languageclient/languageclientfunctionhint.cpp
index 33618649735..8b47b73458c 100644
--- a/src/plugins/languageclient/languageclientfunctionhint.cpp
+++ b/src/plugins/languageclient/languageclientfunctionhint.cpp
@@ -96,6 +96,7 @@ void FunctionHintProcessor::cancel()
{
if (running()) {
m_client->cancelRequest(m_currentRequest);
+ m_client->removeAssistProcessor(this);
m_currentRequest = MessageId();
}
}
@@ -107,6 +108,7 @@ void FunctionHintProcessor::handleSignatureResponse(const SignatureHelpRequest::
m_client->log(error.value());
FunctionHintProposalModelPtr model(
new FunctionHintProposalModel(response.result().value().value()));
+ m_client->removeAssistProcessor(this);
setAsyncProposalAvailable(new FunctionHintProposal(m_pos, model));
}
diff --git a/src/plugins/languageclient/languageclientquickfix.cpp b/src/plugins/languageclient/languageclientquickfix.cpp
index f3b86377aee..410dc94501f 100644
--- a/src/plugins/languageclient/languageclientquickfix.cpp
+++ b/src/plugins/languageclient/languageclientquickfix.cpp
@@ -132,6 +132,7 @@ void LanguageClientQuickFixAssistProcessor::cancel()
{
if (running()) {
m_client->cancelRequest(m_currentRequest);
+ m_client->removeAssistProcessor(this);
m_currentRequest = MessageId();
}
}
@@ -154,6 +155,7 @@ void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
}
}
}
+ m_client->removeAssistProcessor(this);
setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
}
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp
index b1154896745..f5007fc9871 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.cpp
+++ b/src/plugins/texteditor/codeassist/codeassistant.cpp
@@ -252,8 +252,9 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
break;
}
case IAssistProvider::Asynchronous: {
- processor->setAsyncCompletionAvailableHandler(
- [this, reason](IAssistProposal *newProposal){
+ processor->setAsyncCompletionAvailableHandler([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) {
delete newProposal;
m_receivedContentWhileWaiting = false;
@@ -288,8 +289,10 @@ void CodeAssistantPrivate::cancelCurrentRequest()
m_requestRunner->setDiscardProposal(true);
disconnect(m_runnerConnection);
}
- if (m_asyncProcessor)
+ if (m_asyncProcessor) {
m_asyncProcessor->cancel();
+ m_asyncProcessor->setAsyncProposalAvailable(nullptr);
+ }
invalidateCurrentRequestData();
}