diff --git a/src/plugins/cppeditor/cppquickfixassistant.cpp b/src/plugins/cppeditor/cppquickfixassistant.cpp index 87f436639db..dfb03b38c53 100644 --- a/src/plugins/cppeditor/cppquickfixassistant.cpp +++ b/src/plugins/cppeditor/cppquickfixassistant.cpp @@ -51,9 +51,9 @@ namespace Internal { // ------------------------- // CppQuickFixAssistProvider // ------------------------- -bool CppQuickFixAssistProvider::isAsynchronous() const +IAssistProvider::RunType CppQuickFixAssistProvider::runType() const { - return false; + return Synchronous; } bool CppQuickFixAssistProvider::supportsEditor(Core::Id editorId) const diff --git a/src/plugins/cppeditor/cppquickfixassistant.h b/src/plugins/cppeditor/cppquickfixassistant.h index eea8a78dbfd..967b6825cd0 100644 --- a/src/plugins/cppeditor/cppquickfixassistant.h +++ b/src/plugins/cppeditor/cppquickfixassistant.h @@ -77,7 +77,7 @@ private: class CppQuickFixAssistProvider : public TextEditor::QuickFixAssistProvider { public: - bool isAsynchronous() const Q_DECL_OVERRIDE; + IAssistProvider::RunType runType() const Q_DECL_OVERRIDE; bool supportsEditor(Core::Id editorId) const Q_DECL_OVERRIDE; TextEditor::IAssistProcessor *createProcessor() const Q_DECL_OVERRIDE; diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index 3a3b20aedad..d91d20ee455 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -208,9 +208,9 @@ bool VirtualFunctionAssistProvider::configure(const Parameters ¶meters) return true; } -bool VirtualFunctionAssistProvider::isAsynchronous() const +IAssistProvider::RunType VirtualFunctionAssistProvider::runType() const { - return true; + return AsynchronousWithThread; } bool VirtualFunctionAssistProvider::supportsEditor(Core::Id editorId) const diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h index fac0f110907..7a5cf668aaf 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h @@ -63,7 +63,7 @@ public: Parameters params() const { return m_params; } void clearParams() { m_params = Parameters(); } - bool isAsynchronous() const Q_DECL_OVERRIDE; + IAssistProvider::RunType runType() const Q_DECL_OVERRIDE; bool supportsEditor(Core::Id editorId) const Q_DECL_OVERRIDE; TextEditor::IAssistProcessor *createProcessor() const Q_DECL_OVERRIDE; diff --git a/src/plugins/qmljseditor/qmljsquickfixassist.cpp b/src/plugins/qmljseditor/qmljsquickfixassist.cpp index 924da7e78ff..ee5654651c7 100644 --- a/src/plugins/qmljseditor/qmljsquickfixassist.cpp +++ b/src/plugins/qmljseditor/qmljsquickfixassist.cpp @@ -77,9 +77,9 @@ QmlJSQuickFixAssistProvider::QmlJSQuickFixAssistProvider() QmlJSQuickFixAssistProvider::~QmlJSQuickFixAssistProvider() {} -bool QmlJSQuickFixAssistProvider::isAsynchronous() const +IAssistProvider::RunType QmlJSQuickFixAssistProvider::runType() const { - return false; + return Synchronous; } bool QmlJSQuickFixAssistProvider::supportsEditor(Core::Id editorId) const diff --git a/src/plugins/qmljseditor/qmljsquickfixassist.h b/src/plugins/qmljseditor/qmljsquickfixassist.h index 9f5008fd596..9aa337e784f 100644 --- a/src/plugins/qmljseditor/qmljsquickfixassist.h +++ b/src/plugins/qmljseditor/qmljsquickfixassist.h @@ -64,7 +64,7 @@ public: QmlJSQuickFixAssistProvider(); ~QmlJSQuickFixAssistProvider(); - bool isAsynchronous() const Q_DECL_OVERRIDE; + IAssistProvider::RunType runType() const Q_DECL_OVERRIDE; bool supportsEditor(Core::Id editorId) const Q_DECL_OVERRIDE; TextEditor::IAssistProcessor *createProcessor() const Q_DECL_OVERRIDE; diff --git a/src/plugins/texteditor/circularclipboardassist.cpp b/src/plugins/texteditor/circularclipboardassist.cpp index c318de8622d..218d99f8a1c 100644 --- a/src/plugins/texteditor/circularclipboardassist.cpp +++ b/src/plugins/texteditor/circularclipboardassist.cpp @@ -108,9 +108,9 @@ public: } }; -bool ClipboardAssistProvider::isAsynchronous() const +IAssistProvider::RunType ClipboardAssistProvider::runType() const { - return false; + return Synchronous; } bool ClipboardAssistProvider::supportsEditor(Core::Id /*editorId*/) const diff --git a/src/plugins/texteditor/circularclipboardassist.h b/src/plugins/texteditor/circularclipboardassist.h index 81f807723be..05cb67bdaae 100644 --- a/src/plugins/texteditor/circularclipboardassist.h +++ b/src/plugins/texteditor/circularclipboardassist.h @@ -40,7 +40,7 @@ namespace Internal { class ClipboardAssistProvider: public IAssistProvider { public: - bool isAsynchronous() const; + IAssistProvider::RunType runType() const Q_DECL_OVERRIDE; bool supportsEditor(Core::Id editorId) const Q_DECL_OVERRIDE; IAssistProcessor *createProcessor() const Q_DECL_OVERRIDE; }; diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 1dd33bd87ab..e7a4d181ae3 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -101,6 +101,7 @@ private: QList m_quickFixProviders; Internal::ProcessorRunner *m_requestRunner; IAssistProvider *m_requestProvider; + IAssistProcessor *m_asyncProcessor; AssistKind m_assistKind; IAssistProposalWidget *m_proposalWidget; QScopedPointer m_proposal; @@ -121,6 +122,7 @@ CodeAssistantPrivate::CodeAssistantPrivate(CodeAssistant *assistant) , m_editorWidget(0) , m_requestRunner(0) , m_requestProvider(0) + , m_asyncProcessor(0) , m_assistKind(TextEditor::Completion) , m_proposalWidget(0) , m_receivedContentWhileWaiting(false) @@ -230,7 +232,14 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, if (!assistInterface) return; - if (provider->isAsynchronous()) { + switch (provider->runType()) { + case IAssistProvider::Synchronous: { + if (IAssistProposal *newProposal = processor->perform(assistInterface)) + displayProposal(newProposal, reason); + delete processor; + break; + } + case IAssistProvider::AsynchronousWithThread: { if (IAssistProposal *newProposal = processor->immediateProposal(assistInterface)) displayProposal(newProposal, reason); @@ -247,19 +256,41 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, m_requestRunner->setProcessor(processor); m_requestRunner->setAssistInterface(assistInterface); m_requestRunner->start(); - return; + break; } + case IAssistProvider::Asynchronous: { + processor->setAsyncCompletionAvailableHandler( + [this, processor, reason](IAssistProposal *newProposal){ + if (m_asyncProcessor != processor) + return; - if (IAssistProposal *newProposal = processor->perform(assistInterface)) - displayProposal(newProposal, reason); - delete processor; + invalidateCurrentRequestData(); + QTC_CHECK(newProposal); + displayProposal(newProposal, reason); + + emit q->finished(); + }); + + // If there is a proposal, nothing asynchronous happened... + if (IAssistProposal *newProposal = processor->perform(assistInterface)) { + displayProposal(newProposal, reason); + delete processor; + } + + // ...otherwise the async request was triggered + m_asyncProcessor = processor; + break; + } + } // switch } void CodeAssistantPrivate::cancelCurrentRequest() { - m_requestRunner->setDiscardProposal(true); - disconnect(m_requestRunner, &ProcessorRunner::finished, - this, &CodeAssistantPrivate::proposalComputed); + if (m_requestRunner) { + m_requestRunner->setDiscardProposal(true); + disconnect(m_requestRunner, &ProcessorRunner::finished, + this, &CodeAssistantPrivate::proposalComputed); + } invalidateCurrentRequestData(); } @@ -366,11 +397,12 @@ bool CodeAssistantPrivate::isDisplayingProposal() const bool CodeAssistantPrivate::isWaitingForProposal() const { - return m_requestRunner != 0; + return m_requestRunner != 0 || m_asyncProcessor != 0; } void CodeAssistantPrivate::invalidateCurrentRequestData() { + m_asyncProcessor = 0; m_requestRunner = 0; m_requestProvider = 0; } @@ -415,7 +447,7 @@ void CodeAssistantPrivate::notifyChange() bool CodeAssistantPrivate::hasContext() const { - return m_requestRunner || m_proposalWidget; + return m_requestRunner || m_asyncProcessor || m_proposalWidget; } void CodeAssistantPrivate::destroyContext() diff --git a/src/plugins/texteditor/codeassist/completionassistprovider.cpp b/src/plugins/texteditor/codeassist/completionassistprovider.cpp index 3a8496ccf87..14d15ef0942 100644 --- a/src/plugins/texteditor/codeassist/completionassistprovider.cpp +++ b/src/plugins/texteditor/codeassist/completionassistprovider.cpp @@ -40,9 +40,9 @@ CompletionAssistProvider::CompletionAssistProvider() CompletionAssistProvider::~CompletionAssistProvider() {} -bool CompletionAssistProvider::isAsynchronous() const +IAssistProvider::RunType CompletionAssistProvider::runType() const { - return true; + return AsynchronousWithThread; } int CompletionAssistProvider::activationCharSequenceLength() const diff --git a/src/plugins/texteditor/codeassist/completionassistprovider.h b/src/plugins/texteditor/codeassist/completionassistprovider.h index e08113b8a4d..9da8f1533a9 100644 --- a/src/plugins/texteditor/codeassist/completionassistprovider.h +++ b/src/plugins/texteditor/codeassist/completionassistprovider.h @@ -44,7 +44,7 @@ public: CompletionAssistProvider(); ~CompletionAssistProvider(); - bool isAsynchronous() const Q_DECL_OVERRIDE; + IAssistProvider::RunType runType() const Q_DECL_OVERRIDE; virtual int activationCharSequenceLength() const; virtual bool isActivationCharSequence(const QString &sequence) const; virtual bool isContinuationChar(const QChar &c) const; diff --git a/src/plugins/texteditor/codeassist/iassistprocessor.cpp b/src/plugins/texteditor/codeassist/iassistprocessor.cpp index b8fc6210e79..eab985c636d 100644 --- a/src/plugins/texteditor/codeassist/iassistprocessor.cpp +++ b/src/plugins/texteditor/codeassist/iassistprocessor.cpp @@ -47,6 +47,18 @@ IAssistProcessor::IAssistProcessor() IAssistProcessor::~IAssistProcessor() {} +void IAssistProcessor::setAsyncProposalAvailable(IAssistProposal *proposal) +{ + if (m_asyncCompletionsAvailableHandler) + m_asyncCompletionsAvailableHandler(proposal); +} + +void IAssistProcessor::setAsyncCompletionAvailableHandler( + const IAssistProcessor::AsyncCompletionsAvailableHandler &finalizer) +{ + m_asyncCompletionsAvailableHandler = finalizer; +} + /*! \fn IAssistProposal *TextEditor::IAssistProcessor::perform(const AssistInterface *interface) diff --git a/src/plugins/texteditor/codeassist/iassistprocessor.h b/src/plugins/texteditor/codeassist/iassistprocessor.h index b9561490666..0d4fd31e9df 100644 --- a/src/plugins/texteditor/codeassist/iassistprocessor.h +++ b/src/plugins/texteditor/codeassist/iassistprocessor.h @@ -33,6 +33,8 @@ #include +#include + namespace TextEditor { class IAssistProvider; @@ -47,6 +49,15 @@ public: virtual IAssistProposal *immediateProposal(const AssistInterface *) { return 0; } virtual IAssistProposal *perform(const AssistInterface *interface) = 0; + + void setAsyncProposalAvailable(IAssistProposal *proposal); + + // Internal, used by CodeAssist + using AsyncCompletionsAvailableHandler = std::function; + void setAsyncCompletionAvailableHandler(const AsyncCompletionsAvailableHandler &finalizer); + +private: + AsyncCompletionsAvailableHandler m_asyncCompletionsAvailableHandler; }; } // TextEditor diff --git a/src/plugins/texteditor/codeassist/iassistprovider.h b/src/plugins/texteditor/codeassist/iassistprovider.h index 9ca728789be..878ded880fd 100644 --- a/src/plugins/texteditor/codeassist/iassistprovider.h +++ b/src/plugins/texteditor/codeassist/iassistprovider.h @@ -47,7 +47,13 @@ class TEXTEDITOR_EXPORT IAssistProvider : public QObject public: IAssistProvider() {} - virtual bool isAsynchronous() const = 0; + enum RunType { + Synchronous, + Asynchronous, + AsynchronousWithThread + }; + + virtual RunType runType() const = 0; virtual bool supportsEditor(Core::Id editorId) const = 0; virtual IAssistProcessor *createProcessor() const = 0; };