|
3 | 3 | // found in the LICENSE file.
|
4 | 4 |
|
5 | 5 | import 'dart:async';
|
| 6 | +import 'dart:convert'; |
6 | 7 |
|
7 | 8 | import 'package:dds/dap.dart';
|
8 | 9 | import 'package:file/memory.dart';
|
9 | 10 | import 'package:flutter_tools/src/base/file_system.dart';
|
10 | 11 | import 'package:flutter_tools/src/base/platform.dart';
|
11 | 12 | import 'package:flutter_tools/src/cache.dart';
|
| 13 | +import 'package:flutter_tools/src/debug_adapters/error_formatter.dart'; |
12 | 14 | import 'package:flutter_tools/src/debug_adapters/flutter_adapter.dart';
|
13 | 15 | import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart';
|
14 | 16 | import 'package:flutter_tools/src/globals.dart' as globals show fs, platform;
|
@@ -797,6 +799,55 @@ void main() {
|
797 | 799 | expect(adapter.processArgs, contains('tool_args'));
|
798 | 800 | });
|
799 | 801 | });
|
| 802 | + |
| 803 | + group('error formatter', () { |
| 804 | + /// Helpers to build a string representation of the DAP OutputEvents for |
| 805 | + /// the structured error [errorData]. |
| 806 | + String getFormattedError(Map<String, Object?> errorData) { |
| 807 | + // Format the error and write into a buffer in a text format convenient |
| 808 | + // for test expectations. |
| 809 | + final StringBuffer buffer = StringBuffer(); |
| 810 | + FlutterErrorFormatter() |
| 811 | + ..formatError(errorData) |
| 812 | + ..sendOutput((String category, String message, {bool? parseStackFrames, int? variablesReference}) { |
| 813 | + buffer.writeln('${category.padRight(6)} ${jsonEncode(message)}'); |
| 814 | + }); |
| 815 | + return buffer.toString(); |
| 816 | + } |
| 817 | + |
| 818 | + test('includes children of DiagnosticsBlock when writing a summary', () { |
| 819 | + // Format a simulated error that nests the error-causing widget in a |
| 820 | + // diagnostic block and will be displayed in summary mode (because it |
| 821 | + // is not the first error since the last reload). |
| 822 | + // https://github.com/Dart-Code/Dart-Code/issues/4743 |
| 823 | + final String error = getFormattedError(<String, Object?>{ |
| 824 | + 'errorsSinceReload': 1, // Force summary mode |
| 825 | + 'description': 'Exception caught...', |
| 826 | + 'properties': <Map<String, Object?>>[ |
| 827 | + <String, Object>{ |
| 828 | + 'description': 'The following assertion was thrown...', |
| 829 | + }, |
| 830 | + <String, Object?>{ |
| 831 | + 'description': '', |
| 832 | + 'type': 'DiagnosticsBlock', |
| 833 | + 'name': 'The relevant error-causing widget was', |
| 834 | + 'children': <Map<String, Object>>[ |
| 835 | + <String, Object>{ |
| 836 | + 'description': 'MyWidget:file:///path/to/widget.dart:1:2', |
| 837 | + } |
| 838 | + ] |
| 839 | + } |
| 840 | + ], |
| 841 | + }); |
| 842 | + |
| 843 | + expect(error, r''' |
| 844 | +stdout "\n" |
| 845 | +stderr "════════ Exception caught... ═══════════════════════════════════════════════════\n" |
| 846 | +stdout "The relevant error-causing widget was:\n MyWidget:file:///path/to/widget.dart:1:2\n" |
| 847 | +stderr "════════════════════════════════════════════════════════════════════════════════\n" |
| 848 | +'''); |
| 849 | + }); |
| 850 | + }); |
800 | 851 | });
|
801 | 852 | }
|
802 | 853 |
|
|
0 commit comments