Commit 46461fc1 authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski Committed by Erik Verbruggen

C++: code completion for lambda calls

support for lambdas, e.g.:
struct S { int bar; };
[]() { return new S; } ()->bar;
[] { return new S; } ()->bar;
[]() ->S* { return new S(); } ()->bar;
[]() throw() { return new S(); } ()->bar;
[]() throw()->S* { return new S(); } ()->bar;

Task-number: QTCREATORBUG-9523
Change-Id: I43fbf6f0ee0bb11411c53c984df75ef33a276466
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent ab15d387
...@@ -176,6 +176,30 @@ int ExpressionUnderCursor::startOfExpression_helper(BackwardsScanner &tk, int in ...@@ -176,6 +176,30 @@ int ExpressionUnderCursor::startOfExpression_helper(BackwardsScanner &tk, int in
else if (tk[lessIndex - 1].is(T_SLOT)) else if (tk[lessIndex - 1].is(T_SLOT))
return startOfExpression(tk, lessIndex); return startOfExpression(tk, lessIndex);
} }
} else if (tk[matchingBraceIndex - 1].is(T_RBRACE)) {
// lambda: [](){} ()
int leftBraceIndex = tk.startOfMatchingBrace(matchingBraceIndex);
if (matchingBraceIndex != leftBraceIndex) {
int currentIndex = leftBraceIndex;
while (currentIndex >= 0) {
if (tk[currentIndex-1].is(T_RPAREN)) {
int leftParenIndex = tk.startOfMatchingBrace(currentIndex);
if (tk[leftParenIndex-1].is(T_THROW)) {
currentIndex = leftParenIndex-1;
} else if (tk[leftParenIndex-1].is(T_RBRACKET)) {
int leftBracketIndex = tk.startOfMatchingBrace(leftParenIndex);
if (leftBracketIndex != leftParenIndex-1)
return leftBracketIndex;
}
} else if (tk[currentIndex-1].is(T_RBRACKET)) {
int leftBracketIndex = tk.startOfMatchingBrace(currentIndex);
if (leftBracketIndex != currentIndex-1)
return leftBracketIndex;
} else {
--currentIndex;
}
}
}
} }
return startOfExpression(tk, matchingBraceIndex); return startOfExpression(tk, matchingBraceIndex);
} }
......
...@@ -366,6 +366,18 @@ bool ResolveExpression::visit(CompoundExpressionAST *ast) ...@@ -366,6 +366,18 @@ bool ResolveExpression::visit(CompoundExpressionAST *ast)
return false; return false;
} }
bool ResolveExpression::visit(LambdaExpressionAST *ast)
{
accept(ast->statement);
return false;
}
bool ResolveExpression::visit(ReturnStatementAST *ast)
{
accept(ast->expression);
return false;
}
bool ResolveExpression::visit(NestedExpressionAST *ast) bool ResolveExpression::visit(NestedExpressionAST *ast)
{ {
accept(ast->expression); accept(ast->expression);
...@@ -626,6 +638,11 @@ bool ResolveExpression::visit(CallAST *ast) ...@@ -626,6 +638,11 @@ bool ResolveExpression::visit(CallAST *ast)
{ {
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope); const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
if (ast->base_expression->asLambdaExpression()) {
_results = baseResults;
return false;
}
// Compute the types of the actual arguments. // Compute the types of the actual arguments.
unsigned actualArgumentCount = 0; unsigned actualArgumentCount = 0;
......
...@@ -104,6 +104,8 @@ protected: ...@@ -104,6 +104,8 @@ protected:
virtual bool visit(UnaryExpressionAST *ast); virtual bool visit(UnaryExpressionAST *ast);
virtual bool visit(CompoundLiteralAST *ast); virtual bool visit(CompoundLiteralAST *ast);
virtual bool visit(CompoundExpressionAST *ast); virtual bool visit(CompoundExpressionAST *ast);
virtual bool visit(LambdaExpressionAST *ast);
virtual bool visit(ReturnStatementAST *ast);
//names //names
virtual bool visit(QualifiedNameAST *ast); virtual bool visit(QualifiedNameAST *ast);
......
...@@ -2690,3 +2690,138 @@ void CppToolsPlugin::test_completion_enum_inside_function_QTCREATORBUG5456() ...@@ -2690,3 +2690,138 @@ void CppToolsPlugin::test_completion_enum_inside_function_QTCREATORBUG5456()
QVERIFY(completions.contains(QLatin1String("e2"))); QVERIFY(completions.contains(QLatin1String("e2")));
QVERIFY(completions.contains(QLatin1String("e3"))); QVERIFY(completions.contains(QLatin1String("e3")));
} }
void CppToolsPlugin::test_completion_lambdaCalls_1()
{
TestData data;
data.srcText =
"struct S { int bar; };\n"
"void foo()\n"
"{\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("[](){ return new S; } ()->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("S")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
void CppToolsPlugin::test_completion_lambdaCalls_2()
{
TestData data;
data.srcText =
"struct S { int bar; };\n"
"void foo()\n"
"{\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("[] { return new S; } ()->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("S")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
void CppToolsPlugin::test_completion_lambdaCalls_3()
{
TestData data;
data.srcText =
"struct S { int bar; };\n"
"void foo()\n"
"{\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("[]() ->S* { return new S; } ()->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("S")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
void CppToolsPlugin::test_completion_lambdaCalls_4()
{
TestData data;
data.srcText =
"struct S { int bar; };\n"
"void foo()\n"
"{\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("[]() throw() { return new S; } ()->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("S")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
void CppToolsPlugin::test_completion_lambdaCalls_5()
{
TestData data;
data.srcText =
"struct S { int bar; };\n"
"void foo()\n"
"{\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("[]() throw()->S* { return new S; } ()->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("S")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
...@@ -156,6 +156,13 @@ private slots: ...@@ -156,6 +156,13 @@ private slots:
void test_completion_enum_inside_block_inside_function_QTCREATORBUG5456(); void test_completion_enum_inside_block_inside_function_QTCREATORBUG5456();
void test_completion_enum_inside_function_QTCREATORBUG5456(); void test_completion_enum_inside_function_QTCREATORBUG5456();
//lambda
void test_completion_lambdaCalls_1();
void test_completion_lambdaCalls_2();
void test_completion_lambdaCalls_3();
void test_completion_lambdaCalls_4();
void test_completion_lambdaCalls_5();
void test_format_pointerdeclaration_in_simpledeclarations(); void test_format_pointerdeclaration_in_simpledeclarations();
void test_format_pointerdeclaration_in_simpledeclarations_data(); void test_format_pointerdeclaration_in_simpledeclarations_data();
void test_format_pointerdeclaration_in_controlflowstatements(); void test_format_pointerdeclaration_in_controlflowstatements();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment