focus-flow/tool/check_coverage.dart

92 lines
2.7 KiB
Dart

// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Runs the Check Coverage workspace validation tool.
library;
import 'dart:io';
/// Checks an LCOV report against a package-library coverage threshold.
void main(List<String> arguments) {
if (arguments.length != 2) {
stderr.writeln('Usage: dart run tool/check_coverage.dart <lcov> <percent>');
exitCode = 64;
return;
}
final lcovFile = File(arguments[0]);
final threshold = double.tryParse(arguments[1]);
if (threshold == null) {
stderr.writeln('Coverage threshold must be numeric: ${arguments[1]}');
exitCode = 64;
return;
}
if (!lcovFile.existsSync()) {
stderr.writeln('Coverage file not found: ${lcovFile.path}');
exitCode = 1;
return;
}
final coverage = _readCoverage(lcovFile);
if (coverage.totalLines == 0) {
stderr.writeln('Coverage file has no package lib/ lines.');
exitCode = 1;
return;
}
final percent = coverage.percent;
stdout.writeln(
'Package lib coverage: ${percent.toStringAsFixed(2)}% '
'(${coverage.coveredLines}/${coverage.totalLines})',
);
if (percent < threshold) {
stderr.writeln(
'Coverage ${percent.toStringAsFixed(2)}% is below '
'${threshold.toStringAsFixed(2)}%.',
);
exitCode = 1;
}
}
/// Runs the `this operation` top-level operation.
/// This function is part of the file-level API and gives callers a direct way to use the associated scheduler behavior.
({int coveredLines, int totalLines, double percent}) _readCoverage(File file) {
var includeFile = false;
var coveredLines = 0;
var totalLines = 0;
for (final line in file.readAsLinesSync()) {
if (line.startsWith('SF:')) {
includeFile = _includeSourceFile(line.substring(3));
continue;
}
if (!includeFile || !line.startsWith('DA:')) {
continue;
}
final comma = line.indexOf(',');
if (comma == -1) {
continue;
}
totalLines += 1;
final hits = int.tryParse(line.substring(comma + 1).split(',').first) ?? 0;
if (hits > 0) {
coveredLines += 1;
}
}
final percent = totalLines == 0 ? 0.0 : coveredLines * 100 / totalLines;
return (
coveredLines: coveredLines,
totalLines: totalLines,
percent: percent,
);
}
/// Top-level helper that performs the `_includeSourceFile` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
bool _includeSourceFile(String path) {
final normalized = path.replaceAll('\\', '/');
return normalized.contains('/packages/') &&
normalized.contains('/lib/') &&
!normalized.endsWith('.g.dart');
}