diff --git a/plugins/cpp_metrics/model/CMakeLists.txt b/plugins/cpp_metrics/model/CMakeLists.txt index 38d8ca343..807776e24 100644 --- a/plugins/cpp_metrics/model/CMakeLists.txt +++ b/plugins/cpp_metrics/model/CMakeLists.txt @@ -5,7 +5,8 @@ include_directories( set(ODB_SOURCES include/model/cppastnodemetrics.h include/model/cppcohesionmetrics.h - include/model/cppfilemetrics.h) + include/model/cppfilemetrics.h + include/model/cppafferentmetrics.h) generate_odb_files("${ODB_SOURCES}" "cpp") diff --git a/plugins/cpp_metrics/model/include/model/cppafferentmetrics.h b/plugins/cpp_metrics/model/include/model/cppafferentmetrics.h new file mode 100644 index 000000000..25691d62b --- /dev/null +++ b/plugins/cpp_metrics/model/include/model/cppafferentmetrics.h @@ -0,0 +1,38 @@ +#ifndef CC_MODEL_AFFERENTMETRICS_H +#define CC_MODEL_AFFERENTMETRICS_H + +#include +#include +#include + +namespace cc +{ +namespace model +{ + #pragma db view \ + object(CppRecord) \ + object(CppAstNode : CppRecord::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) \ + object(CppMemberType : CppMemberType::memberAstNode) + struct AfferentRecordView + { + #pragma db column(CppEntity::entityHash) + std::size_t entityHash; + + #pragma db column(CppMemberType::typeHash) + std::size_t typeHash; + + #pragma db column(CppEntity::qualifiedName) + std::string qualifiedName; + + #pragma db column(CppEntity::astNodeId) + CppAstNodeId astNodeId; + + #pragma db column(File::path) + std::string filePath; + }; + +} //model +} //cc + +#endif //CC_MODEL_AFFERENTMETRICS_H diff --git a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h index e4c039e8c..68cac1a89 100644 --- a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h +++ b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h @@ -21,6 +21,7 @@ struct CppAstNodeMetrics BUMPY_ROAD = 4, LACK_OF_COHESION = 5, LACK_OF_COHESION_HS = 6, + AFFERENT_COUPLING = 7 }; #pragma db id auto diff --git a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h index 0991b96ad..0e6ae31d4 100644 --- a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h +++ b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h @@ -76,7 +76,8 @@ class CppMetricsParser : public AbstractParser // Calculate the lack of cohesion between member variables // and member functions for every type. void lackOfCohesion(); - + // Calculate afferent coupling metric bewteen types + void afferentCouplingTypeLevel(); /// @brief Constructs an ODB query that you can use to filter only /// the database records of the given parameter type whose path @@ -197,6 +198,7 @@ class CppMetricsParser : public AbstractParser static const int functionMcCabePartitionMultiplier = 5; static const int functionBumpyRoadPartitionMultiplier = 5; static const int lackOfCohesionPartitionMultiplier = 25; + static const int afferentCouplingPartitionMultiplier = 25; }; } // parser diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index a95501512..985bbfe66 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -98,6 +100,61 @@ bool CppMetricsParser::cleanupDatabase() return true; } + +void CppMetricsParser::afferentCouplingTypeLevel() +{ + + // Calculate the cohesion metric for all types on parallel threads. + parallelCalcMetric( + "Afferent coupling", + _threadCount * afferentCouplingPartitionMultiplier, // number of jobs; adjust for granularity + getFilterPathsQuery(), + [&, this](const MetricsTasks& tasks) + { + util::OdbTransaction{_ctx.db}([&,this] + { + std::set typesFound; + std::unordered_map typeFoundCnt; + std::unordered_map astNodeIdOfType; + + for (const model::AfferentRecordView& type + : _ctx.db->query()) + { + if (!cc::util::isRootedUnderAnyOf(_inputPaths, type.filePath)) + { + continue; + } + + typesFound.clear(); + for (const model::CppMemberType& member : _ctx.db->query( + odb::query::typeHash == type.entityHash && + odb::query::kind == model::CppMemberType::Kind::Field)) + { + typesFound.insert(member.memberTypeHash); + } + + astNodeIdOfType[type.typeHash] = type.astNodeId; + + for (const auto& t : typesFound) + { + typeFoundCnt[t]++; + } + } + + for (const auto& pair : typeFoundCnt) + { + model::CppAstNodeMetrics metric; + metric.astNodeId = astNodeIdOfType[pair.first]; + metric.type = model::CppAstNodeMetrics::Type::AFFERENT_COUPLING; + metric.value = pair.second; + _ctx.db->persist(metric); + } + + + }); + }); +} + void CppMetricsParser::functionParameters() { parallelCalcMetric( @@ -376,6 +433,8 @@ bool CppMetricsParser::parse() typeMcCabe(); LOG(info) << "[cppmetricsparser] Computing Lack of Cohesion metric for types."; lackOfCohesion(); + LOG(info) << "[cppmetricsparser] Computing Afferent Coupling metric for types."; + afferentCouplingTypeLevel(); return true; }