Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
});
}