Commit 7cbc7af0 authored by Nikolai Kosjar's avatar Nikolai Kosjar

Clang: Fix completion after qualification (::)

...and maybe other cases.

Since

    Clang: fix findStartOfName handling
    commit 82d0650b

the proposal's base position was calculated wrong. As a result, an early
return triggert in CodeAssistantPrivate::displayProposal (call to
newProposal->hasItemsToPropose(prefix, reason)) and no completions were
displayed.

Fix by ensuring that the added code from the mentioned commit is only
called when needed, namely only for function expressions.

Task-number: QTCREATORBUG-19083
Change-Id: I8f23c9b7186f9d81159939c8b3ef475a09bbe760
Reviewed-by: Ivan Donchevskii's avatarIvan Donchevskii <ivan.donchevskii@qt.io>
Reviewed-by: David Schulz's avatarDavid Schulz <david.schulz@qt.io>
parent 2aed9f5c
...@@ -243,11 +243,14 @@ static bool isValidIdentifierChar(const QChar &character) ...@@ -243,11 +243,14 @@ static bool isValidIdentifierChar(const QChar &character)
int ActivationSequenceContextProcessor::findStartOfName( int ActivationSequenceContextProcessor::findStartOfName(
const TextEditor::AssistInterface *assistInterface, const TextEditor::AssistInterface *assistInterface,
int startPosition) int startPosition,
NameCategory category)
{ {
int position = startPosition; int position = startPosition;
QChar character; QChar character;
if (position > 2 && assistInterface->characterAt(position - 1) == '>'
if (category == NameCategory::Function
&& position > 2 && assistInterface->characterAt(position - 1) == '>'
&& assistInterface->characterAt(position - 2) != '-') { && assistInterface->characterAt(position - 2) != '-') {
uint unbalancedLessGreater = 1; uint unbalancedLessGreater = 1;
--position; --position;
...@@ -267,11 +270,12 @@ int ActivationSequenceContextProcessor::findStartOfName( ...@@ -267,11 +270,12 @@ int ActivationSequenceContextProcessor::findStartOfName(
} while (isValidIdentifierChar(character)); } while (isValidIdentifierChar(character));
int prevPosition = skipPrecedingWhitespace(assistInterface, position); int prevPosition = skipPrecedingWhitespace(assistInterface, position);
if (assistInterface->characterAt(prevPosition) == ':' if (category == NameCategory::Function
&& assistInterface->characterAt(prevPosition) == ':'
&& assistInterface->characterAt(prevPosition - 1) == ':') { && assistInterface->characterAt(prevPosition - 1) == ':') {
// Handle :: case - go recursive // Handle :: case - go recursive
prevPosition = skipPrecedingWhitespace(assistInterface, prevPosition - 2); prevPosition = skipPrecedingWhitespace(assistInterface, prevPosition - 2);
return findStartOfName(assistInterface, prevPosition + 1); return findStartOfName(assistInterface, prevPosition + 1, category);
} }
return position + 1; return position + 1;
......
...@@ -49,8 +49,10 @@ public: ...@@ -49,8 +49,10 @@ public:
const QTextCursor &textCursor_forTestOnly() const; const QTextCursor &textCursor_forTestOnly() const;
enum class NameCategory { Function, NonFunction };
static int findStartOfName(const TextEditor::AssistInterface *assistInterface, static int findStartOfName(const TextEditor::AssistInterface *assistInterface,
int startPosition); int startPosition,
NameCategory category = NameCategory::NonFunction);
static int skipPrecedingWhitespace(const TextEditor::AssistInterface *assistInterface, static int skipPrecedingWhitespace(const TextEditor::AssistInterface *assistInterface,
int startPosition); int startPosition);
......
...@@ -101,8 +101,8 @@ int ClangCompletionContextAnalyzer::startOfFunctionCall(int endOfOperator) const ...@@ -101,8 +101,8 @@ int ClangCompletionContextAnalyzer::startOfFunctionCall(int endOfOperator) const
ExpressionUnderCursor euc(m_languageFeatures); ExpressionUnderCursor euc(m_languageFeatures);
index = euc.startOfFunctionCall(textCursor); index = euc.startOfFunctionCall(textCursor);
index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, index); index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, index);
const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface, const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(
index); m_interface, index, ActivationSequenceContextProcessor::NameCategory::Function);
if (functionNameStart == -1) if (functionNameStart == -1)
return -1; return -1;
......
...@@ -147,7 +147,9 @@ TEST(ActivationSequenceContextProcessor, TemplateFunctionLeftParen) ...@@ -147,7 +147,9 @@ TEST(ActivationSequenceContextProcessor, TemplateFunctionLeftParen)
TEST(ActivationSequenceContextProcessor, TemplateFunctionSecondParameter) TEST(ActivationSequenceContextProcessor, TemplateFunctionSecondParameter)
{ {
ClangCompletionAssistInterface interface("foo<X>(", 7); ClangCompletionAssistInterface interface("foo<X>(", 7);
int startOfname = ContextProcessor::findStartOfName(&interface, 6); int startOfname = ContextProcessor::findStartOfName(&interface,
6,
ContextProcessor::NameCategory::Function);
ASSERT_THAT(startOfname, 0); ASSERT_THAT(startOfname, 0);
} }
......
...@@ -178,6 +178,13 @@ TEST_F(ClangCompletionContextAnalyzer, AfterSpace) ...@@ -178,6 +178,13 @@ TEST_F(ClangCompletionContextAnalyzer, AfterSpace)
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText)); ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText));
} }
TEST_F(ClangCompletionContextAnalyzer, AfterQualification)
{
auto analyzer = runAnalyzer(" Foo::@");
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText));
}
TEST_F(ClangCompletionContextAnalyzer, AtEndOfDotMember) TEST_F(ClangCompletionContextAnalyzer, AtEndOfDotMember)
{ {
auto analyzer = runAnalyzer("o.mem@"); auto analyzer = runAnalyzer("o.mem@");
......
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