Skip to content

Commit e2ef8cf

Browse files
authored
Pass app.started events to the DAP client + dart.debuggerUris for Profile mode (#106337)
1 parent 3c548dd commit e2ef8cf

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

packages/flutter_tools/lib/src/debug_adapters/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ Some custom requests are available for clients to call. Below are the Flutter-sp
7070

7171
The debug adapter may emit several custom events that are useful to clients. Below are the Flutter-specific custom events, and the standard Dart DAP custom events are [documented here](https://github.com/dart-lang/sdk/blob/main/pkg/dds/tool/dap/README.md#custom-events).
7272

73+
### `flutter.appStarted`
74+
75+
This event is emitted when the application has started up. Unlike `dart.debuggerUris`, this event occurs even for `noDebug` launches or those that do not include a VM Service.
76+
7377
### `flutter.serviceExtensionStateChanged`
7478

7579
When the value of a Flutter service extension changes, this event is emitted and includes the new value. Values are always encoded as strings, even if numeric/boolean.

packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,25 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
397397
/// Connects to the VM Service if the app.started event has fired, and a VM Service URI is available.
398398
void _connectDebuggerIfReady() {
399399
final Uri? serviceUri = _vmServiceUri;
400+
400401
if (_receivedAppStarted && serviceUri != null) {
401-
connectDebugger(serviceUri, resumeIfStarting: true);
402+
if (enableDebugger) {
403+
connectDebugger(serviceUri, resumeIfStarting: true);
404+
} else {
405+
// Usually, `connectDebugger` (in the base Dart adapter) will send this
406+
// event when it connects a debugger. Since we're not connecting a
407+
// debugger we send this ourselves, to allow clients to connect to the
408+
// VM Service for things like starting DevTools, even if debugging is
409+
// not available.
410+
// TODO(dantup): Switch this to call `sendDebuggerUris()` on the base
411+
// adapter once rolled into Flutter.
412+
sendEvent(
413+
RawEventBody(<String, Object?>{
414+
'vmServiceUri': serviceUri.toString(),
415+
}),
416+
eventType: 'dart.debuggerUris',
417+
);
418+
}
402419
}
403420
}
404421

@@ -412,6 +429,15 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
412429
void _handleAppStarted() {
413430
appStartedCompleter.complete();
414431
_connectDebuggerIfReady();
432+
433+
// Send a custom event so the editor knows the app has started.
434+
//
435+
// This may be useful when there's no VM Service (for example Profile mode)
436+
// but the editor still wants to know that startup has finished.
437+
sendEvent(
438+
RawEventBody(<String, Object?>{}),
439+
eventType: 'flutter.appStarted',
440+
);
415441
}
416442

417443
/// Handles the daemon.connected event, recording the pid of the flutter_tools process.
@@ -427,12 +453,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
427453

428454
/// Handles the app.debugPort event from Flutter, connecting to the VM Service if everything else is ready.
429455
void _handleDebugPort(Map<String, Object?> params) {
430-
// When running in noDebug mode, Flutter may still provide us a VM Service
431-
// URI, but we will not connect it because we don't want to do any debugging.
432-
if (!enableDebugger) {
433-
return;
434-
}
435-
436456
// Capture the VM Service URL which we'll connect to when we get app.started.
437457
final String? wsUri = params['wsUri'] as String?;
438458
if (wsUri != null) {

packages/flutter_tools/test/integration.shard/debug_adapter/flutter_adapter_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,24 @@ void main() {
302302

303303
await dap.client.terminate();
304304
});
305+
306+
testWithoutContext('provides appStarted events to the client', () async {
307+
final BasicProject project = BasicProject();
308+
await project.setUpIn(tempDir);
309+
310+
// Launch the app and wait for it to send a 'flutter.appStarted' event.
311+
await Future.wait(<Future<void>>[
312+
dap.client.event('flutter.appStarted'),
313+
dap.client.start(
314+
launch: () => dap.client.launch(
315+
cwd: project.dir.path,
316+
toolArgs: <String>['-d', 'flutter-tester'],
317+
),
318+
),
319+
], eagerError: true);
320+
321+
await dap.client.terminate();
322+
});
305323
});
306324

307325
group('attach', () {

0 commit comments

Comments
 (0)