@@ -6,69 +6,35 @@ import 'dart:async';
66import 'dart:math' as math;
77
88import 'package:dds/dap.dart' hide PidTracker;
9- import 'package:meta/meta.dart' ;
109import 'package:vm_service/vm_service.dart' as vm;
1110
12- import '../base/file_system.dart' ;
1311import '../base/io.dart' ;
14- import '../base/platform.dart' ;
1512import '../cache.dart' ;
1613import '../convert.dart' ;
1714import 'flutter_adapter_args.dart' ;
18- import 'mixins .dart' ;
15+ import 'flutter_base_adapter .dart' ;
1916
2017/// 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 {
2319 FlutterDebugAdapter (
2420 super .channel, {
25- required this .fileSystem,
26- required this .platform,
21+ required super .fileSystem,
22+ required super .platform,
2723 super .ipv6,
28- bool enableDds = true ,
24+ super .enableFlutterDds = true ,
2925 super .enableAuthCodes,
3026 super .logger,
3127 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+ });
6129
6230 /// 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 >();
6532
6633 /// Whether or not the app.started event has been received.
67- bool get _receivedAppStarted => appStartedCompleter .isCompleted;
34+ bool get _receivedAppStarted => _appStartedCompleter .isCompleted;
6835
6936 /// The appId of the current running Flutter app.
70- @visibleForTesting
71- String ? appId;
37+ String ? _appId;
7238
7339 /// The ID to use for the next request sent to the Flutter run daemon.
7440 int _flutterRequestId = 1 ;
@@ -84,13 +50,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
8450 @override
8551 bool get supportsRestartRequest => true ;
8652
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-
9453 /// Whether or not the user requested debugging be enabled.
9554 ///
9655 /// For debugging to be enabled, the user must have chosen "Debug" (and not
@@ -104,17 +63,8 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
10463 /// functionality (breakpoints, evaluation, etc.) will not be available.
10564 /// Functionality provided via the daemon (hot reload/restart) will still be
10665 /// 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;
11868
11969 /// Whether the launch configuration arguments specify `--profile` .
12070 ///
@@ -152,13 +102,13 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
152102 'Flutter' ,
153103 message: 'Attaching…' ,
154104 );
155- unawaited (appStartedCompleter .future.then ((_) => progress.end ()));
105+ unawaited (_appStartedCompleter .future.then ((_) => progress.end ()));
156106
157107 final String ? vmServiceUri = args.vmServiceUri;
158108 final List <String > toolArgs = < String > [
159109 'attach' ,
160110 '--machine' ,
161- if (! _enableDds ) '--no-dds' ,
111+ if (! enableFlutterDds ) '--no-dds' ,
162112 if (vmServiceUri != null )
163113 ...< String > ['--debug-uri' , vmServiceUri],
164114 ];
@@ -206,28 +156,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
206156 }
207157 }
208158
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-
231159 @override
232160 Future <void > handleExtensionEvent (vm.Event event) async {
233161 await super .handleExtensionEvent (event);
@@ -274,12 +202,12 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
274202 'Flutter' ,
275203 message: 'Launching…' ,
276204 );
277- unawaited (appStartedCompleter .future.then ((_) => progress.end ()));
205+ unawaited (_appStartedCompleter .future.then ((_) => progress.end ()));
278206
279207 final List <String > toolArgs = < String > [
280208 'run' ,
281209 '--machine' ,
282- if (! _enableDds ) '--no-dds' ,
210+ if (! enableFlutterDds ) '--no-dds' ,
283211 if (enableDebugger) '--start-paused' ,
284212 // Structured errors are enabled by default, but since we don't connect
285213 // the VM Service for noDebug, we need to disable them so that error text
@@ -332,27 +260,6 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
332260 );
333261 }
334262
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-
356263 /// restart is called by the client when the user invokes a restart (for example with the button on the debug toolbar).
357264 ///
358265 /// For Flutter, we handle this ourselves be sending a Hot Restart request
@@ -379,7 +286,7 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
379286 Map <String , Object ?>? params, {
380287 bool failSilently = true ,
381288 }) async {
382- final Process ? process = _process ;
289+ final Process ? process = this .process ;
383290
384291 if (process == null ) {
385292 if (failSilently) {
@@ -416,16 +323,16 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
416323 // Send a request to stop/detach to give Flutter chance to do some cleanup.
417324 // It's possible the Flutter process will terminate before we process the
418325 // response, so accept either a response or the process exiting.
419- if (appId != null ) {
326+ if (_appId != null ) {
420327 final String method = isAttach ? 'app.detach' : 'app.stop' ;
421328 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 (),
424331 ]);
425332 }
426333
427334 terminatePids (ProcessSignal .sigterm);
428- await _process ? .exitCode;
335+ await process ? .exitCode;
429336 }
430337
431338 /// 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
451358
452359 /// Handles the app.start event from Flutter.
453360 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 ) {
456363 throw DebugAdapterException ('Unexpected null `appId` in app.start event' );
457364 }
458365 }
459366
460367 /// Handles the app.started event from Flutter.
461368 Future <void > _handleAppStarted () async {
462- appStartedCompleter .complete ();
369+ _appStartedCompleter .complete ();
463370
464371 // Send a custom event so the editor knows the app has started.
465372 //
466373 // This may be useful when there's no VM Service (for example Profile mode)
467374 // 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+ }
469378 sendEvent (
470379 RawEventBody (< String , Object ? > {}),
471380 eventType: 'flutter.appStarted' ,
@@ -491,13 +400,14 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
491400 final Uri vmServiceUri = Uri .parse (wsUri);
492401 // Also wait for app.started before we connect, to ensure Flutter's
493402 // initialization is all complete.
494- await appStartedCompleter .future;
403+ await _appStartedCompleter .future;
495404 await _connectDebugger (vmServiceUri);
496405 }
497406 }
498407
499408 /// 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) {
501411 final String codeSuffix = code == 0 ? '' : ' ($code )' ;
502412 logger? .call ('Process exited ($code )' );
503413 handleSessionTerminate (codeSuffix);
@@ -542,13 +452,15 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
542452 }
543453 }
544454
545- void _handleStderr (List <int > data) {
455+ @override
456+ void handleStderr (List <int > data) {
546457 logger? .call ('stderr: $data ' );
547458 sendOutput ('stderr' , utf8.decode (data));
548459 }
549460
550461 /// 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) {
552464 // Output intended for us to parse is JSON wrapped in brackets:
553465 // [{"event":"app.foo","params":{"bar":"baz"}}]
554466 // However, it's also possible a user printed things that look a little like
@@ -624,7 +536,7 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
624536
625537 try {
626538 await sendFlutterRequest ('app.restart' , < String , Object ? > {
627- 'appId' : appId ,
539+ 'appId' : _appId ,
628540 'fullRestart' : fullRestart,
629541 'pause' : enableDebugger,
630542 'reason' : reason,
@@ -633,8 +545,7 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
633545 } on DebugAdapterException catch (error) {
634546 final String action = fullRestart ? 'Hot Restart' : 'Hot Reload' ;
635547 sendOutput ('console' , 'Failed to $action : $error ' );
636- }
637- finally {
548+ } finally {
638549 progress.end ();
639550 }
640551 }
0 commit comments