(
testcase: DataDrivenTestCase, actual: list[str], *, incremental_step: int
)
| 19 | |
| 20 | |
| 21 | def _iter_fixes( |
| 22 | testcase: DataDrivenTestCase, actual: list[str], *, incremental_step: int |
| 23 | ) -> Iterator[DataFileFix]: |
| 24 | reports_by_line: dict[tuple[str, int], list[tuple[str, str]]] = defaultdict(list) |
| 25 | for error_line in actual: |
| 26 | comment_match = re.match( |
| 27 | r"^(?P<filename>[^:]+):(?P<lineno>\d+): (?P<severity>error|note|warning): (?P<msg>.+)$", |
| 28 | error_line, |
| 29 | ) |
| 30 | if comment_match: |
| 31 | filename = comment_match.group("filename") |
| 32 | lineno = int(comment_match.group("lineno")) |
| 33 | severity = comment_match.group("severity") |
| 34 | msg = comment_match.group("msg") |
| 35 | reports_by_line[filename, lineno].append((severity, msg)) |
| 36 | |
| 37 | test_items = parse_test_data(testcase.data, testcase.name) |
| 38 | |
| 39 | # If we have [out] and/or [outN], we update just those sections. |
| 40 | if any(re.match(r"^out\d*$", test_item.id) for test_item in test_items): |
| 41 | for test_item in test_items: |
| 42 | if (incremental_step < 2 and test_item.id == "out") or ( |
| 43 | incremental_step >= 2 and test_item.id == f"out{incremental_step}" |
| 44 | ): |
| 45 | yield DataFileFix( |
| 46 | lineno=testcase.line + test_item.line - 1, |
| 47 | end_lineno=testcase.line + test_item.end_line - 1, |
| 48 | lines=actual + [""] * test_item.trimmed_newlines, |
| 49 | ) |
| 50 | |
| 51 | return |
| 52 | |
| 53 | # Update assertion comments within the sections |
| 54 | for test_item in test_items: |
| 55 | if test_item.id == "case": |
| 56 | source_lines = test_item.data |
| 57 | file_path = "main" |
| 58 | elif test_item.id == "file": |
| 59 | source_lines = test_item.data |
| 60 | file_path = f"tmp/{test_item.arg}" |
| 61 | else: |
| 62 | continue # other sections we don't touch |
| 63 | |
| 64 | fix_lines = [] |
| 65 | for lineno, source_line in enumerate(source_lines, start=1): |
| 66 | reports = reports_by_line.get((file_path, lineno)) |
| 67 | comment_match = re.search(r"(?P<indent>\s+)(?P<comment># [EWN]: .+)$", source_line) |
| 68 | if comment_match: |
| 69 | source_line = source_line[: comment_match.start("indent")] # strip old comment |
| 70 | if reports: |
| 71 | indent = comment_match.group("indent") if comment_match else " " |
| 72 | # multiline comments are on the first line and then on subsequent lines empty lines |
| 73 | # with a continuation backslash |
| 74 | for j, (severity, msg) in enumerate(reports): |
| 75 | out_l = source_line if j == 0 else " " * len(source_line) |
| 76 | is_last = j == len(reports) - 1 |
| 77 | severity_char = severity[0].upper() |
| 78 | continuation = "" if is_last else " \\" |
no test coverage detected
searching dependent graphs…