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