logic: implemented recording references to symbols inside lambda capture lists
This commit is contained in:
@@ -310,7 +310,33 @@ bool CxxAstVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc
|
||||
return base::TraverseTemplateArgumentLoc(loc);
|
||||
}
|
||||
|
||||
void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext *d)
|
||||
bool CxxAstVisitor::TraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture)
|
||||
{
|
||||
clang::VarDecl* d = capture->getCapturedVar();
|
||||
if (lambdaExpr->isInitCapture(capture))
|
||||
{
|
||||
TraverseDecl(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
SymbolKind symbolKind = getSymbolKind(d);
|
||||
if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER)
|
||||
{
|
||||
if (!d->getNameAsString().empty()) // don't record anonymous parameters
|
||||
{
|
||||
ParseLocation declLocation = getParseLocation(d->getLocation());
|
||||
std::string name =
|
||||
declLocation.filePath.fileName() + "<" +
|
||||
std::to_string(declLocation.startLineNumber) + ":" +
|
||||
std::to_string(declLocation.startColumnNumber) + ">";
|
||||
m_client->onLocalSymbolParsed(name, getParseLocation(capture->getLocation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext* d)
|
||||
{
|
||||
if (!d)
|
||||
return;
|
||||
@@ -444,28 +470,7 @@ bool CxxAstVisitor::VisitVarDecl(clang::VarDecl* d)
|
||||
{
|
||||
if (shouldVisitDecl(d))
|
||||
{
|
||||
SymbolKind symbolKind = SYMBOL_KIND_MAX;
|
||||
|
||||
if (llvm::isa<clang::ParmVarDecl>(d))
|
||||
{
|
||||
symbolKind = SYMBOL_PARAMETER;
|
||||
}
|
||||
else if (d->getParentFunctionOrMethod() == NULL)
|
||||
{
|
||||
if (d->getAccess() == clang::AS_none)
|
||||
{
|
||||
symbolKind = SYMBOL_GLOBAL_VARIABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolKind = SYMBOL_FIELD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolKind = SYMBOL_LOCAL_VARIABLE;
|
||||
}
|
||||
|
||||
SymbolKind symbolKind = getSymbolKind(d);
|
||||
if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER)
|
||||
{
|
||||
if (!d->getNameAsString().empty()) // don't record anonymous parameters
|
||||
@@ -1225,3 +1230,30 @@ ReferenceKind CxxAstVisitor::consumeDeclRefContextKind()
|
||||
}
|
||||
return refKind;
|
||||
}
|
||||
|
||||
SymbolKind CxxAstVisitor::getSymbolKind(clang::VarDecl* d)
|
||||
{
|
||||
SymbolKind symbolKind = SYMBOL_KIND_MAX;
|
||||
|
||||
if (llvm::isa<clang::ParmVarDecl>(d))
|
||||
{
|
||||
symbolKind = SYMBOL_PARAMETER;
|
||||
}
|
||||
else if (d->getParentFunctionOrMethod() == NULL)
|
||||
{
|
||||
if (d->getAccess() == clang::AS_none)
|
||||
{
|
||||
symbolKind = SYMBOL_GLOBAL_VARIABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolKind = SYMBOL_FIELD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolKind = SYMBOL_LOCAL_VARIABLE;
|
||||
}
|
||||
|
||||
return symbolKind;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ public:
|
||||
virtual bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
virtual bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* s);
|
||||
virtual bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
void traverseDeclContextHelper(clang::DeclContext *d);
|
||||
virtual bool TraverseLambdaCapture(clang::LambdaExpr* lambdaExpr, const clang::LambdaCapture* capture);
|
||||
void traverseDeclContextHelper(clang::DeclContext* d);
|
||||
bool TraverseCallCommon(clang::CallExpr* s);
|
||||
|
||||
// Visitor methods. These actually record stuff and store it in the database.
|
||||
@@ -129,6 +130,7 @@ protected:
|
||||
|
||||
private:
|
||||
ReferenceKind consumeDeclRefContextKind();
|
||||
SymbolKind getSymbolKind(clang::VarDecl* d);
|
||||
|
||||
typedef clang::RecursiveASTVisitor<CxxAstVisitor> base;
|
||||
|
||||
|
||||
@@ -933,6 +933,20 @@ public:
|
||||
TS_ASSERT_EQUALS(client->functions[1], "int lambdaWrapper::lambda at 3:2(int) <3:14 <3:2 3:2> 3:36>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_local_variable_declared_in_lambda_capture()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"void lambdaWrapper()\n"
|
||||
"{\n"
|
||||
" [x(42)]() { return x; };\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->localSymbols.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<3:3> <3:3 3:3>");
|
||||
TS_ASSERT_EQUALS(client->localSymbols[1], "input.cc<3:3> <3:21 3:21>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_definition_of_local_symbol_in_function_parameter_list()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
@@ -2940,6 +2954,21 @@ public:
|
||||
TS_ASSERT_EQUALS(client->calls[1], "void lambdaCaller::lambda at 4:2() const -> void func() <6:3 6:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_local_variable_in_lambda_capture()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"void lambdaWrapper()\n"
|
||||
"{\n"
|
||||
" int x = 2;\n"
|
||||
" [x]() { return 1; }();\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->localSymbols.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<3:6> <3:6 3:6>");
|
||||
TS_ASSERT_EQUALS(client->localSymbols[1], "input.cc<3:6> <4:3 4:3>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_argument_of_unresolved_lookup_expression_as_type_use()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
|
||||
Reference in New Issue
Block a user