refactor context to be implicit-downcast safe (#31622)

diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart
index 3e9cad6..e2bf600 100644
--- a/packages/flutter_tools/lib/src/base/build.dart
+++ b/packages/flutter_tools/lib/src/base/build.dart
@@ -21,7 +21,7 @@
 import 'fingerprint.dart';
 import 'process.dart';
 
-GenSnapshot get genSnapshot => context[GenSnapshot];
+GenSnapshot get genSnapshot => context.get<GenSnapshot>();
 
 /// A snapshot build configuration.
 class SnapshotType {
diff --git a/packages/flutter_tools/lib/src/base/config.dart b/packages/flutter_tools/lib/src/base/config.dart
index 54c440c..388e989 100644
--- a/packages/flutter_tools/lib/src/base/config.dart
+++ b/packages/flutter_tools/lib/src/base/config.dart
@@ -14,7 +14,7 @@
       _values = json.decode(_configFile.readAsStringSync());
   }
 
-  static Config get instance => context[Config];
+  static Config get instance => context.get<Config>();
 
   File _configFile;
   String get configPath => _configFile.path;
diff --git a/packages/flutter_tools/lib/src/base/context.dart b/packages/flutter_tools/lib/src/base/context.dart
index 5bc60d5..84fc8fc 100644
--- a/packages/flutter_tools/lib/src/base/context.dart
+++ b/packages/flutter_tools/lib/src/base/context.dart
@@ -33,7 +33,7 @@
 /// context will not have any values associated with it.
 ///
 /// This is guaranteed to never return `null`.
-AppContext get context => Zone.current[_Key.key] ?? AppContext._root;
+AppContext get context => Zone.current[_Key.key] as AppContext ?? AppContext._root;
 
 /// A lookup table (mapping types to values) and an implied scope, in which
 /// code is run.
@@ -107,6 +107,17 @@
 
   /// Gets the value associated with the specified [type], or `null` if no
   /// such value has been associated.
+  T get<T>() {
+    dynamic value = _generateIfNecessary(T, _overrides);
+    if (value == null && _parent != null) {
+      value = _parent.get<T>();
+    }
+    return _unboxNull(value ?? _generateIfNecessary(T, _fallbacks)) as T;
+  }
+
+  /// Gets the value associated with the specified [type], or `null` if no
+  /// such value has been associated.
+  @Deprecated('use get<T> instead for type safety.')
   Object operator [](Type type) {
     dynamic value = _generateIfNecessary(type, _overrides);
     if (value == null && _parent != null)
diff --git a/packages/flutter_tools/lib/src/base/file_system.dart b/packages/flutter_tools/lib/src/base/file_system.dart
index 5bb23ab..94de99c 100644
--- a/packages/flutter_tools/lib/src/base/file_system.dart
+++ b/packages/flutter_tools/lib/src/base/file_system.dart
@@ -23,7 +23,7 @@
 ///
 /// By default it uses local disk-based implementation. Override this in tests
 /// with [MemoryFileSystem].
-FileSystem get fs => context[FileSystem] ?? _kLocalFs;
+FileSystem get fs => context.get<FileSystem>() ?? _kLocalFs;
 
 /// Gets a [FileSystem] that will record file system activity to the specified
 /// base recording [location].
diff --git a/packages/flutter_tools/lib/src/base/flags.dart b/packages/flutter_tools/lib/src/base/flags.dart
index 81442a9..b4e3ab1 100644
--- a/packages/flutter_tools/lib/src/base/flags.dart
+++ b/packages/flutter_tools/lib/src/base/flags.dart
@@ -8,7 +8,7 @@
 
 /// command-line flags and options that were specified during the invocation of
 /// the Flutter tool.
-Flags get flags => context[Flags];
+Flags get flags => context.get<Flags>();
 
 /// Encapsulation of the command-line flags and options that were specified
 /// during the invocation of the Flutter tool.
diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart
index 1c9761e..4c9d225 100644
--- a/packages/flutter_tools/lib/src/base/io.dart
+++ b/packages/flutter_tools/lib/src/base/io.dart
@@ -163,7 +163,7 @@
   bool get supportsAnsiEscapes => hasTerminal ? io.stdout.supportsAnsiEscapes : false;
 }
 
-Stdio get stdio => context[Stdio];
+Stdio get stdio => context.get<Stdio>();
 io.IOSink get stdout => stdio.stdout;
 Stream<List<int>> get stdin => stdio.stdin;
 io.IOSink get stderr => stdio.stderr;
diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart
index b1402d2..e9e508b 100644
--- a/packages/flutter_tools/lib/src/base/logger.dart
+++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -19,7 +19,7 @@
 /// The [TimeoutConfiguration] instance.
 ///
 /// If not provided via injection, a default instance is provided.
-TimeoutConfiguration get timeoutConfiguration => context[TimeoutConfiguration] ?? const TimeoutConfiguration();
+TimeoutConfiguration get timeoutConfiguration => context.get<TimeoutConfiguration>() ?? const TimeoutConfiguration();
 
 class TimeoutConfiguration {
   const TimeoutConfiguration();
@@ -486,7 +486,7 @@
   final VoidCallback onFinish;
 
   @protected
-  final Stopwatch _stopwatch = context[Stopwatch] ?? Stopwatch();
+  final Stopwatch _stopwatch = context.get<Stopwatch>() ?? Stopwatch();
 
   @protected
   @visibleForTesting
diff --git a/packages/flutter_tools/lib/src/base/net.dart b/packages/flutter_tools/lib/src/base/net.dart
index 742bd8b..f139c9d 100644
--- a/packages/flutter_tools/lib/src/base/net.dart
+++ b/packages/flutter_tools/lib/src/base/net.dart
@@ -36,8 +36,8 @@
 Future<List<int>> _attempt(Uri url, { bool onlyHeaders = false }) async {
   printTrace('Downloading: $url');
   HttpClient httpClient;
-  if (context[HttpClientFactory] != null) {
-    httpClient = (context[HttpClientFactory] as HttpClientFactory)(); // ignore: avoid_as
+  if (context.get<HttpClientFactory>() != null) {
+    httpClient = context.get<HttpClientFactory>()();
   } else {
     httpClient = HttpClient();
   }
diff --git a/packages/flutter_tools/lib/src/base/os.dart b/packages/flutter_tools/lib/src/base/os.dart
index dd75337..30c832e 100644
--- a/packages/flutter_tools/lib/src/base/os.dart
+++ b/packages/flutter_tools/lib/src/base/os.dart
@@ -11,7 +11,7 @@
 import 'process_manager.dart';
 
 /// Returns [OperatingSystemUtils] active in the current app context (i.e. zone).
-OperatingSystemUtils get os => context[OperatingSystemUtils];
+OperatingSystemUtils get os => context.get<OperatingSystemUtils>();
 
 abstract class OperatingSystemUtils {
   factory OperatingSystemUtils() {
diff --git a/packages/flutter_tools/lib/src/base/platform.dart b/packages/flutter_tools/lib/src/base/platform.dart
index 359cc5f..9ab824d 100644
--- a/packages/flutter_tools/lib/src/base/platform.dart
+++ b/packages/flutter_tools/lib/src/base/platform.dart
@@ -14,7 +14,7 @@
 const Platform _kLocalPlatform = LocalPlatform();
 const String _kRecordingType = 'platform';
 
-Platform get platform => context[Platform] ?? _kLocalPlatform;
+Platform get platform => context.get<Platform>() ?? _kLocalPlatform;
 
 /// Serializes the current [platform] to the specified base recording
 /// [location].
diff --git a/packages/flutter_tools/lib/src/base/process_manager.dart b/packages/flutter_tools/lib/src/base/process_manager.dart
index cbf8661..5929ef9 100644
--- a/packages/flutter_tools/lib/src/base/process_manager.dart
+++ b/packages/flutter_tools/lib/src/base/process_manager.dart
@@ -16,7 +16,7 @@
 const ProcessManager _kLocalProcessManager = LocalProcessManager();
 
 /// The active process manager.
-ProcessManager get processManager => context[ProcessManager] ?? _kLocalProcessManager;
+ProcessManager get processManager => context.get<ProcessManager>() ?? _kLocalProcessManager;
 
 /// Gets a [ProcessManager] that will record process invocation activity to the
 /// specified base recording [location].
diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart
index 8f9eb45..396b9a2 100644
--- a/packages/flutter_tools/lib/src/base/terminal.dart
+++ b/packages/flutter_tools/lib/src/base/terminal.dart
@@ -14,9 +14,9 @@
 final AnsiTerminal _kAnsiTerminal = AnsiTerminal();
 
 AnsiTerminal get terminal {
-  return (context == null || context[AnsiTerminal] == null)
+  return (context == null || context.get<AnsiTerminal>() == null)
       ? _kAnsiTerminal
-      : context[AnsiTerminal];
+      : context.get<AnsiTerminal>();
 }
 
 enum TerminalColor {
@@ -31,9 +31,9 @@
 
 final OutputPreferences _kOutputPreferences = OutputPreferences();
 
-OutputPreferences get outputPreferences => (context == null || context[OutputPreferences] == null)
+OutputPreferences get outputPreferences => (context == null || context.get<OutputPreferences>() == null)
     ? _kOutputPreferences
-    : context[OutputPreferences];
+    : context.get<OutputPreferences>();
 
 /// A class that contains the context settings for command text output to the
 /// console.
diff --git a/packages/flutter_tools/lib/src/base/time.dart b/packages/flutter_tools/lib/src/base/time.dart
index 5ba7e02..685fde2 100644
--- a/packages/flutter_tools/lib/src/base/time.dart
+++ b/packages/flutter_tools/lib/src/base/time.dart
@@ -5,7 +5,7 @@
 import 'context.dart';
 
 /// The current system clock instance.
-SystemClock get systemClock => context[SystemClock];
+SystemClock get systemClock => context.get<SystemClock>();
 
 /// A class for making time based operations testable.
 class SystemClock {
diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart
index 104d364..58b83e8 100644
--- a/packages/flutter_tools/lib/src/base/user_messages.dart
+++ b/packages/flutter_tools/lib/src/base/user_messages.dart
@@ -4,7 +4,7 @@
 
 import 'context.dart';
 
-UserMessages get userMessages => context[UserMessages];
+UserMessages get userMessages => context.get<UserMessages>();
 
 /// Class containing message strings that can be produced by Flutter tools.
 class UserMessages {
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index a18ae8b..71f835e 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -49,7 +49,7 @@
 }
 
 bool get isRunningOnBot {
-  final BotDetector botDetector = context[BotDetector] ?? _kBotDetector;
+  final BotDetector botDetector = context.get<BotDetector>() ?? _kBotDetector;
   return botDetector.isRunningOnBot;
 }