More AppContext cleanups (#7073)

diff --git a/packages/flutter_tools/lib/src/base/config.dart b/packages/flutter_tools/lib/src/base/config.dart
index c92d42f..6a53013 100644
--- a/packages/flutter_tools/lib/src/base/config.dart
+++ b/packages/flutter_tools/lib/src/base/config.dart
@@ -16,7 +16,7 @@
       _values = JSON.decode(_configFile.readAsStringSync());
   }
 
-  static Config get instance => context[Config] ?? (context[Config] = new Config());
+  static Config get instance => context[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 3cb1189..96a21f1 100644
--- a/packages/flutter_tools/lib/src/base/context.dart
+++ b/packages/flutter_tools/lib/src/base/context.dart
@@ -36,7 +36,15 @@
 
   dynamic operator[](Type type) => getVariable(type);
 
-  void operator[]=(Type type, dynamic instance) => setVariable(type, instance);
+  dynamic putIfAbsent(Type type, dynamic ifAbsent()) {
+    dynamic value = getVariable(type);
+    if (value != null) {
+      return value;
+    }
+    value = ifAbsent();
+    setVariable(type, value);
+    return value;
+  }
 
   AppContext _calcParent(Zone zone) {
     Zone parentZone = zone.parent;
diff --git a/packages/flutter_tools/lib/src/base/os.dart b/packages/flutter_tools/lib/src/base/os.dart
index 9a4290a..f709d4d 100644
--- a/packages/flutter_tools/lib/src/base/os.dart
+++ b/packages/flutter_tools/lib/src/base/os.dart
@@ -12,9 +12,7 @@
 import 'process.dart';
 
 /// Returns [OperatingSystemUtils] active in the current app context (i.e. zone).
-OperatingSystemUtils get os {
-  return context[OperatingSystemUtils] ?? (context[OperatingSystemUtils] = new OperatingSystemUtils());
-}
+OperatingSystemUtils get os => context[OperatingSystemUtils];
 
 abstract class OperatingSystemUtils {
   factory OperatingSystemUtils() {
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index 6b58cd8..7aee1d5 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -99,7 +99,7 @@
     return _engineRevision;
   }
 
-  static Cache get instance => context[Cache] ?? (context[Cache] = new Cache());
+  static Cache get instance => context[Cache];
 
   /// Return the top-level directory in the cache; this is `bin/cache`.
   Directory getRoot() {
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index 9b1c847..a1a868c 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -48,7 +48,7 @@
 
     AppContext appContext = new AppContext();
     NotifyingLogger notifyingLogger = new NotifyingLogger();
-    appContext[Logger] = notifyingLogger;
+    appContext.setVariable(Logger, notifyingLogger);
 
     Cache.releaseLockEarly();
 
@@ -674,7 +674,7 @@
       _logger = new _AppRunLogger(domain, this);
 
     AppContext appContext = new AppContext();
-    appContext[Logger] = _logger;
+    appContext.setVariable(Logger, _logger);
     return appContext.runInZone(method);
   }
 }
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index da726d5..f727f38 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -56,7 +56,7 @@
   }
 
   /// Returns [XCode] active in the current app context.
-  static XCode get instance => context[XCode] ?? (context[XCode] = new XCode());
+  static XCode get instance => context[XCode];
 
   bool get isInstalledAndMeetsVersionCheck => isInstalled && xcodeVersionSatisfactory;
 
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index 6d405c8..d0bae71 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -37,9 +37,7 @@
 
 class IOSSimulatorUtils {
   /// Returns [IOSSimulatorUtils] active in the current app context (i.e. zone).
-  static IOSSimulatorUtils get instance {
-    return context[IOSSimulatorUtils] ?? (context[IOSSimulatorUtils] = new IOSSimulatorUtils());
-  }
+  static IOSSimulatorUtils get instance => context[IOSSimulatorUtils];
 
   List<IOSSimulator> getAttachedDevices() {
     if (!XCode.instance.isInstalledAndMeetsVersionCheck)
@@ -54,7 +52,7 @@
 /// A wrapper around the `simctl` command line tool.
 class SimControl {
   /// Returns [SimControl] active in the current app context (i.e. zone).
-  static SimControl get instance => context[SimControl] ?? (context[SimControl] = new SimControl());
+  static SimControl get instance => context[SimControl];
 
   Future<bool> boot({ String deviceName }) async {
     if (_isAnyConnected())
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 f023058..bc79962 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -137,8 +137,10 @@
   @override
   Future<Null> runCommand(ArgResults globalResults) async {
     // Check for verbose.
-    if (globalResults['verbose'])
-      context[Logger] = new VerboseLogger();
+    if (globalResults['verbose']) {
+      // Override the logger.
+      context.setVariable(Logger, new VerboseLogger());
+    }
 
     logger.quiet = globalResults['quiet'];
 
@@ -171,8 +173,7 @@
     }
 
     // The Android SDK could already have been set by tests.
-    if (!context.isSet(AndroidSdk))
-      context[AndroidSdk] = AndroidSdk.locateAndroidSdk();
+    context.putIfAbsent(AndroidSdk, () => AndroidSdk.locateAndroidSdk());
 
     if (globalResults['version']) {
       flutterUsage.sendCommand('version');
diff --git a/packages/flutter_tools/lib/src/toolchain.dart b/packages/flutter_tools/lib/src/toolchain.dart
index 61539e6..3145377 100644
--- a/packages/flutter_tools/lib/src/toolchain.dart
+++ b/packages/flutter_tools/lib/src/toolchain.dart
@@ -25,18 +25,11 @@
 /// and the engine artifact directory for a given target platform. It is configurable
 /// via command-line arguments in order to support local engine builds.
 class ToolConfiguration {
-  /// [overrideCache] is configurable for testing.
-  ToolConfiguration({ Cache overrideCache }) {
-    _cache = overrideCache ?? cache;
-  }
+  ToolConfiguration();
 
-  Cache _cache;
+  Cache get cache => context[Cache];
 
-  static ToolConfiguration get instance {
-    if (context[ToolConfiguration] == null)
-      context[ToolConfiguration] = new ToolConfiguration();
-    return context[ToolConfiguration];
-  }
+  static ToolConfiguration get instance => context[ToolConfiguration];
 
   /// Override using the artifacts from the cache directory (--engine-src-path).
   String engineSrcPath;
@@ -63,14 +56,14 @@
 
       // Create something like `android-arm` or `android-arm-release`.
       String dirName = getNameForTargetPlatform(platform) + suffix;
-      Directory engineDir = _cache.getArtifactDirectory('engine');
+      Directory engineDir = cache.getArtifactDirectory('engine');
       return new Directory(path.join(engineDir.path, dirName));
     }
   }
 
   String getHostToolPath(HostTool tool) {
     if (engineBuildPath == null) {
-      return path.join(_cache.getArtifactDirectory('engine').path,
+      return path.join(cache.getArtifactDirectory('engine').path,
                        getNameForHostPlatform(getCurrentHostPlatform()),
                        _kHostToolFileName[tool]);
     }
diff --git a/packages/flutter_tools/lib/src/usage.dart b/packages/flutter_tools/lib/src/usage.dart
index 503a0b7..934522d 100644
--- a/packages/flutter_tools/lib/src/usage.dart
+++ b/packages/flutter_tools/lib/src/usage.dart
@@ -39,7 +39,7 @@
   }
 
   /// Returns [Usage] active in the current app context.
-  static Usage get instance => context[Usage] ?? (context[Usage] = new Usage());
+  static Usage get instance => context[Usage];
 
   Analytics _analytics;