Clang: Fallback to global completion if function call completion fails

We can not offer proper constructor completion with libclang <= 3.6, so
fall back to normal/global completion.

Change-Id: I90bb8d981ae20ed4c228f829ad4267221b92f8a1
Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
This commit is contained in:
Nikolai Kosjar
2015-07-22 13:09:44 +02:00
parent 889237f962
commit 5643a45a83
7 changed files with 40 additions and 9 deletions
@@ -145,8 +145,11 @@ void IpcReceiver::codeCompleted(const CodeCompletedCommand &command)
const quint64 ticket = command.ticketNumber(); const quint64 ticket = command.ticketNumber();
QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket)); QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket));
if (processor) if (processor) {
processor->handleAvailableAsyncCompletions(command.codeCompletions()); const bool finished = processor->handleAvailableAsyncCompletions(command.codeCompletions());
if (!finished)
processor.take();
}
} }
void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistCommand &command) void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistCommand &command)
@@ -232,20 +232,24 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface *
return startCompletionHelper(); // == 0 if results are calculated asynchronously return startCompletionHelper(); // == 0 if results are calculated asynchronously
} }
void ClangCompletionAssistProcessor::handleAvailableAsyncCompletions( bool ClangCompletionAssistProcessor::handleAvailableAsyncCompletions(
const CodeCompletions &completions) const CodeCompletions &completions)
{ {
bool handled = true;
switch (m_sentRequestType) { switch (m_sentRequestType) {
case CompletionRequestType::NormalCompletion: case CompletionRequestType::NormalCompletion:
handleAvailableCompletions(completions); handleAvailableCompletions(completions);
break; break;
case CompletionRequestType::FunctionHintCompletion: case CompletionRequestType::FunctionHintCompletion:
handleAvailableFunctionHintCompletions(completions); handled = handleAvailableFunctionHintCompletions(completions);
break; break;
default: default:
QTC_CHECK(!"Unhandled ClangCompletionAssistProcessor::CompletionRequestType"); QTC_CHECK(!"Unhandled ClangCompletionAssistProcessor::CompletionRequestType");
break; break;
} }
return handled;
} }
const TextEditorWidget *ClangCompletionAssistProcessor::textEditorWidget() const const TextEditorWidget *ClangCompletionAssistProcessor::textEditorWidget() const
@@ -704,7 +708,7 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(const CodeComple
setAsyncProposalAvailable(createProposal()); setAsyncProposalAvailable(createProposal());
} }
void ClangCompletionAssistProcessor::handleAvailableFunctionHintCompletions( bool ClangCompletionAssistProcessor::handleAvailableFunctionHintCompletions(
const CodeCompletions &completions) const CodeCompletions &completions)
{ {
QTC_CHECK(!m_functionName.isEmpty()); QTC_CHECK(!m_functionName.isEmpty());
@@ -715,9 +719,13 @@ void ClangCompletionAssistProcessor::handleAvailableFunctionHintCompletions(
auto *proposal = new FunctionHintProposal(m_positionForProposal, model); auto *proposal = new FunctionHintProposal(m_positionForProposal, model);
setAsyncProposalAvailable(proposal); setAsyncProposalAvailable(proposal);
return true;
} else { } else {
QTC_CHECK(!"Function completion failed. Would fallback to global completion here..."); m_addSnippets = false;
// TODO: If we need this, the processor can't be deleted in IpcClient. m_functionName.clear();
m_sentRequestType = NormalCompletion;
sendCompletionRequest(m_interface->position(), QByteArray());
return false; // We are not yet finished.
} }
} }
@@ -59,7 +59,7 @@ public:
TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override; TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
void handleAvailableAsyncCompletions(const CodeCompletions &completions); bool handleAvailableAsyncCompletions(const CodeCompletions &completions);
const TextEditor::TextEditorWidget *textEditorWidget() const; const TextEditor::TextEditorWidget *textEditorWidget() const;
@@ -91,7 +91,7 @@ private:
void sendCompletionRequest(int position, const QByteArray &customFileContent); void sendCompletionRequest(int position, const QByteArray &customFileContent);
void handleAvailableCompletions(const CodeCompletions &completions); void handleAvailableCompletions(const CodeCompletions &completions);
void handleAvailableFunctionHintCompletions(const CodeCompletions &completions); bool handleAvailableFunctionHintCompletions(const CodeCompletions &completions);
private: private:
QScopedPointer<const ClangCompletionAssistInterface> m_interface; QScopedPointer<const ClangCompletionAssistInterface> m_interface;
@@ -20,5 +20,6 @@
<file>exampleIncludeDir/otherFile.h</file> <file>exampleIncludeDir/otherFile.h</file>
<file>exampleIncludeDir/mylib/mylib.h</file> <file>exampleIncludeDir/mylib/mylib.h</file>
<file>globalCompletion.cpp</file> <file>globalCompletion.cpp</file>
<file>constructorCompletion.cpp</file>
</qresource> </qresource>
</RCC> </RCC>
@@ -874,6 +874,15 @@ void ClangCodeCompletionTest::testCompleteFunctions()
QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)")); QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)"));
} }
void ClangCodeCompletionTest::testCompleteConstructorAndFallbackToGlobalCompletion()
{
ProjectLessCompletionTest t("constructorCompletion.cpp");
QVERIFY(hasItem(t.proposal, "globalVariable"));
QVERIFY(hasItem(t.proposal, "GlobalClassWithCustomConstructor"));
QVERIFY(!hasSnippet(t.proposal, "class"));
}
void ClangCodeCompletionTest::testProjectDependentCompletion() void ClangCodeCompletionTest::testProjectDependentCompletion()
{ {
const TestDocument testDocument("completionWithProject.cpp"); const TestDocument testDocument("completionWithProject.cpp");
@@ -57,6 +57,7 @@ private slots:
void testCompleteGlobals(); void testCompleteGlobals();
void testCompleteMembers(); void testCompleteMembers();
void testCompleteFunctions(); void testCompleteFunctions();
void testCompleteConstructorAndFallbackToGlobalCompletion();
void testProjectDependentCompletion(); void testProjectDependentCompletion();
void testChangingProjectDependentCompletion(); void testChangingProjectDependentCompletion();
@@ -0,0 +1,9 @@
int globalVariable;
struct GlobalClassWithCustomConstructor {
GlobalClassWithCustomConstructor(int) {}
};
void f() {
GlobalClassWithCustomConstructor foo( /* COMPLETE HERE */
}