123set -euo pipefail45REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"6cd "${REPO_ROOT}"78workdir="$(mktemp -d "${TMPDIR:-/tmp}/haven-coverage.XXXXXX")"9cleanup() { trash "${workdir}"; }10trap cleanup EXIT1112swift test --enable-code-coverage1314binary=".build/debug/Haven"15test_profile=".build/debug/codecov/default.profdata"16smoke_profile="${workdir}/smoke.profraw"17merged_profile="${workdir}/merged.profdata"1819LLVM_PROFILE_FILE="${smoke_profile}" HAVEN_COVERAGE_SMOKE=1 "${binary}"20test -s "${smoke_profile}"21xcrun llvm-profdata merge -sparse "${test_profile}" "${smoke_profile}" -o "${merged_profile}"2223printf '\nLLVM aggregate report (compiler-generated mappings included):\n'24xcrun llvm-cov report "${binary}" \25 -instr-profile="${merged_profile}" \26 --ignore-filename-regex='(Tests|\\.build)'2728xcrun llvm-cov export "${binary}" \29 -instr-profile="${merged_profile}" \30 -format=text > "${workdir}/coverage.json"3132REPO_ROOT="${REPO_ROOT}" COVERAGE_JSON="${workdir}/coverage.json" python3 <<'PY'33import json34import os35from pathlib import Path3637repo_root = Path(os.environ["REPO_ROOT"]).resolve()38repo_prefix = f"{repo_root.as_posix().rstrip('/')}/"39coverage = json.loads(Path(os.environ["COVERAGE_JSON"]).read_text())4041covered = 042total = 043missed = []4445for entry in coverage["data"][0]["files"]:46 source_path = Path(entry["filename"]).resolve()47 source_text = source_path.as_posix()48 if not source_text.casefold().startswith(repo_prefix.casefold()):49 continue50 relative_path = Path(source_text[len(repo_prefix) :])51 if relative_path.parts[:2] != ("Sources", "Haven"):52 continue5354 source_lines = source_path.read_text().splitlines()55 line_counts = {}56 for segment in entry["segments"]:57 line, _, count, has_count, *_ = segment58 if has_count:59 line_counts[line] = max(line_counts.get(line, 0), count)6061 for line, count in sorted(line_counts.items()):62 if line > len(source_lines):63 continue64 text = source_lines[line - 1].strip()65 if (66 not text67 or text.startswith("//")68 or text.startswith("/*")69 or text.startswith("*")70 or text.startswith("*/")71 or not any(character.isalnum() for character in text)72 ):73 continue74 total += 175 if count > 0:76 covered += 177 else:78 missed.append(f"{relative_path}:{line}: {text}")7980print(f"\nPhysical repository source lines: {covered}/{total} covered")81if missed:82 print("Uncovered physical source lines:")83 print("\n".join(missed))84 raise SystemExit(1)85PY