From a08336fcc2962976a4edd423ab48629b3f38882e Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 1 Dec 2015 13:21:02 +0100 Subject: [PATCH] Clang: Don't send multiple completions for the same position If we send already a completion we should test if there is already one sent for the same position. Change-Id: Ie88f89bff0e1da1c5e747827a45154c7ccaecabc Reviewed-by: Nikolai Kosjar Reviewed-by: Marco Bubke --- .../clangbackendipcintegration.cpp | 10 ++++ .../clangbackendipcintegration.h | 4 ++ .../clangcompletionassistprocessor.cpp | 59 ++++++++++++++----- .../clangcompletionassistprocessor.h | 2 +- .../texteditor/codeassist/codeassistant.cpp | 12 +--- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 635edb1ed45..63cd16daf90 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -137,6 +137,11 @@ void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *t } } +bool IpcReceiver::isExpectingCodeCompletedMessage() const +{ + return !m_assistProcessorsTable.isEmpty(); +} + void IpcReceiver::alive() { qCDebug(log) << "<<< AliveMessage"; @@ -446,6 +451,11 @@ void IpcCommunicator::updateTranslationUnitVisiblity() updateTranslationUnitVisiblity(currentCppEditorDocumentFilePath(), visibleCppEditorDocumentsFilePaths()); } +bool IpcCommunicator::isNotWaitingForCompletion() const +{ + return !m_ipcReceiver.isExpectingCodeCompletedMessage(); +} + void IpcCommunicator::updateTranslationUnitVisiblity(const Utf8String ¤tEditorFilePath, const Utf8StringVector &visibleEditorsFilePaths) { diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 160de329ef9..2f045f2abe2 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -76,6 +76,8 @@ public: void deleteAndClearWaitingAssistProcessors(); void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget); + bool isExpectingCodeCompletedMessage() const; + private: void alive() override; void echo(const ClangBackEnd::EchoMessage &message) override; @@ -152,6 +154,8 @@ public: void registerFallbackProjectPart(); void updateTranslationUnitVisiblity(); + bool isNotWaitingForCompletion() const; + public: // for tests IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender); void killBackendProcess(); diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 2f6b17ba82e..fe437f52fca 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -342,13 +342,16 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper() case ClangCompletionContextAnalyzer::PassThroughToLibClang: { m_addSnippets = m_completionOperator == T_EOF_SYMBOL; m_sentRequestType = NormalCompletion; - sendCompletionRequest(analyzer.positionForClang(), modifiedFileContent); + const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), + modifiedFileContent); + setPerformWasApplicable(requestSent); break; } case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: { m_sentRequestType = FunctionHintCompletion; m_functionName = analyzer.functionName(); - sendCompletionRequest(analyzer.positionForClang(), QByteArray()); + const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray()); + setPerformWasApplicable(requestSent); break; } default: @@ -702,15 +705,34 @@ bool shouldSendDocumentForCompletion(const QString &filePath, return true; } -void setLastCompletionPositionAndDocumentRevision(const QString &filePath, - int completionPosition) +bool shouldSendCodeCompletion(const QString &filePath, + int completionPosition) { auto *document = cppDocument(filePath); if (document) { - document->sendTracker().setLastCompletionPosition(completionPosition); - document->sendTracker().setLastSentRevision(document->revision()); + auto &sendTracker = document->sendTracker(); + return sendTracker.shouldSendCompletion(completionPosition); } + + return true; +} + +void setLastDocumentRevision(const QString &filePath) +{ + auto *document = cppDocument(filePath); + + if (document) + document->sendTracker().setLastSentRevision(int(document->revision())); +} + +void setLastCompletionPosition(const QString &filePath, + int completionPosition) +{ + auto *document = cppDocument(filePath); + + if (document) + document->sendTracker().setLastCompletionPosition(completionPosition); } QString projectPartIdForEditorDocument(const QString &filePath) @@ -726,7 +748,7 @@ QString projectPartIdForEditorDocument(const QString &filePath) } } -void ClangCompletionAssistProcessor::sendCompletionRequest(int position, +bool ClangCompletionAssistProcessor::sendCompletionRequest(int position, const QByteArray &customFileContent) { int line, column; @@ -735,17 +757,22 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position, const QString filePath = m_interface->fileName(); - if (shouldSendDocumentForCompletion(filePath, position)) { - sendFileContent(customFileContent); - setLastCompletionPositionAndDocumentRevision(filePath, position); + auto &ipcCommunicator = m_interface->ipcCommunicator(); + + if (shouldSendCodeCompletion(filePath, position) + || ipcCommunicator.isNotWaitingForCompletion()) { + if (shouldSendDocumentForCompletion(filePath, position)) { + sendFileContent(customFileContent); + setLastDocumentRevision(filePath); + } + + const QString projectPartId = projectPartIdForEditorDocument(filePath); + ipcCommunicator.completeCode(this, filePath, uint(line), uint(column), projectPartId); + setLastCompletionPosition(filePath, position); + return true; } - const QString projectPartId = projectPartIdForEditorDocument(filePath); - m_interface->ipcCommunicator().completeCode(this, - filePath, - uint(line), - uint(column), - projectPartId); + return false; } TextEditor::IAssistProposal *ClangCompletionAssistProcessor::createProposal() const diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h index 4cecf8a31ed..6a8abddcb71 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h @@ -84,7 +84,7 @@ private: UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const; void sendFileContent(const QByteArray &customFileContent); - void sendCompletionRequest(int position, const QByteArray &customFileContent); + bool sendCompletionRequest(int position, const QByteArray &customFileContent); void handleAvailableCompletions(const CodeCompletions &completions); bool handleAvailableFunctionHintCompletions(const CodeCompletions &completions); diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index cc247d1323b..59fe46e5e3b 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -263,14 +263,8 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, case IAssistProvider::Asynchronous: { processor->setAsyncCompletionAvailableHandler( [this, processor, reason](IAssistProposal *newProposal){ - if (m_asyncProcessor != processor) { - delete newProposal->model(); - delete newProposal; - return; - } - - invalidateCurrentRequestData(); QTC_CHECK(newProposal); + invalidateCurrentRequestData(); displayProposal(newProposal, reason); emit q->finished(); @@ -282,10 +276,10 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, delete processor; } else if (!processor->performWasApplicable()) { delete processor; + } else { // ...async request was triggered + m_asyncProcessor = processor; } - // ...otherwise the async request was triggered - m_asyncProcessor = processor; break; } } // switch