Remove default AppContext and cleanup globals (#6999)
diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 2f1406d..90e20cd 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart
@@ -40,6 +40,7 @@ import 'src/doctor.dart'; import 'src/globals.dart'; import 'src/hot.dart'; +import 'src/usage.dart'; import 'src/runner/flutter_command_runner.dart'; /// Main entry point for commands. @@ -81,8 +82,12 @@ ..addCommand(new UpdatePackagesCommand(hidden: !verboseHelp)) ..addCommand(new UpgradeCommand()); - return Chain.capture/*<Future<Null>>*/(() async { - // Initialize globals. + // Construct a context. + AppContext _executableContext = new AppContext(); + + // Make the context current. + _executableContext.runInZone(() { + // Initialize the context with some defaults. if (context[Logger] == null) context[Logger] = new StdoutLogger(); if (context[DeviceManager] == null) @@ -94,56 +99,58 @@ if (context[HotRunnerConfig] == null) context[HotRunnerConfig] = new HotRunnerConfig(); - await runner.run(args); - _exit(0); - }, onError: (dynamic error, Chain chain) { - if (error is UsageException) { - stderr.writeln(error.message); - stderr.writeln(); - stderr.writeln( - "Run 'flutter -h' (or 'flutter <command> -h') for available " - "flutter commands and options." - ); - // Argument error exit code. - _exit(64); - } else if (error is ToolExit) { - if (error.message != null) + return Chain.capture/*<Future<Null>>*/(() async { + await runner.run(args); + _exit(0); + }, onError: (dynamic error, Chain chain) { + if (error is UsageException) { stderr.writeln(error.message); - if (verbose) { stderr.writeln(); - stderr.writeln(chain.terse.toString()); - stderr.writeln(); - } - _exit(error.exitCode ?? 1); - } else if (error is ProcessExit) { - // We've caught an exit code. - _exit(error.exitCode); - } else { - // We've crashed; emit a log report. - stderr.writeln(); - - flutterUsage.sendException(error, chain); - - if (isRunningOnBot) { - // Print the stack trace on the bots - don't write a crash report. - stderr.writeln('$error'); - stderr.writeln(chain.terse.toString()); - _exit(1); + stderr.writeln( + "Run 'flutter -h' (or 'flutter <command> -h') for available " + "flutter commands and options." + ); + // Argument error exit code. + _exit(64); + } else if (error is ToolExit) { + if (error.message != null) + stderr.writeln(error.message); + if (verbose) { + stderr.writeln(); + stderr.writeln(chain.terse.toString()); + stderr.writeln(); + } + _exit(error.exitCode ?? 1); + } else if (error is ProcessExit) { + // We've caught an exit code. + _exit(error.exitCode); } else { - if (error is String) - stderr.writeln('Oops; flutter has exited unexpectedly: "$error".'); - else - stderr.writeln('Oops; flutter has exited unexpectedly.'); + // We've crashed; emit a log report. + stderr.writeln(); - _createCrashReport(args, error, chain).then((File file) { - stderr.writeln( - 'Crash report written to ${file.path};\n' - 'please let us know at https://github.com/flutter/flutter/issues.' - ); + flutterUsage.sendException(error, chain); + + if (isRunningOnBot) { + // Print the stack trace on the bots - don't write a crash report. + stderr.writeln('$error'); + stderr.writeln(chain.terse.toString()); _exit(1); - }); + } else { + if (error is String) + stderr.writeln('Oops; flutter has exited unexpectedly: "$error".'); + else + stderr.writeln('Oops; flutter has exited unexpectedly.'); + + _createCrashReport(args, error, chain).then((File file) { + stderr.writeln( + 'Crash report written to ${file.path};\n' + 'please let us know at https://github.com/flutter/flutter/issues.' + ); + _exit(1); + }); + } } - } + }); }); }
diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart index 42ab963..caf9686 100644 --- a/packages/flutter_tools/lib/src/android/android_sdk.dart +++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -8,9 +8,12 @@ import 'package:pub_semver/pub_semver.dart'; import '../base/common.dart'; +import '../base/context.dart'; import '../base/os.dart'; import '../globals.dart'; +AndroidSdk get androidSdk => context[AndroidSdk]; + const String kAndroidHome = 'ANDROID_HOME'; // Android SDK layout:
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index d7a68cf..5ed8341 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -7,6 +7,7 @@ import 'package:path/path.dart' as path; import 'package:xml/xml.dart' as xml; +import 'android/android_sdk.dart'; import 'android/gradle.dart'; import 'base/os.dart' show os; import 'base/process.dart';
diff --git a/packages/flutter_tools/lib/src/base/context.dart b/packages/flutter_tools/lib/src/base/context.dart index 12d9156..3cb1189 100644 --- a/packages/flutter_tools/lib/src/base/context.dart +++ b/packages/flutter_tools/lib/src/base/context.dart
@@ -4,16 +4,11 @@ import 'dart:async'; -final AppContext _defaultContext = new AppContext(); - typedef void ErrorHandler(dynamic error, StackTrace stackTrace); /// A singleton for application functionality. This singleton can be different /// on a per-Zone basis. -AppContext get context { - AppContext currentContext = Zone.current['context']; - return currentContext == null ? _defaultContext : currentContext; -} +AppContext get context => Zone.current['context']; class AppContext { Map<Type, dynamic> _instances = <Type, dynamic>{}; @@ -44,18 +39,15 @@ 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; + return null; AppContext deps = parentZone['context']; if (deps == this) { return _calcParent(parentZone); } else { - return deps != null ? deps : _defaultContext; + return deps; } }
diff --git a/packages/flutter_tools/lib/src/base/os.dart b/packages/flutter_tools/lib/src/base/os.dart index 9d54555..9a4290a 100644 --- a/packages/flutter_tools/lib/src/base/os.dart +++ b/packages/flutter_tools/lib/src/base/os.dart
@@ -13,11 +13,11 @@ /// Returns [OperatingSystemUtils] active in the current app context (i.e. zone). OperatingSystemUtils get os { - return context[OperatingSystemUtils] ?? (context[OperatingSystemUtils] = new OperatingSystemUtils._()); + return context[OperatingSystemUtils] ?? (context[OperatingSystemUtils] = new OperatingSystemUtils()); } abstract class OperatingSystemUtils { - factory OperatingSystemUtils._() { + factory OperatingSystemUtils() { if (Platform.isWindows) { return new _WindowsUtils(); } else {
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index 45e2c62..bcadae2 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -6,6 +6,7 @@ import 'package:path/path.dart' as path; +import 'base/context.dart'; import 'base/utils.dart'; import 'globals.dart'; @@ -118,6 +119,11 @@ /// Returns the top-level build output directory. String getBuildDirectory() { + // TODO(johnmccutchan): Stop calling this function as part of setting + // up command line argument processing. + if (context == null) + return 'build'; + String buildDir = config.getValue('build-dir') ?? 'build'; if (path.isAbsolute(buildDir)) { throw new Exception(
diff --git a/packages/flutter_tools/lib/src/commands/config.dart b/packages/flutter_tools/lib/src/commands/config.dart index af16a39..cc1340d 100644 --- a/packages/flutter_tools/lib/src/commands/config.dart +++ b/packages/flutter_tools/lib/src/commands/config.dart
@@ -5,6 +5,7 @@ import 'dart:async'; import '../globals.dart'; +import '../usage.dart'; import '../runner/flutter_command.dart'; class ConfigCommand extends FlutterCommand {
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart index 7676e8c..3d21f16 100644 --- a/packages/flutter_tools/lib/src/commands/create.dart +++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -12,6 +12,7 @@ import '../base/utils.dart'; import '../cache.dart'; import '../dart/pub.dart'; +import '../doctor.dart'; import '../globals.dart'; import '../runner/flutter_command.dart'; import '../template.dart';
diff --git a/packages/flutter_tools/lib/src/commands/devices.dart b/packages/flutter_tools/lib/src/commands/devices.dart index 687a3ac..4547ade 100644 --- a/packages/flutter_tools/lib/src/commands/devices.dart +++ b/packages/flutter_tools/lib/src/commands/devices.dart
@@ -7,6 +7,7 @@ import '../base/common.dart'; import '../base/utils.dart'; import '../device.dart'; +import '../doctor.dart'; import '../globals.dart'; import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/doctor.dart b/packages/flutter_tools/lib/src/commands/doctor.dart index f1a6a17..df4da8c 100644 --- a/packages/flutter_tools/lib/src/commands/doctor.dart +++ b/packages/flutter_tools/lib/src/commands/doctor.dart
@@ -4,7 +4,7 @@ import 'dart:async'; -import '../globals.dart'; +import '../doctor.dart'; import '../runner/flutter_command.dart'; class DoctorCommand extends FlutterCommand {
diff --git a/packages/flutter_tools/lib/src/commands/setup.dart b/packages/flutter_tools/lib/src/commands/setup.dart index 4f3b0cf..afc2326 100644 --- a/packages/flutter_tools/lib/src/commands/setup.dart +++ b/packages/flutter_tools/lib/src/commands/setup.dart
@@ -7,6 +7,7 @@ import '../base/common.dart'; import '../base/os.dart'; import '../base/process.dart'; +import '../doctor.dart'; import '../globals.dart'; import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart index 2e5c8d0..21295fd 100644 --- a/packages/flutter_tools/lib/src/commands/upgrade.dart +++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -7,9 +7,10 @@ import '../base/common.dart'; import '../base/os.dart'; import '../base/process.dart'; +import '../cache.dart'; import '../dart/pub.dart'; import '../dart/summary.dart'; -import '../cache.dart'; +import '../doctor.dart'; import '../globals.dart'; import '../runner/flutter_command.dart'; import '../version.dart';
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 1f9e7a2..67354df 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -9,6 +9,7 @@ import 'android/android_device.dart'; import 'application_package.dart'; import 'base/common.dart'; +import 'base/context.dart'; import 'base/os.dart'; import 'base/utils.dart'; import 'build_info.dart'; @@ -16,6 +17,8 @@ import 'ios/devices.dart'; import 'ios/simulators.dart'; +DeviceManager get deviceManager => context[DeviceManager]; + /// A class to get all available devices. class DeviceManager { /// Constructing DeviceManagers is cheap; they only do expensive work if some
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart index 6161d87..fb97905 100644 --- a/packages/flutter_tools/lib/src/doctor.dart +++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -9,11 +9,14 @@ import 'android/android_workflow.dart'; import 'base/common.dart'; +import 'base/context.dart'; import 'device.dart'; import 'globals.dart'; import 'ios/ios_workflow.dart'; import 'version.dart'; +Doctor get doctor => context[Doctor]; + const Map<String, String> _osNames = const <String, String>{ 'macos': 'Mac OS', 'linux': 'Linux',
diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart index 0d7f4f9..1ca818b 100644 --- a/packages/flutter_tools/lib/src/globals.dart +++ b/packages/flutter_tools/lib/src/globals.dart
@@ -2,24 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'android/android_sdk.dart'; import 'base/config.dart'; import 'base/context.dart'; import 'base/logger.dart'; import 'cache.dart'; -import 'device.dart'; -import 'doctor.dart'; import 'toolchain.dart'; -import 'usage.dart'; -DeviceManager get deviceManager => context[DeviceManager]; Logger get logger => context[Logger]; -AndroidSdk get androidSdk => context[AndroidSdk]; Cache get cache => Cache.instance; Config get config => Config.instance; -Doctor get doctor => context[Doctor]; ToolConfiguration get tools => ToolConfiguration.instance; -Usage get flutterUsage => Usage.instance; /// Display an error level message to the user. Commands should use this if they /// fail in some way.
diff --git a/packages/flutter_tools/lib/src/hot.dart b/packages/flutter_tools/lib/src/hot.dart index 4b3fa80..ec4f3ef 100644 --- a/packages/flutter_tools/lib/src/hot.dart +++ b/packages/flutter_tools/lib/src/hot.dart
@@ -24,6 +24,7 @@ import 'resident_runner.dart'; import 'toolchain.dart'; import 'vmservice.dart'; +import 'usage.dart'; class HotRunnerConfig { /// Should the hot runner compute the minimal Dart dependencies?
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 9970159..d2aa790 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -11,6 +11,7 @@ import '../base/process.dart'; import '../build_info.dart'; import '../device.dart'; +import '../doctor.dart'; import '../globals.dart'; import '../protocol_discovery.dart'; import 'mac.dart';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index e38c53c..747bb1e 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -14,6 +14,7 @@ import '../dart/package_map.dart'; import '../dart/pub.dart'; import '../device.dart'; +import '../doctor.dart'; import '../flx.dart' as flx; import '../globals.dart'; import '../usage.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 8edc60b..f023058 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -15,8 +15,10 @@ import '../base/process.dart'; import '../cache.dart'; import '../dart/package_map.dart'; +import '../device.dart'; import '../globals.dart'; import '../toolchain.dart'; +import '../usage.dart'; import '../version.dart'; const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
diff --git a/packages/flutter_tools/lib/src/services.dart b/packages/flutter_tools/lib/src/services.dart index 91ae97a1..824dd14 100644 --- a/packages/flutter_tools/lib/src/services.dart +++ b/packages/flutter_tools/lib/src/services.dart
@@ -10,6 +10,7 @@ import 'package:yaml/yaml.dart'; import 'dart/package_map.dart'; +import 'android/android_sdk.dart'; import 'globals.dart'; const String _kFlutterManifestPath = 'flutter.yaml';
diff --git a/packages/flutter_tools/lib/src/usage.dart b/packages/flutter_tools/lib/src/usage.dart index cca4a7f..503a0b7 100644 --- a/packages/flutter_tools/lib/src/usage.dart +++ b/packages/flutter_tools/lib/src/usage.dart
@@ -16,6 +16,8 @@ const String _kFlutterUA = 'UA-67589403-6'; +Usage get flutterUsage => Usage.instance; + class Usage { /// Create a new Usage instance; [versionOverride] is used for testing. Usage({ String settingsName: 'flutter', String versionOverride }) {
diff --git a/packages/flutter_tools/test/analytics_test.dart b/packages/flutter_tools/test/analytics_test.dart index 789d7fc..99c3108 100644 --- a/packages/flutter_tools/test/analytics_test.dart +++ b/packages/flutter_tools/test/analytics_test.dart
@@ -9,7 +9,6 @@ import 'package:flutter_tools/src/commands/create.dart'; import 'package:flutter_tools/src/commands/config.dart'; import 'package:flutter_tools/src/commands/doctor.dart'; -import 'package:flutter_tools/src/globals.dart'; import 'package:flutter_tools/src/usage.dart'; import 'package:test/test.dart'; @@ -19,16 +18,13 @@ void main() { group('analytics', () { Directory temp; - bool wasEnabled; setUp(() { Cache.flutterRoot = '../..'; - wasEnabled = flutterUsage.enabled; temp = Directory.systemTemp.createTempSync('flutter_tools'); }); tearDown(() { - flutterUsage.enabled = wasEnabled; temp.deleteSync(recursive: true); });
diff --git a/packages/flutter_tools/test/analyze_duplicate_names_test.dart b/packages/flutter_tools/test/analyze_duplicate_names_test.dart index 7fbe33e..73cd4f5 100644 --- a/packages/flutter_tools/test/analyze_duplicate_names_test.dart +++ b/packages/flutter_tools/test/analyze_duplicate_names_test.dart
@@ -4,7 +4,6 @@ import 'dart:io'; -import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; @@ -26,7 +25,6 @@ group('analyze', () { testUsingContext('flutter analyze with two files with the same name', () async { - File dartFileA = new File(path.join(tempDir.path, 'a.dart')); dartFileA.parent.createSync(); dartFileA.writeAsStringSync('library test;'); @@ -41,8 +39,6 @@ expect(testLogger.statusText, startsWith('Analyzing 2 files...\nNo analyzer warnings!')); }); - }, overrides: <Type, dynamic>{ - OperatingSystemUtils: os }); }); }
diff --git a/packages/flutter_tools/test/os_utils_test.dart b/packages/flutter_tools/test/os_utils_test.dart index 87a7c28..ac37d56 100644 --- a/packages/flutter_tools/test/os_utils_test.dart +++ b/packages/flutter_tools/test/os_utils_test.dart
@@ -4,6 +4,8 @@ import 'dart:io'; +import 'src/context.dart'; + import 'package:flutter_tools/src/base/os.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; @@ -20,7 +22,7 @@ temp.deleteSync(recursive: true); }); - test('makeExecutable', () { + testUsingContext('makeExecutable', () async { File file = new File(path.join(temp.path, 'foo.script')); file.writeAsStringSync('hello world'); os.makeExecutable(file); @@ -31,6 +33,8 @@ // rwxr--r-- expect(mode.substring(0, 3), endsWith('x')); } + }, overrides: <Type, dynamic> { + OperatingSystemUtils: new OperatingSystemUtils(), }); }); }