Clang: Improve function definition completion

Insert argument list together with completion.

Task-number: QTCREATORBUG-20826
Change-Id: I4aa9faaa04bcd3ca014306aad27843c2b4419d3c
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-07-31 09:48:02 +02:00
parent 83024557d6
commit 810896936b
5 changed files with 35 additions and 16 deletions

View File

@@ -45,6 +45,7 @@ public:
enum Kind : quint32 { enum Kind : quint32 {
Other = 0, Other = 0,
FunctionCompletionKind, FunctionCompletionKind,
FunctionDefinitionCompletionKind,
FunctionOverloadCompletionKind, FunctionOverloadCompletionKind,
TemplateFunctionCompletionKind, TemplateFunctionCompletionKind,
ConstructorCompletionKind, ConstructorCompletionKind,

View File

@@ -164,6 +164,7 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface
if (autoInsertBrackets && if (autoInsertBrackets &&
(ccr.completionKind == CodeCompletion::FunctionCompletionKind (ccr.completionKind == CodeCompletion::FunctionCompletionKind
|| ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind
|| ccr.completionKind == CodeCompletion::DestructorCompletionKind || ccr.completionKind == CodeCompletion::DestructorCompletionKind
|| ccr.completionKind == CodeCompletion::SignalCompletionKind || ccr.completionKind == CodeCompletion::SignalCompletionKind
|| ccr.completionKind == CodeCompletion::SlotCompletionKind)) { || ccr.completionKind == CodeCompletion::SlotCompletionKind)) {
@@ -176,17 +177,40 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface
while (manipulator.characterAt(cursor.position()) == ':') while (manipulator.characterAt(cursor.position()) == ':')
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2); cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2);
const int previousWordStart = cursor.position();
// Move to the last character in the previous word // Move to the last character in the previous word
cursor.movePosition(QTextCursor::NextWord); cursor.movePosition(QTextCursor::NextWord);
moveToPrevChar(manipulator, cursor); moveToPrevChar(manipulator, cursor);
const QString previousWord = manipulator.textAt(previousWordStart,
cursor.position() - previousWordStart + 1);
bool abandonParen = false; bool abandonParen = false;
if (manipulator.characterAt(cursor.position()) == '&') { if (previousWord == "&") {
moveToPrevChar(manipulator, cursor); moveToPrevChar(manipulator, cursor);
const QChar prevChar = manipulator.characterAt(cursor.position()); const QChar prevChar = manipulator.characterAt(cursor.position());
abandonParen = QString("(;,{}").contains(prevChar); abandonParen = QString("(;,{}").contains(prevChar);
} }
if (!abandonParen) if (!abandonParen)
abandonParen = isAtUsingDeclaration(manipulator, basePosition); abandonParen = isAtUsingDeclaration(manipulator, basePosition);
if (!abandonParen && ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) {
const CodeCompletionChunk resultType = ccr.chunks.first();
QTC_ASSERT(resultType.kind == CodeCompletionChunk::ResultType, return;);
if (previousWord == resultType.text.toString()) {
bool skipChunks = true;
for (const CodeCompletionChunk &chunk : ccr.chunks) {
if (chunk.kind == CodeCompletionChunk::TypedText) {
skipChunks = false;
continue;
}
if (skipChunks)
continue;
extraCharacters += chunk.text;
}
// To skip the next block.
abandonParen = true;
}
}
if (!abandonParen) { if (!abandonParen) {
if (completionSettings.m_spaceAfterFunctionName) if (completionSettings.m_spaceAfterFunctionName)
extraCharacters += QLatin1Char(' '); extraCharacters += QLatin1Char(' ');
@@ -338,6 +362,7 @@ QIcon ClangAssistProposalItem::icon() const
case CodeCompletion::ConstructorCompletionKind: case CodeCompletion::ConstructorCompletionKind:
case CodeCompletion::DestructorCompletionKind: case CodeCompletion::DestructorCompletionKind:
case CodeCompletion::FunctionCompletionKind: case CodeCompletion::FunctionCompletionKind:
case CodeCompletion::FunctionDefinitionCompletionKind:
case CodeCompletion::TemplateFunctionCompletionKind: case CodeCompletion::TemplateFunctionCompletionKind:
case CodeCompletion::ObjCMessageCompletionKind: case CodeCompletion::ObjCMessageCompletionKind:
switch (m_codeCompletion.availability) { switch (m_codeCompletion.availability) {

View File

@@ -56,24 +56,12 @@ bool ClangCodeCompleteResults::hasResults() const
return !isNull() && !isEmpty(); return !isNull() && !isEmpty();
} }
bool ClangCodeCompleteResults::hasNoResultsForDotCompletion() const
{
return !hasResults() && isDotCompletion();
}
bool ClangCodeCompleteResults::hasUnknownContext() const bool ClangCodeCompleteResults::hasUnknownContext() const
{ {
const unsigned long long contexts = clang_codeCompleteGetContexts(cxCodeCompleteResults); const unsigned long long contexts = clang_codeCompleteGetContexts(cxCodeCompleteResults);
return contexts == CXCompletionContext_Unknown; return contexts == CXCompletionContext_Unknown;
} }
bool ClangCodeCompleteResults::isDotCompletion() const
{
const unsigned long long contexts = clang_codeCompleteGetContexts(cxCodeCompleteResults);
return contexts & CXCompletionContext_DotMemberAccess;
}
CXCodeCompleteResults *ClangCodeCompleteResults::data() const CXCodeCompleteResults *ClangCodeCompleteResults::data() const
{ {
return cxCodeCompleteResults; return cxCodeCompleteResults;

View File

@@ -49,10 +49,8 @@ public:
bool isEmpty() const; bool isEmpty() const;
bool hasResults() const; bool hasResults() const;
bool hasNoResultsForDotCompletion() const;
bool hasUnknownContext() const; bool hasUnknownContext() const;
bool isDotCompletion() const;
CXCodeCompleteResults *data() const; CXCodeCompleteResults *data() const;

View File

@@ -176,6 +176,9 @@ void CodeCompletionsExtractor::extractText()
void CodeCompletionsExtractor::extractMethodCompletionKind() void CodeCompletionsExtractor::extractMethodCompletionKind()
{ {
CXCompletionString cxCompletionString = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex].CompletionString; CXCompletionString cxCompletionString = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex].CompletionString;
const unsigned long long contexts = clang_codeCompleteGetContexts(cxCodeCompleteResults);
const uint annotationCount = clang_getCompletionNumAnnotations(cxCompletionString); const uint annotationCount = clang_getCompletionNumAnnotations(cxCompletionString);
for (uint annotationIndex = 0; annotationIndex < annotationCount; ++annotationIndex) { for (uint annotationIndex = 0; annotationIndex < annotationCount; ++annotationIndex) {
@@ -192,8 +195,12 @@ void CodeCompletionsExtractor::extractMethodCompletionKind()
} }
} }
currentCodeCompletion_.completionKind = CodeCompletion::FunctionDefinitionCompletionKind;
if ((contexts & CXCompletionContext_DotMemberAccess)
|| (contexts & CXCompletionContext_ArrowMemberAccess)) {
currentCodeCompletion_.completionKind = CodeCompletion::FunctionCompletionKind; currentCodeCompletion_.completionKind = CodeCompletion::FunctionCompletionKind;
} }
}
void CodeCompletionsExtractor::extractMacroCompletionKind() void CodeCompletionsExtractor::extractMacroCompletionKind()
{ {