From 24543f783906ff21a1f1d01c69d9fe79e71b2726 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 24 Oct 2018 12:59:39 +0200 Subject: [PATCH] CodeAssist: Refine perfect match criteria The perfect match is used to determine whether to show a completion list window or not. Consider: int foo; int foobar; void f() { // Type "foo" // ==> Previously, the completion window did not even show up as // "foo" was regarded a perfect match. This was annoying if you // have actually intended to complete "foobar". // ==> Now, the completion window does show up and shows both items. // The perfect match now considers other items for prefixes. // Without "foobar", the behavior is as before - no window pop // ups. } Fixes: QTCREATORBUG-20857 Change-Id: Ifdafcf9304a7cb36d646f776755063a854a79a90 Reviewed-by: David Schulz --- .../codeassist/genericproposalmodel.cpp | 58 ++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp index 35e82384b21..1c05e1f1eae 100644 --- a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp @@ -167,29 +167,57 @@ static QString cleanText(const QString &original) return clean; } +static bool textStartsWith(CaseSensitivity cs, const QString &text, const QString &prefix) +{ + switch (cs) { + case TextEditor::CaseInsensitive: + return text.startsWith(prefix, Qt::CaseInsensitive); + case TextEditor::CaseSensitive: + return text.startsWith(prefix, Qt::CaseSensitive); + case TextEditor::FirstLetterCaseSensitive: + return prefix.at(0) == text.at(0) + && prefix.midRef(1).startsWith(text.midRef(1), Qt::CaseInsensitive); + } + + return false; +} + +enum class PerfectMatchType { + None, + StartsWith, + Full, +}; + +static PerfectMatchType perfectMatch(CaseSensitivity cs, const QString &text, const QString &prefix) +{ + if (textStartsWith(cs, text, prefix)) + return prefix.size() == text.size() ? PerfectMatchType::Full : PerfectMatchType::StartsWith; + + return PerfectMatchType::None; +} + bool GenericProposalModel::isPerfectMatch(const QString &prefix) const { if (prefix.isEmpty()) return false; + const CaseSensitivity cs = TextEditorSettings::completionSettings().m_caseSensitivity; + bool hasFullMatch = 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; - } - } + if (current.isEmpty()) + continue; + + const PerfectMatchType match = perfectMatch(cs, current, prefix); + if (match == PerfectMatchType::StartsWith) + return false; + + if (!hasFullMatch && match == PerfectMatchType::Full) + hasFullMatch = true; } - return false; + + return hasFullMatch; } bool GenericProposalModel::isPrefiltered(const QString &prefix) const