diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index dabbca02d..15008059c 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -185,23 +185,30 @@ void CppMetricsParser::typeMcCabe() if (!methodAstNode) continue; - // Lookup the definition (different AST node if not defined in class body) - const auto methodDef = _ctx.db->query_one( + // Lookup its definition (different AST node if not defined in class body) + auto methodDefs = _ctx.db->query( odb::query::entityHash == methodAstNode->entityHash && odb::query::symbolType == AstNode::SymbolType::Function && odb::query::astType == AstNode::AstType::Definition); - if (!methodDef) + if (methodDefs.empty()) continue; + const auto methodDef = *methodDefs.begin(); + // Note: we cannot use query_one, because a project might have multiple + // functions with the same entityHash compiled to different binaries + // So we take the first result, which introduces a small level of + // potential inaccuracy + // This could be optimized in the future if linkage information about + // translation units got added to the database // Skip implicitly defined methods (constructors, operator=, etc.) const auto entity = _ctx.db->query_one( - odb::query::astNodeId == methodDef->id); + odb::query::astNodeId == methodDef.id); if (entity && entity->tags.find(model::Tag::Implicit) != entity->tags.cend()) continue; // Lookup metrics of this definition const auto funcMetrics = _ctx.db->query_one( - odb::query::astNodeId == methodDef->id && + odb::query::astNodeId == methodDef.id && odb::query::type == model::CppAstNodeMetrics::Type::MCCABE); if (funcMetrics) {