8
8
#include < model/cppfilemetrics-odb.hxx>
9
9
#include < model/cppinheritance.h>
10
10
#include < model/cppinheritance-odb.hxx>
11
+ #include < model/cpprecord.h>
12
+ #include < model/cpprecord-odb.hxx>
11
13
12
14
#include < model/cppastnode.h>
13
15
#include < model/cppastnode-odb.hxx>
@@ -428,6 +430,89 @@ void CppMetricsParser::efferentTypeLevel()
428
430
});
429
431
}
430
432
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
+
431
516
bool CppMetricsParser::parse ()
432
517
{
433
518
LOG (info) << " [cppmetricsparser] Computing function parameter count metric." ;
@@ -442,6 +527,8 @@ bool CppMetricsParser::parse()
442
527
lackOfCohesion ();
443
528
LOG (info) << " [cppmetricsparser] Computing efferent coupling metric for types." ;
444
529
efferentTypeLevel ();
530
+ LOG (info) << " [cppmetricsparser] Computing afferent coupling metric for types." ;
531
+ afferentTypeLevel ();
445
532
return true ;
446
533
}
447
534
0 commit comments