formatTerminationReport function
Format a termination warning List as human-readable text. Built from a
line list joined with \n plus a trailing newline (reproducing
StringBuffer.writeln) so it self-hosts on the StringBuffer-less compiled
TS/C++/Rust CLIs.
Implementation
String formatTerminationReport(List warnings) {
final lines = <String>[];
lines.add('Termination Analysis');
lines.add('============================================================');
lines.add('');
if (warnings.isEmpty) {
lines.add('No issues found.');
return '${lines.join('\n')}\n';
}
// Group by category, preserving first-seen order.
final categoryOrder = <String>[];
final byCategory = <String, Object?>{};
for (final w in warnings) {
final cat = w['category'];
if (!byCategory.containsKey(cat)) {
categoryOrder.add(cat);
byCategory[cat] = <Object?>[];
}
final dynamic bucket = byCategory[cat];
bucket.add(w);
}
for (final cat in categoryOrder) {
final dynamic bucket = byCategory[cat];
lines.add('${_categoryLabel(cat)} (${bucket.length}):');
for (final w in bucket) {
final sev = w['severity'];
final icon = sev == 'error' ? '✖' : (sev == 'warning' ? '⚠' : 'ℹ');
lines.add(' $icon ${w['location']}: ${w['message']}');
}
lines.add('');
}
var errors = 0;
var warns = 0;
var infos = 0;
for (final w in warnings) {
final sev = w['severity'];
if (sev == 'error') errors++;
if (sev == 'warning') warns++;
if (sev == 'info') infos++;
}
lines.add('Total: $errors error(s), $warns warning(s), $infos info(s)');
return '${lines.join('\n')}\n';
}