Commit 9f38f7bf authored by Nikolai Kosjar's avatar Nikolai Kosjar

C++: Store lambda captures in the code model.

Done-with: Erik Verbruggen
Task-number: QTCREATORBUG-7968
Task-number: QTCREATORBUG-7949

Change-Id: I0cf727052d0a3536ed96ee894b18768c9538c213
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent be516c7c
......@@ -403,12 +403,22 @@ unsigned CallAST::lastToken() const
/** \generated */
unsigned CaptureAST::firstToken() const
{
if (amper_token)
return amper_token;
if (identifier)
if (unsigned candidate = identifier->firstToken())
return candidate;
return 0;
}
/** \generated */
unsigned CaptureAST::lastToken() const
{
if (identifier)
if (unsigned candidate = identifier->lastToken())
return candidate;
if (amper_token)
return amper_token + 1;
return 1;
}
......
......@@ -4394,8 +4394,14 @@ protected:
class CaptureAST: public AST
{
public:
unsigned amper_token;
NameAST *identifier;
public:
CaptureAST()
: amper_token(0)
, identifier(0)
{}
virtual CaptureAST *asCapture() { return this; }
......
......@@ -1703,6 +1703,9 @@ LambdaCaptureAST *LambdaCaptureAST::clone(MemoryPool *pool) const
CaptureAST *CaptureAST::clone(MemoryPool *pool) const
{
CaptureAST *ast = new (pool) CaptureAST;
ast->amper_token = amper_token;
if (identifier)
ast->identifier = identifier->clone(pool);
return ast;
}
......
......@@ -2898,6 +2898,13 @@ bool ASTMatcher::match(CaptureAST *node, CaptureAST *pattern)
(void) node;
(void) pattern;
pattern->amper_token = node->amper_token;
if (! pattern->identifier)
pattern->identifier = node->identifier;
else if (! AST::match(node->identifier, pattern->identifier, this))
return false;
return true;
}
......
......@@ -1107,9 +1107,10 @@ public:
return __ast;
}
CaptureAST *Capture()
CaptureAST *Capture(NameAST *identifier = 0)
{
CaptureAST *__ast = new (&pool) CaptureAST;
__ast->identifier = identifier;
return __ast;
}
......
......@@ -1237,6 +1237,7 @@ void LambdaCaptureAST::accept0(ASTVisitor *visitor)
void CaptureAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(identifier, visitor);
}
visitor->endVisit(this);
}
......
......@@ -1069,7 +1069,7 @@ void Bind::capture(CaptureAST *ast)
if (! ast)
return;
// See QTCREATORBUG-7968
name(ast->identifier);
}
bool Bind::visit(LambdaDeclaratorAST *ast)
......
......@@ -6294,43 +6294,56 @@ bool Parser::parseLambdaCapture(LambdaCaptureAST *&node)
return true;
}
bool Parser::parseCapture(CaptureAST *&)
bool Parser::parseCapture(CaptureAST *&node)
{
// See QTCREATORBUG-7968
DEBUG_THIS_RULE();
if (LA() == T_IDENTIFIER) {
consumeToken();
return true;
} else if (LA() == T_AMPER && LA(2) == T_IDENTIFIER) {
consumeToken();
if (LA() == T_THIS) {
consumeToken();
return true;
}
} else if (LA() == T_THIS) {
if (LA() == T_AMPER)
consumeToken();
if (LA() == T_IDENTIFIER) {
SimpleNameAST *ast = new (_pool) SimpleNameAST;
ast->identifier_token = consumeToken();
node = new (_pool) CaptureAST;
node->identifier = ast;
return true;
}
return false;
}
bool Parser::parseCaptureList(CaptureListAST *&)
bool Parser::parseCaptureList(CaptureListAST *&node)
{
DEBUG_THIS_RULE();
CaptureAST *capture = 0;
if (parseCapture(capture)) {
node = new (_pool) CaptureListAST;
node->value = capture;
CaptureListAST **l = &node->next;
while (LA() == T_COMMA) {
consumeToken(); // consume `,'
CaptureAST *capture = 0;
parseCapture(capture);
if (capture) {
*l = new (_pool) CaptureListAST;
(*l)->value = capture;
l = &(*l)->next;
}
}
return true;
}
return true;
return false;
}
bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node)
......
......@@ -869,7 +869,7 @@ void FindUsages::capture(CaptureAST *ast)
if (! ast)
return;
// See QTCREATORBUG-7968
this->name(ast->identifier);
}
bool FindUsages::visit(LambdaDeclaratorAST *ast)
......
......@@ -127,6 +127,11 @@ protected:
return true;
}
virtual bool visit(CaptureAST *ast)
{
return checkLocalUse(ast->identifier, ast->firstToken());
}
virtual bool visit(IdExpressionAST *ast)
{
return checkLocalUse(ast->name, ast->firstToken());
......
......@@ -77,7 +77,8 @@ class tst_FindUsages: public QObject
private Q_SLOTS:
void inlineMethod();
// void lambdaArg();
void lambdaCaptureByValue();
void lambdaCaptureByReference();
// Qt keywords
void qproperty_1();
......@@ -124,15 +125,46 @@ void tst_FindUsages::inlineMethod()
QCOMPARE(findUsages.references().size(), 2);
}
#if 0 /* see QTCREATORBUG-7968 */
void tst_FindUsages::lambdaArg()
void tst_FindUsages::lambdaCaptureByValue()
{
const QByteArray src = "\n"
"void f() {\n"
" int test;\n"
" [test] { ++test; };\n"
"}\n";
Document::Ptr doc = Document::create("lambdaArg");
Document::Ptr doc = Document::create("lambdaCaptureByValue");
doc->setUtf8Source(src);
doc->parse();
doc->check();
QVERIFY(doc->diagnosticMessages().isEmpty());
QCOMPARE(doc->globalSymbolCount(), 1U);
Snapshot snapshot;
snapshot.insert(doc);
Function *f = doc->globalSymbolAt(0)->asFunction();
QVERIFY(f);
QCOMPARE(f->memberCount(), 1U);
Block *b = f->memberAt(0)->asBlock();
QCOMPARE(b->memberCount(), 2U);
Declaration *d = b->memberAt(0)->asDeclaration();
QVERIFY(d);
QCOMPARE(d->name()->identifier()->chars(), "test");
FindUsages findUsages(src, doc, snapshot);
findUsages(d);
QCOMPARE(findUsages.usages().size(), 3);
}
void tst_FindUsages::lambdaCaptureByReference()
{
const QByteArray src = "\n"
"void f() {\n"
" int test;\n"
" [&test] { ++test; };\n"
"}\n";
Document::Ptr doc = Document::create("lambdaCaptureByReference");
doc->setUtf8Source(src);
doc->parse();
doc->check();
......@@ -156,7 +188,6 @@ void tst_FindUsages::lambdaArg()
findUsages(d);
QCOMPARE(findUsages.usages().size(), 3);
}
#endif
#if 0
@interface Clazz {} +(void)method:(int)arg; @end
......
......@@ -1645,6 +1645,9 @@ virtual bool visit(LambdaCaptureAST *ast)
virtual bool visit(CaptureAST *ast)
{
if (ast->amper_token)
terminal(ast->amper_token, ast);
nonterminal(ast->identifier);
return false;
}
......
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