summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2017-04-27 15:44:37 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2017-05-02 11:07:48 +0000
commitfab4dd068ed51f612e7beaf0985bcbe4411d2f01 (patch)
treecf973e574acb31baa87aae0ad991be9c82691e1f
parenta4a78ae8b116d7f16a141700bbda6da722e0699d (diff)
downloadqt-creator-fab4dd068ed51f612e7beaf0985bcbe4411d2f01.tar.gz
CodeAssist: Fix auto completion if function signature is shown
This reverts commit 3bf19030aba43e4c8326d921e2bf0b4506ea9bce. CodeAssist: Fragile proposals aren't closed by automatic proposals. which fixed the case [1] but introduced the regression in case [2]. Re- implement the fix for [1] in a different way: Check whether the new proposal has any items to show before closing the function signature hint. Case [1] void f(int); void g() { f(bar // This is what we will have in the end. The steps are: // 1. Type "f(" // --> OK, function signature pop up is shown. // 2. Type "bar" // --> OPS, function signature pop up is closed and no // new completion list is shown because "bar" does // not match any declarations. } Case [2] int barman = 0; void f(int); void g() { f(bar // This is what we will have in the end. The steps are: // 1. Type "f(" // --> OK, function signature pop up is shown. // 2. Type "bar" // --> OPS, no auto completion list for "barman" is // proposed. } Task-number: QTCREATORBUG-16934 Change-Id: I8456275d951de9e6fc53285a5dbcbd448d49ad08 Reviewed-by: David Schulz <david.schulz@qt.io>
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp32
-rw-r--r--src/plugins/texteditor/codeassist/genericproposal.cpp10
-rw-r--r--src/plugins/texteditor/codeassist/genericproposal.h1
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.cpp57
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.h7
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalwidget.cpp53
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposal.h3
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 &current = 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 &current = 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);