Unverified Commit b39a9473 authored by Danny Tuppeny's avatar Danny Tuppeny Committed by GitHub

Handle Flutter.Error events and disable structure errors for noDebug mode (#100149)

parent 6ec0b835
...@@ -223,11 +223,29 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments ...@@ -223,11 +223,29 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
case 'Flutter.ServiceExtensionStateChanged': case 'Flutter.ServiceExtensionStateChanged':
_sendServiceExtensionStateChanged(event.extensionData); _sendServiceExtensionStateChanged(event.extensionData);
break; break;
case 'Flutter.Error':
_handleFlutterErrorEvent(event.extensionData);
break;
} }
break; break;
} }
} }
/// Sends OutputEvents to the client for a Flutter.Error event.
void _handleFlutterErrorEvent(vm.ExtensionData? data) {
final Map<String, dynamic>? errorData = data?.data;
if (errorData == null) {
return;
}
final String errorText = (errorData['renderedErrorText'] as String?)
?? (errorData['description'] as String?)
// We should never not error text, but if we do at least send something
// so it's not just completely silent.
?? 'Unknown error in Flutter.Error event';
sendOutput('stderr', '$errorText\n');
}
/// Called by [launchRequest] to request that we actually start the app to be run/debugged. /// Called by [launchRequest] to request that we actually start the app to be run/debugged.
/// ///
/// For debugging, this should start paused, connect to the VM Service, set /// For debugging, this should start paused, connect to the VM Service, set
...@@ -240,6 +258,12 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments ...@@ -240,6 +258,12 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
'run', 'run',
'--machine', '--machine',
if (enableDebugger) '--start-paused', if (enableDebugger) '--start-paused',
// Structured errors are enabled by default, but since we don't connect
// the VM Service for noDebug, we need to disable them so that error text
// is sent to stderr. Otherwise the user will not see any exception text
// (because nobody is listening for Flutter.Error events).
if (!enableDebugger)
'--dart-define=flutter.inspector.structuredErrors=false',
]; ];
await _startProcess( await _startProcess(
......
...@@ -115,6 +115,40 @@ void main() { ...@@ -115,6 +115,40 @@ void main() {
expect(output, contains('Exited (1)')); expect(output, contains('Exited (1)'));
}); });
/// Helper that tests exception output in either debug or noDebug mode.
Future<void> testExceptionOutput({required bool noDebug}) async {
final BasicProjectThatThrows project = BasicProjectThatThrows();
await project.setUpIn(tempDir);
final List<OutputEventBody> outputEvents =
await dap.client.collectAllOutput(launch: () {
// Terminate the app after we see the exception because otherwise
// it will keep running and `collectAllOutput` won't end.
dap.client.output
.firstWhere((String output) => output.contains(endOfErrorOutputMarker))
.then((_) => dap.client.terminate());
return dap.client.launch(
noDebug: noDebug,
cwd: project.dir.path,
toolArgs: <String>['-d', 'flutter-tester'],
);
});
final String output = _uniqueOutputLines(outputEvents);
final List<String> outputLines = output.split('\n');
expect( outputLines, containsAllInOrder(<String>[
'══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════',
'The following _Exception was thrown building App(dirty):',
'Exception: c',
'The relevant error-causing widget was:',
]));
expect(output, contains('App:${Uri.file(project.dir.path)}/lib/main.dart:24:12'));
}
testWithoutContext('correctly outputs exceptions in debug mode', () => testExceptionOutput(noDebug: false));
testWithoutContext('correctly outputs exceptions in noDebug mode', () => testExceptionOutput(noDebug: true));
testWithoutContext('can hot reload', () async { testWithoutContext('can hot reload', () async {
final BasicProject project = BasicProject(); final BasicProject project = BasicProject();
await project.setUpIn(tempDir); await project.setUpIn(tempDir);
......
...@@ -33,6 +33,9 @@ final bool useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true' ...@@ -33,6 +33,9 @@ final bool useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true'
/// Service traffic (wrapped in a custom 'dart.log' event). /// Service traffic (wrapped in a custom 'dart.log' event).
final bool verboseLogging = Platform.environment['DAP_TEST_VERBOSE'] == 'true'; final bool verboseLogging = Platform.environment['DAP_TEST_VERBOSE'] == 'true';
const String startOfErrorOutputMarker = '══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════';
const String endOfErrorOutputMarker = '════════════════════════════════════════════════════════════════════════════════════════════════════';
/// Expects the lines in [actual] to match the relevant matcher in [expected], /// Expects the lines in [actual] to match the relevant matcher in [expected],
/// ignoring differences in line endings and trailing whitespace. /// ignoring differences in line endings and trailing whitespace.
void expectLines( void expectLines(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment