summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@theqtcompany.com>2015-07-29 12:15:15 +0200
committerNikolai Kosjar <nikolai.kosjar@theqtcompany.com>2015-07-29 12:18:39 +0000
commita1da7182f91a8d3a197f6356eafbba46e52cd2a3 (patch)
tree14b7e7d91a3007beeb35adf358f7eb0aae3f6953
parent6bb2aa6ba15519e1593d82d93ac818ff95e9d443 (diff)
downloadqt-creator-a1da7182f91a8d3a197f6356eafbba46e52cd2a3.tar.gz
Clang: Fix memory leak on completion II
...for the following case: void fun1(); void fun2(); void g() { fu // Type 'n', wait for the widget, hit return to choose the item } Once e.g. "fun1" is chosen, the completion is triggered again but the processor (and as result the assist interface) is not freed. The assumption was that for the AsynchronousWithThread case IAssistProcessor::perform() would either return 0 (async completion was started) or != 0 for an immediate proposal. It turns out there is a third case: no proposal if the completion is not applicable, e.g. choosing an item in the example above will retrigger completion, however no completion makes sense for "fun1()<CURSOR>" for an idle editor. Workaround the case with a getter/setter in IAssistProcessor. Proper solution should (slightly?) rework the IAssistProcessor API. Change-Id: I44dde8287998d54ded1ea07e7c39a5157cf62029 Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp4
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp2
-rw-r--r--src/plugins/texteditor/codeassist/iassistprocessor.h4
3 files changed, 9 insertions, 1 deletions
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
index 4c1304b351..bff0c4577e 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
@@ -226,8 +226,10 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface *
{
m_interface.reset(static_cast<const ClangCompletionAssistInterface *>(interface));
- if (interface->reason() != ExplicitlyInvoked && !accepts())
+ if (interface->reason() != ExplicitlyInvoked && !accepts()) {
+ setPerformWasApplicable(false);
return 0;
+ }
return startCompletionHelper(); // == 0 if results are calculated asynchronously
}
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp
index 65a899a384..8b4c5600de 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.cpp
+++ b/src/plugins/texteditor/codeassist/codeassistant.cpp
@@ -281,6 +281,8 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
if (IAssistProposal *newProposal = processor->perform(assistInterface)) {
displayProposal(newProposal, reason);
delete processor;
+ } else if (!processor->performWasApplicable()) {
+ delete processor;
}
// ...otherwise the async request was triggered
diff --git a/src/plugins/texteditor/codeassist/iassistprocessor.h b/src/plugins/texteditor/codeassist/iassistprocessor.h
index 0d4fd31e9d..3456434c86 100644
--- a/src/plugins/texteditor/codeassist/iassistprocessor.h
+++ b/src/plugins/texteditor/codeassist/iassistprocessor.h
@@ -56,8 +56,12 @@ public:
using AsyncCompletionsAvailableHandler = std::function<void (IAssistProposal *proposal)>;
void setAsyncCompletionAvailableHandler(const AsyncCompletionsAvailableHandler &finalizer);
+ bool performWasApplicable() { return m_performWasApplicable; }
+ void setPerformWasApplicable(bool applicable) { m_performWasApplicable = applicable; }
+
private:
AsyncCompletionsAvailableHandler m_asyncCompletionsAvailableHandler;
+ bool m_performWasApplicable = true;
};
} // TextEditor