Skip to content

Commit

Permalink
Efferent coupling of types (#711)
Browse files Browse the repository at this point in the history
  • Loading branch information
intjftw authored Aug 30, 2024
1 parent 2b5a216 commit ec42ea0
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 2 deletions.
23 changes: 23 additions & 0 deletions plugins/cpp/model/include/model/cppfunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,29 @@ struct CppFunctionBumpyRoad
unsigned int statementCount;
};

#pragma db view \
object(CppFunction) \
object(CppVariable = Parameters : CppFunction::parameters)
struct CppFunctionParamTypeView
{
#pragma db column(CppFunction::astNodeId)
CppAstNodeId astNodeId;

#pragma db column(Parameters::typeHash)
std::uint64_t paramTypeHash;
};

#pragma db view \
object(CppFunction) \
object(CppVariable = Locals : CppFunction::locals)
struct CppFunctionLocalTypeView
{
#pragma db column(CppFunction::astNodeId)
CppAstNodeId astNodeId;

#pragma db column(Locals::typeHash)
std::uint64_t paramTypeHash;
};
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct CppAstNodeMetrics
BUMPY_ROAD = 4,
LACK_OF_COHESION = 5,
LACK_OF_COHESION_HS = 6,
EFFERENT_TYPE = 7
};

#pragma db id auto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class CppMetricsParser : public AbstractParser
// Calculate the lack of cohesion between member variables
// and member functions for every type.
void lackOfCohesion();
// Calculate the efferent coupling of types.
void efferentTypeLevel();


/// @brief Constructs an ODB query that you can use to filter only
Expand Down Expand Up @@ -197,6 +199,7 @@ class CppMetricsParser : public AbstractParser
static const int functionMcCabePartitionMultiplier = 5;
static const int functionBumpyRoadPartitionMultiplier = 5;
static const int lackOfCohesionPartitionMultiplier = 25;
static const int efferentCouplingTypesPartitionMultiplier = 5;
};

} // parser
Expand Down
66 changes: 66 additions & 0 deletions plugins/cpp_metrics/parser/src/cppmetricsparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <model/cppcohesionmetrics-odb.hxx>
#include <model/cppfilemetrics.h>
#include <model/cppfilemetrics-odb.hxx>
#include <model/cppinheritance.h>
#include <model/cppinheritance-odb.hxx>

#include <model/cppastnode.h>
#include <model/cppastnode-odb.hxx>
Expand Down Expand Up @@ -364,6 +366,68 @@ void CppMetricsParser::lackOfCohesion()
});
}

void CppMetricsParser::efferentTypeLevel()
{
parallelCalcMetric<model::CohesionCppRecordView>(
"Efferent coupling of types",
_threadCount * efferentCouplingTypesPartitionMultiplier,// number of jobs; adjust for granularity
getFilterPathsQuery<model::CohesionCppRecordView>(),
[&, this](const MetricsTasks<model::CohesionCppRecordView>& tasks)
{
util::OdbTransaction{_ctx.db}([&, this]
{
typedef odb::query<cc::model::CppMemberType> MemTypeQuery;
typedef odb::query<cc::model::CppInheritanceCount> InheritanceQuery;
typedef odb::query<cc::model::CppFunctionParamTypeView> ParamQuery;
typedef odb::query<cc::model::CppFunctionLocalTypeView> LocalQuery;
typedef odb::query<cc::model::CppFunction> FuncQuery;

std::set<std::uint64_t> dependentTypes;
for (const model::CohesionCppRecordView& type : tasks)
{
dependentTypes.clear();

// Count parent types
auto inheritanceView = _ctx.db->query<model::CppInheritanceCount>(
InheritanceQuery::derived == type.entityHash);

// Count unique attribute types
// and unique types in function parameters and local variables
for (const model::CppMemberType& mem: _ctx.db->query<model::CppMemberType>(
MemTypeQuery::typeHash == type.entityHash))
{
auto funcAstNodeId = mem.memberAstNode.load()->id;

if (mem.kind == cc::model::CppMemberType::Field)
{
dependentTypes.insert(mem.memberTypeHash);
}
else
{
for (const auto& param: _ctx.db->query<model::CppFunctionParamTypeView>(
FuncQuery::astNodeId == funcAstNodeId))
{
dependentTypes.insert(param.paramTypeHash);
}

for (const auto& local: _ctx.db->query<model::CppFunctionLocalTypeView>(
FuncQuery::astNodeId == funcAstNodeId))
{
dependentTypes.insert(local.paramTypeHash);
}
}
}

model::CppAstNodeMetrics metric;
metric.astNodeId = type.astNodeId;
metric.type = model::CppAstNodeMetrics::Type::EFFERENT_TYPE;
metric.value = inheritanceView.begin()->count + dependentTypes.size();
_ctx.db->persist(metric);
}
});
});
}

bool CppMetricsParser::parse()
{
LOG(info) << "[cppmetricsparser] Computing function parameter count metric.";
Expand All @@ -376,6 +440,8 @@ bool CppMetricsParser::parse()
typeMcCabe();
LOG(info) << "[cppmetricsparser] Computing Lack of Cohesion metric for types.";
lackOfCohesion();
LOG(info) << "[cppmetricsparser] Computing efferent coupling metric for types.";
efferentTypeLevel();
return true;
}

Expand Down
1 change: 1 addition & 0 deletions plugins/cpp_metrics/service/cxxmetrics.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ enum CppAstNodeMetricsType
BumpyRoad = 4,
LackOfCohesion = 5,
LackOfCohesionHS = 6,
EfferentType = 7
}

enum CppModuleMetricsType
Expand Down
7 changes: 5 additions & 2 deletions plugins/cpp_metrics/service/src/cppmetricsservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ void CppMetricsServiceHandler::getCppAstNodeMetricsTypeNames(
typeName.type = CppAstNodeMetricsType::LackOfCohesionHS;
typeName.name = "Lack of cohesion of type (Henderson-Sellers variant)";
_return.push_back(typeName);

typeName.type = CppAstNodeMetricsType::EfferentType;
typeName.name = "Efferent coupling of type";
_return.push_back(typeName);
}

void CppMetricsServiceHandler::getCppModuleMetricsTypeNames(
Expand Down Expand Up @@ -194,9 +198,8 @@ void CppMetricsServiceHandler::getCppAstNodeMetricsDetailedForPath(
metric.astValue = node.astValue;
metric.symbolType = cc::model::symbolTypeToString(node.symbolType);
metric.astType = cc::model::astTypeToString(node.astType);
metric.metrics.insert(pair);

std::map<CppAstNodeMetricsType::type, double> metricsList;
metricsList.insert(pair);
_return.insert(std::make_pair(std::to_string(node.astNodeId), metric));
}
}
Expand Down

0 comments on commit ec42ea0

Please sign in to comment.