forked from qt-creator/qt-creator
Clang: Treat brace initialization as constructor completion
Try to complete constructor after left brace with fallback to normal completion. Task-number: QTCREATORBUG-20957 Change-Id: I6c33790a3ee1e623a3d8abe9a44cfd821b6f3106 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -262,7 +262,7 @@ int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor) const
|
||||
|
||||
if (tk.is(T_EOF_SYMBOL)) {
|
||||
break;
|
||||
} else if (tk.is(T_LPAREN)) {
|
||||
} else if (tk.is(T_LPAREN) || tk.is(T_LBRACE)) {
|
||||
return scanner.startPosition() + tk.utf16charsBegin();
|
||||
} else if (tk.is(T_RPAREN)) {
|
||||
int matchingBrace = scanner.startOfMatchingBrace(index);
|
||||
|
@@ -83,7 +83,7 @@ void ActivationSequenceContextProcessor::process()
|
||||
processComment();
|
||||
processInclude();
|
||||
processSlashOutsideOfAString();
|
||||
processLeftParen();
|
||||
processLeftParenOrBrace();
|
||||
processPreprocessorInclude();
|
||||
}
|
||||
|
||||
@@ -163,9 +163,9 @@ void ActivationSequenceContextProcessor::processSlashOutsideOfAString()
|
||||
m_completionKind = CPlusPlus::T_EOF_SYMBOL;
|
||||
}
|
||||
|
||||
void ActivationSequenceContextProcessor::processLeftParen()
|
||||
void ActivationSequenceContextProcessor::processLeftParenOrBrace()
|
||||
{
|
||||
if (m_completionKind == CPlusPlus::T_LPAREN) {
|
||||
if (m_completionKind == CPlusPlus::T_LPAREN || m_completionKind == CPlusPlus::T_LBRACE) {
|
||||
if (m_tokenIndex > 0) {
|
||||
// look at the token at the left of T_LPAREN
|
||||
const CPlusPlus::Token &previousToken = m_tokens.at(m_tokenIndex - 1);
|
||||
|
@@ -67,7 +67,7 @@ protected:
|
||||
void processComment();
|
||||
void processInclude();
|
||||
void processSlashOutsideOfAString();
|
||||
void processLeftParen();
|
||||
void processLeftParenOrBrace();
|
||||
void processPreprocessorInclude();
|
||||
void resetPositionsForEOFCompletionKind();
|
||||
|
||||
|
@@ -90,6 +90,7 @@ void ActivationSequenceProcessor::process()
|
||||
processDot();
|
||||
processComma();
|
||||
processLeftParen();
|
||||
processLeftBrace();
|
||||
processColonColon();
|
||||
processArrow();
|
||||
processDotStar();
|
||||
@@ -125,6 +126,14 @@ void ActivationSequenceProcessor::processLeftParen()
|
||||
}
|
||||
}
|
||||
|
||||
void ActivationSequenceProcessor::processLeftBrace()
|
||||
{
|
||||
if (m_char3 == QLatin1Char('{') && m_wantFunctionCall) {
|
||||
m_completionKind = CPlusPlus::T_LBRACE;
|
||||
m_offset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ActivationSequenceProcessor::processColonColon()
|
||||
{
|
||||
if (m_char2 == QLatin1Char(':') && m_char3 == QLatin1Char(':')) {
|
||||
|
@@ -49,6 +49,7 @@ private:
|
||||
void processDot();
|
||||
void processComma();
|
||||
void processLeftParen();
|
||||
void processLeftBrace();
|
||||
void processColonColon();
|
||||
void processArrow();
|
||||
void processDotStar();
|
||||
|
@@ -188,7 +188,8 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface *
|
||||
static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions)
|
||||
{
|
||||
return ::Utils::filtered(completions, [](const CodeCompletion &completion) {
|
||||
return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind;
|
||||
return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind
|
||||
|| completion.completionKind == CodeCompletion::ConstructorCompletionKind;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,19 +198,24 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(
|
||||
{
|
||||
QTC_CHECK(m_completions.isEmpty());
|
||||
|
||||
if (m_sentRequestType == NormalCompletion) {
|
||||
m_completions = toAssistProposalItems(completions, m_interface.data());
|
||||
|
||||
if (m_addSnippets && !m_completions.isEmpty())
|
||||
addSnippets();
|
||||
|
||||
setAsyncProposalAvailable(createProposal());
|
||||
} else {
|
||||
if (m_sentRequestType == FunctionHintCompletion){
|
||||
const CodeCompletions functionSignatures = filterFunctionSignatures(completions);
|
||||
if (!functionSignatures.isEmpty())
|
||||
if (!functionSignatures.isEmpty()) {
|
||||
setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures));
|
||||
// else: Not a function call, but e.g. a function declaration like "void f("
|
||||
return;
|
||||
}
|
||||
// else: Proceed with a normal completion in case:
|
||||
// 1) it was not a function call, but e.g. a function declaration like "void f("
|
||||
// 2) '{' meant not a constructor call.
|
||||
}
|
||||
|
||||
//m_sentRequestType == NormalCompletion or function signatures were empty
|
||||
m_completions = toAssistProposalItems(completions, m_interface.data());
|
||||
|
||||
if (m_addSnippets && !m_completions.isEmpty())
|
||||
addSnippets();
|
||||
|
||||
setAsyncProposalAvailable(createProposal());
|
||||
}
|
||||
|
||||
const TextEditorWidget *ClangCompletionAssistProcessor::textEditorWidget() const
|
||||
|
@@ -145,7 +145,7 @@ void ClangCompletionContextAnalyzer::handleCommaInFunctionCall()
|
||||
|
||||
void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPosition)
|
||||
{
|
||||
if (m_completionOperator == T_LPAREN) {
|
||||
if (m_completionOperator == T_LPAREN || m_completionOperator == T_LBRACE) {
|
||||
ExpressionUnderCursor expressionUnderCursor(m_languageFeatures);
|
||||
QTextCursor textCursor(m_interface->textDocument());
|
||||
textCursor.setPosition(m_positionEndOfExpression);
|
||||
|
@@ -269,6 +269,27 @@ TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName)
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, ConstructorCallWithBraceInitializer)
|
||||
{
|
||||
auto analyzer = runAnalyzer("f{@");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtConstructorCallWithBraceInitializer)
|
||||
{
|
||||
auto analyzer = runAnalyzer("f{1, @");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, WhitespaceBeforeConstructorCallWithBraceInitializer)
|
||||
{
|
||||
auto analyzer = runAnalyzer("foo {@");
|
||||
|
||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
||||
}
|
||||
|
||||
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
|
||||
{
|
||||
auto analyzer = runAnalyzer("(@");
|
||||
|
Reference in New Issue
Block a user