Skip to content

Commit ec42ea0

Browse files
authored
Efferent coupling of types (#711)
1 parent 2b5a216 commit ec42ea0

6 files changed

Lines changed: 99 additions & 2 deletions

File tree

plugins/cpp/model/include/model/cppfunction.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,29 @@ struct CppFunctionBumpyRoad
9595
unsigned int statementCount;
9696
};
9797

98+
#pragma db view \
99+
object(CppFunction) \
100+
object(CppVariable = Parameters : CppFunction::parameters)
101+
struct CppFunctionParamTypeView
102+
{
103+
#pragma db column(CppFunction::astNodeId)
104+
CppAstNodeId astNodeId;
105+
106+
#pragma db column(Parameters::typeHash)
107+
std::uint64_t paramTypeHash;
108+
};
109+
110+
#pragma db view \
111+
object(CppFunction) \
112+
object(CppVariable = Locals : CppFunction::locals)
113+
struct CppFunctionLocalTypeView
114+
{
115+
#pragma db column(CppFunction::astNodeId)
116+
CppAstNodeId astNodeId;
117+
118+
#pragma db column(Locals::typeHash)
119+
std::uint64_t paramTypeHash;
120+
};
98121
}
99122
}
100123

plugins/cpp_metrics/model/include/model/cppastnodemetrics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct CppAstNodeMetrics
2222
BUMPY_ROAD = 4,
2323
LACK_OF_COHESION = 5,
2424
LACK_OF_COHESION_HS = 6,
25+
EFFERENT_TYPE = 7
2526
};
2627

2728
#pragma db id auto

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ class CppMetricsParser : public AbstractParser
7676
// Calculate the lack of cohesion between member variables
7777
// and member functions for every type.
7878
void lackOfCohesion();
79+
// Calculate the efferent coupling of types.
80+
void efferentTypeLevel();
7981

8082

8183
/// @brief Constructs an ODB query that you can use to filter only
@@ -197,6 +199,7 @@ class CppMetricsParser : public AbstractParser
197199
static const int functionMcCabePartitionMultiplier = 5;
198200
static const int functionBumpyRoadPartitionMultiplier = 5;
199201
static const int lackOfCohesionPartitionMultiplier = 25;
202+
static const int efferentCouplingTypesPartitionMultiplier = 5;
200203
};
201204

202205
} // parser

plugins/cpp_metrics/parser/src/cppmetricsparser.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <model/cppcohesionmetrics-odb.hxx>
77
#include <model/cppfilemetrics.h>
88
#include <model/cppfilemetrics-odb.hxx>
9+
#include <model/cppinheritance.h>
10+
#include <model/cppinheritance-odb.hxx>
911

1012
#include <model/cppastnode.h>
1113
#include <model/cppastnode-odb.hxx>
@@ -364,6 +366,68 @@ void CppMetricsParser::lackOfCohesion()
364366
});
365367
}
366368

369+
void CppMetricsParser::efferentTypeLevel()
370+
{
371+
parallelCalcMetric<model::CohesionCppRecordView>(
372+
"Efferent coupling of types",
373+
_threadCount * efferentCouplingTypesPartitionMultiplier,// number of jobs; adjust for granularity
374+
getFilterPathsQuery<model::CohesionCppRecordView>(),
375+
[&, this](const MetricsTasks<model::CohesionCppRecordView>& tasks)
376+
{
377+
util::OdbTransaction{_ctx.db}([&, this]
378+
{
379+
typedef odb::query<cc::model::CppMemberType> MemTypeQuery;
380+
typedef odb::query<cc::model::CppInheritanceCount> InheritanceQuery;
381+
typedef odb::query<cc::model::CppFunctionParamTypeView> ParamQuery;
382+
typedef odb::query<cc::model::CppFunctionLocalTypeView> LocalQuery;
383+
typedef odb::query<cc::model::CppFunction> FuncQuery;
384+
385+
std::set<std::uint64_t> dependentTypes;
386+
for (const model::CohesionCppRecordView& type : tasks)
387+
{
388+
dependentTypes.clear();
389+
390+
// Count parent types
391+
auto inheritanceView = _ctx.db->query<model::CppInheritanceCount>(
392+
InheritanceQuery::derived == type.entityHash);
393+
394+
// Count unique attribute types
395+
// and unique types in function parameters and local variables
396+
for (const model::CppMemberType& mem: _ctx.db->query<model::CppMemberType>(
397+
MemTypeQuery::typeHash == type.entityHash))
398+
{
399+
auto funcAstNodeId = mem.memberAstNode.load()->id;
400+
401+
if (mem.kind == cc::model::CppMemberType::Field)
402+
{
403+
dependentTypes.insert(mem.memberTypeHash);
404+
}
405+
else
406+
{
407+
for (const auto& param: _ctx.db->query<model::CppFunctionParamTypeView>(
408+
FuncQuery::astNodeId == funcAstNodeId))
409+
{
410+
dependentTypes.insert(param.paramTypeHash);
411+
}
412+
413+
for (const auto& local: _ctx.db->query<model::CppFunctionLocalTypeView>(
414+
FuncQuery::astNodeId == funcAstNodeId))
415+
{
416+
dependentTypes.insert(local.paramTypeHash);
417+
}
418+
}
419+
}
420+
421+
model::CppAstNodeMetrics metric;
422+
metric.astNodeId = type.astNodeId;
423+
metric.type = model::CppAstNodeMetrics::Type::EFFERENT_TYPE;
424+
metric.value = inheritanceView.begin()->count + dependentTypes.size();
425+
_ctx.db->persist(metric);
426+
}
427+
});
428+
});
429+
}
430+
367431
bool CppMetricsParser::parse()
368432
{
369433
LOG(info) << "[cppmetricsparser] Computing function parameter count metric.";
@@ -376,6 +440,8 @@ bool CppMetricsParser::parse()
376440
typeMcCabe();
377441
LOG(info) << "[cppmetricsparser] Computing Lack of Cohesion metric for types.";
378442
lackOfCohesion();
443+
LOG(info) << "[cppmetricsparser] Computing efferent coupling metric for types.";
444+
efferentTypeLevel();
379445
return true;
380446
}
381447

plugins/cpp_metrics/service/cxxmetrics.thrift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ enum CppAstNodeMetricsType
1212
BumpyRoad = 4,
1313
LackOfCohesion = 5,
1414
LackOfCohesionHS = 6,
15+
EfferentType = 7
1516
}
1617

1718
enum CppModuleMetricsType

plugins/cpp_metrics/service/src/cppmetricsservice.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ void CppMetricsServiceHandler::getCppAstNodeMetricsTypeNames(
5353
typeName.type = CppAstNodeMetricsType::LackOfCohesionHS;
5454
typeName.name = "Lack of cohesion of type (Henderson-Sellers variant)";
5555
_return.push_back(typeName);
56+
57+
typeName.type = CppAstNodeMetricsType::EfferentType;
58+
typeName.name = "Efferent coupling of type";
59+
_return.push_back(typeName);
5660
}
5761

5862
void CppMetricsServiceHandler::getCppModuleMetricsTypeNames(
@@ -194,9 +198,8 @@ void CppMetricsServiceHandler::getCppAstNodeMetricsDetailedForPath(
194198
metric.astValue = node.astValue;
195199
metric.symbolType = cc::model::symbolTypeToString(node.symbolType);
196200
metric.astType = cc::model::astTypeToString(node.astType);
201+
metric.metrics.insert(pair);
197202

198-
std::map<CppAstNodeMetricsType::type, double> metricsList;
199-
metricsList.insert(pair);
200203
_return.insert(std::make_pair(std::to_string(node.astNodeId), metric));
201204
}
202205
}

0 commit comments

Comments
 (0)