forked from qt-creator/qt-creator
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: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
10
src/libs/3rdparty/cplusplus/AST.cpp
vendored
10
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
6
src/libs/3rdparty/cplusplus/AST.h
vendored
6
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -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; }
|
||||
|
||||
3
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
3
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
7
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
7
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
1
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -1237,6 +1237,7 @@ void LambdaCaptureAST::accept0(ASTVisitor *visitor)
|
||||
void CaptureAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
accept(identifier, visitor);
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
2
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
2
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -1069,7 +1069,7 @@ void Bind::capture(CaptureAST *ast)
|
||||
if (! ast)
|
||||
return;
|
||||
|
||||
// See QTCREATORBUG-7968
|
||||
name(ast->identifier);
|
||||
}
|
||||
|
||||
bool Bind::visit(LambdaDeclaratorAST *ast)
|
||||
|
||||
41
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
41
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -6294,45 +6294,58 @@ 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_THIS) {
|
||||
consumeToken();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (LA() == T_AMPER)
|
||||
consumeToken();
|
||||
|
||||
if (LA() == T_IDENTIFIER) {
|
||||
consumeToken();
|
||||
return true;
|
||||
SimpleNameAST *ast = new (_pool) SimpleNameAST;
|
||||
ast->identifier_token = consumeToken();
|
||||
|
||||
} else if (LA() == T_AMPER && LA(2) == T_IDENTIFIER) {
|
||||
consumeToken();
|
||||
consumeToken();
|
||||
return true;
|
||||
|
||||
} else if (LA() == T_THIS) {
|
||||
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 false;
|
||||
}
|
||||
|
||||
bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node)
|
||||
{
|
||||
DEBUG_THIS_RULE();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user