| 330 | } |
| 331 | |
| 332 | CurrentCoverageRegions getCurrentCoverageRegions() |
| 333 | { |
| 334 | ensureCoverageMapLoaded(); |
| 335 | |
| 336 | auto name_refs = getCurrentCoveredNameRefs(); |
| 337 | |
| 338 | /// Collect unique (file, line_start, line_end) triples — same dedup logic as collectAndInsertCoverage. |
| 339 | struct LineKey |
| 340 | { |
| 341 | std::string file; |
| 342 | uint32_t line_start; |
| 343 | uint32_t line_end; |
| 344 | |
| 345 | bool operator==(const LineKey & o) const |
| 346 | { |
| 347 | return line_start == o.line_start && line_end == o.line_end && file == o.file; |
| 348 | } |
| 349 | }; |
| 350 | struct LineKeyHash |
| 351 | { |
| 352 | std::size_t operator()(const LineKey & k) const |
| 353 | { |
| 354 | std::size_t h = std::hash<std::string>{}(k.file); |
| 355 | h ^= std::hash<uint32_t>{}(k.line_start) + 0x9e3779b9u + (h << 6) + (h >> 2); |
| 356 | h ^= std::hash<uint32_t>{}(k.line_end) + 0x9e3779b9u + (h << 6) + (h >> 2); |
| 357 | return h; |
| 358 | } |
| 359 | }; |
| 360 | |
| 361 | std::unordered_map<LineKey, bool, LineKeyHash> seen; |
| 362 | seen.reserve(name_refs.size()); |
| 363 | |
| 364 | CurrentCoverageRegions out; |
| 365 | for (const auto & [name_hash, func_hash, counter_id, min_depth] : name_refs) |
| 366 | { |
| 367 | const auto it = g_coverage_map.find(CoverageKey{name_hash, func_hash, counter_id}); |
| 368 | if (it == g_coverage_map.end()) |
| 369 | continue; |
| 370 | |
| 371 | const CoverageRegion & region = it->second; |
| 372 | if (region.file.empty() || region.line_start == 0) |
| 373 | continue; |
| 374 | |
| 375 | LineKey key{region.file, region.line_start, region.line_end}; |
| 376 | if (!seen.emplace(key, true).second) |
| 377 | continue; |
| 378 | |
| 379 | out.files.push_back(region.file); |
| 380 | out.line_starts.push_back(region.line_start); |
| 381 | out.line_ends.push_back(region.line_end); |
| 382 | } |
| 383 | |
| 384 | return out; |
| 385 | } |
| 386 | |
| 387 | } |
| 388 |
no test coverage detected