forked from qt-creator/qt-creator
Clang: Fix completion after '{'
Follow-up fix for 8d0391a4f9
.
Do not complete after '{' coming not after an identifier.
Take constructor completions only for '{' and function
completions only for '('. Filter constructor completions by
class/struct type.
Task-number: QTCREATORBUG-21004
Change-Id: I7ae2d6bee23cf907648c42b93eb12742942833f6
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -131,6 +131,16 @@ public:
|
|||||||
return byteArray.indexOf(text);
|
return byteArray.indexOf(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lastIndexOf(const Utf8String &text) const
|
||||||
|
{
|
||||||
|
return byteArray.lastIndexOf(text.byteArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastIndexOf(const char *text) const
|
||||||
|
{
|
||||||
|
return byteArray.lastIndexOf(text);
|
||||||
|
}
|
||||||
|
|
||||||
int indexOf(char character) const
|
int indexOf(char character) const
|
||||||
{
|
{
|
||||||
return byteArray.indexOf(character);
|
return byteArray.indexOf(character);
|
||||||
|
@@ -190,8 +190,22 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface *
|
|||||||
static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions)
|
static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions)
|
||||||
{
|
{
|
||||||
return ::Utils::filtered(completions, [](const CodeCompletion &completion) {
|
return ::Utils::filtered(completions, [](const CodeCompletion &completion) {
|
||||||
return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind
|
return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind;
|
||||||
|| completion.completionKind == CodeCompletion::ConstructorCompletionKind;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static CodeCompletions filterConstructorSignatures(Utf8String textBefore,
|
||||||
|
const CodeCompletions &completions)
|
||||||
|
{
|
||||||
|
const int prevStatementEnd = textBefore.lastIndexOf(";");
|
||||||
|
if (prevStatementEnd != -1)
|
||||||
|
textBefore = textBefore.mid(prevStatementEnd + 1);
|
||||||
|
|
||||||
|
return ::Utils::filtered(completions, [&textBefore](const CodeCompletion &completion) {
|
||||||
|
if (completion.completionKind != CodeCompletion::ConstructorCompletionKind)
|
||||||
|
return false;
|
||||||
|
const Utf8String type = completion.chunks.at(0).text;
|
||||||
|
return textBefore.indexOf(type) != -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +215,18 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(
|
|||||||
QTC_CHECK(m_completions.isEmpty());
|
QTC_CHECK(m_completions.isEmpty());
|
||||||
|
|
||||||
if (m_sentRequestType == FunctionHintCompletion){
|
if (m_sentRequestType == FunctionHintCompletion){
|
||||||
const CodeCompletions functionSignatures = filterFunctionSignatures(completions);
|
CodeCompletions functionSignatures;
|
||||||
|
if (m_completionOperator == T_LPAREN) {
|
||||||
|
functionSignatures = filterFunctionSignatures(completions);
|
||||||
|
} else {
|
||||||
|
const QTextBlock block = m_interface->textDocument()->findBlock(
|
||||||
|
m_interface->position());
|
||||||
|
const QString textBefore = block.text().left(
|
||||||
|
m_interface->position() - block.position());
|
||||||
|
|
||||||
|
functionSignatures = filterConstructorSignatures(textBefore, completions);
|
||||||
|
}
|
||||||
|
|
||||||
if (!functionSignatures.isEmpty()) {
|
if (!functionSignatures.isEmpty()) {
|
||||||
setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures));
|
setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures));
|
||||||
return;
|
return;
|
||||||
|
@@ -68,6 +68,22 @@ static bool isDoxygenTagCompletionCharacter(const QChar &character)
|
|||||||
|| character == QLatin1Char('@') ;
|
|| character == QLatin1Char('@') ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool twoIndentifiersBeforeLBrace(const Tokens &tokens, int tokenIdx)
|
||||||
|
{
|
||||||
|
const Token &previousToken = tokens.at(tokenIdx - 1);
|
||||||
|
if (previousToken.kind() != T_IDENTIFIER)
|
||||||
|
return false;
|
||||||
|
for (int index = tokenIdx - 2; index >= 0; index -= 2) {
|
||||||
|
const Token &token = tokens.at(index);
|
||||||
|
if (token.kind() == T_IDENTIFIER)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (token.kind() != T_COLON_COLON)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CppCompletionAssistProcessor::startOfOperator(QTextDocument *textDocument,
|
void CppCompletionAssistProcessor::startOfOperator(QTextDocument *textDocument,
|
||||||
int positionInDocument,
|
int positionInDocument,
|
||||||
unsigned *kind,
|
unsigned *kind,
|
||||||
@@ -146,6 +162,11 @@ void CppCompletionAssistProcessor::startOfOperator(QTextDocument *textDocument,
|
|||||||
start = positionInDocument;
|
start = positionInDocument;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (*kind == T_LBRACE) {
|
||||||
|
if (tokenIdx > 0 && !twoIndentifiersBeforeLBrace(tokens, tokenIdx)) {
|
||||||
|
*kind = T_EOF_SYMBOL;
|
||||||
|
start = positionInDocument;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Check for include preprocessor directive
|
// Check for include preprocessor directive
|
||||||
else if (*kind == T_STRING_LITERAL || *kind == T_ANGLE_STRING_LITERAL || *kind == T_SLASH
|
else if (*kind == T_STRING_LITERAL || *kind == T_ANGLE_STRING_LITERAL || *kind == T_SLASH
|
||||||
|
@@ -290,6 +290,13 @@ TEST_F(ClangCompletionContextAnalyzer, WhitespaceBeforeConstructorCallWithBraceI
|
|||||||
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangCompletionContextAnalyzer, OpenFunctionScopeNotAConstructor)
|
||||||
|
{
|
||||||
|
auto analyzer = runAnalyzer("foo() {@");
|
||||||
|
|
||||||
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
|
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
|
||||||
{
|
{
|
||||||
auto analyzer = runAnalyzer("(@");
|
auto analyzer = runAnalyzer("(@");
|
||||||
|
Reference in New Issue
Block a user