diff --git a/src/plugins/clangcodemodel/clangdcompletion.cpp b/src/plugins/clangcodemodel/clangdcompletion.cpp index dc5feccf037..8b7799e8684 100644 --- a/src/plugins/clangcodemodel/clangdcompletion.cpp +++ b/src/plugins/clangcodemodel/clangdcompletion.cpp @@ -81,7 +81,9 @@ private: class ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor { public: - ClangdCompletionAssistProcessor(ClangdClient *client, const QString &snippetsGroup); + ClangdCompletionAssistProcessor(ClangdClient *client, + const IAssistProvider *provider, + const QString &snippetsGroup); ~ClangdCompletionAssistProcessor(); private: @@ -164,7 +166,7 @@ IAssistProcessor *ClangdCompletionAssistProvider::createProcessor( : QString(); qCDebug(clangdLogCompletion) << "creating proper completion processor" << (snippetsGroup.isEmpty() ? "without" : "with") << "snippets"; - return new ClangdCompletionAssistProcessor(m_client, snippetsGroup); + return new ClangdCompletionAssistProcessor(m_client, this, snippetsGroup); } bool ClangdCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const @@ -554,8 +556,9 @@ QList CustomAssistProcessor::completeIncludePath( } ClangdCompletionAssistProcessor::ClangdCompletionAssistProcessor(ClangdClient *client, + const IAssistProvider *provider, const QString &snippetsGroup) - : LanguageClientCompletionAssistProcessor(client, snippetsGroup) + : LanguageClientCompletionAssistProcessor(client, provider, snippetsGroup) , m_client(client) { m_timer.start(); diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index 8b47f7fe5b3..575c3b93952 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -42,6 +42,7 @@ public: : TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR; if (Core::Command *command = Core::ActionManager::command(id)) m_sequence = command->keySequence(); + setFragile(true); } protected: @@ -169,9 +170,7 @@ IAssistProcessor *VirtualFunctionAssistProvider::createProcessor(const AssistInt VirtualFunctionProposal::VirtualFunctionProposal( int cursorPos, const QList &items, bool openInSplit) : GenericProposal(cursorPos, items), m_openInSplit(openInSplit) -{ - setFragile(true); -} +{ } IAssistProposalWidget *VirtualFunctionProposal::createWidget() const { diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp index 2762e2b32e7..afee00a5acc 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.cpp +++ b/src/plugins/languageclient/languageclientcompletionassist.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,13 @@ public: bool supportsPrefixExpansion() const override { return false; } QList items() const { return m_currentItems; } + + bool isComplete(const QString prefix) + { return m_completePrefix && prefix.startsWith(*m_completePrefix); } + void setCompletePrefix(const QString &completePrefix) { m_completePrefix = completePrefix; } + +private: + std::optional m_completePrefix; }; bool LanguageClientCompletionModel::isSortable(const QString &) const @@ -252,13 +260,85 @@ void LanguageClientCompletionModel::sort(const QString &prefix) }); } +class LanguageClientCompletionWidget : public GenericProposalWidget +{ +public: + LanguageClientCompletionWidget(const IAssistProvider *provider) + : m_provider(provider) + {} + + ~LanguageClientCompletionWidget() { deleteCurrentProcessor(); } + + void deleteCurrentProcessor() + { + if (m_processor) { + m_processor->cancel(); + delete m_processor; + m_processor = nullptr; + } + } + + bool isComplete(const AssistInterface *interface) + { + const QString prefix = interface->textAt(basePosition(), + interface->position() - basePosition()); + return static_cast(model().data())->isComplete(prefix); + } + + void setProposal(IAssistProposal *proposal) + { + if (!proposal) + return; + updateModel(proposal->model()); + delete proposal; + } + + void updateProposal(std::unique_ptr &&interface) override + { + deleteCurrentProcessor(); + if (!m_provider || isComplete(interface.get())) { + GenericProposalWidget::updateProposal(std::move(interface)); + return; + } + auto processor = m_provider->createProcessor(interface.get()); + QTC_ASSERT(processor, return); + + processor->setAsyncCompletionAvailableHandler([this, processor](IAssistProposal *proposal) { + QTC_ASSERT(processor == m_processor, return); + if (!processor->running()) { + // do not delete this processor directly since this function is called from within the processor + QMetaObject::invokeMethod( + QCoreApplication::instance(), + [processor] { delete processor; }, + Qt::QueuedConnection); + m_processor = nullptr; + } + setProposal(proposal); + }); + + setProposal(processor->start(std::move(interface))); + if (processor->running()) + m_processor = processor; + else + delete processor; + } + +private: + QPointer m_provider; + std::optional m_currentRequestId; + IAssistProcessor *m_processor = nullptr; +}; + class LanguageClientCompletionProposal : public GenericProposal { public: - LanguageClientCompletionProposal(int cursorPos, LanguageClientCompletionModel *model) + LanguageClientCompletionProposal(const IAssistProvider *provider, + int cursorPos, + LanguageClientCompletionModel *model) : GenericProposal(cursorPos, GenericProposalModelPtr(model)) , m_model(model) - { } + , m_provider(provider) + {} // IAssistProposal interface bool hasItemsToPropose(const QString &/*text*/, AssistReason reason) const override @@ -274,15 +354,21 @@ public: }); } + IAssistProposalWidget *createWidget() const override + { + return new LanguageClientCompletionWidget(m_provider); + } + LanguageClientCompletionModel *m_model; QPointer m_document; + QPointer m_provider; int m_pos = -1; }; LanguageClientCompletionAssistProcessor::LanguageClientCompletionAssistProcessor( - Client *client, - const QString &snippetsGroup) + Client *client, const IAssistProvider *provider, const QString &snippetsGroup) : m_client(client) + , m_provider(provider) , m_snippetsGroup(snippetsGroup) {} @@ -409,32 +495,36 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse( return; } + const QString prefix = Utils::Text::textAt(QTextCursor(document()), + m_basePos, + m_pos - m_basePos); + QList items; - bool isComplete = false; + bool isComplete = true; if (std::holds_alternative(*result)) { const auto &list = std::get(*result); items = list.items().value_or(QList()); - isComplete = !list.isIncomplete(); + if (list.isIncomplete()) + isComplete = false; } else if (std::holds_alternative>(*result)) { items = std::get>(*result); } auto proposalItems = generateCompletionItems(items); if (!m_snippetsGroup.isEmpty()) { - proposalItems << TextEditor::SnippetAssistCollector( - m_snippetsGroup, QIcon(":/texteditor/images/snippet.png")).collect(); + proposalItems << TextEditor::SnippetAssistCollector(m_snippetsGroup, + QIcon( + ":/texteditor/images/snippet.png")) + .collect(); } auto model = new LanguageClientCompletionModel(); model->loadContent(proposalItems); - LanguageClientCompletionProposal *proposal = new LanguageClientCompletionProposal(m_basePos, + if (isComplete) + model->setCompletePrefix(prefix); + LanguageClientCompletionProposal *proposal = new LanguageClientCompletionProposal(m_provider, + m_basePos, model); proposal->m_document = document(); proposal->m_pos = m_pos; - const QString completePrefix = Utils::Text::textAt(QTextCursor(document()), - m_basePos, - m_pos - m_basePos); - proposal->setPrefixChecker([isComplete, completePrefix](const QString &candidate) { - return isComplete && candidate.startsWith(completePrefix); - }); setAsyncProposalAvailable(proposal); m_client->removeAssistProcessor(this); qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : " @@ -449,8 +539,7 @@ LanguageClientCompletionAssistProvider::LanguageClientCompletionAssistProvider(C IAssistProcessor *LanguageClientCompletionAssistProvider::createProcessor( const AssistInterface *) const { - return new LanguageClientCompletionAssistProcessor(m_client, - m_snippetsGroup); + return new LanguageClientCompletionAssistProcessor(m_client, this, m_snippetsGroup); } int LanguageClientCompletionAssistProvider::activationCharSequenceLength() const @@ -460,7 +549,7 @@ int LanguageClientCompletionAssistProvider::activationCharSequenceLength() const bool LanguageClientCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const { - return Utils::anyOf(m_triggerChars, [sequence](const QString &trigger){ + return Utils::anyOf(m_triggerChars, [sequence](const QString &trigger) { return trigger.endsWith(sequence); }); } diff --git a/src/plugins/languageclient/languageclientcompletionassist.h b/src/plugins/languageclient/languageclientcompletionassist.h index fec5d74072f..b719b2a37d8 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.h +++ b/src/plugins/languageclient/languageclientcompletionassist.h @@ -57,7 +57,9 @@ class LANGUAGECLIENT_EXPORT LanguageClientCompletionAssistProcessor : public TextEditor::IAssistProcessor { public: - LanguageClientCompletionAssistProcessor(Client *client, const QString &snippetsGroup); + LanguageClientCompletionAssistProcessor(Client *client, + const TextEditor::IAssistProvider *provider, + const QString &snippetsGroup); ~LanguageClientCompletionAssistProcessor() override; TextEditor::IAssistProposal *perform() override; bool running() override; @@ -76,6 +78,7 @@ private: Utils::FilePath m_filePath; QPointer m_client; + QPointer m_provider; std::optional m_currentRequest; QMetaObject::Connection m_postponedUpdateConnection; const QString m_snippetsGroup; diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 8f583e4d381..db5553b03f8 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -77,12 +77,10 @@ private: private: CodeAssistant *q = nullptr; TextEditorWidget *m_editorWidget = nullptr; - QMetaObject::Connection m_runnerConnection; IAssistProvider *m_requestProvider = nullptr; IAssistProcessor *m_processor = nullptr; AssistKind m_assistKind = TextEditor::Completion; IAssistProposalWidget *m_proposalWidget = nullptr; - QScopedPointer m_proposal; bool m_receivedContentWhileWaiting = false; QTimer m_automaticProposalTimer; CompletionSettings m_settings; @@ -117,12 +115,11 @@ void CodeAssistantPrivate::invoke(AssistKind kind, IAssistProvider *provider) { stopAutomaticProposalTimer(); - if (isDisplayingProposal() && m_assistKind == kind && !m_proposal->isFragile() - && m_proposal->supportsPrefixFiltering(proposalPrefix())) { + if (isDisplayingProposal() && m_assistKind == kind && !m_proposalWidget->isFragile()) { m_proposalWidget->setReason(ExplicitlyInvoked); - m_proposalWidget->updateProposal(m_editorWidget->textAt( - m_proposal->basePosition(), - m_editorWidget->position() - m_proposal->basePosition())); + m_proposalWidget->filterProposal(m_editorWidget->textAt( + m_proposalWidget->basePosition(), + m_editorWidget->position() - m_proposalWidget->basePosition())); } else { requestProposal(ExplicitlyInvoked, kind, provider); } @@ -239,14 +236,12 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR return; // TODO: The proposal should own the model until someone takes it explicitly away. - QScopedPointer proposalCandidate(newProposal); + QScopedPointer deleter(newProposal); - if (isDisplayingProposal() && !m_proposal->isFragile() - && !m_proposalWidget->supportsModelUpdate(proposalCandidate->id())) { + if (isDisplayingProposal() && !m_proposalWidget->isFragile()) return; - } - int basePosition = proposalCandidate->basePosition(); + int basePosition = newProposal->basePosition(); if (m_editorWidget->position() < basePosition) { destroyContext(); return; @@ -266,28 +261,16 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR return; } - if (m_proposalWidget - && basePosition == proposalCandidate->basePosition() - && m_proposalWidget->supportsModelUpdate(proposalCandidate->id())) { - m_proposal.reset(proposalCandidate.take()); - m_proposal->setReason(reason); - m_proposalWidget->updateModel(m_proposal->model()); - m_proposalWidget->updateProposal(prefix); - return; - } - destroyContext(); clearAbortedPosition(); - m_proposal.reset(proposalCandidate.take()); - m_proposal->setReason(reason); - if (m_proposal->isCorrective(m_editorWidget)) - m_proposal->makeCorrection(m_editorWidget); + if (newProposal->isCorrective(m_editorWidget)) + newProposal->makeCorrection(m_editorWidget); m_editorWidget->keepAutoCompletionHighlight(true); - basePosition = m_proposal->basePosition(); - m_proposalWidget = m_proposal->createWidget(); + basePosition = newProposal->basePosition(); + m_proposalWidget = newProposal->createWidget(); connect(m_proposalWidget, &QObject::destroyed, this, &CodeAssistantPrivate::finalizeProposal); connect(m_proposalWidget, &IAssistProposalWidget::prefixExpanded, @@ -301,7 +284,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR m_proposalWidget->setKind(m_assistKind); m_proposalWidget->setBasePosition(basePosition); m_proposalWidget->setUnderlyingWidget(m_editorWidget); - m_proposalWidget->setModel(m_proposal->model()); + m_proposalWidget->setModel(newProposal->model()); m_proposalWidget->setDisplayRect(m_editorWidget->cursorRect(basePosition)); m_proposalWidget->setIsSynchronized(!m_receivedContentWhileWaiting); m_proposalWidget->showProposal(prefix); @@ -309,9 +292,9 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR void CodeAssistantPrivate::processProposalItem(AssistProposalItemInterface *proposalItem) { - QTC_ASSERT(m_proposal, return); + QTC_ASSERT(m_proposalWidget, return); TextDocumentManipulator manipulator(m_editorWidget); - proposalItem->apply(manipulator, m_proposal->basePosition()); + proposalItem->apply(manipulator, m_proposalWidget->basePosition()); destroyContext(); m_editorWidget->encourageApply(); if (!proposalItem->isSnippet()) @@ -320,34 +303,33 @@ void CodeAssistantPrivate::processProposalItem(AssistProposalItemInterface *prop void CodeAssistantPrivate::handlePrefixExpansion(const QString &newPrefix) { - QTC_ASSERT(m_proposal, return); + QTC_ASSERT(m_proposalWidget, return); QTextCursor cursor(m_editorWidget->document()); - cursor.setPosition(m_proposal->basePosition()); + cursor.setPosition(m_proposalWidget->basePosition()); cursor.movePosition(QTextCursor::EndOfWord); int currentPosition = m_editorWidget->position(); const QString textAfterCursor = m_editorWidget->textAt(currentPosition, cursor.position() - currentPosition); if (!textAfterCursor.startsWith(newPrefix)) { - if (newPrefix.indexOf(textAfterCursor, currentPosition - m_proposal->basePosition()) >= 0) + if (newPrefix.indexOf(textAfterCursor, currentPosition - m_proposalWidget->basePosition()) >= 0) currentPosition = cursor.position(); const QStringView prefixAddition = QStringView(newPrefix).mid(currentPosition - - m_proposal->basePosition()); + - m_proposalWidget->basePosition()); // If remaining string starts with the prefix addition if (textAfterCursor.startsWith(prefixAddition)) currentPosition += prefixAddition.size(); } - m_editorWidget->setCursorPosition(m_proposal->basePosition()); - m_editorWidget->replace(currentPosition - m_proposal->basePosition(), newPrefix); + m_editorWidget->setCursorPosition(m_proposalWidget->basePosition()); + m_editorWidget->replace(currentPosition - m_proposalWidget->basePosition(), newPrefix); notifyChange(); } void CodeAssistantPrivate::finalizeProposal() { stopAutomaticProposalTimer(); - m_proposal.reset(); m_proposalWidget = nullptr; if (m_receivedContentWhileWaiting) m_receivedContentWhileWaiting = false; @@ -367,8 +349,8 @@ QString CodeAssistantPrivate::proposalPrefix() const { if (!isDisplayingProposal()) return {}; - return m_editorWidget->textAt(m_proposal->basePosition(), - m_editorWidget->position() - m_proposal->basePosition()); + return m_editorWidget->textAt(m_proposalWidget->basePosition(), + m_editorWidget->position() - m_proposalWidget->basePosition()); } void CodeAssistantPrivate::invalidateCurrentRequestData() @@ -409,18 +391,14 @@ void CodeAssistantPrivate::notifyChange() stopAutomaticProposalTimer(); if (isDisplayingProposal()) { - QTC_ASSERT(m_proposal, return); - if (m_editorWidget->position() < m_proposal->basePosition()) { + QTC_ASSERT(m_proposalWidget, return); + if (m_editorWidget->position() < m_proposalWidget->basePosition()) { destroyContext(); } else { - const QString prefix = proposalPrefix(); - if (m_proposal->supportsPrefixFiltering(prefix)) { - m_proposalWidget->updateProposal(prefix); - if (!isDisplayingProposal()) - requestActivationCharProposal(); - } else { - requestProposal(m_proposal->reason(), m_assistKind, m_requestProvider, true); - } + m_proposalWidget->updateProposal( + m_editorWidget->createAssistInterface(m_assistKind, m_proposalWidget->reason())); + if (!isDisplayingProposal()) + requestActivationCharProposal(); } } } @@ -466,7 +444,7 @@ void CodeAssistantPrivate::automaticProposalTimeout() { if (isWaitingForProposal() || m_editorWidget->multiTextCursor().hasMultipleCursors() - || (isDisplayingProposal() && !m_proposal->isFragile())) { + || (isDisplayingProposal() && !m_proposalWidget->isFragile())) { return; } @@ -488,8 +466,8 @@ void CodeAssistantPrivate::updateFromCompletionSettings( void CodeAssistantPrivate::explicitlyAborted() { - QTC_ASSERT(m_proposal, return); - m_abortedBasePosition = m_proposal->basePosition(); + QTC_ASSERT(m_proposalWidget, return); + m_abortedBasePosition = m_proposalWidget->basePosition(); } void CodeAssistantPrivate::clearAbortedPosition() diff --git a/src/plugins/texteditor/codeassist/functionhintproposal.cpp b/src/plugins/texteditor/codeassist/functionhintproposal.cpp index 5c713d23303..fcc3b247eb7 100644 --- a/src/plugins/texteditor/codeassist/functionhintproposal.cpp +++ b/src/plugins/texteditor/codeassist/functionhintproposal.cpp @@ -12,9 +12,7 @@ using namespace TextEditor; FunctionHintProposal::FunctionHintProposal(int cursorPos, FunctionHintProposalModelPtr model) : IAssistProposal(functionHintId, cursorPos) , m_model(model) -{ - setFragile(true); -} +{} FunctionHintProposal::~FunctionHintProposal() = default; diff --git a/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp b/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp index 5811c100c8b..e6753c46051 100644 --- a/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp @@ -138,6 +138,7 @@ FunctionHintProposalWidget::FunctionHintProposalWidget() }); setFocusPolicy(Qt::NoFocus); + setFragile(true); } FunctionHintProposalWidget::~FunctionHintProposalWidget() @@ -150,9 +151,6 @@ void FunctionHintProposalWidget::setAssistant(CodeAssistant *assistant) d->m_assistant = assistant; } -void FunctionHintProposalWidget::setReason(AssistReason) -{} - void FunctionHintProposalWidget::setKind(AssistKind) {} @@ -190,7 +188,7 @@ void FunctionHintProposalWidget::showProposal(const QString &prefix) d->m_popupFrame->show(); } -void FunctionHintProposalWidget::updateProposal(const QString &prefix) +void FunctionHintProposalWidget::filterProposal(const QString &prefix) { updateAndCheck(prefix); } diff --git a/src/plugins/texteditor/codeassist/functionhintproposalwidget.h b/src/plugins/texteditor/codeassist/functionhintproposalwidget.h index 28813ccf8cb..97580ede248 100644 --- a/src/plugins/texteditor/codeassist/functionhintproposalwidget.h +++ b/src/plugins/texteditor/codeassist/functionhintproposalwidget.h @@ -19,7 +19,6 @@ public: ~FunctionHintProposalWidget() override; void setAssistant(CodeAssistant *assistant) override; - void setReason(AssistReason reason) override; void setKind(AssistKind kind) override; void setUnderlyingWidget(const QWidget *underlyingWidget) override; void setModel(ProposalModelPtr model) override; @@ -27,7 +26,7 @@ public: void setIsSynchronized(bool isSync) override; void showProposal(const QString &prefix) override; - void updateProposal(const QString &prefix) override; + void filterProposal(const QString &prefix) override; void closeProposal() override; bool proposalIsVisible() const override; diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp index 83fe23404ff..9eb3fdcd373 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp @@ -249,7 +249,6 @@ public: QRect m_displayRect; bool m_isSynchronized = true; bool m_explicitlySelected = false; - AssistReason m_reason = IdleEditor; AssistKind m_kind = Completion; bool m_justInvoked = false; QPointer m_infoFrame; @@ -358,9 +357,9 @@ void GenericProposalWidget::setAssistant(CodeAssistant *assistant) void GenericProposalWidget::setReason(AssistReason reason) { - d->m_reason = reason; - if (d->m_reason == ExplicitlyInvoked) + if (reason == ExplicitlyInvoked) d->m_justInvoked = true; + IAssistProposalWidget::setReason(reason); } void GenericProposalWidget::setKind(AssistKind kind) @@ -393,11 +392,6 @@ void GenericProposalWidget::setIsSynchronized(bool isSync) d->m_isSynchronized = isSync; } -bool GenericProposalWidget::supportsModelUpdate(const Utils::Id &proposalId) const -{ - return proposalId == Constants::GENERIC_PROPOSAL_ID; -} - void GenericProposalWidget::updateModel(ProposalModelPtr model) { QString currentText; @@ -418,6 +412,7 @@ void GenericProposalWidget::updateModel(ProposalModelPtr model) d->m_completionListView->selectRow(currentRow); else d->m_explicitlySelected = false; + updatePositionAndSize(); } void GenericProposalWidget::showProposal(const QString &prefix) @@ -431,7 +426,7 @@ void GenericProposalWidget::showProposal(const QString &prefix) d->m_completionListView->setFocus(); } -void GenericProposalWidget::updateProposal(const QString &prefix) +void GenericProposalWidget::filterProposal(const QString &prefix) { if (!isVisible()) return; @@ -470,7 +465,7 @@ bool GenericProposalWidget::updateAndCheck(const QString &prefix) if (!prefix.isEmpty()) d->m_model->filter(prefix); } - if (!d->m_model->hasItemsToPropose(prefix, d->m_reason)) { + if (!d->m_model->hasItemsToPropose(prefix, reason())) { d->m_completionListView->reset(); abort(); return false; @@ -660,7 +655,7 @@ bool GenericProposalWidget::eventFilter(QObject *o, QEvent *e) AssistProposalItemInterface *item = d->m_model->proposalItem(d->m_completionListView->currentIndex().row()); if (item->prematurelyApplies(typedChar) - && (d->m_reason == ExplicitlyInvoked || item->text().endsWith(typedChar))) { + && (reason() == ExplicitlyInvoked || item->text().endsWith(typedChar))) { abort(); emit proposalItemActivated(item); return true; diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.h b/src/plugins/texteditor/codeassist/genericproposalwidget.h index 901a8b1dfea..c38ccc9f47f 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.h +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.h @@ -31,11 +31,10 @@ public: void setDisplayRect(const QRect &rect) override; void setIsSynchronized(bool isSync) override; - bool supportsModelUpdate(const Utils::Id &proposalId) const override; - void updateModel(ProposalModelPtr model) override; + void updateModel(ProposalModelPtr model); void showProposal(const QString &prefix) override; - void updateProposal(const QString &prefix) override; + void filterProposal(const QString &prefix) override; void closeProposal() override; private: diff --git a/src/plugins/texteditor/codeassist/iassistproposal.cpp b/src/plugins/texteditor/codeassist/iassistproposal.cpp index b2c7dffc9f3..d6918ba7972 100644 --- a/src/plugins/texteditor/codeassist/iassistproposal.cpp +++ b/src/plugins/texteditor/codeassist/iassistproposal.cpp @@ -63,16 +63,6 @@ int IAssistProposal::basePosition() const return m_basePosition; } -bool IAssistProposal::isFragile() const -{ - return m_isFragile; -} - -bool IAssistProposal::supportsPrefixFiltering(const QString &prefix) const -{ - return !m_prefixChecker || m_prefixChecker(prefix); -} - /*! \fn bool TextEditor::IAssistProposal::isCorrective() const @@ -98,16 +88,6 @@ void IAssistProposal::makeCorrection(TextEditorWidget *editorWidget) Q_UNUSED(editorWidget) } -void IAssistProposal::setFragile(bool fragile) -{ - m_isFragile = fragile; -} - -void IAssistProposal::setPrefixChecker(const PrefixChecker checker) -{ - m_prefixChecker = checker; -} - /*! \fn IAssistModel *TextEditor::IAssistProposal::model() const diff --git a/src/plugins/texteditor/codeassist/iassistproposal.h b/src/plugins/texteditor/codeassist/iassistproposal.h index 5c64a880665..1761fc29bf8 100644 --- a/src/plugins/texteditor/codeassist/iassistproposal.h +++ b/src/plugins/texteditor/codeassist/iassistproposal.h @@ -22,30 +22,17 @@ public: virtual ~IAssistProposal(); int basePosition() const; - bool isFragile() const; - bool supportsPrefixFiltering(const QString &prefix) const; virtual bool hasItemsToPropose(const QString &, AssistReason) const { return true; } virtual bool isCorrective(TextEditorWidget *editorWidget) const; virtual void makeCorrection(TextEditorWidget *editorWidget); virtual TextEditor::ProposalModelPtr model() const = 0; virtual IAssistProposalWidget *createWidget() const = 0; - void setFragile(bool fragile); - Utils::Id id() const { return m_id; } - AssistReason reason() const { return m_reason; } - void setReason(const AssistReason &reason) { m_reason = reason; } - - using PrefixChecker = std::function; - void setPrefixChecker(const PrefixChecker checker); - protected: Utils::Id m_id; int m_basePosition; - bool m_isFragile = false; - PrefixChecker m_prefixChecker; - AssistReason m_reason = IdleEditor; }; } // TextEditor diff --git a/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp b/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp index f1ea7428ebc..fe5e3d823da 100644 --- a/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp @@ -3,6 +3,8 @@ #include "iassistproposalwidget.h" +#include "assistinterface.h" + using namespace TextEditor; /*! @@ -30,6 +32,11 @@ IAssistProposalWidget::IAssistProposalWidget() : QFrame(nullptr, Qt::Popup) {} +void IAssistProposalWidget::updateProposal(std::unique_ptr &&interface) +{ + filterProposal(interface->textAt(m_basePosition, interface->position() - m_basePosition)); +} + IAssistProposalWidget::~IAssistProposalWidget() = default; int IAssistProposalWidget::basePosition() const diff --git a/src/plugins/texteditor/codeassist/iassistproposalwidget.h b/src/plugins/texteditor/codeassist/iassistproposalwidget.h index fafe1b48b4a..68600b399c9 100644 --- a/src/plugins/texteditor/codeassist/iassistproposalwidget.h +++ b/src/plugins/texteditor/codeassist/iassistproposalwidget.h @@ -14,8 +14,9 @@ namespace Utils { class Id; } namespace TextEditor { -class CodeAssistant; +class AssistInterface; class AssistProposalItemInterface; +class CodeAssistant; class TEXTEDITOR_EXPORT IAssistProposalWidget : public QFrame { @@ -26,7 +27,7 @@ public: ~IAssistProposalWidget() override; virtual void setAssistant(CodeAssistant *assistant) = 0; - virtual void setReason(AssistReason reason) = 0; + virtual void setReason(AssistReason reason) { m_reason = reason; } virtual void setKind(AssistKind kind) = 0; virtual void setUnderlyingWidget(const QWidget *underlyingWidget) = 0; virtual void setModel(ProposalModelPtr model) = 0; @@ -34,16 +35,20 @@ public: virtual void setIsSynchronized(bool isSync) = 0; virtual void showProposal(const QString &prefix) = 0; - virtual void updateProposal(const QString &prefix) = 0; + virtual void filterProposal(const QString &prefix) = 0; + virtual void updateProposal(std::unique_ptr &&interface); virtual void closeProposal() = 0; virtual bool proposalIsVisible() const { return isVisible(); } - virtual bool supportsModelUpdate(const Utils::Id &/*proposalId*/) const { return false; } - virtual void updateModel(ProposalModelPtr) {} int basePosition() const; void setBasePosition(int basePosition); + void setFragile(bool fragile) { m_isFragile = fragile; } + bool isFragile() const { return m_isFragile; } + + AssistReason reason() const { return m_reason; } + signals: void prefixExpanded(const QString &newPrefix); void proposalItemActivated(AssistProposalItemInterface *proposalItem); @@ -51,6 +56,8 @@ signals: protected: int m_basePosition = -1; + bool m_isFragile = false; + AssistReason m_reason = IdleEditor; }; } // TextEditor