Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 223f416

Browse files
author
Dan Rubel
authored
Flutter run with machine output (flutter#6645)
* add flutter run --machine flag * refactor daemon stdin/out command stream/response * extract daemon startApp method * refactor flutter run --machine to call daemon.startApp
1 parent 1c2be02 commit 223f416

File tree

2 files changed

+69
-39
lines changed

2 files changed

+69
-39
lines changed

packages/flutter_tools/lib/src/commands/daemon.dart

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,14 @@ class DaemonCommand extends FlutterCommand {
5252
Cache.releaseLockEarly();
5353

5454
return appContext.runInZone(() {
55-
Stream<Map<String, dynamic>> commandStream = stdin
56-
.transform(UTF8.decoder)
57-
.transform(const LineSplitter())
58-
.where((String line) => line.startsWith('[{') && line.endsWith('}]'))
59-
.map((String line) {
60-
line = line.substring(1, line.length - 1);
61-
return JSON.decode(line);
62-
});
63-
64-
Daemon daemon = new Daemon(commandStream, (Map<String, dynamic> command) {
65-
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
66-
}, daemonCommand: this, notifyingLogger: notifyingLogger);
55+
Daemon daemon = new Daemon(
56+
stdinCommandStream, stdoutCommandResponse,
57+
daemonCommand: this, notifyingLogger: notifyingLogger);
6758

6859
return daemon.onExit;
6960
}, onError: _handleError);
7061
}
7162

72-
dynamic _jsonEncodeObject(dynamic object) {
73-
if (object is Device)
74-
return _deviceToMap(object);
75-
if (object is OperationResult)
76-
return _operationResultToMap(object);
77-
return object;
78-
}
79-
8063
dynamic _handleError(dynamic error, StackTrace stackTrace) {
8164
printError('Error from flutter daemon: $error', stackTrace);
8265
return null;
@@ -306,6 +289,23 @@ class AppDomain extends Domain {
306289
throw "'$projectDirectory' does not exist";
307290

308291
BuildMode buildMode = getBuildModeForName(mode) ?? BuildMode.debug;
292+
293+
AppInstance app = startApp(
294+
device, projectDirectory, target, route,
295+
buildMode, startPaused, enableHotReload);
296+
297+
return <String, dynamic>{
298+
'appId': app.id,
299+
'deviceId': device.id,
300+
'directory': projectDirectory,
301+
'supportsRestart': isRestartSupported(enableHotReload, device)
302+
};
303+
}
304+
305+
AppInstance startApp(
306+
Device device, String projectDirectory, String target, String route,
307+
BuildMode buildMode, bool startPaused, bool enableHotReload) {
308+
309309
DebuggingOptions options;
310310

311311
switch (buildMode) {
@@ -342,14 +342,12 @@ class AppDomain extends Domain {
342342
);
343343
}
344344

345-
bool supportsRestart = enableHotReload ? device.supportsHotMode : device.supportsRestart;
346-
347345
AppInstance app = new AppInstance(_getNewAppId(), runner);
348346
_apps.add(app);
349347
_sendAppEvent(app, 'start', <String, dynamic>{
350-
'deviceId': deviceId,
348+
'deviceId': device.id,
351349
'directory': projectDirectory,
352-
'supportsRestart': supportsRestart
350+
'supportsRestart': isRestartSupported(enableHotReload, device)
353351
});
354352

355353
Completer<DebugConnectionInfo> connectionInfoCompleter;
@@ -375,14 +373,12 @@ class AppDomain extends Domain {
375373
});
376374
});
377375

378-
return <String, dynamic>{
379-
'appId': app.id,
380-
'deviceId': deviceId,
381-
'directory': projectDirectory,
382-
'supportsRestart': supportsRestart
383-
};
376+
return app;
384377
}
385378

379+
bool isRestartSupported(bool enableHotReload, Device device) =>
380+
enableHotReload ? device.supportsHotMode : device.supportsRestart;
381+
386382
Future<OperationResult> restart(Map<String, dynamic> args) async {
387383
String appId = _getStringArg(args, 'appId', required: true);
388384
bool fullRestart = _getBoolArg(args, 'fullRestart') ?? false;
@@ -561,6 +557,27 @@ class DeviceDomain extends Domain {
561557
}
562558
}
563559

560+
Stream<Map<String, dynamic>> get stdinCommandStream => stdin
561+
.transform(UTF8.decoder)
562+
.transform(const LineSplitter())
563+
.where((String line) => line.startsWith('[{') && line.endsWith('}]'))
564+
.map((String line) {
565+
line = line.substring(1, line.length - 1);
566+
return JSON.decode(line);
567+
});
568+
569+
void stdoutCommandResponse(Map<String, dynamic> command) {
570+
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
571+
}
572+
573+
dynamic _jsonEncodeObject(dynamic object) {
574+
if (object is Device)
575+
return _deviceToMap(object);
576+
if (object is OperationResult)
577+
return _operationResultToMap(object);
578+
return object;
579+
}
580+
564581
Map<String, dynamic> _deviceToMap(Device device) {
565582
return <String, dynamic>{
566583
'id': device.id,

packages/flutter_tools/lib/src/commands/run.dart

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import '../resident_runner.dart';
1919
import '../run.dart';
2020
import '../runner/flutter_command.dart';
2121
import 'build_apk.dart';
22+
import 'daemon.dart';
2223
import 'install.dart';
2324
import 'trace.dart';
2425

@@ -61,6 +62,10 @@ class RunCommand extends RunCommandBase {
6162
argParser.addOption('use-application-binary',
6263
hide: !verboseHelp,
6364
help: 'Specify a pre-built application binary to use when running.');
65+
argParser.addFlag('machine',
66+
hide: !verboseHelp,
67+
help: 'Handle machine structured JSON command input\n'
68+
'and provide output and progress in machine friendly format.');
6469
usesPubOption();
6570

6671
// Option to enable hot reloading.
@@ -79,7 +84,6 @@ class RunCommand extends RunCommandBase {
7984
'and SIGUSR2 to trigger a full restart.'
8085
);
8186

82-
8387
// Hidden option to enable a benchmarking mode. This will run the given
8488
// application, measure the startup time and the app restart time, write the
8589
// results out to 'refresh_benchmark.json', and exit. This flag is intended
@@ -153,8 +157,23 @@ class RunCommand extends RunCommandBase {
153157

154158
@override
155159
Future<int> runCommand() async {
156-
int debugPort;
157160

161+
Cache.releaseLockEarly();
162+
163+
// Enable hot mode by default if `--no-hot` was not passed and we are in
164+
// debug mode.
165+
final bool hotMode = shouldUseHotMode();
166+
167+
if (argResults['machine']) {
168+
Daemon daemon = new Daemon(stdinCommandStream, stdoutCommandResponse,
169+
notifyingLogger: new NotifyingLogger());
170+
AppInstance app = daemon.appDomain.startApp(
171+
device, Directory.current.path, targetFile, route,
172+
getBuildMode(), argResults['start-paused'], hotMode);
173+
return app.runner.waitForAppToFinish();
174+
}
175+
176+
int debugPort;
158177
if (argResults['debug-port'] != null) {
159178
try {
160179
debugPort = int.parse(argResults['debug-port']);
@@ -181,12 +200,6 @@ class RunCommand extends RunCommandBase {
181200
);
182201
}
183202

184-
Cache.releaseLockEarly();
185-
186-
// Enable hot mode by default if ``--no-hot` was not passed and we are in
187-
// debug mode.
188-
final bool hotMode = shouldUseHotMode();
189-
190203
if (hotMode) {
191204
if (!device.supportsHotMode) {
192205
printError('Hot mode is not supported by this device. '
@@ -207,7 +220,7 @@ class RunCommand extends RunCommandBase {
207220
device,
208221
target: targetFile,
209222
debuggingOptions: options,
210-
benchmarkMode: argResults['benchmark'],
223+
benchmarkMode: argResults['benchmark']
211224
);
212225
} else {
213226
runner = new RunAndStayResident(

0 commit comments

Comments
 (0)