Commit da4c4b80 authored by Alexey Semenko's avatar Alexey Semenko Committed by Nikolai Kosjar

Completions: move continuations upper in proposals list.

Since fuzzy completions are allowed, the lexicographically first proposal
is not necessarily most relevant. The patch modifies sorting of proposals
so that the exact match and continuations go first, and fuzzy completions
follow.

Moreover, being a continuation seem to be a more important characteristic
of a proposal, than being it a function argument or keyword etc. That's why
the check for continuation is placed before the check for order.

Task-number: QTCREATORBUG-8737
Task-number: QTCREATORBUG-9236
Change-Id: I89aae9d2ce6bfa59af7c2f75e6f3af00212008ca
Reviewed-by: default avatarAndré Hartmann <aha_1980@gmx.de>
Reviewed-by: default avatarAlexey Zhondin <lexxmark.dev@gmail.com>
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent adee8336
......@@ -121,6 +121,8 @@ public:
const QString prefix = Convenience::textAt(QTextCursor(editorWidget->document()), pos, length);
if (!prefix.isEmpty())
listmodel->filter(prefix);
if (listmodel->isSortable(prefix))
listmodel->sort(prefix);
for (int i = 0; i < listmodel->size(); ++i)
completions << listmodel->text(i);
......@@ -2069,6 +2071,56 @@ void CppToolsPlugin::test_completion_recursive_using_typedef_declarations()
QCOMPARE(completions.size(), 0);
}
void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_8737()
{
const QByteArray source =
"void f()\n"
"{\n"
" int a_b_c, a_c, a_c_a;\n"
" @;\n"
" // padding so we get the scope right\n"
"}\n"
;
CompletionTestCase test(source, "a_c");
QStringList completions = test.getCompletions();
QVERIFY(completions.size() >= 2);
QCOMPARE(completions.at(0), QLatin1String("a_c"));
QCOMPARE(completions.at(1), QLatin1String("a_c_a"));
QVERIFY(completions.contains(QLatin1String("a_b_c")));
}
void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_9236()
{
const QByteArray source =
"class r_etclass\n"
"{\n"
"public:\n"
" int raEmTmber;\n"
" void r_e_t(int re_t)\n"
" {\n"
" int r_et;\n"
" int rETUCASE;\n"
" @\n"
" // padding so we get the scope right\n"
" }\n"
"};\n"
;
CompletionTestCase test(source, "ret");
QStringList completions = test.getCompletions();
QVERIFY(completions.size() >= 2);
QCOMPARE(completions.at(0), QLatin1String("return"));
QCOMPARE(completions.at(1), QLatin1String("rETUCASE"));
QVERIFY(completions.contains(QLatin1String("r_etclass")));
QVERIFY(completions.contains(QLatin1String("raEmTmber")));
QVERIFY(completions.contains(QLatin1String("r_e_t")));
QVERIFY(completions.contains(QLatin1String("re_t")));
QVERIFY(completions.contains(QLatin1String("r_et")));
}
void CppToolsPlugin::test_completion_class_declaration_inside_function_or_block_QTCREATORBUG3620()
{
test_completion();
......
......@@ -150,6 +150,8 @@ private slots:
void test_completion_recursive_using_declarations1();
void test_completion_recursive_using_declarations2();
void test_completion_recursive_using_typedef_declarations();
void test_completion_prefix_first_QTCREATORBUG_8737();
void test_completion_prefix_first_QTCREATORBUG_9236();
void test_completion_class_declaration_inside_function_or_block_QTCREATORBUG3620();
void test_completion_class_declaration_inside_function_or_block_QTCREATORBUG3620_data();
......
......@@ -1024,7 +1024,7 @@ void QmlJSAssistProposalModel::filter(const QString &prefix)
m_currentItems = newCurrentItems;
}
void QmlJSAssistProposalModel::sort()
void QmlJSAssistProposalModel::sort(const QString &)
{
qSort(currentItems().first, currentItems().second, QmlJSLessThan());
}
......
......@@ -70,7 +70,7 @@ public:
{}
virtual void filter(const QString &prefix);
virtual void sort();
virtual void sort(const QString &prefix);
virtual bool keepPerfectMatch(TextEditor::AssistReason reason) const;
};
......
......@@ -53,16 +53,28 @@ const int kMaxPrefixFilter = 100;
struct ContentLessThan
{
ContentLessThan(const QString &prefix)
: m_prefix(prefix)
{}
bool operator()(const BasicProposalItem *a, const BasicProposalItem *b)
{
// If order is different, show higher ones first.
if (a->order() != b->order())
return a->order() > b->order();
// The order is case-insensitive in principle, but case-sensitive when this
// would otherwise mean equality
const QString &lowera = a->text().toLower();
const QString &lowerb = b->text().toLower();
const QString &lowerprefix = m_prefix.toLower();
// All continuations should go before all fuzzy matches
if (int diff = lowera.startsWith(lowerprefix) - lowerb.startsWith(lowerprefix))
return diff > 0;
if (int diff = a->text().startsWith(m_prefix) - b->text().startsWith(m_prefix))
return diff > 0;
// If order is different, show higher ones first.
if (a->order() != b->order())
return a->order() > b->order();
if (lowera == lowerb)
return lessThan(a->text(), b->text());
else
......@@ -113,6 +125,9 @@ struct ContentLessThan
return a < b;
}
};
private:
QString m_prefix;
};
} // Anonymous
......@@ -263,9 +278,9 @@ bool BasicProposalItemListModel::isSortable(const QString &prefix) const
return false;
}
void BasicProposalItemListModel::sort()
void BasicProposalItemListModel::sort(const QString &prefix)
{
qStableSort(m_currentItems.begin(), m_currentItems.end(), ContentLessThan());
qStableSort(m_currentItems.begin(), m_currentItems.end(), ContentLessThan(prefix));
}
int BasicProposalItemListModel::persistentId(int index) const
......
......@@ -58,7 +58,7 @@ public:
virtual void removeDuplicates();
virtual void filter(const QString &prefix);
virtual bool isSortable(const QString &prefix) const;
virtual void sort();
virtual void sort(const QString &prefix);
virtual bool supportsPrefixExpansion() const;
virtual QString proposalPrefix() const;
virtual bool keepPerfectMatch(AssistReason reason) const;
......
......@@ -448,7 +448,7 @@ bool GenericProposalWidget::updateAndCheck(const QString &prefix)
return false;
}
if (d->m_model->isSortable(prefix))
d->m_model->sort();
d->m_model->sort(prefix);
d->m_completionListView->reset();
// Try to find the previosly explicit selection (if any). If we can find the item set it
......
......@@ -53,7 +53,7 @@ public:
virtual void removeDuplicates() = 0;
virtual void filter(const QString &prefix) = 0;
virtual bool isSortable(const QString &prefix) const = 0;
virtual void sort() = 0;
virtual void sort(const QString &prefix) = 0;
virtual bool supportsPrefixExpansion() const = 0;
virtual QString proposalPrefix() const = 0;
virtual bool keepPerfectMatch(AssistReason reason) const = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment