Skip to content

Commit ff35a5e

Browse files
author
Barnabás Domozi
committed
Implement afferent coupling at module level.
1 parent bfe84de commit ff35a5e

File tree

7 files changed

+106
-7
lines changed

7 files changed

+106
-7
lines changed

plugins/cpp_metrics/model/include/model/cppfilemetrics.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ struct CppFileMetrics
1313
{
1414
enum Type
1515
{
16-
EFFERENT_MODULE
16+
EFFERENT_MODULE,
17+
AFFERENT_MODULE
1718
};
1819

1920
#pragma db id auto

plugins/cpp_metrics/model/include/model/cpptypedependencymetrics.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,26 @@ struct CppTypeDependencyMetricsPathView
5757
object(CppAstNode = DependencyAstNode : CppTypeDependencyMetrics::dependencyHash == DependencyAstNode::entityHash \
5858
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
5959
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
60-
struct CppTypeDependencyMetricsPathViewDistinctCount
60+
struct CppTypeDependencyMetrics_Distinct_D_Count
6161
{
6262
#pragma db column("count(distinct" + CppTypeDependencyMetrics::dependencyHash + ")")
6363
std::size_t count;
6464
};
6565

66+
#pragma db view \
67+
object(CppTypeDependencyMetrics) \
68+
object(CppAstNode = EntityAstNode : CppTypeDependencyMetrics::entityHash == EntityAstNode::entityHash \
69+
&& EntityAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
70+
object(File = EntityFile : EntityAstNode::location.file == EntityFile::id) \
71+
object(CppAstNode = DependencyAstNode : CppTypeDependencyMetrics::dependencyHash == DependencyAstNode::entityHash \
72+
&& DependencyAstNode::astType == cc::model::CppAstNode::AstType::Definition) \
73+
object(File = DependencyFile : DependencyAstNode::location.file == DependencyFile::id)
74+
struct CppTypeDependencyMetrics_Distinct_E_Count
75+
{
76+
#pragma db column("count(distinct" + CppTypeDependencyMetrics::entityHash + ")")
77+
std::size_t count;
78+
};
79+
6680
} // model
6781
} // cc
6882

plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class CppMetricsParser : public AbstractParser
8282
void afferentTypeLevel();
8383
// Calculate the efferent coupling at module level.
8484
void efferentModuleLevel();
85+
// Calculate the afferent coupling at module level.
86+
void afferentModuleLevel();
8587
// Returns module path query based on parser configuration.
8688
odb::query<model::File> getModulePathsQuery();
8789

@@ -207,6 +209,7 @@ class CppMetricsParser : public AbstractParser
207209
static const int efferentCouplingTypesPartitionMultiplier = 5;
208210
static const int afferentCouplingTypesPartitionMultiplier = 5;
209211
static const int efferentCouplingModulesPartitionMultiplier = 5;
212+
static const int afferentCouplingModulesPartitionMultiplier = 5;
210213
};
211214

212215
} // parser

plugins/cpp_metrics/parser/src/cppmetricsparser.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -557,12 +557,12 @@ void CppMetricsParser::efferentModuleLevel()
557557
{
558558
util::OdbTransaction{_ctx.db}([&, this]
559559
{
560-
typedef odb::query<model::CppTypeDependencyMetricsPathViewDistinctCount> TypeDependencyQuery;
561-
typedef model::CppTypeDependencyMetricsPathViewDistinctCount TypeDependencyResult;
560+
typedef odb::query<model::CppTypeDependencyMetrics_Distinct_D_Count> TypeDependencyQuery;
561+
typedef model::CppTypeDependencyMetrics_Distinct_D_Count TypeDependencyResult;
562562

563563
for (const model::File& file : tasks)
564564
{
565-
TypeDependencyResult types = _ctx.db->query_value<model::CppTypeDependencyMetricsPathViewDistinctCount>(
565+
TypeDependencyResult types = _ctx.db->query_value<model::CppTypeDependencyMetrics_Distinct_D_Count>(
566566
TypeDependencyQuery::EntityFile::path.like(file.path + '%') &&
567567
!TypeDependencyQuery::DependencyFile::path.like(file.path + '%'));
568568

@@ -576,6 +576,35 @@ void CppMetricsParser::efferentModuleLevel()
576576
});
577577
}
578578

579+
void CppMetricsParser::afferentModuleLevel()
580+
{
581+
parallelCalcMetric<model::File>(
582+
"Afferent coupling at module level",
583+
_threadCount * afferentCouplingModulesPartitionMultiplier,// number of jobs; adjust for granularity
584+
getModulePathsQuery(),
585+
[&, this](const MetricsTasks<model::File>& tasks)
586+
{
587+
util::OdbTransaction{_ctx.db}([&, this]
588+
{
589+
typedef odb::query<model::CppTypeDependencyMetrics_Distinct_E_Count> TypeDependencyQuery;
590+
typedef model::CppTypeDependencyMetrics_Distinct_E_Count TypeDependencyResult;
591+
592+
for (const model::File& file : tasks)
593+
{
594+
TypeDependencyResult types = _ctx.db->query_value<model::CppTypeDependencyMetrics_Distinct_E_Count>(
595+
!TypeDependencyQuery::EntityFile::path.like(file.path + '%') &&
596+
TypeDependencyQuery::DependencyFile::path.like(file.path + '%'));
597+
598+
model::CppFileMetrics metric;
599+
metric.file = file.id;
600+
metric.type = model::CppFileMetrics::Type::AFFERENT_MODULE;
601+
metric.value = types.count;
602+
_ctx.db->persist(metric);
603+
}
604+
});
605+
});
606+
}
607+
579608
bool CppMetricsParser::parse()
580609
{
581610
LOG(info) << "[cppmetricsparser] Computing function parameter count metric.";
@@ -594,6 +623,8 @@ bool CppMetricsParser::parse()
594623
afferentTypeLevel();
595624
LOG(info) << "[cppmetricsparser] Computing efferent coupling metric at module level.";
596625
efferentModuleLevel(); // This metric needs to be calculated after efferentTypeLevel
626+
LOG(info) << "[cppmetricsparser] Computing afferent coupling metric at module level.";
627+
afferentModuleLevel(); // This metric needs to be calculated after efferentTypeLevel
597628
return true;
598629
}
599630

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef CC_CPP_MODULE_METRICS_TEST_D1
2+
#define CC_CPP_MODULE_METRICS_TEST_D1
3+
4+
#include "../module_c/c1.h"
5+
#include "../module_c/c2.h"
6+
7+
namespace CC_CPP_MODULE_METRICS_TEST
8+
{
9+
class D1 {
10+
C1 c1;
11+
C2 c2;
12+
};
13+
}
14+
15+
#endif

plugins/cpp_metrics/test/sources/parser/modulemetrics.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
#include "./module_b/b2.h"
55
#include "./module_c/c1.h"
66
#include "./module_c/c2.h"
7+
#include "./module_d/d1.h"

plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,10 @@ class ParameterizedEfferentModuleCouplingTest
330330
{};
331331

332332
std::vector<StringUintParam> paramEfferentModule = {
333-
{"%/test/sources/parser/module_a", 1},
333+
{"%/test/sources/parser/module_a", 1}, // B1
334334
{"%/test/sources/parser/module_b", 0},
335-
{"%/test/sources/parser/module_c", 2},
335+
{"%/test/sources/parser/module_c", 2}, // A2, B1
336+
{"%/test/sources/parser/module_d", 2}, // D1, D2
336337
};
337338

338339
TEST_P(ParameterizedEfferentModuleCouplingTest, ModuleEfferentTest) {
@@ -353,3 +354,36 @@ INSTANTIATE_TEST_SUITE_P(
353354
ParameterizedEfferentModuleCouplingTest,
354355
::testing::ValuesIn(paramEfferentModule)
355356
);
357+
358+
// Afferent coupling at module level
359+
360+
class ParameterizedAfferentModuleCouplingTest
361+
: public CppMetricsParserTest,
362+
public ::testing::WithParamInterface<StringUintParam>
363+
{};
364+
365+
std::vector<StringUintParam> paramAfferentModule = {
366+
{"%/test/sources/parser/module_a", 1}, // C2
367+
{"%/test/sources/parser/module_b", 3}, // A2, C1, C2
368+
{"%/test/sources/parser/module_c", 1}, // D1
369+
{"%/test/sources/parser/module_d", 0},
370+
};
371+
372+
TEST_P(ParameterizedAfferentModuleCouplingTest, ModuleAfferentTest) {
373+
_transaction([&, this]() {
374+
375+
typedef odb::query<model::CppModuleMetricsForPathView> CppModuleMetricsQuery;
376+
377+
const auto metric = _db->query_value<model::CppModuleMetricsForPathView>(
378+
CppModuleMetricsQuery::CppFileMetrics::type == model::CppFileMetrics::Type::AFFERENT_MODULE &&
379+
CppModuleMetricsQuery::File::path.like(GetParam().first));
380+
381+
EXPECT_EQ(GetParam().second, metric.value);
382+
});
383+
}
384+
385+
INSTANTIATE_TEST_SUITE_P(
386+
ParameterizedAfferentModuleCouplingTestSuite,
387+
ParameterizedAfferentModuleCouplingTest,
388+
::testing::ValuesIn(paramAfferentModule)
389+
);

0 commit comments

Comments
 (0)