Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ast visitor function for using declarations. #645

Merged
merged 9 commits into from
Nov 13, 2023
2 changes: 2 additions & 0 deletions plugins/cpp/model/include/model/cppastnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct CppAstNode
LocalTypeLoc,
TypedefTypeLoc,
InheritanceTypeLoc,
UsingLoc,
Other = 1000
};

Expand Down Expand Up @@ -133,6 +134,7 @@ inline std::string astTypeToString(CppAstNode::AstType type_)
case CppAstNode::AstType::LocalTypeLoc: return "LocalTypeLoc";
case CppAstNode::AstType::TypedefTypeLoc: return "TypedefTypeLoc";
case CppAstNode::AstType::InheritanceTypeLoc: return "InheritanceTypeLoc";
case CppAstNode::AstType::UsingLoc: return "UsingLoc";
case CppAstNode::AstType::Other: return "Other";
}

Expand Down
56 changes: 55 additions & 1 deletion plugins/cpp/parser/src/clangastvisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,60 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
return true;
}


bool VisitUsingDecl(clang::UsingDecl* ud_)
{
//--- CppAstNode ---//

for (const clang::UsingShadowDecl* nd : ud_->shadows()) {
model::CppAstNodePtr astNode = std::make_shared<model::CppAstNode>();

astNode->astValue = getSourceText(
_clangSrcMgr,
ud_->getBeginLoc(),
ud_->getLocation(),
true);
astNode->location = getFileLoc(ud_->getBeginLoc(), ud_->getEndLoc());
astNode->entityHash = util::fnvHash(getUSR(nd->getTargetDecl()));

astNode->symbolType = model::CppAstNode::SymbolType::Other;
astNode->astType = model::CppAstNode::AstType::UsingLoc;

astNode->id = model::createIdentifier(*astNode);

if (insertToCache(nd, astNode))
_astNodes.push_back(astNode);
}

return true;
}

bool VisitUsingDirectiveDecl(clang::UsingDirectiveDecl* udd_)
{
//--- CppAstNode ---//

model::CppAstNodePtr astNode = std::make_shared<model::CppAstNode>();

const clang::NamespaceDecl* nd = udd_->getNominatedNamespace();

astNode->astValue = getSourceText(
_clangSrcMgr,
udd_->getBeginLoc(),
udd_->getLocation(),
true);
astNode->location = getFileLoc(udd_->getBeginLoc(), udd_->getEndLoc());
astNode->entityHash = util::fnvHash(getUSR(nd));
astNode->symbolType = model::CppAstNode::SymbolType::Namespace;
astNode->astType = model::CppAstNode::AstType::Usage;

astNode->id = model::createIdentifier(*astNode);

if (insertToCache(udd_, astNode))
_astNodes.push_back(astNode);

return true;
}

bool VisitCXXConstructExpr(clang::CXXConstructExpr* ce_)
{
model::CppAstNodePtr astNode = std::make_shared<model::CppAstNode>();
Expand Down Expand Up @@ -1298,7 +1352,7 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>

clang::SourceLocation realStart = start_;
clang::SourceLocation realEnd = end_;

if (_clangSrcMgr.isMacroBodyExpansion(start_))
realStart = _clangSrcMgr.getExpansionLoc(start_);
if (_clangSrcMgr.isMacroArgExpansion(start_))
Expand Down
1 change: 1 addition & 0 deletions plugins/cpp/test/sources/parser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ add_library(CppTestProject STATIC
cxxrecord.cpp
enum.cpp
function.cpp
using.cpp
variable.cpp
namespace.cpp)
33 changes: 33 additions & 0 deletions plugins/cpp/test/sources/parser/using.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace Nested
{
namespace MyNamespace
{
class C
{
};

void g(C) { }

void g(double) { }

constexpr C VAR1{};

template<class T>
constexpr T VAR2 = T{};
}
}

using namespace Nested;
void g() {}
using MyNamespace::g;

void using_fun()
{
using MyNamespace::C;
using MyNamespace::VAR1;
using MyNamespace::VAR2;

g();
g(VAR1);
g(VAR2<double>);
}
73 changes: 70 additions & 3 deletions plugins/cpp/test/src/cppparsertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ TEST_F(CppParserTest, FilesAreInDatabase)
file = _db->query_value<model::File>(QFile::filename == "namespace.cpp");
EXPECT_EQ(file.type, "CPP");
EXPECT_EQ(file.parseStatus, model::File::PSFullyParsed);

file = _db->query_value<model::File>(QFile::filename == "using.cpp");
EXPECT_EQ(file.type, "CPP");
EXPECT_EQ(file.parseStatus, model::File::PSFullyParsed);
});
}

Expand Down Expand Up @@ -546,7 +550,7 @@ TEST_F(CppParserTest, Fields)
{
_transaction([&, this] {
model::CppVariable fieldFunction = _db->query_value<model::CppVariable>(
QCppFunction::name == "fieldFunction");
QCppVariable::name == "fieldFunction");
RCppAstNode astNodes = _db->query<model::CppAstNode>(
QCppAstNode::entityHash == fieldFunction.entityHash);

Expand Down Expand Up @@ -686,11 +690,11 @@ TEST_F(CppParserTest, Namespace)
model::CppNamespace myNamespace1 = _db->query_value<model::CppNamespace>(
QCppNamespace::name == "MyNamespace1");
model::CppAstNode astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == myNamespace1.entityHash);
QCppAstNode::entityHash == myNamespace1.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::Definition);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Namespace);
EXPECT_EQ(astNode.location.range.start.line, 1);
EXPECT_EQ(astNode.astType, model::CppAstNode::AstType::Definition);

model::CppNamespace myNamespace2 = _db->query_value<model::CppNamespace>(
QCppNamespace::name == "MyNamespace2");
Expand All @@ -702,3 +706,66 @@ TEST_F(CppParserTest, Namespace)
EXPECT_EQ(astNode.astType, model::CppAstNode::AstType::Definition);
});
}

TEST_F(CppParserTest, Using)
{
_transaction([&, this] {
model::CppNamespace nested = _db->query_value<model::CppNamespace>(
QCppNamespace::name == "Nested");

model::CppAstNode astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == nested.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::Usage);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Namespace);
EXPECT_EQ(astNode.location.range.start.line, 20);


model::CppRecord cClass = _db->query_value<model::CppRecord>(
QCppRecord::qualifiedName == "Nested::MyNamespace::C");

astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == cClass.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::UsingLoc);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Other);
EXPECT_EQ(astNode.location.range.start.line, 26);


model::CppVariable var1 = _db->query_value<model::CppVariable>(
QCppVariable::name == "VAR1");

astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == var1.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::UsingLoc);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Other);
EXPECT_EQ(astNode.location.range.start.line, 27);

astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == var1.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::Read);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Variable);
EXPECT_EQ(astNode.location.range.start.line, 31);

RCppFunction functions_with_g = _db->query<model::CppFunction>(
QCppFunction::qualifiedName == "Nested::MyNamespace::g");

for (const model::CppFunction& func : functions_with_g) {
astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == func.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::UsingLoc);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Other);
EXPECT_EQ(astNode.location.range.start.line, 22);


astNode = _db->query_value<model::CppAstNode>(
QCppAstNode::entityHash == func.entityHash &&
QCppAstNode::astType == model::CppAstNode::AstType::Usage);

EXPECT_EQ(astNode.symbolType, model::CppAstNode::SymbolType::Function);
}
});
}
Loading