From 3c305487607bc997f4308df4e8f8a85557bf82eb Mon Sep 17 00:00:00 2001 From: David Morgan Date: Tue, 12 Aug 2025 17:56:35 +0200 Subject: [PATCH] Make failure logs more prominent. --- .../lib/src/generate/build_definition.dart | 5 -- .../lib/src/logging/ansi_buffer.dart | 7 ++- .../lib/src/logging/build_log.dart | 20 +++++-- .../lib/src/logging/build_log_messages.dart | 52 ++++++++++++++----- .../logging/build_log_console_mode_test.dart | 33 ++++++------ .../test/logging/build_log_messages_test.dart | 17 +++--- 6 files changed, 89 insertions(+), 45 deletions(-) diff --git a/build_runner_core/lib/src/generate/build_definition.dart b/build_runner_core/lib/src/generate/build_definition.dart index 9f4ce4491..3635d82a2 100644 --- a/build_runner_core/lib/src/generate/build_definition.dart +++ b/build_runner_core/lib/src/generate/build_definition.dart @@ -212,11 +212,6 @@ class _Loader { RunnerAssetWriter writer, ) async { if (conflictingAssets.isEmpty) return; - - buildLog.info( - 'Deleting ${conflictingAssets.length} declared outputs ' - 'which already existed on disk.', - ); await Future.wait(conflictingAssets.map((id) => writer.delete(id))); } } diff --git a/build_runner_core/lib/src/logging/ansi_buffer.dart b/build_runner_core/lib/src/logging/ansi_buffer.dart index d73ca14f9..0f88455d1 100644 --- a/build_runner_core/lib/src/logging/ansi_buffer.dart +++ b/build_runner_core/lib/src/logging/ansi_buffer.dart @@ -14,6 +14,7 @@ class AnsiBuffer { static const String nbsp = '\u00A0'; static const reset = '\x1B[0m'; static const bold = '\x1B[1m'; + static const boldRed = '\x1B[1;31m'; static const _nbspCodeUnit = 0xA0; static const _spaceCodeUnit = 32; @@ -127,7 +128,7 @@ class AnsiBuffer { /// Removes all ANSI constants from [string], for testing. static String removeAnsi(String string) => - string.replaceAll(reset, '').replaceAll(bold, ''); + string.replaceAll(reset, '').replaceAll(bold, '').replaceAll(boldRed, ''); } /// A line for writing to an [AnsiBuffer]. @@ -167,7 +168,9 @@ class AnsiBufferLine { } bool _isAnsi(String item) => - item == AnsiBuffer.reset || item == AnsiBuffer.bold; + item == AnsiBuffer.reset || + item == AnsiBuffer.bold || + item == AnsiBuffer.boldRed; bool get _showingAnsi => buildLog.configuration.forceAnsiConsoleForTesting ?? diff --git a/build_runner_core/lib/src/logging/build_log.dart b/build_runner_core/lib/src/logging/build_log.dart index cd851a49c..8edc68f27 100644 --- a/build_runner_core/lib/src/logging/build_log.dart +++ b/build_runner_core/lib/src/logging/build_log.dart @@ -419,7 +419,11 @@ class BuildLog { _display.block(render()); _display.flush(); } else { - _display.message(Severity.info, _status.join('')); + _display.message( + Severity.info, + // Removes ANSI codes if necessary. + AnsiBufferLine(_status).toString(), + ); } } @@ -498,14 +502,22 @@ class BuildLog { if (displayedProgressEntries.isNotEmpty) { result.writeLine([]); } + + final renderedMessages = _messages.render(); + if (renderedMessages.warningLines.isNotEmpty) { + for (final line in renderedMessages.warningLines) { + result.write(line); + } + result.writeEmptyLine(); + } + if (_status.isNotEmpty) { result.writeLine(_status); } - final renderedMessages = _messages.render(); - if (renderedMessages.isNotEmpty) { + if (renderedMessages.errorLines.isNotEmpty) { result.writeEmptyLine(); - for (final line in renderedMessages) { + for (final line in renderedMessages.errorLines) { result.write(line); } } diff --git a/build_runner_core/lib/src/logging/build_log_messages.dart b/build_runner_core/lib/src/logging/build_log_messages.dart index 2e1a8e321..45e6e3798 100644 --- a/build_runner_core/lib/src/logging/build_log_messages.dart +++ b/build_runner_core/lib/src/logging/build_log_messages.dart @@ -51,8 +51,8 @@ class BuildLogMessages { bool hasMessages({required String? phaseName}) => _phaseNamesWithMessages.contains(phaseName); - List render() { - final result = []; + RenderResult render() { + final result = RenderResult(); final buildRunnerCategories = >>[]; for (final entry in _messageByCategory.entries) { @@ -72,40 +72,50 @@ class BuildLogMessages { return result; } - List _renderCategory( + RenderResult _renderCategory( MapEntry<_MessageCategory, List> entry, ) { - final result = []; final category = entry.key; final context = category.context; + + final messages = _messageByCategory[category]!; + final failed = messages.any( + (message) => message.severity == Severity.error, + ); + + final result = []; result.add( AnsiBufferLine([ - 'log output for ', - AnsiBuffer.bold, - category.phaseName ?? 'build_runner', - AnsiBuffer.reset, if (context != null) ...[ - ' on ', - AnsiBuffer.bold, + failed ? AnsiBuffer.boldRed : AnsiBuffer.bold, context, AnsiBuffer.reset, + ' ', ], + AnsiBuffer.bold, + category.phaseName ?? 'build_runner', + AnsiBuffer.reset, ]), ); - for (final message in _messageByCategory[category]!) { + for (final message in messages) { var first = true; for (final line in message.text.split('\n')) { result.add( AnsiBufferLine([ + if (message.severity == Severity.error) AnsiBuffer.boldRed, first ? message.severity.prefix : ' ', + if (message.severity == Severity.error) AnsiBuffer.reset, line, ], hangingIndent: 2), ); first = false; } } - return result; + + return failed + ? RenderResult.failed(result) + : RenderResult.succeeded(result); } } @@ -177,3 +187,21 @@ enum Severity { Severity.error => 'E ', }; } + +class RenderResult { + final List warningLines; + final List errorLines; + + RenderResult() : warningLines = [], errorLines = []; + RenderResult.failed(List lines) + : errorLines = lines, + warningLines = []; + RenderResult.succeeded(List lines) + : warningLines = lines, + errorLines = []; + + void addAll(RenderResult other) { + warningLines.addAll(other.warningLines); + errorLines.addAll(other.errorLines); + } +} diff --git a/build_runner_core/test/logging/build_log_console_mode_test.dart b/build_runner_core/test/logging/build_log_console_mode_test.dart index 08a676cc1..682fc6e7d 100644 --- a/build_runner_core/test/logging/build_log_console_mode_test.dart +++ b/build_runner_core/test/logging/build_log_console_mode_test.dart @@ -62,7 +62,7 @@ columns because it will not fit.'''), padLinesRight(''' Some setup. -log output for build_runner +build_runner Some info. W A warning. W Another warning. @@ -238,15 +238,16 @@ Building, full build.'''), 0s builder1 on 10 inputs; pkg|lib/l0.dart 0s builder2 on 15 inputs -Building, full build. - -log output for builder1 on lib/l0.dart +lib/l0.dart builder1 Some info. Some more info. -log output for builder2 on lib/l1.dart + +Building, full build. + +lib/l1.dart builder2 W A warning. E An error. -log output for builder2 on lib/l3.dart +lib/l3.dart builder2 E An error.'''), ); @@ -275,17 +276,18 @@ E An error.'''), 0s builder2 on 15 inputs 0s builder1 (lazy): 1 no-op -Building, full build. - -log output for builder1 on lib/l0.dart +lib/l0.dart builder1 Some info. Some more info. -log output for builder2 on lib/l1.dart + +Building, full build. + +lib/l1.dart builder2 W A warning. E An error. -log output for builder2 on lib/l3.dart +lib/l3.dart builder2 E An error. -log output for builder1 (lazy) on lib/l3.dart +lib/l3.dart builder1 (lazy) E An error.'''), ); }); @@ -343,11 +345,12 @@ E An error.'''), 0s builder1 on 1 input: 1 output 0s builder2 on 1 input: 1 output +lib/l0.dart builder1 + Some info. + Built with build_runner in 0s with warnings; wrote 2 outputs. -log output for builder1 on lib/l0.dart - Some info. -log output for builder2 on lib/l0.dart +lib/l0.dart builder2 W A warning. E An error.'''), ); diff --git a/build_runner_core/test/logging/build_log_messages_test.dart b/build_runner_core/test/logging/build_log_messages_test.dart index 4cbebbc2c..bc27d1aff 100644 --- a/build_runner_core/test/logging/build_log_messages_test.dart +++ b/build_runner_core/test/logging/build_log_messages_test.dart @@ -95,19 +95,22 @@ void main() { context: 'file1', severity: Severity.info, ); - expect(messages.render().map((l) => l.toString()).toList(), [ - 'log output for phase1 on file1', - 'E message1', - 'W message3', - 'log output for phase2 on file1', + final rendered = messages.render(); + expect(rendered.warningLines.map((l) => l.toString()).toList(), [ + 'file1 phase2', ' message2', ' message6', - 'log output for phase1 on file2', + 'file2 phase1', ' message4', - 'log output for build_runner', + 'build_runner', 'W message0', ' message5', ]); + expect(rendered.errorLines.map((l) => l.toString()).toList(), [ + 'file1 phase1', + 'E message1', + 'W message3', + ]); }); }); }