prettyPrint function
Testing/Debug: pretty-print, dump iterable, assert equals with tolerance, range, repeat, timed. Roadmap #366-375.
Recursively renders obj as an indented, human-readable string for
debugging. Maps and lists are expanded over multiple lines; null becomes
'null' and any other value falls back to its toString(). indent sets
the starting nesting depth (two spaces per level).
Example:
prettyPrint({'a': 1, 'b': [2, 3]});
// {
// a: 1
// b: [
// 2,
// 3
// ]
// }
Implementation
/// Recursively renders [obj] as an indented, human-readable string for
/// debugging. Maps and lists are expanded over multiple lines; `null` becomes
/// `'null'` and any other value falls back to its `toString()`. [indent] sets
/// the starting nesting depth (two spaces per level).
///
/// Example:
/// ```dart
/// prettyPrint({'a': 1, 'b': [2, 3]});
/// // {
/// // a: 1
/// // b: [
/// // 2,
/// // 3
/// // ]
/// // }
/// ```
String prettyPrint(Object? obj, {int indent = 0}) {
const int spaces = 2;
final String pad = ' ' * (indent * spaces);
if (obj == null) return 'null';
if (obj is Map) {
if (obj.isEmpty) return '{}';
final List<String> parts = <String>[];
for (final MapEntry<dynamic, dynamic> e in obj.entries) {
parts.add('$pad${e.key}: ${prettyPrint(e.value, indent: indent + 1)}');
}
return '{\n${parts.join('\n')}\n$pad}';
}
if (obj is List) {
if (obj.isEmpty) return '[]';
final List<String> parts = obj.map((Object? e) => prettyPrint(e, indent: indent + 1)).toList();
return '[\n$pad${parts.join(',\n$pad')}\n$pad]';
}
return obj.toString();
}