introduce globals scoped to the app's context
diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index e92e058..b6ff950 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart
@@ -8,6 +8,8 @@ import 'package:args/command_runner.dart'; import 'package:stack_trace/stack_trace.dart'; +import 'src/base/context.dart'; +import 'src/base/logger.dart'; import 'src/base/process.dart'; import 'src/commands/analyze.dart'; import 'src/commands/apk.dart'; @@ -27,6 +29,7 @@ import 'src/commands/test.dart'; import 'src/commands/trace.dart'; import 'src/commands/upgrade.dart'; +import 'src/device.dart'; import 'src/runner/flutter_command_runner.dart'; /// Main entry point for commands. @@ -62,7 +65,12 @@ if (args.isNotEmpty && args[0] == 'init') args[0] = 'create'; + // Initialize globals. + context[Logger] = new StdoutLogger(); + context[DeviceManager] = new DeviceManager(); + dynamic result = await runner.run(args); + if (result is int) exit(result); }, onError: (error, Chain chain) {
diff --git a/packages/flutter_tools/lib/src/android/adb.dart b/packages/flutter_tools/lib/src/android/adb.dart index aad03e3..e8b0f94 100644 --- a/packages/flutter_tools/lib/src/android/adb.dart +++ b/packages/flutter_tools/lib/src/android/adb.dart
@@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:io'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; // https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT
diff --git a/packages/flutter_tools/lib/src/android/device_android.dart b/packages/flutter_tools/lib/src/android/device_android.dart index e0eadf9..c55e0d4 100644 --- a/packages/flutter_tools/lib/src/android/device_android.dart +++ b/packages/flutter_tools/lib/src/android/device_android.dart
@@ -10,7 +10,7 @@ import '../application_package.dart'; import '../base/common.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/os.dart'; import '../base/process.dart'; import '../build_configuration.dart';
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 123b752..4d304ed 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -8,7 +8,7 @@ import 'package:archive/archive.dart'; import 'package:path/path.dart' as path; -import 'base/context.dart'; +import 'base/globals.dart'; import 'base/os.dart'; import 'base/process.dart'; import 'build_configuration.dart';
diff --git a/packages/flutter_tools/lib/src/base/context.dart b/packages/flutter_tools/lib/src/base/context.dart index 21054a4..8c1f54d 100644 --- a/packages/flutter_tools/lib/src/base/context.dart +++ b/packages/flutter_tools/lib/src/base/context.dart
@@ -3,9 +3,8 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:io'; -final AppContext _defaultContext = new _DefaultAppContext(); +final AppContext _defaultContext = new AppContext(); /// A singleton for application functionality. This singleton can be different /// on a per-Zone basis. @@ -14,57 +13,42 @@ return currentContext == null ? _defaultContext : currentContext; } -/// Display an error level message to the user. Commands should use this if they -/// fail in some way. -void printError(String message, [StackTrace stackTrace]) => context.printError(message, stackTrace); +class AppContext { + Map<Type, dynamic> _instances = <Type, dynamic>{}; -/// Display normal output of the command. This should be used for things like -/// progress messages, success messages, or just normal command output. -void printStatus(String message) => context.printStatus(message); + dynamic getVariable(Type type) { + if (_instances.containsKey(type)) + return _instances[type]; -/// Use this for verbose tracing output. Users can turn this output on in order -/// to help diagnose issues with the toolchain or with their setup. -void printTrace(String message) => context.printTrace(message); - -abstract class AppContext { - bool get verbose; - set verbose(bool value); - - void printError(String message, [StackTrace stackTrace]); - void printStatus(String message); - void printTrace(String message); -} - -class _DefaultAppContext implements AppContext { - DateTime _startTime = new DateTime.now(); - - bool _verbose = false; - - bool get verbose => _verbose; - - set verbose(bool value) { - _verbose = value; + AppContext parent = _calcParent(Zone.current); + return parent?.getVariable(type); } - void printError(String message, [StackTrace stackTrace]) { - stderr.writeln(_prefix + message); - if (stackTrace != null) - stderr.writeln(stackTrace); + void setVariable(Type type, dynamic instance) { + _instances[type] = instance; } - void printStatus(String message) { - print(_prefix + message); + dynamic operator[](Type type) => getVariable(type); + + void operator[]=(Type type, dynamic instance) => setVariable(type, instance); + + AppContext _calcParent(Zone zone) { + if (this == _defaultContext) + return null; + + Zone parentZone = zone.parent; + if (parentZone == null) + return _defaultContext; + + AppContext deps = parentZone['context']; + if (deps == this) { + return _calcParent(parentZone); + } else { + return deps != null ? deps : _defaultContext; + } } - void printTrace(String message) { - if (_verbose) - print('$_prefix- $message'); - } - - String get _prefix { - if (!_verbose) - return ''; - Duration elapsed = new DateTime.now().difference(_startTime); - return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] '; + dynamic runInZone(dynamic method()) { + return runZoned(method, zoneValues: {'context': this}); } }
diff --git a/packages/flutter_tools/lib/src/base/globals.dart b/packages/flutter_tools/lib/src/base/globals.dart new file mode 100644 index 0000000..5c86fb2 --- /dev/null +++ b/packages/flutter_tools/lib/src/base/globals.dart
@@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../device.dart'; +import 'context.dart'; +import 'logger.dart'; + +DeviceManager get deviceManager => context[DeviceManager]; +Logger get logger => context[Logger]; + +/// Display an error level message to the user. Commands should use this if they +/// fail in some way. +void printError(String message, [StackTrace stackTrace]) => logger.printError(message, stackTrace); + +/// Display normal output of the command. This should be used for things like +/// progress messages, success messages, or just normal command output. +void printStatus(String message) => logger.printStatus(message); + +/// Use this for verbose tracing output. Users can turn this output on in order +/// to help diagnose issues with the toolchain or with their setup. +void printTrace(String message) => logger.printTrace(message);
diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart new file mode 100644 index 0000000..0489279 --- /dev/null +++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -0,0 +1,65 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +abstract class Logger { + bool verbose = false; + + /// Display an error level message to the user. Commands should use this if they + /// fail in some way. + void printError(String message, [StackTrace stackTrace]); + + /// Display normal output of the command. This should be used for things like + /// progress messages, success messages, or just normal command output. + void printStatus(String message); + + /// Use this for verbose tracing output. Users can turn this output on in order + /// to help diagnose issues with the toolchain or with their setup. + void printTrace(String message); +} + +class StdoutLogger implements Logger { + DateTime _startTime = new DateTime.now(); + + bool verbose = false; + + void printError(String message, [StackTrace stackTrace]) { + stderr.writeln(_prefix + message); + if (stackTrace != null) + stderr.writeln(stackTrace); + } + + void printStatus(String message) { + print(_prefix + message); + } + + void printTrace(String message) { + if (verbose) + print('$_prefix- $message'); + } + + String get _prefix { + if (!verbose) + return ''; + Duration elapsed = new DateTime.now().difference(_startTime); + return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] '; + } +} + +class BufferLogger implements Logger { + StringBuffer _error = new StringBuffer(); + StringBuffer _status = new StringBuffer(); + StringBuffer _trace = new StringBuffer(); + + bool verbose = false; + + String get errorText => _error.toString(); + String get statusText => _status.toString(); + String get traceText => _trace.toString(); + + void printError(String message, [StackTrace stackTrace]) => _error.writeln(message); + void printStatus(String message) => _status.writeln(message); + void printTrace(String message) => _trace.writeln(message); +}
diff --git a/packages/flutter_tools/lib/src/base/process.dart b/packages/flutter_tools/lib/src/base/process.dart index 7da7699..cac6702 100644 --- a/packages/flutter_tools/lib/src/base/process.dart +++ b/packages/flutter_tools/lib/src/base/process.dart
@@ -6,7 +6,7 @@ import 'dart:convert'; import 'dart:io'; -import 'context.dart'; +import 'globals.dart'; typedef String StringConverter(String string);
diff --git a/packages/flutter_tools/lib/src/build_configuration.dart b/packages/flutter_tools/lib/src/build_configuration.dart index 82a5bbb..160334b 100644 --- a/packages/flutter_tools/lib/src/build_configuration.dart +++ b/packages/flutter_tools/lib/src/build_configuration.dart
@@ -6,7 +6,7 @@ import 'package:path/path.dart' as path; -import 'base/context.dart'; +import 'base/globals.dart'; enum BuildType { prebuilt,
diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart index 7d6742f..b50b90e 100644 --- a/packages/flutter_tools/lib/src/commands/analyze.dart +++ b/packages/flutter_tools/lib/src/commands/analyze.dart
@@ -11,7 +11,7 @@ import 'package:path/path.dart' as path; import '../artifacts.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import '../build_configuration.dart'; import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart index 14070c9..f0f728f 100644 --- a/packages/flutter_tools/lib/src/commands/apk.dart +++ b/packages/flutter_tools/lib/src/commands/apk.dart
@@ -12,8 +12,8 @@ import '../android/device_android.dart'; import '../application_package.dart'; import '../artifacts.dart'; -import '../base/context.dart'; import '../base/file_system.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import '../build_configuration.dart'; import '../device.dart';
diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart index 1cfa1b0..5e1f763 100644 --- a/packages/flutter_tools/lib/src/commands/build.dart +++ b/packages/flutter_tools/lib/src/commands/build.dart
@@ -4,7 +4,7 @@ import 'dart:async'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../flx.dart'; import '../runner/flutter_command.dart'; import '../toolchain.dart';
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart index 60da5e5..f58bc77 100644 --- a/packages/flutter_tools/lib/src/commands/create.dart +++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -11,7 +11,7 @@ import '../android/android.dart' as android; import '../artifacts.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; class CreateCommand extends Command {
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 1656d8e..0dee7cc 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -9,6 +9,8 @@ import '../android/adb.dart'; import '../android/device_android.dart'; import '../base/context.dart'; +import '../base/globals.dart'; +import '../base/logger.dart'; import '../device.dart'; import '../ios/device_ios.dart'; import '../ios/simulator.dart'; @@ -33,9 +35,11 @@ Future<int> runInProject() { printStatus('Starting device daemon...'); - NotifyingAppContext appContext = new NotifyingAppContext(); + AppContext appContext = new AppContext(); + NotifyingLogger notifyingLogger = new NotifyingLogger(); + appContext[Logger] = notifyingLogger; - return runZoned(() { + return appContext.runInZone(() { Stream<Map<String, dynamic>> commandStream = stdin .transform(UTF8.decoder) .transform(const LineSplitter()) @@ -47,10 +51,10 @@ Daemon daemon = new Daemon(commandStream, (Map command) { stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]'); - }, daemonCommand: this, appContext: appContext); + }, daemonCommand: this, notifyingLogger: notifyingLogger); return daemon.onExit; - }, zoneValues: {'context': appContext}); + }); } dynamic _jsonEncodeObject(dynamic object) { @@ -67,7 +71,7 @@ class Daemon { Daemon(Stream<Map> commandStream, this.sendCommand, { this.daemonCommand, - this.appContext + this.notifyingLogger }) { // Set up domains. _registerDomain(new DaemonDomain(this)); @@ -83,7 +87,7 @@ final DispatchComand sendCommand; final DaemonCommand daemonCommand; - final NotifyingAppContext appContext; + final NotifyingLogger notifyingLogger; final Completer<int> _onExitCompleter = new Completer<int>(); final Map<String, Domain> _domainMap = <String, Domain>{}; @@ -185,7 +189,7 @@ registerHandler('version', version); registerHandler('shutdown', shutdown); - _subscription = daemon.appContext.onMessage.listen((LogMessage message) { + _subscription = daemon.notifyingLogger.onMessage.listen((LogMessage message) { if (message.stackTrace != null) { sendEvent('daemon.logMessage', { 'level': message.level, @@ -467,13 +471,11 @@ return '$obj'; } -class NotifyingAppContext implements AppContext { +class NotifyingLogger extends Logger { StreamController<LogMessage> _messageController = new StreamController<LogMessage>.broadcast(); Stream<LogMessage> get onMessage => _messageController.stream; - bool verbose = false; - void printError(String message, [StackTrace stackTrace]) { _messageController.add(new LogMessage('error', message, stackTrace)); }
diff --git a/packages/flutter_tools/lib/src/commands/ios.dart b/packages/flutter_tools/lib/src/commands/ios.dart index b424981..96f110a 100644 --- a/packages/flutter_tools/lib/src/commands/ios.dart +++ b/packages/flutter_tools/lib/src/commands/ios.dart
@@ -8,7 +8,7 @@ import "package:path/path.dart" as path; import "../artifacts.dart"; -import "../base/context.dart"; +import "../base/globals.dart"; import "../base/process.dart"; import "../runner/flutter_command.dart"; import "../runner/flutter_command_runner.dart";
diff --git a/packages/flutter_tools/lib/src/commands/list.dart b/packages/flutter_tools/lib/src/commands/list.dart index 885ba15..2eb0437 100644 --- a/packages/flutter_tools/lib/src/commands/list.dart +++ b/packages/flutter_tools/lib/src/commands/list.dart
@@ -4,7 +4,7 @@ import 'dart:async'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../device.dart'; import '../runner/flutter_command.dart'; @@ -15,9 +15,7 @@ bool get requiresProjectRoot => false; Future<int> runInProject() async { - DeviceManager deviceManager = new DeviceManager(); - - List<Device> devices = await deviceManager.getDevices(); + List<Device> devices = await deviceManager.getAllConnectedDevices(); if (devices.isEmpty) { printStatus('No connected devices.');
diff --git a/packages/flutter_tools/lib/src/commands/listen.dart b/packages/flutter_tools/lib/src/commands/listen.dart index b139355..4fd76de 100644 --- a/packages/flutter_tools/lib/src/commands/listen.dart +++ b/packages/flutter_tools/lib/src/commands/listen.dart
@@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:io'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import 'start.dart';
diff --git a/packages/flutter_tools/lib/src/commands/logs.dart b/packages/flutter_tools/lib/src/commands/logs.dart index 0b274d3..3766de2 100644 --- a/packages/flutter_tools/lib/src/commands/logs.dart +++ b/packages/flutter_tools/lib/src/commands/logs.dart
@@ -4,7 +4,7 @@ import 'dart:async'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../device.dart'; import '../runner/flutter_command.dart'; @@ -24,21 +24,14 @@ Future<int> runInProject() async { DeviceManager deviceManager = new DeviceManager(); - List<Device> devices; + deviceManager.specifiedDeviceId = globalResults['device-id']; - String deviceId = globalResults['device-id']; - if (deviceId != null) { - Device device = await deviceManager.getDeviceById(deviceId); - if (device == null) { - printError("No device found with id '$deviceId'."); - return 1; - } - devices = <Device>[device]; - } else { - devices = await deviceManager.getDevices(); - } + List<Device> devices = await deviceManager.getDevices(); - if (devices.isEmpty) { + if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) { + printError("No device found with id '${deviceManager.specifiedDeviceId}'."); + return 1; + } else if (devices.isEmpty) { printStatus('No connected devices.'); return 0; }
diff --git a/packages/flutter_tools/lib/src/commands/refresh.dart b/packages/flutter_tools/lib/src/commands/refresh.dart index 02bb4d5..35ff972 100644 --- a/packages/flutter_tools/lib/src/commands/refresh.dart +++ b/packages/flutter_tools/lib/src/commands/refresh.dart
@@ -7,7 +7,7 @@ import 'package:path/path.dart' as path; -import '../base/context.dart'; +import '../base/globals.dart'; import '../flx.dart'; import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/run_mojo.dart b/packages/flutter_tools/lib/src/commands/run_mojo.dart index 9acffbc..77dc2a1 100644 --- a/packages/flutter_tools/lib/src/commands/run_mojo.dart +++ b/packages/flutter_tools/lib/src/commands/run_mojo.dart
@@ -8,7 +8,7 @@ import 'package:path/path.dart' as path; import '../artifacts.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import '../build_configuration.dart'; import '../flx.dart' as flx; @@ -118,7 +118,7 @@ if (useDevtools) { final String buildFlag = argResults['mojo-debug'] ? '--debug' : '--release'; args.add(buildFlag); - if (context.verbose) + if (logger.verbose) args.add('--verbose'); }
diff --git a/packages/flutter_tools/lib/src/commands/start.dart b/packages/flutter_tools/lib/src/commands/start.dart index ba653b0..9b9259e 100644 --- a/packages/flutter_tools/lib/src/commands/start.dart +++ b/packages/flutter_tools/lib/src/commands/start.dart
@@ -9,7 +9,7 @@ import '../application_package.dart'; import '../base/common.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../build_configuration.dart'; import '../device.dart'; import '../flx.dart';
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 127391b..e7ebac2 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -9,7 +9,7 @@ import 'package:test/src/executable.dart' as executable; import '../artifacts.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../build_configuration.dart'; import '../runner/flutter_command.dart'; import '../test/loader.dart' as loader;
diff --git a/packages/flutter_tools/lib/src/commands/trace.dart b/packages/flutter_tools/lib/src/commands/trace.dart index d66b741..a40af6d 100644 --- a/packages/flutter_tools/lib/src/commands/trace.dart +++ b/packages/flutter_tools/lib/src/commands/trace.dart
@@ -6,7 +6,7 @@ import '../android/device_android.dart'; import '../application_package.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../runner/flutter_command.dart'; class TraceCommand extends FlutterCommand {
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart index b9d249c..5e2a124 100644 --- a/packages/flutter_tools/lib/src/commands/upgrade.dart +++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -5,7 +5,7 @@ import 'dart:async'; import '../artifacts.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import '../runner/flutter_command.dart'; import '../runner/version.dart';
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 460ade4..7c865b3 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -7,33 +7,48 @@ import 'android/device_android.dart'; import 'application_package.dart'; import 'base/common.dart'; -import 'base/context.dart'; +import 'base/globals.dart'; import 'build_configuration.dart'; import 'ios/device_ios.dart'; import 'toolchain.dart'; /// A class to get all available devices. class DeviceManager { + /// Constructing DeviceManagers is cheap; they only do expensive work if some + /// of their methods are invoked. DeviceManager() { - // Init the known discoverers. + // Register the known discoverers. _deviceDiscoverers.add(new AndroidDeviceDiscovery()); _deviceDiscoverers.add(new IOSDeviceDiscovery()); _deviceDiscoverers.add(new IOSSimulatorDiscovery()); + } - Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) { - if (!discoverer.supportsPlatform) - return null; - return discoverer.init(); - }).then((_) { - _initedCompleter.complete(); - }).catchError((error, stackTrace) { - _initedCompleter.completeError(error, stackTrace); - }); + Future _init() { + if (_initedCompleter == null) { + _initedCompleter = new Completer(); + + Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) { + if (!discoverer.supportsPlatform) + return null; + return discoverer.init(); + }).then((_) { + _initedCompleter.complete(); + }).catchError((error, stackTrace) { + _initedCompleter.completeError(error, stackTrace); + }); + } + + return _initedCompleter.future; } List<DeviceDiscovery> _deviceDiscoverers = <DeviceDiscovery>[]; - Completer _initedCompleter = new Completer(); + /// A user-specified device ID. + String specifiedDeviceId; + + Completer _initedCompleter; + + bool get hasSpecifiedDeviceId => specifiedDeviceId != null; /// Return the device with the matching ID; else, complete the Future with /// `null`. @@ -41,15 +56,26 @@ /// This does a case insentitive compare with `deviceId`. Future<Device> getDeviceById(String deviceId) async { deviceId = deviceId.toLowerCase(); - List<Device> devices = await getDevices(); + List<Device> devices = await getAllConnectedDevices(); return devices.firstWhere( (Device device) => device.id.toLowerCase() == deviceId, orElse: () => null ); } + /// Return the list of connected devices, filtered by any user-specified device id. Future<List<Device>> getDevices() async { - await _initedCompleter.future; + if (specifiedDeviceId == null) { + return getAllConnectedDevices(); + } else { + Device device = await getDeviceById(specifiedDeviceId); + return device == null ? <Device>[] : <Device>[device]; + } + } + + /// Return the list of all connected devices. + Future<List<Device>> getAllConnectedDevices() async { + await _init(); return _deviceDiscoverers .where((DeviceDiscovery discoverer) => discoverer.supportsPlatform)
diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart index 2fb6efc..00973bc 100644 --- a/packages/flutter_tools/lib/src/flx.dart +++ b/packages/flutter_tools/lib/src/flx.dart
@@ -13,7 +13,7 @@ import 'package:path/path.dart' as path; import 'package:yaml/yaml.dart'; -import 'base/context.dart'; +import 'base/globals.dart'; import 'base/file_system.dart'; import 'toolchain.dart';
diff --git a/packages/flutter_tools/lib/src/ios/device_ios.dart b/packages/flutter_tools/lib/src/ios/device_ios.dart index 321ef61..6ce1789 100644 --- a/packages/flutter_tools/lib/src/ios/device_ios.dart +++ b/packages/flutter_tools/lib/src/ios/device_ios.dart
@@ -9,7 +9,7 @@ import '../application_package.dart'; import '../base/common.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import '../build_configuration.dart'; import '../device.dart';
diff --git a/packages/flutter_tools/lib/src/ios/simulator.dart b/packages/flutter_tools/lib/src/ios/simulator.dart index eecd1af..f776382 100644 --- a/packages/flutter_tools/lib/src/ios/simulator.dart +++ b/packages/flutter_tools/lib/src/ios/simulator.dart
@@ -6,7 +6,7 @@ import 'dart:convert' show JSON; import 'dart:io'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; const String _xcrunPath = '/usr/bin/xcrun';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 4df0131..2e94cbc 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -8,9 +8,9 @@ import 'package:args/command_runner.dart'; import '../application_package.dart'; -import '../base/context.dart'; -import '../build_configuration.dart'; import '../artifacts.dart'; +import '../base/globals.dart'; +import '../build_configuration.dart'; import '../device.dart'; import '../toolchain.dart'; import 'flutter_command_runner.dart';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart index 65da945..a01c21f 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -10,7 +10,7 @@ import 'package:path/path.dart' as path; import '../artifacts.dart'; -import '../base/context.dart'; +import '../base/globals.dart'; import '../base/process.dart'; import '../build_configuration.dart'; import 'version.dart'; @@ -158,10 +158,15 @@ } Future<int> runCommand(ArgResults globalResults) { - if (globalResults['verbose']) - context.verbose = true; - _globalResults = globalResults; + + // Check for verbose. + if (globalResults['verbose']) + logger.verbose = true; + + // See if the user specified a specific device. + deviceManager.specifiedDeviceId = globalResults['device-id']; + ArtifactStore.flutterRoot = path.normalize(path.absolute(globalResults['flutter-root'])); if (globalResults.wasParsed('package-root')) ArtifactStore.packageRoot = path.normalize(path.absolute(globalResults['package-root']));
diff --git a/packages/flutter_tools/test/android_device_test.dart b/packages/flutter_tools/test/android_device_test.dart index 13122c3..1d34f1e 100644 --- a/packages/flutter_tools/test/android_device_test.dart +++ b/packages/flutter_tools/test/android_device_test.dart
@@ -5,11 +5,13 @@ import 'package:flutter_tools/src/android/device_android.dart'; import 'package:test/test.dart'; +import 'src/test_context.dart'; + main() => defineTests(); defineTests() { group('android_device', () { - test('stores the requested id', () { + testUsingContext('stores the requested id', () { String deviceId = '1234'; AndroidDevice device = new AndroidDevice(deviceId); expect(device.id, equals(deviceId));
diff --git a/packages/flutter_tools/test/context_test.dart b/packages/flutter_tools/test/context_test.dart index c7d81e2..74ecb0c 100644 --- a/packages/flutter_tools/test/context_test.dart +++ b/packages/flutter_tools/test/context_test.dart
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - -import 'package:flutter_tools/src/base/context.dart'; +import 'package:flutter_tools/src/base/context.dart' hide context; +import 'package:flutter_tools/src/base/globals.dart'; +import 'package:flutter_tools/src/base/logger.dart'; import 'package:test/test.dart'; main() => defineTests(); @@ -12,55 +12,45 @@ defineTests() { group('DeviceManager', () { test('error', () async { - MockContext mockContext = new MockContext(); + AppContext context = new AppContext(); + BufferLogger mockLogger = new BufferLogger(); + context[Logger] = mockLogger; - runZoned(() { + context.runInZone(() { printError('foo bar'); - }, zoneValues: {'context': mockContext}); + }); - expect(mockContext.errorText, 'foo bar\n'); - expect(mockContext.statusText, ''); - expect(mockContext.traceText, ''); + expect(mockLogger.errorText, 'foo bar\n'); + expect(mockLogger.statusText, ''); + expect(mockLogger.traceText, ''); }); test('status', () async { - MockContext mockContext = new MockContext(); + AppContext context = new AppContext(); + BufferLogger mockLogger = new BufferLogger(); + context[Logger] = mockLogger; - runZoned(() { + context.runInZone(() { printStatus('foo bar'); - }, zoneValues: {'context': mockContext}); + }); - expect(mockContext.errorText, ''); - expect(mockContext.statusText, 'foo bar\n'); - expect(mockContext.traceText, ''); + expect(mockLogger.errorText, ''); + expect(mockLogger.statusText, 'foo bar\n'); + expect(mockLogger.traceText, ''); }); test('trace', () async { - MockContext mockContext = new MockContext(); + AppContext context = new AppContext(); + BufferLogger mockLogger = new BufferLogger(); + context[Logger] = mockLogger; - runZoned(() { + context.runInZone(() { printTrace('foo bar'); - }, zoneValues: {'context': mockContext}); + }); - expect(mockContext.errorText, ''); - expect(mockContext.statusText, ''); - expect(mockContext.traceText, 'foo bar\n'); + expect(mockLogger.errorText, ''); + expect(mockLogger.statusText, ''); + expect(mockLogger.traceText, 'foo bar\n'); }); }); } - -class MockContext implements AppContext { - bool verbose = false; - - StringBuffer _error = new StringBuffer(); - StringBuffer _status = new StringBuffer(); - StringBuffer _trace = new StringBuffer(); - - String get errorText => _error.toString(); - String get statusText => _status.toString(); - String get traceText => _trace.toString(); - - void printError(String message, [StackTrace stackTrace]) => _error.writeln(message); - void printStatus(String message) => _status.writeln(message); - void printTrace(String message) => _trace.writeln(message); -}
diff --git a/packages/flutter_tools/test/create_test.dart b/packages/flutter_tools/test/create_test.dart index 69939aa..4e736d9 100644 --- a/packages/flutter_tools/test/create_test.dart +++ b/packages/flutter_tools/test/create_test.dart
@@ -11,6 +11,8 @@ import 'package:path/path.dart' as path; import 'package:test/test.dart'; +import 'src/test_context.dart'; + main() => defineTests(); defineTests() { @@ -31,7 +33,7 @@ // TODO(devoncarew): https://github.com/flutter/flutter/issues/1709 if (Platform.isLinux) { // Verify that we create a project that is well-formed. - test('flutter-simple', () async { + testUsingContext('flutter-simple', () async { ArtifactStore.flutterRoot = '../..'; CreateCommand command = new CreateCommand(); CommandRunner runner = new CommandRunner('test_flutter', '')
diff --git a/packages/flutter_tools/test/daemon_test.dart b/packages/flutter_tools/test/daemon_test.dart index d7a771f..7ad73a1 100644 --- a/packages/flutter_tools/test/daemon_test.dart +++ b/packages/flutter_tools/test/daemon_test.dart
@@ -5,6 +5,8 @@ import 'dart:async'; import 'package:flutter_tools/src/base/context.dart'; +import 'package:flutter_tools/src/base/globals.dart'; +import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/commands/daemon.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; @@ -16,10 +18,13 @@ defineTests() { group('daemon', () { Daemon daemon; - NotifyingAppContext appContext; + AppContext appContext; + NotifyingLogger notifyingLogger; setUp(() { - appContext = new NotifyingAppContext(); + appContext = new AppContext(); + notifyingLogger = new NotifyingLogger(); + appContext[Logger] = notifyingLogger; }); tearDown(() { @@ -33,7 +38,7 @@ daemon = new Daemon( commands.stream, (Map<String, dynamic> result) => responses.add(result), - appContext: appContext + notifyingLogger: notifyingLogger ); commands.add({'id': 0, 'method': 'daemon.version'}); Map response = await responses.stream.where(_notEvent).first; @@ -43,13 +48,13 @@ }); test('daemon.logMessage', () { - return runZoned(() async { + return appContext.runInZone(() async { StreamController<Map<String, dynamic>> commands = new StreamController(); StreamController<Map<String, dynamic>> responses = new StreamController(); daemon = new Daemon( commands.stream, (Map<String, dynamic> result) => responses.add(result), - appContext: appContext + notifyingLogger: notifyingLogger ); printError('daemon.logMessage test'); Map<String, dynamic> response = await responses.stream.where((Map<String, dynamic> map) { @@ -60,7 +65,7 @@ Map<String, String> logMessage = response['params']; expect(logMessage['level'], 'error'); expect(logMessage['message'], 'daemon.logMessage test'); - }, zoneValues: {'context': appContext}); + }); }); test('daemon.shutdown', () async { @@ -69,7 +74,7 @@ daemon = new Daemon( commands.stream, (Map<String, dynamic> result) => responses.add(result), - appContext: appContext + notifyingLogger: notifyingLogger ); commands.add({'id': 0, 'method': 'daemon.shutdown'}); return daemon.onExit.then((int code) { @@ -87,7 +92,7 @@ commands.stream, (Map<String, dynamic> result) => responses.add(result), daemonCommand: command, - appContext: appContext + notifyingLogger: notifyingLogger ); MockDeviceStore mockDevices = command.devices; @@ -113,7 +118,7 @@ daemon = new Daemon( commands.stream, (Map<String, dynamic> result) => responses.add(result), - appContext: appContext + notifyingLogger: notifyingLogger ); commands.add({'id': 0, 'method': 'device.getDevices'}); Map response = await responses.stream.where(_notEvent).first;
diff --git a/packages/flutter_tools/test/device_test.dart b/packages/flutter_tools/test/device_test.dart index 62903bd..dd9b5c6 100644 --- a/packages/flutter_tools/test/device_test.dart +++ b/packages/flutter_tools/test/device_test.dart
@@ -5,11 +5,13 @@ import 'package:flutter_tools/src/device.dart'; import 'package:test/test.dart'; +import 'src/test_context.dart'; + main() => defineTests(); defineTests() { group('DeviceManager', () { - test('getDevices', () async { + testUsingContext('getDevices', () async { // Test that DeviceManager.getDevices() doesn't throw. DeviceManager deviceManager = new DeviceManager(); List<Device> devices = await deviceManager.getDevices();
diff --git a/packages/flutter_tools/test/install_test.dart b/packages/flutter_tools/test/install_test.dart index c5c8776..f876456 100644 --- a/packages/flutter_tools/test/install_test.dart +++ b/packages/flutter_tools/test/install_test.dart
@@ -33,7 +33,7 @@ CommandRunner runner = new CommandRunner('test_flutter', '') ..addCommand(command); - runner.run(['install']).then((int code) => expect(code, equals(0))); + return runner.run(['install']).then((int code) => expect(code, equals(0))); }); test('returns 0 when iOS is connected and ready for an install', () { @@ -55,7 +55,7 @@ CommandRunner runner = new CommandRunner('test_flutter', '') ..addCommand(command); - runner.run(['install']).then((int code) => expect(code, equals(0))); + return runner.run(['install']).then((int code) => expect(code, equals(0))); }); }); }
diff --git a/packages/flutter_tools/test/list_test.dart b/packages/flutter_tools/test/list_test.dart index 91c05b7..f01949c 100644 --- a/packages/flutter_tools/test/list_test.dart +++ b/packages/flutter_tools/test/list_test.dart
@@ -10,12 +10,13 @@ import 'package:test/test.dart'; import 'src/mocks.dart'; +import 'src/test_context.dart'; main() => defineTests(); defineTests() { group('list', () { - test('returns 0 when called', () { + testUsingContext('returns 0 when called', () { final String mockCommand = Platform.isWindows ? 'cmd /c echo' : 'echo'; ListCommand command = new ListCommand(); @@ -36,9 +37,8 @@ // Instead, cause the test to run the echo command. when(mockDevices.iOSSimulator.xcrunPath).thenReturn(mockCommand); - CommandRunner runner = new CommandRunner('test_flutter', '') - ..addCommand(command); - runner.run(['list']).then((int code) => expect(code, equals(0))); + CommandRunner runner = new CommandRunner('test_flutter', '')..addCommand(command); + return runner.run(['list']).then((int code) => expect(code, equals(0))); }); }); }
diff --git a/packages/flutter_tools/test/listen_test.dart b/packages/flutter_tools/test/listen_test.dart index 18170bb..dcbf122 100644 --- a/packages/flutter_tools/test/listen_test.dart +++ b/packages/flutter_tools/test/listen_test.dart
@@ -9,12 +9,13 @@ import 'package:test/test.dart'; import 'src/mocks.dart'; +import 'src/test_context.dart'; main() => defineTests(); defineTests() { group('listen', () { - test('returns 0 when no device is connected', () { + testUsingContext('returns 0 when no device is connected', () { ListenCommand command = new ListenCommand(singleRun: true); applyMocksToCommand(command); MockDeviceStore mockDevices = command.devices; @@ -24,7 +25,7 @@ when(mockDevices.iOSSimulator.isConnected()).thenReturn(false); CommandRunner runner = new FlutterCommandRunner()..addCommand(command); - runner.run(['listen']).then((int code) => expect(code, equals(0))); + return runner.run(['listen']).then((int code) => expect(code, equals(0))); }); }); }
diff --git a/packages/flutter_tools/test/logs_test.dart b/packages/flutter_tools/test/logs_test.dart index 1e5590b..2dd67d5 100644 --- a/packages/flutter_tools/test/logs_test.dart +++ b/packages/flutter_tools/test/logs_test.dart
@@ -8,16 +8,17 @@ import 'package:test/test.dart'; import 'src/mocks.dart'; +import 'src/test_context.dart'; main() => defineTests(); defineTests() { group('logs', () { - test('fail with a bad device id', () { + testUsingContext('fail with a bad device id', () { LogsCommand command = new LogsCommand(); applyMocksToCommand(command); CommandRunner runner = new FlutterCommandRunner()..addCommand(command); - runner.run(<String>['-d', 'abc123', 'logs']).then((int code) { + return runner.run(<String>['-d', 'abc123', 'logs']).then((int code) { expect(code, equals(1)); }); });
diff --git a/packages/flutter_tools/test/src/test_context.dart b/packages/flutter_tools/test/src/test_context.dart new file mode 100644 index 0000000..c5a5d9d --- /dev/null +++ b/packages/flutter_tools/test/src/test_context.dart
@@ -0,0 +1,30 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter_tools/src/base/context.dart'; +import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/device.dart'; +import 'package:test/test.dart'; + +void testUsingContext(String description, dynamic testMethod(), { Timeout timeout }) { + test(description, () { + AppContext testContext = new AppContext(); + + testContext[Logger] = new BufferLogger(); + testContext[DeviceManager] = new MockDeviceManager(); + + return testContext.runInZone(testMethod); + }, timeout: timeout); +} + +class MockDeviceManager implements DeviceManager { + String specifiedDeviceId; + bool get hasSpecifiedDeviceId => specifiedDeviceId != null; + + Future<List<Device>> getAllConnectedDevices() => new Future.value(<Device>[]); + Future<Device> getDeviceById(String deviceId) => new Future.value(null); + Future<List<Device>> getDevices() => getAllConnectedDevices(); +}
diff --git a/packages/flutter_tools/test/stop_test.dart b/packages/flutter_tools/test/stop_test.dart index 40583cd..f700e3b 100644 --- a/packages/flutter_tools/test/stop_test.dart +++ b/packages/flutter_tools/test/stop_test.dart
@@ -29,7 +29,7 @@ CommandRunner runner = new CommandRunner('test_flutter', '') ..addCommand(command); - runner.run(['stop']).then((int code) => expect(code, equals(0))); + return runner.run(['stop']).then((int code) => expect(code, equals(0))); }); test('returns 0 when iOS is connected and ready to be stopped', () { @@ -48,7 +48,7 @@ CommandRunner runner = new CommandRunner('test_flutter', '') ..addCommand(command); - runner.run(['stop']).then((int code) => expect(code, equals(0))); + return runner.run(['stop']).then((int code) => expect(code, equals(0))); }); }); }
diff --git a/packages/flutter_tools/test/trace_test.dart b/packages/flutter_tools/test/trace_test.dart index e55648c..279e7a8 100644 --- a/packages/flutter_tools/test/trace_test.dart +++ b/packages/flutter_tools/test/trace_test.dart
@@ -8,12 +8,13 @@ import 'package:test/test.dart'; import 'src/mocks.dart'; +import 'src/test_context.dart'; main() => defineTests(); defineTests() { group('trace', () { - test('returns 1 when no Android device is connected', () { + testUsingContext('returns 1 when no Android device is connected', () { TraceCommand command = new TraceCommand(); applyMocksToCommand(command); MockDeviceStore mockDevices = command.devices; @@ -22,7 +23,7 @@ CommandRunner runner = new CommandRunner('test_flutter', '') ..addCommand(command); - runner.run(['trace']).then((int code) => expect(code, equals(1))); + return runner.run(['trace']).then((int code) => expect(code, equals(1))); }); }); }