• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from __future__ import annotations
2
3from typing import NamedTuple
4
5
6class LlvmCoverageSegment(NamedTuple):
7    line: int
8    col: int
9    segment_count: int
10    has_count: int
11    is_region_entry: int
12    is_gap_entry: int | None
13
14    @property
15    def has_coverage(self) -> bool:
16        return self.segment_count > 0
17
18    @property
19    def is_executable(self) -> bool:
20        return self.has_count > 0
21
22    def get_coverage(
23        self, prev_segment: LlvmCoverageSegment
24    ) -> tuple[list[int], list[int]]:
25        # Code adapted from testpilot.testinfra.runners.gtestcoveragerunner.py
26        if not prev_segment.is_executable:
27            return [], []
28
29        # this segment ends at the line if col == 1
30        # (so segment effectively ends on the line) and
31        # line+1 if col is > 1 (so it touches at least some part of last line).
32        end_of_segment = self.line if self.col == 1 else self.line + 1
33        lines_range = list(range(prev_segment.line, end_of_segment))
34        return (lines_range, []) if prev_segment.has_coverage else ([], lines_range)
35
36
37def parse_segments(raw_segments: list[list[int]]) -> list[LlvmCoverageSegment]:
38    """
39    Creates LlvmCoverageSegment from a list of lists in llvm export json.
40    each segment is represented by 5-element array.
41    """
42    ret: list[LlvmCoverageSegment] = []
43    for raw_segment in raw_segments:
44        assert (
45            len(raw_segment) == 5 or len(raw_segment) == 6
46        ), "list is not compatible with llvmcom export:"
47        " Expected to have 5 or 6 elements"
48        if len(raw_segment) == 5:
49            ret.append(
50                LlvmCoverageSegment(
51                    raw_segment[0],
52                    raw_segment[1],
53                    raw_segment[2],
54                    raw_segment[3],
55                    raw_segment[4],
56                    None,
57                )
58            )
59        else:
60            ret.append(LlvmCoverageSegment(*raw_segment))
61
62    return ret
63