88#include < model/cppfilemetrics-odb.hxx>
99#include < model/cppinheritance.h>
1010#include < model/cppinheritance-odb.hxx>
11+ #include < model/cpprecord.h>
12+ #include < model/cpprecord-odb.hxx>
1113
1214#include < model/cppastnode.h>
1315#include < model/cppastnode-odb.hxx>
@@ -428,6 +430,89 @@ void CppMetricsParser::efferentTypeLevel()
428430 });
429431}
430432
433+ void CppMetricsParser::afferentTypeLevel ()
434+ {
435+ parallelCalcMetric<model::CohesionCppRecordView>(
436+ " Afferent coupling of types" ,
437+ _threadCount * afferentCouplingTypesPartitionMultiplier,// number of jobs; adjust for granularity
438+ getFilterPathsQuery<model::CohesionCppRecordView>(),
439+ [&, this ](const MetricsTasks<model::CohesionCppRecordView>& tasks)
440+ {
441+ util::OdbTransaction{_ctx.db }([&, this ]
442+ {
443+ typedef odb::query<cc::model::CppAstNode> AstQuery;
444+ typedef odb::query<cc::model::CppInheritance> InheritanceQuery;
445+ typedef odb::query<cc::model::CppMemberType> MemTypeQuery;
446+ typedef odb::result<cc::model::CppAstNode> AstResult;
447+ typedef odb::result<cc::model::CppMemberTypeAstView> MemTypeAstResult;
448+
449+ std::set<std::uint64_t > dependentTypes;
450+ for (const model::CohesionCppRecordView& type : tasks)
451+ {
452+ dependentTypes.clear ();
453+
454+ // Find derived types
455+ for (const model::CppInheritance& inheritance : _ctx.db ->query <model::CppInheritance>(
456+ InheritanceQuery::base == type.entityHash ))
457+ {
458+ dependentTypes.insert (inheritance.derived );
459+ }
460+
461+ // Find usages of the type
462+ for (const model::CppAstNode& usage : _ctx.db ->query <model::CppAstNode>(
463+ AstQuery::entityHash == type.entityHash &&
464+ AstQuery::location.range .end .line != model::Position::npos))
465+ {
466+ // Check if usage is in class member function or attribute
467+ MemTypeAstResult memberNode = _ctx.db ->query <model::CppMemberTypeAstView>(
468+ AstQuery::symbolType.in (model::CppAstNode::SymbolType::Function, model::CppAstNode::SymbolType::Variable) &&
469+ AstQuery::astType.in (model::CppAstNode::AstType::Definition, model::CppAstNode::AstType::Declaration) &&
470+ AstQuery::location.file == usage.location .file .object_id () &&
471+ AstQuery::location.range .start .line <= usage.location .range .start .line &&
472+ AstQuery::location.range .end .line >= usage.location .range .end .line &&
473+ MemTypeQuery::typeHash != usage.entityHash );
474+
475+ if (!memberNode.empty ())
476+ {
477+ dependentTypes.insert (memberNode.begin ()->typeHash );
478+ } else {
479+ // The usage can be in a member function defined outside of the class definition
480+ // E.g. void ClassName::foo() { A a; }
481+ // ^ usage here
482+
483+ // Find parent function
484+ AstResult parentFunction = _ctx.db ->query <model::CppAstNode>(
485+ AstQuery::symbolType == model::CppAstNode::SymbolType::Function &&
486+ AstQuery::astType == model::CppAstNode::AstType::Definition &&
487+ AstQuery::location.file == usage.location .file .object_id () &&
488+ AstQuery::location.range .start .line <= usage.location .range .start .line &&
489+ AstQuery::location.range .end .line >= usage.location .range .end .line );
490+
491+ if (!parentFunction.empty ())
492+ {
493+ // Find if the function is a member function of a class
494+ MemTypeAstResult memberFunction = _ctx.db ->query <model::CppMemberTypeAstView>(
495+ AstQuery::entityHash == parentFunction.begin ()->entityHash &&
496+ MemTypeQuery::typeHash != usage.entityHash );
497+
498+ if (!memberFunction.empty ())
499+ {
500+ dependentTypes.insert (memberFunction.begin ()->typeHash );
501+ }
502+ }
503+ }
504+ }
505+
506+ model::CppAstNodeMetrics metric;
507+ metric.astNodeId = type.astNodeId ;
508+ metric.type = model::CppAstNodeMetrics::Type::AFFERENT_TYPE;
509+ metric.value = dependentTypes.size ();
510+ _ctx.db ->persist (metric);
511+ }
512+ });
513+ });
514+ }
515+
431516bool CppMetricsParser::parse ()
432517{
433518 LOG (info) << " [cppmetricsparser] Computing function parameter count metric." ;
@@ -442,6 +527,8 @@ bool CppMetricsParser::parse()
442527 lackOfCohesion ();
443528 LOG (info) << " [cppmetricsparser] Computing efferent coupling metric for types." ;
444529 efferentTypeLevel ();
530+ LOG (info) << " [cppmetricsparser] Computing afferent coupling metric for types." ;
531+ afferentTypeLevel ();
445532 return true ;
446533}
447534
0 commit comments