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 <david.schulz@qt.io>
This commit is contained in:
Nikolai Kosjar
2018-10-24 12:59:39 +02:00
parent 44b71f7a16
commit 24543f7839

View File

@@ -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 &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;
}
}
}
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 hasFullMatch;
}
bool GenericProposalModel::isPrefiltered(const QString &prefix) const