@@ -6,69 +6,35 @@ import 'dart:async';
6
6
import 'dart:math' as math;
7
7
8
8
import 'package:dds/dap.dart' hide PidTracker;
9
- import 'package:meta/meta.dart' ;
10
9
import 'package:vm_service/vm_service.dart' as vm;
11
10
12
- import '../base/file_system.dart' ;
13
11
import '../base/io.dart' ;
14
- import '../base/platform.dart' ;
15
12
import '../cache.dart' ;
16
13
import '../convert.dart' ;
17
14
import 'flutter_adapter_args.dart' ;
18
- import 'mixins .dart' ;
15
+ import 'flutter_base_adapter .dart' ;
19
16
20
17
/// A DAP Debug Adapter for running and debugging Flutter applications.
21
- class FlutterDebugAdapter extends DartDebugAdapter <FlutterLaunchRequestArguments , FlutterAttachRequestArguments >
22
- with PidTracker , FlutterAdapter {
18
+ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
23
19
FlutterDebugAdapter (
24
20
super .channel, {
25
- required this .fileSystem,
26
- required this .platform,
21
+ required super .fileSystem,
22
+ required super .platform,
27
23
super .ipv6,
28
- bool enableDds = true ,
24
+ super .enableFlutterDds = true ,
29
25
super .enableAuthCodes,
30
26
super .logger,
31
27
super .onError,
32
- }) : _enableDds = enableDds,
33
- flutterSdkRoot = Cache .flutterRoot! ,
34
- // Always disable in the DAP layer as it's handled in the spawned
35
- // 'flutter' process.
36
- super (enableDds: false ) {
37
- configureOrgDartlangSdkMappings ();
38
- }
39
-
40
- @override
41
- FileSystem fileSystem;
42
- Platform platform;
43
- Process ? _process;
44
-
45
- @override
46
- final String flutterSdkRoot;
47
-
48
- /// Whether DDS should be enabled in the Flutter process.
49
- ///
50
- /// We never enable DDS in the DAP process for Flutter, so this value is not
51
- /// the same as what is passed to the base class, which is always provided 'false'.
52
- final bool _enableDds;
53
-
54
- @override
55
- final FlutterLaunchRequestArguments Function (Map <String , Object ?> obj)
56
- parseLaunchArgs = FlutterLaunchRequestArguments .fromJson;
57
-
58
- @override
59
- final FlutterAttachRequestArguments Function (Map <String , Object ?> obj)
60
- parseAttachArgs = FlutterAttachRequestArguments .fromJson;
28
+ });
61
29
62
30
/// A completer that completes when the app.started event has been received.
63
- @visibleForTesting
64
- final Completer <void > appStartedCompleter = Completer <void >();
31
+ final Completer <void > _appStartedCompleter = Completer <void >();
65
32
66
33
/// Whether or not the app.started event has been received.
67
- bool get _receivedAppStarted => appStartedCompleter .isCompleted;
34
+ bool get _receivedAppStarted => _appStartedCompleter .isCompleted;
68
35
69
36
/// The appId of the current running Flutter app.
70
- @visibleForTesting
71
- String ? appId;
37
+ String ? _appId;
72
38
73
39
/// The ID to use for the next request sent to the Flutter run daemon.
74
40
int _flutterRequestId = 1 ;
@@ -84,13 +50,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
84
50
@override
85
51
bool get supportsRestartRequest => true ;
86
52
87
- /// Whether the VM Service closing should be used as a signal to terminate the debug session.
88
- ///
89
- /// Since we always have a process for Flutter (whether run or attach) we'll
90
- /// always use its termination instead, so this is always false.
91
- @override
92
- bool get terminateOnVmServiceClose => false ;
93
-
94
53
/// Whether or not the user requested debugging be enabled.
95
54
///
96
55
/// For debugging to be enabled, the user must have chosen "Debug" (and not
@@ -104,17 +63,8 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
104
63
/// functionality (breakpoints, evaluation, etc.) will not be available.
105
64
/// Functionality provided via the daemon (hot reload/restart) will still be
106
65
/// available.
107
- bool get enableDebugger {
108
- final DartCommonLaunchAttachRequestArguments args = this .args;
109
- if (args is FlutterLaunchRequestArguments ) {
110
- // Invert DAP's noDebug flag, treating it as false (so _do_ debug) if not
111
- // provided.
112
- return ! (args.noDebug ?? false ) && ! profileMode && ! releaseMode;
113
- }
114
-
115
- // Otherwise (attach), always debug.
116
- return true ;
117
- }
66
+ @override
67
+ bool get enableDebugger => super .enableDebugger && ! profileMode && ! releaseMode;
118
68
119
69
/// Whether the launch configuration arguments specify `--profile` .
120
70
///
@@ -152,13 +102,13 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
152
102
'Flutter' ,
153
103
message: 'Attaching…' ,
154
104
);
155
- unawaited (appStartedCompleter .future.then ((_) => progress.end ()));
105
+ unawaited (_appStartedCompleter .future.then ((_) => progress.end ()));
156
106
157
107
final String ? vmServiceUri = args.vmServiceUri;
158
108
final List <String > toolArgs = < String > [
159
109
'attach' ,
160
110
'--machine' ,
161
- if (! _enableDds ) '--no-dds' ,
111
+ if (! enableFlutterDds ) '--no-dds' ,
162
112
if (vmServiceUri != null )
163
113
...< String > ['--debug-uri' , vmServiceUri],
164
114
];
@@ -206,28 +156,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
206
156
}
207
157
}
208
158
209
- @override
210
- Future <void > debuggerConnected (vm.VM vmInfo) async {
211
- // Usually we'd capture the pid from the VM here and record it for
212
- // terminating, however for Flutter apps it may be running on a remote
213
- // device so it's not valid to terminate a process with that pid locally.
214
- // For attach, pids should never be collected as terminateRequest() should
215
- // not terminate the debugee.
216
- }
217
-
218
- /// Called by [disconnectRequest] to request that we forcefully shut down the app being run (or in the case of an attach, disconnect).
219
- ///
220
- /// Client IDEs/editors should send a terminateRequest before a
221
- /// disconnectRequest to allow a graceful shutdown. This method must terminate
222
- /// quickly and therefore may leave orphaned processes.
223
- @override
224
- Future <void > disconnectImpl () async {
225
- if (isAttach) {
226
- await preventBreakingAndResume ();
227
- }
228
- terminatePids (ProcessSignal .sigkill);
229
- }
230
-
231
159
@override
232
160
Future <void > handleExtensionEvent (vm.Event event) async {
233
161
await super .handleExtensionEvent (event);
@@ -274,12 +202,12 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
274
202
'Flutter' ,
275
203
message: 'Launching…' ,
276
204
);
277
- unawaited (appStartedCompleter .future.then ((_) => progress.end ()));
205
+ unawaited (_appStartedCompleter .future.then ((_) => progress.end ()));
278
206
279
207
final List <String > toolArgs = < String > [
280
208
'run' ,
281
209
'--machine' ,
282
- if (! _enableDds ) '--no-dds' ,
210
+ if (! enableFlutterDds ) '--no-dds' ,
283
211
if (enableDebugger) '--start-paused' ,
284
212
// Structured errors are enabled by default, but since we don't connect
285
213
// the VM Service for noDebug, we need to disable them so that error text
@@ -332,27 +260,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
332
260
);
333
261
}
334
262
335
- @visibleForOverriding
336
- Future <void > launchAsProcess ({
337
- required String executable,
338
- required List <String > processArgs,
339
- required Map <String , String >? env,
340
- }) async {
341
- logger? .call ('Spawning $executable with $processArgs in ${args .cwd }' );
342
- final Process process = await Process .start (
343
- executable,
344
- processArgs,
345
- workingDirectory: args.cwd,
346
- environment: env,
347
- );
348
- _process = process;
349
- pidsToTerminate.add (process.pid);
350
-
351
- process.stdout.transform (ByteToLineTransformer ()).listen (_handleStdout);
352
- process.stderr.listen (_handleStderr);
353
- unawaited (process.exitCode.then (_handleExitCode));
354
- }
355
-
356
263
/// restart is called by the client when the user invokes a restart (for example with the button on the debug toolbar).
357
264
///
358
265
/// For Flutter, we handle this ourselves be sending a Hot Restart request
@@ -379,7 +286,7 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
379
286
Map <String , Object ?>? params, {
380
287
bool failSilently = true ,
381
288
}) async {
382
- final Process ? process = _process ;
289
+ final Process ? process = this .process ;
383
290
384
291
if (process == null ) {
385
292
if (failSilently) {
@@ -416,16 +323,16 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
416
323
// Send a request to stop/detach to give Flutter chance to do some cleanup.
417
324
// It's possible the Flutter process will terminate before we process the
418
325
// response, so accept either a response or the process exiting.
419
- if (appId != null ) {
326
+ if (_appId != null ) {
420
327
final String method = isAttach ? 'app.detach' : 'app.stop' ;
421
328
await Future .any <void >(< Future <void >> [
422
- sendFlutterRequest (method, < String , Object ? > {'appId' : appId }),
423
- _process ? .exitCode ?? Future <void >.value (),
329
+ sendFlutterRequest (method, < String , Object ? > {'appId' : _appId }),
330
+ process ? .exitCode ?? Future <void >.value (),
424
331
]);
425
332
}
426
333
427
334
terminatePids (ProcessSignal .sigterm);
428
- await _process ? .exitCode;
335
+ await process ? .exitCode;
429
336
}
430
337
431
338
/// Connects to the VM Service if the app.started event has fired, and a VM Service URI is available.
@@ -451,21 +358,23 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
451
358
452
359
/// Handles the app.start event from Flutter.
453
360
void _handleAppStart (Map <String , Object ?> params) {
454
- appId = params['appId' ] as String ? ;
455
- if (appId == null ) {
361
+ _appId = params['appId' ] as String ? ;
362
+ if (_appId == null ) {
456
363
throw DebugAdapterException ('Unexpected null `appId` in app.start event' );
457
364
}
458
365
}
459
366
460
367
/// Handles the app.started event from Flutter.
461
368
Future <void > _handleAppStarted () async {
462
- appStartedCompleter .complete ();
369
+ _appStartedCompleter .complete ();
463
370
464
371
// Send a custom event so the editor knows the app has started.
465
372
//
466
373
// This may be useful when there's no VM Service (for example Profile mode)
467
374
// but the editor still wants to know that startup has finished.
468
- await debuggerInitialized; // Ensure we're fully initialized before sending.
375
+ if (enableDebugger) {
376
+ await debuggerInitialized; // Ensure we're fully initialized before sending.
377
+ }
469
378
sendEvent (
470
379
RawEventBody (< String , Object ? > {}),
471
380
eventType: 'flutter.appStarted' ,
@@ -491,13 +400,14 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
491
400
final Uri vmServiceUri = Uri .parse (wsUri);
492
401
// Also wait for app.started before we connect, to ensure Flutter's
493
402
// initialization is all complete.
494
- await appStartedCompleter .future;
403
+ await _appStartedCompleter .future;
495
404
await _connectDebugger (vmServiceUri);
496
405
}
497
406
}
498
407
499
408
/// Handles the Flutter process exiting, terminating the debug session if it has not already begun terminating.
500
- void _handleExitCode (int code) {
409
+ @override
410
+ void handleExitCode (int code) {
501
411
final String codeSuffix = code == 0 ? '' : ' ($code )' ;
502
412
logger? .call ('Process exited ($code )' );
503
413
handleSessionTerminate (codeSuffix);
@@ -542,13 +452,15 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
542
452
}
543
453
}
544
454
545
- void _handleStderr (List <int > data) {
455
+ @override
456
+ void handleStderr (List <int > data) {
546
457
logger? .call ('stderr: $data ' );
547
458
sendOutput ('stderr' , utf8.decode (data));
548
459
}
549
460
550
461
/// Handles stdout from the `flutter run --machine` process, decoding the JSON and calling the appropriate handlers.
551
- void _handleStdout (String data) {
462
+ @override
463
+ void handleStdout (String data) {
552
464
// Output intended for us to parse is JSON wrapped in brackets:
553
465
// [{"event":"app.foo","params":{"bar":"baz"}}]
554
466
// However, it's also possible a user printed things that look a little like
@@ -624,7 +536,7 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
624
536
625
537
try {
626
538
await sendFlutterRequest ('app.restart' , < String , Object ? > {
627
- 'appId' : appId ,
539
+ 'appId' : _appId ,
628
540
'fullRestart' : fullRestart,
629
541
'pause' : enableDebugger,
630
542
'reason' : reason,
@@ -633,8 +545,7 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
633
545
} on DebugAdapterException catch (error) {
634
546
final String action = fullRestart ? 'Hot Restart' : 'Hot Reload' ;
635
547
sendOutput ('console' , 'Failed to $action : $error ' );
636
- }
637
- finally {
548
+ } finally {
638
549
progress.end ();
639
550
}
640
551
}
0 commit comments