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
3 changes: 2 additions & 1 deletion plugins/cpp/model/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ set(ODB_SOURCES
include/model/cppmacro.h
include/model/cppmacroexpansion.h
include/model/cppedge.h
include/model/cppdoccomment.h)
include/model/cppdoccomment.h
include/model/cpptypedependency.h)

generate_odb_files("${ODB_SOURCES}")

Expand Down
5 changes: 5 additions & 0 deletions plugins/cpp/model/include/model/cppfunction.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CC_MODEL_CPPFUNCTION_H
#define CC_MODEL_CPPFUNCTION_H

#include <cstdint>
#include <vector>

#include "cppentity.h"
Expand All @@ -23,6 +24,10 @@ struct CppFunction : CppTypedEntity
unsigned int bumpiness;
unsigned int statementCount;

// Hash of the record (e.g. class or struct) in which this function is declared
// recordHash = 0 means this is a global function
std::uint64_t recordHash = 0;

std::string toString() const
{
return std::string("CppFunction")
Expand Down
126 changes: 126 additions & 0 deletions plugins/cpp/model/include/model/cpptypedependency.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#ifndef CC_MODEL_CPPTYPEDEPENDENCY_H
#define CC_MODEL_CPPTYPEDEPENDENCY_H

#include <cstdint>
#include <string>
#include <model/cppentity.h>
#include <model/cpprecord.h>
#include <model/cppastnode.h>
#include <model/file.h>

namespace cc
{
namespace model
{

#pragma db object
struct CppTypeDependency
{
#pragma db id auto
std::uint64_t id;

#pragma db not_null
std::uint64_t entityHash;

#pragma db not_null
std::uint64_t dependencyHash;

std::string toString() const
{
return std::string("CppTypeDependency")
.append("\nid = ").append(std::to_string(id))
.append("\nentityHash = ").append(std::to_string(entityHash))
.append("\ndependencyHash = ").append(std::to_string(dependencyHash));
}

#pragma db index member(entityHash)
#pragma db index member(dependencyHash)
};

typedef std::shared_ptr<CppTypeDependency> CppTypeDependencyPtr;

#pragma db view \
object(CppTypeDependency) \
object(CppAstNode = EntityAstNode : CppTypeDependency::entityHash == EntityAstNode::entityHash \
&& EntityAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = EntityFile : EntityAstNode::location.file == EntityFile::id) \
object(CppAstNode = DependencyAstNode : CppTypeDependency::dependencyHash == DependencyAstNode::entityHash \
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
Comment on lines +42 to +49
Copy link

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The ODB view definitions for CppTypeDependency are very repetitive across multiple structs. Consider extracting the common view clauses into a macro or helper to reduce duplication and simplify future updates.

Suggested change
#pragma db view \
object(CppTypeDependency) \
object(CppAstNode = EntityAstNode : CppTypeDependency::entityHash == EntityAstNode::entityHash \
&& EntityAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = EntityFile : EntityAstNode::location.file == EntityFile::id) \
object(CppAstNode = DependencyAstNode : CppTypeDependency::dependencyHash == DependencyAstNode::entityHash \
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
#define COMMON_CPP_TYPE_DEPENDENCY_VIEW \
COMMON_CPP_TYPE_DEPENDENCY_VIEW

Copilot uses AI. Check for mistakes.
struct CppTypeDependencyPathView
{
#pragma db column(CppTypeDependency::entityHash)
std::size_t entityHash;

#pragma db column(CppTypeDependency::dependencyHash)
std::size_t dependencyHash;

#pragma db column(EntityFile::path)
std::string entityPath;

#pragma db column(DependencyFile::path)
std::string dependencyPath;
};

#pragma db view \
object(CppTypeDependency) \
object(CppAstNode = EntityAstNode : CppTypeDependency::entityHash == EntityAstNode::entityHash \
&& EntityAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = EntityFile : EntityAstNode::location.file == EntityFile::id) \
object(CppAstNode = DependencyAstNode : CppTypeDependency::dependencyHash == DependencyAstNode::entityHash \
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
struct CppTypeDependency_Count
{
#pragma db column("count(" + CppTypeDependency::id + ")")
std::size_t count;
};

#pragma db view \
object(CppTypeDependency) \
object(CppAstNode = EntityAstNode : CppTypeDependency::entityHash == EntityAstNode::entityHash \
&& EntityAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = EntityFile : EntityAstNode::location.file == EntityFile::id) \
object(CppAstNode = DependencyAstNode : CppTypeDependency::dependencyHash == DependencyAstNode::entityHash \
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
struct CppTypeDependency_Distinct_D_Count
{
#pragma db column("count(distinct" + CppTypeDependency::dependencyHash + ")")
std::size_t count;
};

#pragma db view \
object(CppTypeDependency) \
object(CppAstNode = EntityAstNode : CppTypeDependency::entityHash == EntityAstNode::entityHash \
&& EntityAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = EntityFile : EntityAstNode::location.file == EntityFile::id) \
object(CppAstNode = DependencyAstNode : CppTypeDependency::dependencyHash == DependencyAstNode::entityHash \
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
struct CppTypeDependency_Distinct_E_Count
{
#pragma db column("count(distinct" + CppTypeDependency::entityHash + ")")
std::size_t count;
};

#pragma db view \
object(CppTypeDependency)
struct CppTypeDependency_Efferent_Count
{
#pragma db column("count(distinct" + CppTypeDependency::dependencyHash + ")")
std::size_t count;
};

#pragma db view \
object(CppTypeDependency)
struct CppTypeDependency_Afferent_Count
{
#pragma db column("count(distinct" + CppTypeDependency::entityHash + ")")
std::size_t count;
};

} // model
} // cc

#endif // CC_MODEL_CPPTYPEDEPENDENCY_H
30 changes: 30 additions & 0 deletions plugins/cpp/parser/src/clangastvisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include <model/cpprecord-odb.hxx>
#include <model/cpptypedef.h>
#include <model/cpptypedef-odb.hxx>
#include <model/cpptypedependency.h>
#include <model/cpptypedependency-odb.hxx>

#include <parser/parsercontext.h>
#include <parser/sourcemanager.h>
Expand Down Expand Up @@ -129,6 +131,7 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
util::persistAll(_friends, _ctx.db);
util::persistAll(_functions, _ctx.db);
util::persistAll(_relations, _ctx.db);
util::persistAll(_typeDependencies, _ctx.db);
});
}

Expand Down Expand Up @@ -571,6 +574,27 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>

_locToTypeLoc[tl_.getBeginLoc().getRawEncoding()] = astNode;

//--- CppTypeDependency ---//
std::uint64_t typeHash = 0;
if (!_typeStack.empty())
{
typeHash = _typeStack.top()->entityHash;
}

if (typeHash == 0 && !_functionStack.empty())
{
typeHash = _functionStack.top()->recordHash;
}

if (typeHash != 0 && typeHash != astNode->entityHash)
{
model::CppTypeDependencyPtr td = std::make_shared<model::CppTypeDependency>();
_typeDependencies.push_back(td);

td->entityHash = typeHash;
td->dependencyHash = astNode->entityHash;
}

return true;
}

Expand Down Expand Up @@ -913,6 +937,11 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
clang::CXXMethodDecl* md = llvm::dyn_cast<clang::CXXMethodDecl>(fn_);
if (md)
{
if (const clang::CXXRecordDecl* parent = md->getParent())
{
cppFunction->recordHash = util::fnvHash(getUSR(parent));
}

if (md->isVirtual())
cppFunction->tags.insert(model::Tag::Virtual);

Expand Down Expand Up @@ -1837,6 +1866,7 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
std::vector<model::CppInheritancePtr> _inheritances;
std::vector<model::CppFriendshipPtr> _friends;
std::vector<model::CppRelationPtr> _relations;
std::vector<model::CppTypeDependencyPtr> _typeDependencies;

// TODO: Maybe we don't even need a stack, if functions can't be nested.
// Check lambda.
Expand Down
3 changes: 1 addition & 2 deletions plugins/cpp_metrics/model/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ include_directories(
set(ODB_SOURCES
include/model/cppastnodemetrics.h
include/model/cppcohesionmetrics.h
include/model/cppfilemetrics.h
include/model/cpptypedependencymetrics.h)
include/model/cppfilemetrics.h)

generate_odb_files("${ODB_SOURCES}" "cpp")

Expand Down
100 changes: 0 additions & 100 deletions plugins/cpp_metrics/model/include/model/cpptypedependencymetrics.h

This file was deleted.

Loading
Loading