Make AppContext immutable and race-free (#15984)
This updates AppContext per the recommendations in #15352
Fixes #15352
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 5d8bc67..9abaec3 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -4,38 +4,73 @@
import 'dart:async';
-import 'package:process/process.dart';
+import 'package:quiver/time.dart';
+import 'android/android_sdk.dart';
+import 'android/android_studio.dart';
+import 'android/android_workflow.dart';
+import 'artifacts.dart';
+import 'asset.dart';
+import 'base/build.dart';
import 'base/config.dart';
import 'base/context.dart';
-import 'base/file_system.dart';
+import 'base/flags.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'base/os.dart';
import 'base/platform.dart';
+import 'base/port_scanner.dart';
import 'base/utils.dart';
import 'cache.dart';
-import 'disabled_usage.dart';
+import 'devfs.dart';
+import 'device.dart';
+import 'doctor.dart';
+import 'ios/cocoapods.dart';
+import 'ios/ios_workflow.dart';
+import 'ios/mac.dart';
+import 'ios/simulators.dart';
+import 'ios/xcodeproj.dart';
+import 'run_hot.dart';
import 'usage.dart';
+import 'version.dart';
-typedef Future<Null> Runner(List<String> args);
-
-Future<Null> runInContext(List<String> args, Runner runner) {
- final AppContext executableContext = new AppContext();
- executableContext.setVariable(Logger, new StdoutLogger());
- return executableContext.runInZone(() {
- // Initialize the context with some defaults.
- // This list must be kept in sync with lib/executable.dart.
- context.putIfAbsent(BotDetector, () => const BotDetector());
- context.putIfAbsent(Stdio, () => const Stdio());
- context.putIfAbsent(Platform, () => const LocalPlatform());
- context.putIfAbsent(FileSystem, () => const LocalFileSystem());
- context.putIfAbsent(ProcessManager, () => const LocalProcessManager());
- context.putIfAbsent(Logger, () => new StdoutLogger());
- context.putIfAbsent(Cache, () => new Cache());
- context.putIfAbsent(Config, () => new Config());
- context.putIfAbsent(OperatingSystemUtils, () => new OperatingSystemUtils());
- context.putIfAbsent(Usage, () => new DisabledUsage());
- return runner(args);
- });
+Future<T> runInContext<T>(
+ FutureOr<T> runner(), {
+ Map<Type, dynamic> overrides,
+}) async {
+ return await context.run<Future<T>>(
+ name: 'global fallbacks',
+ body: () async => await runner(),
+ overrides: overrides,
+ fallbacks: <Type, Generator>{
+ AndroidSdk: AndroidSdk.locateAndroidSdk,
+ AndroidStudio: AndroidStudio.latestValid,
+ AndroidWorkflow: () => new AndroidWorkflow(),
+ Artifacts: () => new CachedArtifacts(),
+ AssetBundleFactory: () => AssetBundleFactory.defaultInstance,
+ BotDetector: () => const BotDetector(),
+ Cache: () => new Cache(),
+ Clock: () => const Clock(),
+ CocoaPods: () => const CocoaPods(),
+ Config: () => new Config(),
+ DevFSConfig: () => new DevFSConfig(),
+ DeviceManager: () => new DeviceManager(),
+ Doctor: () => new Doctor(),
+ Flags: () => const EmptyFlags(),
+ FlutterVersion: () => new FlutterVersion(const Clock()),
+ GenSnapshot: () => const GenSnapshot(),
+ HotRunnerConfig: () => new HotRunnerConfig(),
+ IMobileDevice: () => const IMobileDevice(),
+ IOSSimulatorUtils: () => new IOSSimulatorUtils(),
+ IOSWorkflow: () => const IOSWorkflow(),
+ Logger: () => platform.isWindows ? new WindowsStdoutLogger() : new StdoutLogger(),
+ OperatingSystemUtils: () => new OperatingSystemUtils(),
+ PortScanner: () => const HostPortScanner(),
+ SimControl: () => new SimControl(),
+ Stdio: () => const Stdio(),
+ Usage: () => new Usage(),
+ Xcode: () => new Xcode(),
+ XcodeProjectInterpreter: () => new XcodeProjectInterpreter(),
+ },
+ );
}