Skip to content

Commit d622a9c

Browse files
authored
Merge pull request Ericsson#801 from mcserep/lackofcohesion-performance
Improve performance for Lack of Cohesion metric
2 parents b4f435c + 3447677 commit d622a9c

File tree

2 files changed

+64
-24
lines changed

2 files changed

+64
-24
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: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -315,36 +315,63 @@ 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
324-
: _ctx.db->query<model::CohesionCppMethodView>(
325-
QMethodTypeHash == type.entityHash
326-
))
324+
: _ctx.db->query<model::CohesionCppMethodView>(QMethodTypeHash == type.entityHash))
327325
{
328326
// Do not consider methods with no explicit bodies.
329327
const model::Position start(method.startLine, method.startColumn);
330328
const model::Position end(method.endLine, method.endColumn);
331-
if (start < end)
329+
if (!(start < end))
332330
{
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
331+
continue;
332+
}
333+
334+
methods.push_back(method);
335+
336+
// Query AST nodes that use a variable for reading or writing...
337+
nodeQuery = nodeQuery ||
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
343343
&& QNodeRange.start.column >= start.column)) &&
344-
(QNodeRange.end.line <= end.line
345-
|| (QNodeRange.end.line == end.line
346-
&& QNodeRange.end.column <= end.column)))
347-
))
344+
(QNodeRange.end.line < end.line
345+
|| (QNodeRange.end.line == end.line
346+
&& QNodeRange.end.column <= end.column)));
347+
}
348+
349+
// Query all nodes in a single operation.
350+
std::vector<model::CohesionCppAstNodeView> nodes;
351+
for (const model::CohesionCppAstNodeView& node: _ctx.db->query<model::CohesionCppAstNodeView>(nodeQuery))
352+
{
353+
nodes.push_back(node);
354+
}
355+
356+
// Counter variables.
357+
std::size_t fieldCount = fieldHashes.size();
358+
std::size_t methodCount = methods.size();
359+
std::size_t totalCohesion = 0;
360+
361+
// For each node, find the method it belongs to and check for field usage.
362+
for (const auto& method : methods) {
363+
model::Position start(method.startLine, method.startColumn);
364+
model::Position end(method.endLine, method.endColumn);
365+
366+
std::unordered_set<HashType> usedFields;
367+
368+
for (const auto& node : nodes) {
369+
// Filter AST nodes used in this method.
370+
if (node.filePath == method.filePath &&
371+
(node.startLine > start.line ||
372+
(node.startLine == start.line && node.startColumn >= start.column)) &&
373+
(node.endLine < end.line ||
374+
(node.endLine == end.line && node.endColumn <= end.column)))
348375
{
349376
// If this AST node is a reference to a field of the type...
350377
if (fieldHashes.find(node.entityHash) != fieldHashes.end())
@@ -353,10 +380,9 @@ void CppMetricsParser::lackOfCohesion()
353380
usedFields.insert(node.entityHash);
354381
}
355382
}
356-
357-
++methodCount;
358-
totalCohesion += usedFields.size();
359383
}
384+
385+
totalCohesion += usedFields.size();
360386
}
361387

362388
// Calculate and record metrics.

0 commit comments

Comments
 (0)