Clang: Show function signature hint for constructors and functors

For "foo(|" [1] we requested a completion from libclang with the cursor
position just before "foo" and then filtered the function declarations
for functions matching the name "foo". This worked fine for ordinary
functions, but obviously not for constructors and functors.

Recent versions of libclang support proper function call completion with
XCursor_OverloadCandidate, so make use of that.

[1] '|' represents the cursor position

Task-number: QTCREATORBUG-14882
Task-number: QTCREATORBUG-14884
Change-Id: I9d31b3960ccff6a8b9440dbcb7ff9f5ca9f61266
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Nikolai Kosjar
2017-04-28 17:46:40 +02:00
parent f127cb3c59
commit 64ec695566
17 changed files with 109 additions and 128 deletions

View File

@@ -91,8 +91,7 @@ void ClangCompletionContextAnalyzer::analyze()
}
}
ClangCompletionContextAnalyzer::FunctionInfo
ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const
bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) const
{
int index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface,
endOfOperator);
@@ -104,15 +103,15 @@ ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const
index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, index);
const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface,
index);
if (functionNameStart == -1)
return false;
QTextCursor textCursor2(m_interface->textDocument());
textCursor2.setPosition(functionNameStart);
textCursor2.setPosition(index, QTextCursor::KeepAnchor);
QTextCursor functionNameSelector(m_interface->textDocument());
functionNameSelector.setPosition(functionNameStart);
functionNameSelector.setPosition(index, QTextCursor::KeepAnchor);
const QString functionName = functionNameSelector.selectedText().trimmed();
FunctionInfo info;
info.functionNamePosition = functionNameStart;
info.functionName = textCursor2.selectedText().trimmed();
return info;
return !functionName.isEmpty();
}
void ClangCompletionContextAnalyzer::setActionAndClangPosition(CompletionAction action,
@@ -158,16 +157,15 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio
// No function completion if cursor is not after '(' or ','
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
} else {
const FunctionInfo functionInfo = analyzeFunctionCall(afterOperatorPosition);
if (functionInfo.isValid()) {
m_functionName = functionInfo.functionName;
setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
functionInfo.functionNamePosition);
} else {
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
}
} else if (looksLikeAFunctionCall(afterOperatorPosition)) {
// Always pass the position right after '(' to libclang because
// positions after the comma might be problematic if a preceding
// argument is invalid code.
setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
m_positionForProposal);
} else { // e.g. "(" without any function name in front
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
}
}
}