@@ -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