diff options
Diffstat (limited to 'src')
7 files changed, 107 insertions, 56 deletions
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 023e853d99..ab3b9907a9 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -181,8 +181,7 @@ void CodeAssistantPrivate::process() } } - if (!isDisplayingProposal()) - startAutomaticProposalTimer(); + startAutomaticProposalTimer(); } else { m_assistKind = TextEditor::Completion; } @@ -288,18 +287,33 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR QScopedPointer<IAssistProposal> proposalCandidate(newProposal); + bool destroyCurrentContext = false; if (isDisplayingProposal()) { if (!m_proposal->isFragile()) return; - destroyContext(); + destroyCurrentContext = true; } int basePosition = proposalCandidate->basePosition(); - if (m_editorWidget->position() < basePosition) + if (m_editorWidget->position() < basePosition) { + if (destroyCurrentContext) + destroyContext(); return; + } - if (m_abortedBasePosition == basePosition && reason != ExplicitlyInvoked) + if (m_abortedBasePosition == basePosition && reason != ExplicitlyInvoked) { + if (destroyCurrentContext) + destroyContext(); return; + } + + const QString prefix = m_editorWidget->textAt(basePosition, + m_editorWidget->position() - basePosition); + if (!newProposal->hasItemsToPropose(prefix, reason)) + return; + + if (destroyCurrentContext) + destroyContext(); clearAbortedPosition(); m_proposal.reset(proposalCandidate.take()); @@ -325,9 +339,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR m_proposalWidget->setModel(m_proposal->model()); m_proposalWidget->setDisplayRect(m_editorWidget->cursorRect(basePosition)); m_proposalWidget->setIsSynchronized(!m_receivedContentWhileWaiting); - m_proposalWidget->showProposal(m_editorWidget->textAt( - basePosition, - m_editorWidget->position() - basePosition)); + m_proposalWidget->showProposal(prefix); } void CodeAssistantPrivate::processProposalItem(AssistProposalItemInterface *proposalItem) @@ -406,6 +418,8 @@ void CodeAssistantPrivate::notifyChange() m_proposalWidget->updateProposal( m_editorWidget->textAt(m_proposal->basePosition(), m_editorWidget->position() - m_proposal->basePosition())); + if (m_proposal->isFragile()) + startAutomaticProposalTimer(); } } } @@ -438,7 +452,7 @@ void CodeAssistantPrivate::startAutomaticProposalTimer() void CodeAssistantPrivate::automaticProposalTimeout() { - if (isWaitingForProposal() || isDisplayingProposal()) + if (isWaitingForProposal() || (isDisplayingProposal() && !m_proposal->isFragile())) return; requestProposal(IdleEditor, Completion); diff --git a/src/plugins/texteditor/codeassist/genericproposal.cpp b/src/plugins/texteditor/codeassist/genericproposal.cpp index e8e19f1536..7d0105319c 100644 --- a/src/plugins/texteditor/codeassist/genericproposal.cpp +++ b/src/plugins/texteditor/codeassist/genericproposal.cpp @@ -49,6 +49,16 @@ bool GenericProposal::isFragile() const return false; } +bool GenericProposal::hasItemsToPropose(const QString &prefix, AssistReason reason) const +{ + if (!prefix.isEmpty()) { + m_model->filter(prefix); + m_model->setPrefilterPrefix(prefix); + } + + return m_model->hasItemsToPropose(prefix, reason); +} + IAssistProposalModel *GenericProposal::model() const { return m_model; diff --git a/src/plugins/texteditor/codeassist/genericproposal.h b/src/plugins/texteditor/codeassist/genericproposal.h index 19c743dbdb..385f9978df 100644 --- a/src/plugins/texteditor/codeassist/genericproposal.h +++ b/src/plugins/texteditor/codeassist/genericproposal.h @@ -41,6 +41,7 @@ public: ~GenericProposal(); bool isFragile() const override; + bool hasItemsToPropose(const QString &prefix, AssistReason reason) const override; IAssistProposalModel *model() const override; IAssistProposalWidget *createWidget() const override; diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp index 1afd0b8451..34ed001823 100644 --- a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp @@ -145,8 +145,65 @@ void GenericProposalModel::loadContent(const QList<AssistProposalItemInterface * m_idByText.insert(m_originalItems.at(i)->text(), i); } +bool GenericProposalModel::hasItemsToPropose(const QString &prefix, AssistReason reason) const +{ + return size() != 0 && (keepPerfectMatch(reason) || !isPerfectMatch(prefix)); +} + +static QString cleanText(const QString &original) +{ + QString clean = original; + int ignore = 0; + for (int i = clean.length() - 1; i >= 0; --i, ++ignore) { + const QChar &c = clean.at(i); + if (c.isLetterOrNumber() || c == QLatin1Char('_') + || c.isHighSurrogate() || c.isLowSurrogate()) { + break; + } + } + if (ignore) + clean.chop(ignore); + return clean; +} + +bool GenericProposalModel::isPerfectMatch(const QString &prefix) const +{ + if (prefix.isEmpty()) + return false; + + for (int i = 0; i < size(); ++i) { + const QString ¤t = cleanText(text(i)); + if (!current.isEmpty()) { + CaseSensitivity cs = TextEditorSettings::completionSettings().m_caseSensitivity; + if (cs == TextEditor::CaseSensitive) { + if (prefix == current) + return true; + } else if (cs == TextEditor::CaseInsensitive) { + if (prefix.compare(current, Qt::CaseInsensitive) == 0) + return true; + } else if (cs == TextEditor::FirstLetterCaseSensitive) { + if (prefix.at(0) == current.at(0) + && prefix.midRef(1).compare(current.midRef(1), Qt::CaseInsensitive) == 0) + return true; + } + } + } + return false; +} + +bool GenericProposalModel::isPrefiltered(const QString &prefix) const +{ + return !m_prefilterPrefix.isEmpty() && prefix == m_prefilterPrefix; +} + +void GenericProposalModel::setPrefilterPrefix(const QString &prefix) +{ + m_prefilterPrefix = prefix; +} + void GenericProposalModel::reset() { + m_prefilterPrefix.clear(); m_currentItems = m_originalItems; } diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.h b/src/plugins/texteditor/codeassist/genericproposalmodel.h index d3ff31fb6f..538ed81712 100644 --- a/src/plugins/texteditor/codeassist/genericproposalmodel.h +++ b/src/plugins/texteditor/codeassist/genericproposalmodel.h @@ -65,11 +65,18 @@ public: void loadContent(const QList<AssistProposalItemInterface *> &items); + bool isPerfectMatch(const QString &prefix) const; + bool hasItemsToPropose(const QString &prefix, AssistReason reason) const; + + bool isPrefiltered(const QString &prefix) const; + void setPrefilterPrefix(const QString &prefix); + protected: QList<AssistProposalItemInterface *> m_currentItems; private: QHash<QString, int> m_idByText; QList<AssistProposalItemInterface *> m_originalItems; + QString m_prefilterPrefix; }; } // TextEditor diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp index 1ce01ffa18..cdeb6638df 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp @@ -54,47 +54,6 @@ using namespace Utils; namespace TextEditor { -static QString cleanText(const QString &original) -{ - QString clean = original; - int ignore = 0; - for (int i = clean.length() - 1; i >= 0; --i, ++ignore) { - const QChar &c = clean.at(i); - if (c.isLetterOrNumber() || c == QLatin1Char('_') - || c.isHighSurrogate() || c.isLowSurrogate()) { - break; - } - } - if (ignore) - clean.chop(ignore); - return clean; -} - -static bool isPerfectMatch(const QString &prefix, const GenericProposalModel *model) -{ - if (prefix.isEmpty()) - return false; - - for (int i = 0; i < model->size(); ++i) { - const QString ¤t = cleanText(model->text(i)); - if (!current.isEmpty()) { - CaseSensitivity cs = TextEditorSettings::completionSettings().m_caseSensitivity; - if (cs == TextEditor::CaseSensitive) { - if (prefix == current) - return true; - } else if (cs == TextEditor::CaseInsensitive) { - if (prefix.compare(current, Qt::CaseInsensitive) == 0) - return true; - } else if (cs == TextEditor::FirstLetterCaseSensitive) { - if (prefix.at(0) == current.at(0) - && prefix.midRef(1).compare(current.midRef(1), Qt::CaseInsensitive) == 0) - return true; - } - } - } - return false; -} - // ------------ // ModelAdapter // ------------ @@ -442,12 +401,12 @@ bool GenericProposalWidget::updateAndCheck(const QString &prefix) d->m_model->persistentId(d->m_completionListView->currentIndex().row()); // Filter, sort, etc. - d->m_model->reset(); - if (!prefix.isEmpty()) - d->m_model->filter(prefix); - if (d->m_model->size() == 0 - || (!d->m_model->keepPerfectMatch(d->m_reason) - && isPerfectMatch(prefix, d->m_model))) { + if (!d->m_model->isPrefiltered(prefix)) { + d->m_model->reset(); + if (!prefix.isEmpty()) + d->m_model->filter(prefix); + } + if (!d->m_model->hasItemsToPropose(prefix, d->m_reason)) { d->m_completionListView->reset(); abort(); return false; diff --git a/src/plugins/texteditor/codeassist/iassistproposal.h b/src/plugins/texteditor/codeassist/iassistproposal.h index 9a6332808c..732fe9a468 100644 --- a/src/plugins/texteditor/codeassist/iassistproposal.h +++ b/src/plugins/texteditor/codeassist/iassistproposal.h @@ -25,6 +25,8 @@ #pragma once +#include "assistenums.h" + #include <texteditor/texteditor_global.h> namespace TextEditor { @@ -40,6 +42,7 @@ public: virtual ~IAssistProposal(); int basePosition() const; + virtual bool hasItemsToPropose(const QString &, AssistReason) const { return true; } virtual bool isFragile() const = 0; virtual bool isCorrective(TextEditorWidget *editorWidget) const; virtual void makeCorrection(TextEditorWidget *editorWidget); |