Skip to content

Commit e9b78eb

Browse files
committed
Improve performance for Lack of Cohesion metric.
1 parent b4f435c commit e9b78eb

File tree

2 files changed

+65
-23
lines changed

2 files changed

+65
-23
lines changed

plugins/cpp_metrics/model/include/model/cppcohesionmetrics.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,22 @@ struct CohesionCppMethodView
7474
|| CppAstNode::astType == cc::model::CppAstNode::AstType::Write) && (?))
7575
struct CohesionCppAstNodeView
7676
{
77+
typedef cc::model::Position::PosType PosType;
78+
7779
#pragma db column(CppAstNode::entityHash)
7880
std::uint64_t entityHash;
81+
82+
#pragma db column(CppAstNode::location.range.start.line)
83+
PosType startLine;
84+
#pragma db column(CppAstNode::location.range.start.column)
85+
PosType startColumn;
86+
#pragma db column(CppAstNode::location.range.end.line)
87+
PosType endLine;
88+
#pragma db column(CppAstNode::location.range.end.column)
89+
PosType endColumn;
90+
91+
#pragma db column(File::path)
92+
std::string filePath;
7993
};
8094

8195
} //model

plugins/cpp_metrics/parser/src/cppmetricsparser.cpp

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -315,36 +315,65 @@ void CppMetricsParser::lackOfCohesion()
315315
// Record these fields for later use.
316316
fieldHashes.insert(field.entityHash);
317317
}
318-
std::size_t fieldCount = fieldHashes.size();
319318

320-
std::size_t methodCount = 0;
321-
std::size_t totalCohesion = 0;
322319
// Query all methods of the current type.
320+
std::vector<model::CohesionCppMethodView> methods;
321+
// Build a query for variable access that within ANY of the methods.
322+
odb::query<model::CohesionCppAstNodeView> nodeQuery(false);
323323
for (const model::CohesionCppMethodView& method
324324
: _ctx.db->query<model::CohesionCppMethodView>(
325-
QMethodTypeHash == type.entityHash
326-
))
325+
QMethodTypeHash == type.entityHash
326+
))
327327
{
328328
// Do not consider methods with no explicit bodies.
329329
const model::Position start(method.startLine, method.startColumn);
330330
const model::Position end(method.endLine, method.endColumn);
331-
if (start < end)
331+
if (!(start < end))
332332
{
333-
std::unordered_set<HashType> usedFields;
334-
335-
// Query AST nodes that use a variable for reading or writing...
336-
for (const model::CohesionCppAstNodeView& node
337-
: _ctx.db->query<model::CohesionCppAstNodeView>(
338-
// ... in the same file as the current method
339-
(QNodeFilePath == method.filePath &&
340-
// ... within the textual scope of the current method's body.
341-
(QNodeRange.start.line >= start.line
342-
|| (QNodeRange.start.line == start.line
333+
continue;
334+
}
335+
336+
methods.push_back(method);
337+
338+
// Query AST nodes that use a variable for reading or writing...
339+
nodeQuery = nodeQuery ||
340+
// ... in the same file as the current method
341+
(QNodeFilePath == method.filePath &&
342+
// ... within the textual scope of the current method's body.
343+
(QNodeRange.start.line > start.line
344+
|| (QNodeRange.start.line == start.line
343345
&& QNodeRange.start.column >= start.column)) &&
344-
(QNodeRange.end.line <= end.line
345-
|| (QNodeRange.end.line == end.line
346-
&& QNodeRange.end.column <= end.column)))
347-
))
346+
(QNodeRange.end.line < end.line
347+
|| (QNodeRange.end.line == end.line
348+
&& QNodeRange.end.column <= end.column)));
349+
}
350+
351+
// Query all nodes in a single operation.
352+
std::vector<model::CohesionCppAstNodeView> nodes;
353+
for (const model::CohesionCppAstNodeView& node: _ctx.db->query<model::CohesionCppAstNodeView>(nodeQuery))
354+
{
355+
nodes.push_back(node);
356+
}
357+
358+
// Counter variables.
359+
std::size_t fieldCount = fieldHashes.size();
360+
std::size_t methodCount = methods.size();
361+
std::size_t totalCohesion = 0;
362+
363+
// For each node, find the method it belongs to and check for field usage.
364+
for (const auto& method : methods) {
365+
model::Position start(method.startLine, method.startColumn);
366+
model::Position end(method.endLine, method.endColumn);
367+
368+
std::unordered_set<HashType> usedFields;
369+
370+
for (const auto& node : nodes) {
371+
// Filter AST nodes used in this method.
372+
if (node.filePath == method.filePath &&
373+
(node.startLine > start.line ||
374+
(node.startLine == start.line && node.startColumn >= start.column)) &&
375+
(node.endLine < end.line ||
376+
(node.endLine == end.line && node.endColumn <= end.column)))
348377
{
349378
// If this AST node is a reference to a field of the type...
350379
if (fieldHashes.find(node.entityHash) != fieldHashes.end())
@@ -353,10 +382,9 @@ void CppMetricsParser::lackOfCohesion()
353382
usedFields.insert(node.entityHash);
354383
}
355384
}
356-
357-
++methodCount;
358-
totalCohesion += usedFields.size();
359385
}
386+
387+
totalCohesion += usedFields.size();
360388
}
361389

362390
// Calculate and record metrics.

0 commit comments

Comments
 (0)